# 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