From 3c92079139ac7149a3bf959a2059f4f4bab8e1b3 Mon Sep 17 00:00:00 2001 From: Niklas Keller Date: Fri, 7 Jul 2017 14:39:22 +0200 Subject: [PATCH] Initial commit --- .editorconfig | 8 ++++ .gitignore | 4 ++ .php_cs.dist | 39 +++++++++++++++++++ .travis.yml | 29 ++++++++++++++ LICENSE | 22 +++++++++++ README.md | 31 +++++++++++++++ composer.json | 25 ++++++++++++ phpunit.xml.dist | 31 +++++++++++++++ src/EncodingInputStream.php | 65 ++++++++++++++++++++++++++++++++ test/EncodingInputStreamTest.php | 36 ++++++++++++++++++ 10 files changed, 290 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .php_cs.dist create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/EncodingInputStream.php create mode 100644 test/EncodingInputStreamTest.php diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3564b94 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = spaces +charset = utf-8 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c77cc1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.php_cs.cache +/composer.lock +/coverage +/vendor diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..921263f --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,39 @@ +setRiskyAllowed(true) + ->setRules([ + "@PSR1" => true, + "@PSR2" => true, + "braces" => [ + "allow_single_line_closure" => true, + "position_after_functions_and_oop_constructs" => "same", + ], + "array_syntax" => ["syntax" => "short"], + "cast_spaces" => true, + "combine_consecutive_unsets" => true, + "function_to_constant" => true, + "no_multiline_whitespace_before_semicolons" => true, + "no_unused_imports" => true, + "no_useless_else" => true, + "no_useless_return" => true, + "no_whitespace_before_comma_in_array" => true, + "no_whitespace_in_blank_line" => true, + "non_printable_character" => true, + "normalize_index_brace" => true, + "ordered_imports" => true, + "php_unit_construct" => true, + "php_unit_dedicate_assert" => true, + "php_unit_fqcn_annotation" => true, + "phpdoc_summary" => true, + "phpdoc_types" => true, + "psr4" => true, + "return_type_declaration" => ["space_before" => "none"], + "short_scalar_cast" => true, + "single_blank_line_before_namespace" => true, + ]) + ->setFinder( + PhpCsFixer\Finder::create() + ->in(__DIR__ . "/src") + ->in(__DIR__ . "/test") + ); \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..799c600 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +sudo: false + +language: php + +php: + - 7.0 + - 7.1 + - nightly + +matrix: + allow_failures: + - php: nightly + fast_finish: true + +before_script: + # --ignore-platform-reqs, because https://github.com/FriendsOfPHP/PHP-CS-Fixer/pull/2722 + - composer update -n --prefer-dist --ignore-platform-reqs + - composer require satooshi/php-coveralls dev-master --ignore-platform-reqs + +script: + - phpdbg -qrr vendor/bin/phpunit --coverage-text --coverage-clover build/logs/clover.xml + - PHP_CS_FIXER_IGNORE_ENV=1 php vendor/bin/php-cs-fixer --diff --dry-run -v fix + +after_script: + - php vendor/bin/coveralls -v + +cache: + directories: + - $HOME/.composer/cache/files \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..88a9573 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2017 Niklas Keller + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ce8178d --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# streaming-base64 + +[![Build Status](https://img.shields.io/travis/kelunik/streaming-base64/master.svg?style=flat-square)](https://travis-ci.org/kelunik/streaming-base64) +[![CoverageStatus](https://img.shields.io/coveralls/kelunik/streaming-base64/master.svg?style=flat-square)](https://coveralls.io/github/kelunik/streaming-base64?branch=master) +![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square) + +`kelunik/streaming-base64` is a streaming Base64 encoder / decoder for Amp's streams. + +## Installation + +This package can be installed as a [Composer](https://getcomposer.org/) dependency. + +```bash +composer require kelunik/streaming-base64 +``` + +## Requirements + +- PHP 7.0+ + +## Versioning + +`kelunik/streaming-base64` follows the [semver](http://semver.org/) semantic versioning specification. + +## Security + +If you discover any security related issues, please email [`me@kelunik.com`](mailto:me@kelunik.com) instead of using the issue tracker. + +## License + +The MIT License (MIT). Please see [`LICENSE`](./LICENSE) for more information. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..bca24be --- /dev/null +++ b/composer.json @@ -0,0 +1,25 @@ +{ + "name": "kelunik/streaming-base64", + "description": "On the fly Base64 encoding for Amp's streams.", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "autoload": { + "psr-4": { + "Kelunik\\StreamingBase64\\": "src" + } + }, + "require": { + "amphp/byte-stream": "^1.1", + "amphp/phpunit-util": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^6", + "friendsofphp/php-cs-fixer": "^2.3" + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..5175c37 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + test + + + test + + + + + src + + + + + + diff --git a/src/EncodingInputStream.php b/src/EncodingInputStream.php new file mode 100644 index 0000000..dc2b45e --- /dev/null +++ b/src/EncodingInputStream.php @@ -0,0 +1,65 @@ +source = $source; + $this->type = $type; + $this->buffer = ""; + } + + /** @inheritdoc */ + public function read(): Promise { + return call(function () { + if ($this->buffer === null) { + return null; + } + + $data = yield $this->source->read(); + + if ($data === null) { + $buffer = $this->buffer; + + $this->buffer = null; + $this->source = null; + + if ($buffer !== "") { + if ($this->type === self::TYPE_BASE64) { + return \base64_encode($buffer); + } else { + return \rtrim(\strtr(\base64_encode($buffer), "+/", "-_"), "="); + } + } + + return null; + } + + $this->buffer .= $data; + $length = \strlen($this->buffer); + $buffer = \substr($this->buffer, 0, $length - $length % 3); + $this->buffer = \substr($this->buffer, $length - $length % 3); + + if ($buffer !== "") { + if ($this->type === self::TYPE_BASE64) { + return \base64_encode($buffer); + } else { + return \strtr(\base64_encode($buffer), "+/", "-_"); + } + } + + return ""; + }); + } +} diff --git a/test/EncodingInputStreamTest.php b/test/EncodingInputStreamTest.php new file mode 100644 index 0000000..38100a9 --- /dev/null +++ b/test/EncodingInputStreamTest.php @@ -0,0 +1,36 @@ +assertSame(\base64_encode(\implode("", $array)), $result); + }); + } + + public function testBase64Url() { + Loop::run(function () { + $array = [\random_bytes(16), \random_bytes(1), \random_bytes(23)]; + $stream = new IteratorStream(fromIterable($array, 10)); + + $encodingStream = new EncodingInputStream($stream, EncodingInputStream::TYPE_BASE64URL); + $result = yield new Message($encodingStream); + + $this->assertSame(\rtrim(\strtr(\base64_encode(\implode("", $array)), "+/", "-_"), "="), $result); + }); + } +}