brcode 1.4.2

Crate to parse and emit BR Codes
Documentation
# dartbrcode

Dart wrapper of `brcode` to parse and emit [PIX BR Code](https://www.bcb.gov.br/content/estabilidadefinanceira/spb_docs/ManualBRCode.pdf).

## Usage

1. Include `dartbrcode` in `pubspec.yaml`
```yaml
dependencies:
  dartbrcode: ^0.3.0
```
2. Copy `libbrcode.*` from [brcode](https://github.com/naomijub/brcode) to your Dart/Flutter project root:
  - for Linux/Android copy `libbrcode.so`.
  - for macOS/iOS copy `libbrcode.dylib`.
  - `cargo build --release` project from [git](https://github.com/naomijub/brcode) and copy the `libbrcode.*` from `target/release/libbrcode.*` to your Dart project root. Mobile in the section `Building for mobile`.
  - Shellscript to get files from release:
  **So**
  ```sh
  curl -s https://api.github.com/repos/naomijub/brcode/releases/latest \
  | grep "browser_download_url.*so" \
  | cut -d : -f 2,3 \
  | tr -d \" \
  | wget -qi -
  ```

  **dylib**
  ```sh
  curl -s https://api.github.com/repos/naomijub/brcode/releases/latest \
  | grep "browser_download_url.*dylib" \
  | cut -d : -f 2,3 \
  | tr -d \" \
  | wget -qi -
  ```

3. Use it!

**Parse**
```dart
import 'package:dartbrcode/dartbrcode.dart';

final json = '{"payload_version":1,"initiation_method":null,"merchant_account_information":"12345678901234","merchant_information":[{"id":26,"info":[{"id":0,"info":"BR.GOV.BCB.PIX"},{"id":1,"info":"123e4567-e12b-12d1-a456-426655440000"}]},{"id":27,"info":[{"id":0,"info":"BR.COM.OUTRO"},{"id":1,"info":"0123456789"}]}],"merchant_category_code":0,"merchant_name":"NOME DO RECEBEDOR","merchant_city":"BRASILIA","postal_code":"70074900","currency":"986","amount":123.45,"country_code":"BR","field_template":[{"reference_label":"RP12345678-2019"}],"crc1610":"AD38","templates":[{"id":80,"info":[{"id":0,"info":"BR.COM.OUTRO"},{"id":1,"info":"0123.ABCD.3456.WXYZ"}]}]}';

void main() {
  jsonToBrcode(json);
  // '00020104141234567890123426580014BR.GOV.BCB.PIX0136123e4567-e12b-12d1-a456-42665544000027300012BR.COM.OUTRO011001234567895204000053039865406123.455802BR5917NOME DO RECEBEDOR6008BRASILIA61087007490062190515RP12345678-201980390012BR.COM.OUTRO01190123.ABCD.3456.WXYZ6304AD38'
}
```

**Emit**
```dart
import 'package:dartbrcode/dartbrcode.dart';

final brcode = '00020104141234567890123426580014BR.GOV.BCB.PIX0136123e4567-e12b-12d1-a456-42665544000027300012BR.COM.OUTRO011001234567895204000053039865406123.455802BR5917NOME DO RECEBEDOR6008BRASILIA61087007490062190515RP12345678-201980390012BR.COM.OUTRO01190123.ABCD.3456.WXYZ6304AD38';

void main() {
  jsonFromBrcode(brcode);
  // '{"payload_version":1,"initiation_method":null,"merchant_account_information":"12345678901234","merchant_information":[{"id":26,"info":[{"id":0,"info":"BR.GOV.BCB.PIX"},{"id":1,"info":"123e4567-e12b-12d1-a456-426655440000"}]},{"id":27,"info":[{"id":0,"info":"BR.COM.OUTRO"},{"id":1,"info":"0123456789"}]}],"merchant_category_code":0,"merchant_name":"NOME DO RECEBEDOR","merchant_city":"BRASILIA","postal_code":"70074900","currency":"986","amount":123.45,"country_code":"BR","field_template":[{"reference_label":"RP12345678-2019"}],"crc1610":"AD38","templates":[{"id":80,"info":[{"id":0,"info":"BR.COM.OUTRO"},{"id":1,"info":"0123.ABCD.3456.WXYZ"}]}]}'
}
```

**Crc16Ccitt**
```dart
import 'package:dartbrcode/dartbrcode.dart';

final uncheckedBrcode = '00020104141234567890123426580014BR.GOV.BCB.PIX0136123e4567-e12b-12d1-a456-42665544000027300012BR.COM.OUTRO011001234567895204000053039865406123.455802BR5917NOME DO RECEBEDOR6008BRASILIA61087007490062190515RP12345678-201980390012BR.COM.OUTRO01190123.ABCD.3456.WXYZ6304';

void main() {
  crc16Ccitt(uncheckedBrcode);
  // 'AD38'
}
```

## Building for mobile
[Building FFI with Flutter](https://medium.com/flutter-community/using-ffi-on-flutter-plugins-to-run-native-rust-code-d64c0f14f9c2)

### Android
1. Install Android NDK
2. Add Rust target for android `rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android`
3. Build cargo for every target
```sh
# $ANDROID_NDK_HOME is already set and pointing to the Android NDK folder

# ENV
AARCH64_LINKER=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang
ARMV7_LINKER=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi26-clang
I686_LINKER=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android26-clang

# Build
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$AARCH64_LINKER cargo build - target aarch64-linux-android - release
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=$ARMV7_LINKER cargo build - target armv7-linux-androideabi - release
CARGO_TARGET_I686_LINUX_ANDROID_LINKER=$I686_LINKER cargo build - target i686-linux-android - release
```
4. Files will be found at:
```
target/aarch64-linux-android/release/libbrcode.so
target/armv7-linux-androideabi/release/libbrcode.so
target/i686-linux-android/release/libbrcode.so
```

### iOS
1. Instal xcode
2. Add Rust targets for iOS `rustup target add aarch64-apple-ios armv7-apple-ios armv7s-apple-ios x86_64-apple-ios i386-apple-ios`
3. Install `cargo-lipo` `cargo install cargo-lipo`.
4. Install `cbindgen` `cargo install cbindgen`.
5. Build targets for iOS  with `cargo lipo --release`.
6. Create a `cbindgen.toml`:
```toml
language = "C"
autogen_warning = "// NOTE: Append the lines below to ios/Classes/Brcode.h"
#namespace = "ffi"
#include_guard = "CBINDGEN_BINDINGS_H"

[defines]
"target_os = ios" = "TARGET_OS_IOS"
"target_os = macos" = "TARGET_OS_MACOS"
```
7. Create C bindigns via:  `cbindgen ./src/lib.rs -c cbindgen.toml | grep -v \#include | uniq`

## Benchmarks

### with `dart_benchmark`
**jsonToBrcode**
```
For 100 runs: peak: 371 us,	bottom: 048 us,	avg: ~083 us
```

**brcodeToJson**
```
For 100 runs: peak: 327 us,	bottom: 069 us,	avg: ~101 us
```

### with `benchmark_harness`
**jsonToBrcode**
```
For 10 runs: 207.51774227018055 us.
```

**brcodeToJson**
```
For 10 runs: 378.68780764861793 us.
```

## Milestones
- [x] parse, `brcodeToJson`
- [x] emit, `jsonToBrcode`
- [x] parse returning `Map<String, dynamic>`
- [x] emit receiving `Map<String, dynamic>` as args