diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c44ab0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Files and directories created by pub +.dart_tool/ +.packages + +# Omit commiting pubspec.lock for library packages: +# https://dart.dev/guides/libraries/private-files#pubspeclock +pubspec.lock + +# Conventional directory for build outputs +build/ + +# Directory created by dartdoc +doc/api/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..687440b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version, created by Stagehand diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..54a446b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Oliver Ni + +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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5260376 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# Bottom + +This is a Dart implementation of [bottom](https://github.com/kaylynn234/bottom). + +Bottom encodes UTF-8 text into a sequence comprised of bottom emoji (`πŸ«‚βœ¨πŸ₯Ίβ€οΈ`, with `,` sprinkled in for good measure) followed by `πŸ‘‰πŸ‘ˆ`. It can encode any valid UTF-8 β€” being a bottom transcends language, after all β€” and decode back into UTF-8. + +## Usage + +Here's a simple example: + +```dart +import 'package:bottom/bottom.dart'; + +void main(List args) { + print(bottom.encode(args.join(' '))); +} +``` diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..a686c1b --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,14 @@ +# Defines a default set of lint rules enforced for +# projects at Google. For details and rationale, +# see https://github.com/dart-lang/pedantic#enabled-lints. +include: package:pedantic/analysis_options.yaml + +# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. +# Uncomment to specify additional rules. +# linter: +# rules: +# - camel_case_types + +analyzer: +# exclude: +# - path/to/excluded/files/** diff --git a/example/bottom_example.dart b/example/bottom_example.dart new file mode 100644 index 0000000..2814047 --- /dev/null +++ b/example/bottom_example.dart @@ -0,0 +1,5 @@ +import 'package:bottom/bottom.dart'; + +void main(List args) { + print(bottom.encode(args.join(' '))); +} diff --git a/lib/bottom.dart b/lib/bottom.dart new file mode 100644 index 0000000..00d32ef --- /dev/null +++ b/lib/bottom.dart @@ -0,0 +1,60 @@ +library bottom; + +import 'dart:convert'; + +Map _charValues = { + 'πŸ«‚': 200, + 'πŸ’–': 50, + '✨': 10, + 'πŸ₯Ί': 5, + ',': 1, +}; + +const _zero = '❀️'; +const _sectionSeparator = 'πŸ‘‰πŸ‘ˆ'; +final _terminator = RegExp('$_sectionSeparator?\$'); + +class BottomEncoder extends Converter { + String _encodeByte(int value) { + if (value == 0) return ''; + final largest = + _charValues.entries.firstWhere((entry) => value >= entry.value); + return largest.key + _encodeByte(value - largest.value); + } + + String encodeByte(int value) { + return value == 0 ? _zero : _encodeByte(value); + } + + @override + String convert(String input) { + return utf8 + .encode(input) + .map((value) => encodeByte(value) + _sectionSeparator) + .join(); + } +} + +class BottomDecoder extends Converter { + @override + String convert(String input) { + return utf8.decode(input + .trim() + .replaceAll(_terminator, '') + .split(_sectionSeparator) + .map((chars) => chars + .split('') + .map((x) => _charValues[x]) + .reduce((a, b) => a + b))); + } +} + +class BottomCodec extends Codec { + @override + BottomEncoder get encoder => BottomEncoder(); + + @override + BottomDecoder get decoder => BottomDecoder(); +} + +final bottom = BottomCodec(); diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..54d1065 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,11 @@ +name: bottom +description: A starting point for Dart libraries or applications. +version: 1.0.0 +homepage: https://github.com/oliver-ni/bottom-dart + +environment: + sdk: ">=2.8.1 <3.0.0" + +dev_dependencies: + pedantic: ^1.9.0 + test: ^1.14.4 diff --git a/test/bottom_dart_test.dart b/test/bottom_dart_test.dart new file mode 100644 index 0000000..c586ad7 --- /dev/null +++ b/test/bottom_dart_test.dart @@ -0,0 +1,24 @@ +import 'package:bottom/bottom.dart'; +import 'package:test/test.dart'; + +Map pairs = { + 'Test': 'πŸ’–βœ¨βœ¨βœ¨,,,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨πŸ₯ΊπŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨πŸ₯Ί,πŸ‘‰πŸ‘ˆ', + 'Hello World': + 'πŸ’–βœ¨βœ¨,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–πŸ₯Ί,,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–πŸ₯Ί,,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨,πŸ‘‰πŸ‘ˆβœ¨βœ¨βœ¨,,πŸ‘‰πŸ‘ˆπŸ’–βœ¨βœ¨βœ¨πŸ₯Ί,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨,,,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–πŸ₯Ί,,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–πŸ‘‰πŸ‘ˆ', + 'γŒγ‚“γ°γ‚Œ': + 'πŸ«‚βœ¨βœ¨πŸ₯Ί,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨βœ¨πŸ₯Ί,,,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨βœ¨βœ¨βœ¨πŸ‘‰πŸ‘ˆπŸ«‚βœ¨βœ¨πŸ₯Ί,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨βœ¨βœ¨πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨βœ¨βœ¨βœ¨πŸ₯Ί,,πŸ‘‰πŸ‘ˆπŸ«‚βœ¨βœ¨πŸ₯Ί,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨βœ¨πŸ₯Ί,,,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–πŸ’–βœ¨βœ¨πŸ₯Ί,πŸ‘‰πŸ‘ˆπŸ«‚βœ¨βœ¨πŸ₯Ί,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨βœ¨βœ¨πŸ‘‰πŸ‘ˆπŸ’–πŸ’–βœ¨βœ¨βœ¨βœ¨πŸ‘‰πŸ‘ˆ', + 'πŸ₯Ί': 'πŸ«‚βœ¨βœ¨βœ¨βœ¨πŸ‘‰πŸ‘ˆπŸ’–πŸ’–πŸ’–πŸ₯Ί,,,,πŸ‘‰πŸ‘ˆπŸ’–πŸ’–πŸ’–βœ¨πŸ₯ΊπŸ‘‰πŸ‘ˆπŸ’–πŸ’–πŸ’–βœ¨βœ¨βœ¨πŸ₯Ί,πŸ‘‰πŸ‘ˆ', + '\x00': 'β€οΈπŸ‘‰πŸ‘ˆ', +}; + +void main() { + group('Bottom tests', () { + test('Encodes properly', () { + pairs.forEach((text, result) => expect(bottom.encode(text), result)); + }); + + test('Decodes properly', () { + pairs.forEach((text, result) => expect(bottom.decode(result), text)); + }); + }); +}