diff --git a/mobile/lib/bridge_definitions.dart b/mobile/lib/bridge_definitions.dart index bd62891..6c2789a 100644 --- a/mobile/lib/bridge_definitions.dart +++ b/mobile/lib/bridge_definitions.dart @@ -12,6 +12,10 @@ abstract class Native { Future getTxConfig({required Uint8List bytes, dynamic hint}); FlutterRustBridgeTaskConstMeta get kGetTxConfigConstMeta; + + Future checkRaptor({required Uint8List buffer, required TxConfig txconf, dynamic hint}); + + FlutterRustBridgeTaskConstMeta get kCheckRaptorConstMeta; } class TxConfig { diff --git a/mobile/lib/bridge_generated.dart b/mobile/lib/bridge_generated.dart index e251d34..140944b 100644 --- a/mobile/lib/bridge_generated.dart +++ b/mobile/lib/bridge_generated.dart @@ -40,6 +40,23 @@ class NativeImpl implements Native { argNames: ["bytes"], ); + Future checkRaptor({required Uint8List buffer, required TxConfig txconf, dynamic hint}) { + var arg0 = _platform.api2wire_uint_8_list(buffer); + var arg1 = _platform.api2wire_box_autoadd_tx_config(txconf); + return _platform.executeNormal(FlutterRustBridgeTask( + callFfi: (port_) => _platform.inner.wire_check_raptor(port_, arg0, arg1), + parseSuccessData: _wire2api_bool, + constMeta: kCheckRaptorConstMeta, + argValues: [buffer, txconf], + hint: hint, + )); + } + + FlutterRustBridgeTaskConstMeta get kCheckRaptorConstMeta => const FlutterRustBridgeTaskConstMeta( + debugName: "check_raptor", + argNames: ["buffer", "txconf"], + ); + void dispose() { _platform.dispose(); } @@ -49,6 +66,10 @@ class NativeImpl implements Native { return raw as String; } + bool _wire2api_bool(dynamic raw) { + return raw as bool; + } + TxConfig _wire2api_box_autoadd_tx_config(dynamic raw) { return _wire2api_tx_config(raw); } @@ -86,6 +107,11 @@ class NativeImpl implements Native { // Section: api2wire +@protected +int api2wire_u16(int raw) { + return raw; +} + @protected int api2wire_u8(int raw) { return raw; @@ -98,6 +124,23 @@ class NativePlatform extends FlutterRustBridgeBase { // Section: api2wire + @protected + ffi.Pointer api2wire_String(String raw) { + return api2wire_uint_8_list(utf8.encoder.convert(raw)); + } + + @protected + ffi.Pointer api2wire_box_autoadd_tx_config(TxConfig raw) { + final ptr = inner.new_box_autoadd_tx_config_0(); + _api_fill_to_wire_tx_config(raw, ptr.ref); + return ptr; + } + + @protected + int api2wire_u64(int raw) { + return raw; + } + @protected ffi.Pointer api2wire_uint_8_list(Uint8List raw) { final ans = inner.new_uint_8_list_0(raw.length); @@ -107,6 +150,16 @@ class NativePlatform extends FlutterRustBridgeBase { // Section: finalizer // Section: api_fill_to_wire + + void _api_fill_to_wire_box_autoadd_tx_config(TxConfig apiObj, ffi.Pointer wireObj) { + _api_fill_to_wire_tx_config(apiObj, wireObj.ref); + } + + void _api_fill_to_wire_tx_config(TxConfig apiObj, wire_TxConfig wireObj) { + wireObj.len = api2wire_u64(apiObj.len); + wireObj.mtu = api2wire_u16(apiObj.mtu); + wireObj.description = api2wire_String(apiObj.description); + } } // ignore_for_file: camel_case_types, non_constant_identifier_names, avoid_positional_boolean_parameters, annotate_overrides, constant_identifier_names @@ -202,6 +255,33 @@ class NativeWire implements FlutterRustBridgeWireBase { late final _wire_get_tx_config = _wire_get_tx_configPtr.asFunction)>(); + void wire_check_raptor( + int port_, + ffi.Pointer buffer, + ffi.Pointer txconf, + ) { + return _wire_check_raptor( + port_, + buffer, + txconf, + ); + } + + late final _wire_check_raptorPtr = _lookup< + ffi.NativeFunction, ffi.Pointer)>>( + 'wire_check_raptor'); + late final _wire_check_raptor = + _wire_check_raptorPtr.asFunction, ffi.Pointer)>(); + + ffi.Pointer new_box_autoadd_tx_config_0() { + return _new_box_autoadd_tx_config_0(); + } + + late final _new_box_autoadd_tx_config_0Ptr = + _lookup Function()>>('new_box_autoadd_tx_config_0'); + late final _new_box_autoadd_tx_config_0 = + _new_box_autoadd_tx_config_0Ptr.asFunction Function()>(); + ffi.Pointer new_uint_8_list_0( int len, ) { @@ -236,6 +316,16 @@ final class wire_uint_8_list extends ffi.Struct { external int len; } +final class wire_TxConfig extends ffi.Struct { + @ffi.Uint64() + external int len; + + @ffi.Uint16() + external int mtu; + + external ffi.Pointer description; +} + typedef DartPostCObjectFnType = ffi.Pointer message)>>; typedef DartPort = ffi.Int64; diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 6716d37..b3aad83 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -49,9 +49,10 @@ class _MyHomePageState extends State { late final Stream> _barcodesStream = _barcodesController.stream; final _scrollController = ScrollController(); - final TxConfig? _txConfig = null; - final _rxData = []; - final _cuttleState = CuttleState.unitialized; + TxConfig? _txConfig; + String? _rxText; + var _cuttleState = CuttleState.unitialized; + final _rxData = []; @override void dispose() { @@ -68,7 +69,7 @@ class _MyHomePageState extends State { androidOptions: const AndroidAnalysisOptions.nv21( width: 1024, ), - maxFramesPerSecond: 5, + maxFramesPerSecond: null, autoStart: false, ), builder: (cameraModeState, previewSize, previewRect) { @@ -88,7 +89,44 @@ class _MyHomePageState extends State { try { var recognizedBarCodes = await _barcodeScanner.processImage(inputImage); for (Barcode barcode in recognizedBarCodes) { - debugPrint("Barcode: [${barcode.format}]: ${barcode.rawBytes}"); + var bytes = barcode.rawBytes; + if (bytes == null) { + continue; + } + final dbytes = bytes; + switch (_cuttleState) { + case CuttleState.unitialized: + { + var txconf = await api.getTxConfig(bytes: dbytes); + if (txconf != null) { + _txConfig = txconf; + _cuttleState = CuttleState.receiving; + debugPrint( + "txconf: ${txconf.len} bytes, \"${txconf.description}\""); + continue; + } + // implicit else here; txconf was null + var text = barcode.rawValue; + if (text != null) { + // it's not a txconfig, and it's not a raptor packet, so it must be a regular qr code + _rxText = text; + _cuttleState = CuttleState.received; + } + } + + case CuttleState.receiving: + { + final check = await api.checkRaptor( + buffer: Uint8List.fromList(_rxData), txconf: _txConfig!); + if (check) { + _cuttleState = CuttleState.received; + } + } + + case CuttleState.received: + continue; + } + _addBarcode("[${barcode.format.name}]: ${barcode.rawValue}"); } } catch (error) { diff --git a/mobile/native/src/api.rs b/mobile/native/src/api.rs index 2639527..7075e68 100644 --- a/mobile/native/src/api.rs +++ b/mobile/native/src/api.rs @@ -27,3 +27,7 @@ pub fn get_tx_config(bytes: Vec) -> Option { } None } + +pub fn check_raptor(buffer: Vec, txconf: TxConfig) -> bool { + false +} diff --git a/mobile/native/src/bridge_generated.io.rs b/mobile/native/src/bridge_generated.io.rs index 97bfe87..0870c5d 100644 --- a/mobile/native/src/bridge_generated.io.rs +++ b/mobile/native/src/bridge_generated.io.rs @@ -6,8 +6,22 @@ pub extern "C" fn wire_get_tx_config(port_: i64, bytes: *mut wire_uint_8_list) { wire_get_tx_config_impl(port_, bytes) } +#[no_mangle] +pub extern "C" fn wire_check_raptor( + port_: i64, + buffer: *mut wire_uint_8_list, + txconf: *mut wire_TxConfig, +) { + wire_check_raptor_impl(port_, buffer, txconf) +} + // Section: allocate functions +#[no_mangle] +pub extern "C" fn new_box_autoadd_tx_config_0() -> *mut wire_TxConfig { + support::new_leak_box_ptr(wire_TxConfig::new_with_null_ptr()) +} + #[no_mangle] pub extern "C" fn new_uint_8_list_0(len: i32) -> *mut wire_uint_8_list { let ans = wire_uint_8_list { @@ -21,6 +35,28 @@ pub extern "C" fn new_uint_8_list_0(len: i32) -> *mut wire_uint_8_list { // Section: impl Wire2Api +impl Wire2Api for *mut wire_uint_8_list { + fn wire2api(self) -> String { + let vec: Vec = self.wire2api(); + String::from_utf8_lossy(&vec).into_owned() + } +} +impl Wire2Api for *mut wire_TxConfig { + fn wire2api(self) -> TxConfig { + let wrap = unsafe { support::box_from_leak_ptr(self) }; + Wire2Api::::wire2api(*wrap).into() + } +} +impl Wire2Api for wire_TxConfig { + fn wire2api(self) -> TxConfig { + TxConfig { + len: self.len.wire2api(), + mtu: self.mtu.wire2api(), + description: self.description.wire2api(), + } + } +} + impl Wire2Api> for *mut wire_uint_8_list { fn wire2api(self) -> Vec { unsafe { @@ -31,6 +67,14 @@ impl Wire2Api> for *mut wire_uint_8_list { } // Section: wire structs +#[repr(C)] +#[derive(Clone)] +pub struct wire_TxConfig { + len: u64, + mtu: u16, + description: *mut wire_uint_8_list, +} + #[repr(C)] #[derive(Clone)] pub struct wire_uint_8_list { @@ -50,6 +94,22 @@ impl NewWithNullPtr for *mut T { } } +impl NewWithNullPtr for wire_TxConfig { + fn new_with_null_ptr() -> Self { + Self { + len: Default::default(), + mtu: Default::default(), + description: core::ptr::null_mut(), + } + } +} + +impl Default for wire_TxConfig { + fn default() -> Self { + Self::new_with_null_ptr() + } +} + // Section: sync execution mode utility #[no_mangle] diff --git a/mobile/native/src/bridge_generated.rs b/mobile/native/src/bridge_generated.rs index a556e89..6c63a24 100644 --- a/mobile/native/src/bridge_generated.rs +++ b/mobile/native/src/bridge_generated.rs @@ -35,6 +35,24 @@ fn wire_get_tx_config_impl(port_: MessagePort, bytes: impl Wire2Api> + U }, ) } +fn wire_check_raptor_impl( + port_: MessagePort, + buffer: impl Wire2Api> + UnwindSafe, + txconf: impl Wire2Api + UnwindSafe, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap::<_, _, _, bool>( + WrapInfo { + debug_name: "check_raptor", + port: Some(port_), + mode: FfiCallMode::Normal, + }, + move || { + let api_buffer = buffer.wire2api(); + let api_txconf = txconf.wire2api(); + move |task_callback| Ok(check_raptor(api_buffer, api_txconf)) + }, + ) +} // Section: wrapper structs // Section: static checks @@ -57,6 +75,17 @@ where (!self.is_null()).then(|| self.wire2api()) } } + +impl Wire2Api for u16 { + fn wire2api(self) -> u16 { + self + } +} +impl Wire2Api for u64 { + fn wire2api(self) -> u64 { + self + } +} impl Wire2Api for u8 { fn wire2api(self) -> u8 { self