diff --git a/README.rst b/README.rst index c5ce704..3af3020 100644 --- a/README.rst +++ b/README.rst @@ -18,7 +18,7 @@ This repository contains: * A small Rust bridge crate referencing ``ccc_rust`` via a git tag * Generated ``flutter_rust_bridge`` bindings -* A Flutter plugin scaffold (iOS / Android / macOS) +* A Flutter plugin scaffold (iOS / Android / macOS / Linux / Windows) * A clean Dart API surface for applications This plugin does **not** implement cryptography itself. diff --git a/android/build.gradle b/android/build.gradle index ae7c4c5..c9a4fe7 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,7 +1,7 @@ // The Android Gradle Plugin builds the native code with the Android NDK. -group = "com.example.ccc_cryptography" -version = "1.0" +group 'com.flutter_rust_bridge.ccc_cryptography' +version '1.0' buildscript { repositories { @@ -11,7 +11,7 @@ buildscript { dependencies { // The Android Gradle Plugin knows how to build native code with the NDK. - classpath("com.android.tools.build:gradle:8.11.1") + classpath 'com.android.tools.build:gradle:7.3.0' } } @@ -22,42 +22,35 @@ rootProject.allprojects { } } -apply plugin: "com.android.library" +apply plugin: 'com.android.library' android { - namespace = "com.example.ccc_cryptography" + if (project.android.hasProperty("namespace")) { + namespace 'com.flutter_rust_bridge.ccc_cryptography' + } - // Bumping the plugin compileSdk version requires all clients of this plugin + // Bumping the plugin compileSdkVersion requires all clients of this plugin // to bump the version in their app. - compileSdk = 36 + compileSdkVersion 33 // Use the NDK version // declared in /android/app/build.gradle file of the Flutter project. - // Replace it with a version number if this plugin requires a specific NDK version. + // Replace it with a version number if this plugin requires a specfic NDK version. // (e.g. ndkVersion "23.1.7779620") - ndkVersion = android.ndkVersion - - // Invoke the shared CMake build with the Android Gradle Plugin. - externalNativeBuild { - cmake { - path = "../src/CMakeLists.txt" - - // The default CMake version for the Android Gradle Plugin is 3.10.2. - // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake - // - // The Flutter tooling requires that developers have CMake 3.10 or later - // installed. You should not increase this version, as doing so will cause - // the plugin to fail to compile for some customers of the plugin. - // version "3.10.2" - } - } + ndkVersion android.ndkVersion compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } defaultConfig { - minSdk = 24 + minSdkVersion 19 } } + +apply from: "../cargokit/gradle/plugin.gradle" +cargokit { + manifestDir = "../rust" + libname = "ccc_cryptography" +} diff --git a/docs/README_DEV.rst b/docs/README_DEV.rst new file mode 100644 index 0000000..d763797 --- /dev/null +++ b/docs/README_DEV.rst @@ -0,0 +1,49 @@ + + + +FRB v2 +====== +With flutter_rust_bridge, the Rust dependency lives in Cargo.toml, not pubspec.yaml + +FRB v2 ships with Cargokit — a build helper that hooks into each platform's build +system (Gradle, Xcode, CMake) and compiles the Rust crate automatically at flutter build time. +This means: + * ccc_rust does not need a pubspec.yaml + * ccc_rust stays a pure Rust crate + * The current lum_ccc_rust entry in pubspec.yaml would be removed — it moves to rust/Cargo.toml + +:: + + ccc_dart_plugin/ + ├── pubspec.yaml ← NO reference to ccc_rust here + ├── rust/ + │ ├── Cargo.toml ← ccc_rust referenced HERE as a Rust crate dep + │ └── src/api.rs ← thin wrappers calling ccc_rust + + +ccc_rust +======== +The Rust crypto library remains a pure Rust crate with no Flutter or FFI-specific code. +Option 1: Build from source via Cargokit (recommended for development) + * The Rust crate references ccc_rust via a git tag in Cargo.toml + * Cargokit compiles the Rust code at build time for each platform + * No precompiled binaries are needed + +Option 2: Cargokit precompiled binaries via GitHub Releases (recommended for pub.dev) + * The Rust crate is compiled into platform-specific binaries (staticlib for iOS/macOS, cdylib for Android) + * Binaries are uploaded to GitHub Releases + * Cargokit fetches the correct binary at build time based on the target platform + * This allows pub.dev users to get native performance without needing Rust or a build environment + + +Workflow +-------- +* CI builds the Rust crate for all 5 platform targets +* CI uploads the .so/.dylib/.dll/.framework to a GitHub Release tagged with the Cargo package hash +* When consumers run flutter build, Cargokit downloads the precompiled binary instead of compiling +* If no precompiled binary exists, it falls back to source build +* Pros: Fast builds for consumers, no Rust toolchain needed, no repo bloat, built into FRB, single repo +* Cons: Requires CI pipeline to build + upload binaries +* Best for: pub.dev releases, distributing to teams without Rust installed + + diff --git a/docs/ccc_fplugin_architecture_design.rst b/docs/ccc_fplugin_architecture_design.rst index c6ab0fd..cba4447 100644 --- a/docs/ccc_fplugin_architecture_design.rst +++ b/docs/ccc_fplugin_architecture_design.rst @@ -1,9 +1,9 @@ CCC Dart Plugin — Architecture & Integration Guide ==================================================== -:Status: Milestone 2 (Planned) -:Depends on: ``ccc_rust`` ≥ v0.1.0 -:Target: Flutter (iOS, Android, macOS) +:Status: Milestone 2 (In Progress) +:Depends on: ``ccc_rust`` ≥ v0.1.0 (ready) +:Target: Flutter (iOS, Android, macOS, Linux, Windows) :Bridge: ``flutter_rust_bridge`` v2 Overview @@ -23,7 +23,7 @@ This repository contains: * A small Rust bridge crate referencing ``ccc_rust`` via a git tag * Generated ``flutter_rust_bridge`` bindings -* A Flutter plugin scaffold (iOS / Android / macOS) +* A Flutter plugin scaffold (iOS / Android / macOS / Linux / Windows) * A clean Dart API surface for applications This plugin does **not** implement cryptography itself. @@ -100,21 +100,25 @@ Repository Structure ccc_dart_plugin/ ├── pubspec.yaml + ├── flutter_rust_bridge.yaml ├── lib/ + │ ├── ccc_cryptography.dart # barrel export │ ├── ccc_crypto.dart │ ├── ccc_provider_catalog.dart │ ├── ccc_self_test.dart + │ ├── ccc_exceptions.dart │ └── src/ - │ └── frb_generated.dart + │ └── frb_generated.dart # auto-generated by FRB ├── rust/ │ ├── Cargo.toml │ └── src/ │ ├── lib.rs - │ └── api.rs - ├── flutter_rust_bridge.yaml + │ └── api.rs # thin wrappers over ccc_rust ├── ios/ ├── android/ ├── macos/ + ├── linux/ + ├── windows/ └── test/ └── roundtrip_test.dart @@ -128,7 +132,7 @@ Rust Bridge Crate .. code-block:: toml [package] - name = "ccc_dart_bridge" + name = "ccc_cryptography" version = "0.1.0" edition = "2021" @@ -228,13 +232,19 @@ Testing Requirements Before tagging ``v0.1.0`` of this plugin: * Rust bridge builds for: - - iOS (aarch64-apple-ios) - - Android (arm64 + x86_64) - - macOS (aarch64) -* Flutter integration tests: + - iOS (aarch64-apple-ios, aarch64-apple-ios-sim) + - Android (aarch64-linux-android, x86_64-linux-android) + - macOS (aarch64-apple-darwin, x86_64-apple-darwin) + - Linux (x86_64-unknown-linux-gnu) + - Windows (x86_64-pc-windows-msvc) +* Unit tests (Dart-side, host platform): - AEAD roundtrip encrypt/decrypt - HKDF known-vector test - X25519 key agreement test + - Provider catalog and self-test validation + - Error handling / exception mapping +* Flutter integration tests (on-device, all five platforms): + - Full init → encrypt → decrypt flow * ``CccSelfTest.runAll()`` returns success * No Dart-side crypto logic present * No modification of ``ccc_rust`` source @@ -296,3 +306,11 @@ Planned enhancements after Milestone 2: ---- +Related Documents +----------------- + +* ``docs/milestone2_phases.rst`` — Phase-by-phase implementation + tracker with task checklists and exit criteria. + +---- + diff --git a/docs/ccc_rust_milestone2_phases.rst b/docs/ccc_rust_milestone2_phases.rst new file mode 100644 index 0000000..5aebd0a --- /dev/null +++ b/docs/ccc_rust_milestone2_phases.rst @@ -0,0 +1,574 @@ +CCC Dart Plugin — Milestone 2 Implementation Phases +===================================================== + +:Created: 2026-03-11 +:Last Updated: 2026-03-11 +:Status: In Progress +:Depends on: ``ccc_rust`` ≥ v0.1.0 (ready) +:Bridge: ``flutter_rust_bridge`` v2 +:Platforms: iOS, Android, macOS, Linux, Windows +:Rust repo: ``ssh://git@10.0.5.109:j3g/lum_ccc_rust.git`` +:Local override: ``/Volumes/LUM/source/letusmsg_proj/app/lum_ccc_rust`` + +This document tracks the implementation phases for Milestone 2 — +building the ``flutter_rust_bridge``-based Flutter plugin that exposes +``ccc_rust`` cryptographic providers to Dart. + +Related Documents +~~~~~~~~~~~~~~~~~ + +* ``docs/ccc_fplugin_architecture_design.rst`` — Architecture & integration guide +* ``docs/ccc_rust_plan.rst`` — Master three-milestone architecture plan +* ``docs/ccc_rust_plan_phases.rst`` — Phase tracking across all milestones +* ``docs/ccc_rust_milestone2_session_state_OLD.rst`` — Earlier planning (superseded by this doc) + +Preconditions (verified) +~~~~~~~~~~~~~~~~~~~~~~~~ + +* ``[x]`` Milestone 1 verification gate passed +* ``[x]`` Conformance vectors passed in Rust workspace +* ``[x]`` Rust target builds validated (iOS + Android) +* ``[x]`` ``cargo audit`` — no known CVEs + +---- + +Phase Overview +-------------- + +====== ========================================== ========== ============ +Phase Title Status Depends on +====== ========================================== ========== ============ +1 Project Restructure & FRB Setup Done — +2 Rust Bridge Crate (DTOs + API) Not Started Phase 1 +3 Dart API Surface Not Started Phase 2 +4 Platform Build Verification Not Started Phase 3 +5 Unit Tests Not Started Phase 3 +6 Integration Tests & Polish Not Started Phase 4, 5 +====== ========================================== ========== ============ + +---- + +Phase 1 — Project Restructure & FRB Setup +------------------------------------------ + +:Status: Done + +**Goal:** Replace the placeholder C FFI scaffold with a +``flutter_rust_bridge`` v2 project structure. + +Tasks +~~~~~ + +.. list-table:: + :header-rows: 1 + :widths: 5 60 15 + + * - # + - Task + - Status + * - 1.1 + - Remove placeholder C source files (``src/ccc_cryptography.c``, + ``src/ccc_cryptography.h``) + - ✅ + * - 1.2 + - Remove ``ffigen.yaml`` and generated bindings + (``lib/ccc_cryptography_bindings_generated.dart``) + - ✅ + * - 1.3 + - Create ``rust/`` directory with bridge crate scaffold + (``Cargo.toml``, ``src/lib.rs``, ``src/api/``); FRB directory + structure via ``flutter_rust_bridge_codegen integrate``; + set ``crate-type = ["cdylib", "staticlib"]`` + - ✅ + * - 1.4 + - Add ``flutter_rust_bridge`` v2 dependency to ``rust/Cargo.toml``; + reference ``ccc_rust`` crates via local path deps for dev + (git deps commented for CI/release); + crate name set to ``ccc_cryptography`` to match plugin + - ✅ + * - 1.5 + - Create ``flutter_rust_bridge.yaml`` configuration + (``rust_input: crate::api``, ``dart_output: lib/src/rust``) + - ✅ + * - 1.6 + - Update ``pubspec.yaml``: replace ``ffigen`` with + ``flutter_rust_bridge``, add freezed, integration_test + - ✅ + * - 1.7 + - Platform build configs generated by FRB integrate + + Cargokit (CMakeLists, Podspecs, Gradle) + - ✅ + * - 1.8 + - Run ``flutter_rust_bridge_codegen generate`` — bridge compiles; + ``flutter build macos`` succeeds (42.7 MB example app) + - ✅ + +Exit Criteria +~~~~~~~~~~~~~ + +* ``flutter_rust_bridge_codegen generate`` succeeds. +* ``flutter build`` runs without errors on host (macOS). +* No C FFI scaffolding remains. + +---- + +Phase 2 — Rust Bridge Crate (DTOs + API) +------------------------------------------ + +:Status: Not Started +:Depends on: Phase 1 + +**Goal:** Implement DTOs and thin Rust wrappers in the bridge crate that +expose all ``ccc_rust`` provider functionality across the FRB bridge. + +The bridge crate lives at ``rust/`` and must not contain any cryptographic +logic — only type conversions and delegation to ``ccc_rust`` providers. + +DTOs (``rust/src/dto.rs``) +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Bridge-visible data transfer objects with ``From`` impls: + +.. list-table:: + :header-rows: 1 + :widths: 5 60 15 + + * - # + - Task + - Status + * - 2.1 + - ``CapabilitiesDto`` — maps from ``ProviderCapabilities`` + (provider name, algorithm availability, efficiency/reliability + scores) + - ☐ + * - 2.2 + - ``KemKeyPairDto`` — maps from ``KemKeyPair`` + (public_key, private_key as ``Vec``) + - ☐ + * - 2.3 + - ``KemEncapDto`` — maps from KEM encapsulation result + (ciphertext, shared_secret) + - ☐ + * - 2.4 + - ``SelfTestDto`` — maps from ``SelfTestReport`` + (overall pass/fail, per-algorithm results) + - ☐ + * - 2.5 + - ``AlgoTestResultDto`` — maps from ``AlgoTestResult`` + (algorithm ID, pass/fail, diagnostic message) + - ☐ + +Bridge API (``rust/src/api.rs``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + :widths: 5 60 15 + + * - # + - Task + - Status + * - 2.6 + - ``ccc_init()`` — register WolfSslProvider, run capability probe + - ☐ + * - 2.7 + - ``ccc_list_providers()`` — return registered provider names + - ☐ + * - 2.8 + - ``ccc_capabilities()`` / ``ccc_available_algorithms()`` + — return ``CapabilitiesDto`` for a provider + - ☐ + * - 2.9 + - ``ccc_aead_encrypt(algorithm, key, nonce, plaintext, aad)`` + — thin wrapper over provider AEAD encrypt + - ☐ + * - 2.10 + - ``ccc_aead_decrypt(algorithm, key, nonce, ciphertext, aad)`` + — thin wrapper over provider AEAD decrypt + - ☐ + * - 2.11 + - ``ccc_kdf_derive(algorithm, ikm, salt, info, len)`` + — thin wrapper over provider KDF + - ☐ + * - 2.12 + - ``ccc_mac_compute(algorithm, key, data)`` + — thin wrapper over provider MAC compute + - ☐ + * - 2.13 + - ``ccc_mac_verify(algorithm, key, data, mac)`` + — thin wrapper over provider MAC verify + - ☐ + * - 2.14 + - ``ccc_hash(algorithm, data)`` + — thin wrapper over provider hash + - ☐ + * - 2.15 + - ``ccc_kem_generate_keypair(algorithm)`` + — return ``KemKeyPairDto`` + - ☐ + * - 2.16 + - ``ccc_kem_encapsulate(algorithm, public_key)`` + — return ``KemEncapDto`` + - ☐ + * - 2.17 + - ``ccc_kem_decapsulate(algorithm, private_key, ciphertext)`` + — return shared secret + - ☐ + * - 2.18 + - ``ccc_self_test()`` — return ``SelfTestDto`` + - ☐ + * - 2.19 + - Define bridge-visible error enum mapping ``CryptoError`` + variants to structured types (``UnsupportedAlgorithm``, + ``InvalidKey``, ``InvalidNonce``, ``AuthenticationFailed``, + ``InternalError``) + - ☐ + * - 2.20 + - Run ``flutter_rust_bridge_codegen generate`` — verify all + wrappers produce valid Dart bindings + - ☐ + +DTO ↔ Rust Type Mapping +~~~~~~~~~~~~~~~~~~~~~~~~ + +======================== =================================== ======================== +Bridge DTO Rust Core Type Direction +======================== =================================== ======================== +``CapabilitiesDto`` ``ProviderCapabilities`` Rust → Dart +``KemKeyPairDto`` ``KemKeyPair`` Rust → Dart +``KemEncapDto`` (ciphertext, shared_secret) Rust → Dart +``SelfTestDto`` ``SelfTestReport`` Rust → Dart +``AlgoTestResultDto`` ``AlgoTestResult`` Rust → Dart +``CryptoError`` enum ``CryptoError`` Rust → Dart exception +======================== =================================== ======================== + +Exit Criteria +~~~~~~~~~~~~~ + +* All DTOs defined with ``From<>`` impls. +* All 13 bridge entry points exist in ``api.rs``. +* Codegen produces Dart bindings without warnings. +* Rust crate compiles with ``ccc_rust`` linked. + +---- + +Phase 3 — Dart API Surface +---------------------------- + +:Status: Not Started +:Depends on: Phase 2 + +**Goal:** Build the clean Dart API layer that application code will +consume, wired to the FRB-generated bindings. + +Tasks +~~~~~ + +.. list-table:: + :header-rows: 1 + :widths: 5 60 15 + + * - # + - Task + - Status + * - 3.1 + - Create ``lib/ccc_crypto.dart`` — primary entry point class + ``CccCrypto`` with all public methods: + ``cccInit``, ``listProviders``, ``getCapabilities``, + ``encryptAead``, ``decryptAead``, ``deriveKey``, + ``computeMac``, ``verifyMac``, ``hash``, + ``kemGenerateKeypair``, ``kemEncapsulate``, ``kemDecapsulate``, + ``runSelfTest`` + - ☐ + * - 3.2 + - Create ``lib/ccc_provider_catalog.dart`` — ``CccProviderCatalog`` + (provider name, algorithms, efficiency/reliability scores) + - ☐ + * - 3.3 + - Create ``lib/ccc_self_test.dart`` — ``CccSelfTestResult`` + (per-algorithm pass/fail, overall status, diagnostics) + - ☐ + * - 3.4 + - Create ``lib/ccc_exceptions.dart`` — structured exception + classes (``CccUnsupportedAlgorithm``, ``CccInvalidKey``, + ``CccInvalidNonce``, ``CccAuthenticationFailed``, + ``CccInternalError``) + - ☐ + * - 3.5 + - Create ``lib/ccc_algorithm_ids.dart`` — algorithm ID constants + matching Rust enum discriminants 1-to-1 (values from + ``cipher_constants.dart``); no remapping + - ☐ + * - 3.6 + - Wire all Dart API methods to FRB-generated bindings + - ☐ + * - 3.7 + - Create barrel export file ``lib/ccc_cryptography.dart`` + re-exporting the public API + - ☐ + * - 3.8 + - Remove old placeholder Dart code (``sum``, ``sumAsync``) + - ☐ + +Exit Criteria +~~~~~~~~~~~~~ + +* ``dart analyze`` reports no errors or warnings. +* Public API matches the contract in the architecture design doc. +* No crypto logic exists in Dart — orchestration only. + +---- + +Phase 4 — Platform Build Verification +--------------------------------------- + +:Status: Not Started +:Depends on: Phase 3 + +**Goal:** Verify the Rust bridge crate cross-compiles and links +correctly on all five target platforms. + +Tasks +~~~~~ + +.. list-table:: + :header-rows: 1 + :widths: 5 60 15 + + * - # + - Task + - Status + * - 4.1 + - Build for **iOS** (``aarch64-apple-ios``, + ``aarch64-apple-ios-sim``) + - ☐ + * - 4.2 + - Build for **Android** (``aarch64-linux-android``, + ``x86_64-linux-android``) + - ☐ + * - 4.3 + - Build for **macOS** (``aarch64-apple-darwin``, + ``x86_64-apple-darwin``) + - ☐ + * - 4.4 + - Build for **Linux** (``x86_64-unknown-linux-gnu``) + - ☐ + * - 4.5 + - Build for **Windows** (``x86_64-pc-windows-msvc``) + - ☐ + * - 4.6 + - Fix any platform-specific linker or NDK issues + - ☐ + * - 4.7 + - Verify ``flutter run`` launches on at least one + physical/emulated device per platform + - ☐ + +Exit Criteria +~~~~~~~~~~~~~ + +* ``flutter build`` succeeds for all five platforms. +* Native library is bundled correctly in each platform's output. + +---- + +Phase 5 — Unit Tests +--------------------- + +:Status: Not Started +:Depends on: Phase 3 + +**Goal:** Verify correctness of the bridge and Dart API via +Dart-side unit tests. + +Tasks +~~~~~ + +.. list-table:: + :header-rows: 1 + :widths: 5 60 15 + + * - # + - Task + - Status + * - 5.1 + - AEAD roundtrip test — encrypt then decrypt 1 KB + (AES-256-GCM), verify plaintext equality + - ☐ + * - 5.2 + - AEAD roundtrip test — encrypt then decrypt 1 KB + (ChaCha20-Poly1305) + - ☐ + * - 5.3 + - AEAD tamper test — modify ciphertext, verify + ``CccAuthenticationFailed`` is thrown + - ☐ + * - 5.4 + - KDF known-vector test — HKDF-SHA256 output compared against + RFC 5869 test vectors + - ☐ + * - 5.5 + - MAC roundtrip test — ``computeMac`` then ``verifyMac`` + (HMAC-SHA256), verify returns true + - ☐ + * - 5.6 + - MAC tamper test — modify data after MAC, verify returns false + - ☐ + * - 5.7 + - Hash known-vector test — compare output against known + SHA-256 / SHA-384 / SHA-512 digests + - ☐ + * - 5.8 + - KEM roundtrip test — ``kemGenerateKeypair``, + ``kemEncapsulate``, ``kemDecapsulate`` (X25519); verify + shared secrets match + - ☐ + * - 5.9 + - KEM roundtrip test — X448 keygen/encap/decap flow + - ☐ + * - 5.10 + - Provider catalog test — verify ``listProviders()`` returns + non-empty list, ``getCapabilities()`` returns per-algorithm + availability and scores + - ☐ + * - 5.11 + - Self-test validation — ``runSelfTest()`` returns overall pass + with per-algorithm results + - ☐ + * - 5.12 + - Error handling tests — verify each ``CccException`` subtype + is thrown for the corresponding error condition + (unsupported algorithm, invalid key, invalid nonce) + - ☐ + * - 5.13 + - Algorithm ID mapping test — verify Dart constants match + Rust enum discriminants (1-to-1, no drift) + - ☐ + +Exit Criteria +~~~~~~~~~~~~~ + +* All unit tests pass on host platform (macOS). +* No Dart-side crypto logic introduced by tests. + +---- + +Phase 6 — Integration Tests & Polish +-------------------------------------- + +:Status: Not Started +:Depends on: Phase 4, Phase 5 + +**Goal:** End-to-end validation on real devices/simulators, example +app update, documentation, and release preparation. + +Tasks +~~~~~ + +.. list-table:: + :header-rows: 1 + :widths: 5 60 15 + + * - # + - Task + - Status + * - 6.1 + - Write Flutter integration tests (``integration_test/``) that + exercise the full init → encrypt → decrypt flow on-device + - ☐ + * - 6.2 + - Integration test: KEM keygen → encap → decap roundtrip + - ☐ + * - 6.3 + - Integration test: self-test API returns all-pass + - ☐ + * - 6.4 + - Run integration tests on iOS simulator + - ☐ + * - 6.5 + - Run integration tests on Android emulator + - ☐ + * - 6.6 + - Run integration tests on macOS + - ☐ + * - 6.7 + - Run integration tests on Linux + - ☐ + * - 6.8 + - Run integration tests on Windows + - ☐ + * - 6.9 + - Update example app (``example/``) — replace ``sum`` demo with + real crypto demo (encrypt/decrypt, provider listing, self-test) + - ☐ + * - 6.10 + - Update ``CHANGELOG.md`` for v0.1.0 + - ☐ + * - 6.11 + - Final review — confirm no Dart crypto logic, no ``ccc_rust`` + source modifications, all tests green + - ☐ + * - 6.12 + - Tag ``v0.1.0`` of the plugin + - ☐ + +Exit Criteria +~~~~~~~~~~~~~ + +* Integration tests pass on all five platforms. +* Example app demonstrates real cryptographic operations. +* ``CHANGELOG.md`` is updated. +* Repository tagged ``v0.1.0``. + +---- + +Milestone 2 Verification Gate +------------------------------ + +*All items must be checked before the* ``v0.1.0`` *tag is cut.* + +* ``[ ]`` FRB bridge API compiles and loads in Flutter plugin +* ``[ ]`` Generated Dart bindings are committed and reproducible +* ``[ ]`` All unit tests pass on host platform (macOS) +* ``[ ]`` ``flutter build ios`` succeeds +* ``[ ]`` ``flutter build apk`` succeeds +* ``[ ]`` ``flutter build macos`` succeeds +* ``[ ]`` ``flutter build linux`` succeeds +* ``[ ]`` ``flutter build windows`` succeeds +* ``[ ]`` Integration tests pass on iOS simulator +* ``[ ]`` Integration tests pass on Android emulator/device +* ``[ ]`` Integration tests pass on macOS +* ``[ ]`` Integration tests pass on Linux +* ``[ ]`` Integration tests pass on Windows +* ``[ ]`` No Dart-side crypto logic present +* ``[ ]`` No modification of ``ccc_rust`` source +* ``[ ]`` ``ccc_rust`` dependency pinned to exact commit/tag +* ``[ ]`` Plugin package tagged ``v0.1.0`` + +---- + +Milestone 3 Handoff Checklist +------------------------------ + +Before handing off to the LetUsMsg app team: + +☐ All Phase 1–6 exit criteria met +☐ Milestone 2 Verification Gate passed +☐ ``CccCrypto`` public API is stable and documented +☐ No floating dependencies (all git refs pinned) +☐ Self-test passes on all platforms +☐ Example app runs on all platforms +☐ No raw private keys exposed to Dart +☐ ``pubspec.yaml`` is publishable (or git-installable) + +The LetUsMsg app will: + +* Add this plugin via ``pubspec.yaml`` +* Call ``CccCrypto.cccInit()`` at startup +* Replace existing crypto stubs with plugin calls +* Populate ``CccProviderCatalog`` from runtime capabilities +* Surface ``CccSelfTest.runAll()`` in debug UI + +No Rust changes and no bridge changes are permitted during Milestone 3. + +---- diff --git a/docs/ccc_rust_milestone2_session_state_OLD.rst b/docs/ccc_rust_milestone2_session_state_OLD.rst new file mode 100644 index 0000000..e3121a6 --- /dev/null +++ b/docs/ccc_rust_milestone2_session_state_OLD.rst @@ -0,0 +1,127 @@ +===================================================== +CCC Rust Milestone 2 — Session State (Planning) +===================================================== + +:Status: Not started +:Date: 2026-02-26 +:Repository target: ``ccc_cryptography`` (plugin repo) +:Depends on: ``ccc_rust`` Milestone 1 complete + +Related Documents +================= + +* Milestone 1 completion record: + ``docs/ccc_rust_milestone1.rst`` + +Overview +======== + +This document tracks Milestone 2 execution state for Flutter plugin + bridge work. +Milestone 2 begins with Milestone 1 already verified and complete. + +Current Gate Preconditions +========================== + +* ``[x]`` Milestone 1 verification gate passed. +* ``[x]`` Conformance vectors passed in Rust workspace. +* ``[x]`` Rust target builds validated (iOS + Android). + +Milestone 2 Work Checklist +========================== + +Phase 1 — Repository + Scaffold +------------------------------- + +* ``[ ]`` Create/confirm ``ccc_cryptography`` repository and branch strategy. +* ``[ ]`` Create Flutter plugin scaffold (``pubspec.yaml``, ``ios/``, ``android/``, ``macos/``). +* ``[ ]`` Add Rust bridge crate with ``crate-type = ["cdylib", "staticlib"]``. +* ``[ ]`` Wire dependency on ``ccc_rust`` pinned tag/revision. + +Phase 2 — Bridge API Surface +---------------------------- + +* ``[ ]`` Define DTOs: + + * ``CapabilitiesDto`` + * ``KemKeyPairDto`` + * ``KemEncapDto`` + * ``SelfTestDto`` + * ``AlgoTestResultDto`` + +* ``[ ]`` Implement bridge entry points: + + * ``ccc_init`` + * ``ccc_list_providers`` + * ``ccc_capabilities`` / ``ccc_available_algorithms`` + * ``ccc_aead_encrypt`` / ``ccc_aead_decrypt`` + * ``ccc_kdf_derive`` + * ``ccc_mac_compute`` / ``ccc_mac_verify`` + * ``ccc_hash`` + * ``ccc_kem_generate_keypair`` + * ``ccc_kem_encapsulate`` / ``ccc_kem_decapsulate`` + * ``ccc_self_test`` + +Phase 3 — FRB Codegen + Build Integration +----------------------------------------- + +* ``[ ]`` Add ``flutter_rust_bridge`` configuration + codegen scripts. +* ``[ ]`` Run FRB codegen and commit generated artifacts. +* ``[ ]`` Verify plugin compiles for iOS. +* ``[ ]`` Verify plugin compiles for Android. +* ``[ ]`` Verify plugin compiles for macOS. + +Phase 4 — Dart API Layer +------------------------ + +* ``[ ]`` Implement ``CccCrypto`` service API wrapper. +* ``[ ]`` Implement ``CccSelfTest`` wrapper. +* ``[ ]`` Implement runtime ``CccProviderCatalog`` population. +* ``[ ]`` Ensure algorithm ID mapping remains 1:1 with Rust discriminants. + +Phase 5 — Integration + Validation +---------------------------------- + +* ``[ ]`` Add integration tests for AEAD roundtrip (at least AES-GCM and ChaCha20). +* ``[ ]`` Add integration tests for KEM keygen/encap/decap flow. +* ``[ ]`` Add integration tests for self-test API. +* ``[ ]`` Run on iOS simulator. +* ``[ ]`` Run on Android emulator/device. + +Milestone 2 TODO Queue +====================== + +Immediate TODOs (next session) +------------------------------ + +* ``[ ]`` Decide exact Milestone 2 repository location/URL and baseline branch. +* ``[ ]`` Pin ``ccc_rust`` dependency to a reproducible reference (tag or commit hash). +* ``[ ]`` Define FRB module layout and generated file commit policy. +* ``[ ]`` Draft DTO type mapping table (Rust type -> bridge DTO -> Dart model). + +Backlog TODOs +------------- + +* ``[ ]`` Add CI job matrix for iOS/macOS/Android plugin builds. +* ``[ ]`` Add versioning/release policy for plugin package. +* ``[ ]`` Add troubleshooting notes for NDK/Xcode toolchains. + +Milestone 2 Verification Gate +============================= + +All of the following must pass before declaring Milestone 2 complete: + +* ``[ ]`` FRB bridge API compiles and loads in Flutter plugin. +* ``[ ]`` Generated Dart bindings are committed and reproducible. +* ``[ ]`` ``flutter build ios`` succeeds. +* ``[ ]`` ``flutter build apk`` succeeds. +* ``[ ]`` ``flutter build macos`` succeeds. +* ``[ ]`` Integration test suite passes on iOS simulator. +* ``[ ]`` Integration test suite passes on Android emulator/device. +* ``[ ]`` Plugin package is tagged/released at ``v0.1.0`` (or agreed target version). + +Notes +===== + +* Milestone 2 is the first place where ``flutter_rust_bridge`` is allowed. +* Milestone 1 Rust workspace remains bridge-free and should not be modified + for Dart/plugin scaffolding. diff --git a/docs/ccc_rust_plan.rst b/docs/ccc_rust_plan.rst new file mode 100644 index 0000000..eba3360 --- /dev/null +++ b/docs/ccc_rust_plan.rst @@ -0,0 +1,387 @@ +=============================================== +CCC Rust Crypto Provider — Architecture Plan +=============================================== + +:Status: Approved +:Date: 2026-02-24 +:Author: Engineering + + +Overview +-------- + +This document describes the architecture for the **CCC Rust Crypto Provider**, +the first of three milestones in delivering hardware-grade cryptography to the +LetUsMsg application. + +The guiding constraint is *clean separation*: each milestone is a distinct, +independently testable artifact with no forbidden upward dependencies. + +---- + +Three-Milestone Strategy +------------------------ + +============= =================================== ========================== =========================== +Milestone Repository What ships Depends on +============= =================================== ========================== =========================== +**1 (this)** ``ccc_rust`` Pure Rust crypto library wolfSSL (vendored) +**2** ``ccc_dart_plugin`` Flutter plugin + Dart API ``ccc_rust`` (git/semver) +**3** ``letusmsg`` (existing app) App integration ``ccc_dart_plugin`` package +============= =================================== ========================== =========================== + +Milestone 1 is complete and independently verified *before* any bridge or Dart +code is written. Milestone 2 owns the ``flutter_rust_bridge`` dependency and +all generated Dart bindings. Milestone 3 makes no Rust changes; it consumes +only the published Dart package. + +---- + +Milestone 1 — ``ccc_rust`` Scope (this repository) + +**Goal**: a fully tested, provider-agnostic Rust crypto library. + +**Hard boundaries** — this repo must never contain: + +* ``flutter_rust_bridge`` or any Flutter/Dart dependency +* Generated Dart files (``frb_generated.rs``, ``*.dart``) +* ``flutter_rust_bridge.yaml`` +* Any platform plugin scaffold (``ios/``, ``android/``, ``macos/``) + +Guiding Principles +~~~~~~~~~~~~~~~~~~ + +1. Every provider reports its own capabilities at runtime — no compile-time + hard-coding of ``available: true/false``. +2. Algorithm IDs in Rust map 1-to-1 to the integer constants in + ``cipher_constants.dart`` — zero Dart changes needed when wiring up. +3. Key material is zeroed on drop (``zeroize`` crate) everywhere. +4. A conformance test suite validates NIST/RFC vectors for every algorithm + before any provider is marked ``available``. +5. The library has no runtime dependency on Flutter; it is consumable by any + FFI host (Flutter plugin, Python tests, CLI tools). + +Repository Layout (Milestone 1 — this repo) + +:: + + ccc_rust/ + ├── Cargo.toml ← workspace manifest (3 members, no bridge) + ├── rust-toolchain.toml ← pinned stable toolchain + ├── .cargo/ + │ └── config.toml ← cross-compile target aliases + ├── vendors/ + │ ├── README.md ← submodule pin rationale + upgrade notes + │ └── wolfssl/ ← git submodule (wolfSSL/wolfssl @ v5.7.2-stable) + ├── crates/ + │ ├── ccc-crypto-core/ ← shared traits, enums, registry + │ │ ├── Cargo.toml + │ │ └── src/ + │ │ ├── lib.rs + │ │ ├── algorithms.rs ← algorithm enums (values == cipher_constants.dart) + │ │ ├── capabilities.rs ← AlgorithmCapability, ProviderCapabilities + │ │ ├── error.rs ← CryptoError enum + │ │ ├── provider.rs ← CryptoProvider umbrella trait + │ │ ├── registry.rs ← ProviderRegistry (OnceLock>) + │ │ └── types.rs ← KemKeyPair, SelfTestReport, BenchmarkReport + │ └── ccc-crypto-wolfssl/ ← wolfSSL provider implementation + │ ├── Cargo.toml + │ └── src/ + │ ├── lib.rs + │ ├── aead.rs ← AES-256-GCM, ChaCha20-Poly1305, XChaCha20-Poly1305 + │ ├── kdf.rs ← HKDF-SHA256/384/512, Argon2id, BLAKE2b-KDF + │ ├── mac.rs ← HMAC-SHA256/384/512, BLAKE2b-MAC + │ ├── hash.rs ← SHA-256/384/512, SHA3-256/512, BLAKE2b-512 + │ ├── kem.rs ← X25519, X448 (ML-KEM deferred Phase 5) + │ ├── capabilities.rs ← probe-at-startup + benchmark() + │ └── provider.rs ← WolfSslProvider: CryptoProvider impl + └── tests/ + └── conformance/ + ├── Cargo.toml + └── src/ + └── main.rs ← NIST/RFC vectors for all algorithms + +Step 1 — Cargo Workspace Scaffold + +``Cargo.toml``:: + + [workspace] + resolver = "2" + members = [ + "crates/ccc-crypto-core", + "crates/ccc-crypto-wolfssl", + "tests/conformance", + ] + +``rust-toolchain.toml``:: + + [toolchain] + channel = "stable" + +``.cargo/config.toml``:: + + [alias] + build-ios = "build --target aarch64-apple-ios" + build-android-arm64 = "build --target aarch64-linux-android" + build-android-x64 = "build --target x86_64-linux-android" + build-macos = "build --target aarch64-apple-darwin" + +Step 2 — ``ccc-crypto-core`` Trait Crate + +Algorithm Enumerations +~~~~~~~~~~~~~~~~~~~~~~ + +All discriminant values match the integer constants in ``cipher_constants.dart`` +exactly, so the Dart cipher-sequencing logic requires zero changes. + +=================== ========================================================= +Enum Variants → value +=================== ========================================================= +``AeadAlgorithm`` AesGcm256=12, ChaCha20Poly1305=13, XChaCha20Poly1305=14, + Ascon128a=15 +``KdfAlgorithm`` Sha256=1, Sha384=2, Sha512=3, Blake2b512=4 +``MacAlgorithm`` HmacSha256=30, HmacSha512=32, Blake2bMac=33 +``HashAlgorithm`` Sha256=40, Sha384=41, Sha512=42, Blake2b512=43, Sha3_256=44 +``KemAlgorithm`` X25519=50, X448=51, MlKem768=52, MlKem1024=53, + ClassicMcEliece=54 +=================== ========================================================= + +Key Structs +~~~~~~~~~~~ + +``AlgorithmCapability``:: + + available: bool + deterministic_io: bool + efficiency_score: u8 // populated by WolfSslProvider::benchmark() + reliability_score: u8 // populated by WolfSslProvider::self_test() + +``ProviderCapabilities``:: + + provider_name: &'static str + aead: HashMap + kdf: HashMap + mac: HashMap + hash: HashMap + kem: HashMap + +``KemKeyPair``:: + + public_key: Zeroizing> + private_key: Zeroizing> + +``CryptoError``:: + + UnsupportedAlgorithm(String) + InvalidKey(String) + InvalidNonce(String) + AuthenticationFailed + InternalError(String) + +Provider Traits +~~~~~~~~~~~~~~~ + +.. code-block:: rust + + pub trait AeadProvider { + fn encrypt_aead( + &self, algo: AeadAlgorithm, + key: &[u8], nonce: &[u8], + plaintext: &[u8], aad: &[u8], + ) -> Result, CryptoError>; + fn decrypt_aead( + &self, algo: AeadAlgorithm, + key: &[u8], nonce: &[u8], + ciphertext: &[u8], aad: &[u8], + ) -> Result, CryptoError>; + } + + pub trait KdfProvider { + fn derive_key( + &self, algo: KdfAlgorithm, + ikm: &[u8], salt: &[u8], info: &[u8], length: usize, + ) -> Result>, CryptoError>; + } + + pub trait MacProvider { + fn compute_mac( + &self, algo: MacAlgorithm, key: &[u8], data: &[u8], + ) -> Result, CryptoError>; + fn verify_mac( + &self, algo: MacAlgorithm, key: &[u8], + data: &[u8], mac: &[u8], + ) -> Result; + } + + pub trait HashProvider { + fn hash( + &self, algo: HashAlgorithm, data: &[u8], + ) -> Result, CryptoError>; + } + + pub trait KemProvider { + fn generate_keypair( + &self, algo: KemAlgorithm, + ) -> Result; + fn encapsulate( + &self, algo: KemAlgorithm, public_key: &[u8], + ) -> Result<(Vec, Zeroizing>), CryptoError>; + fn decapsulate( + &self, algo: KemAlgorithm, + private_key: &[u8], ciphertext: &[u8], + ) -> Result>, CryptoError>; + } + + pub trait CryptoProvider: + AeadProvider + KdfProvider + MacProvider + HashProvider + Send + Sync + { + fn provider_name(&self) -> &'static str; + fn capabilities(&self) -> ProviderCapabilities; + fn self_test(&self) -> SelfTestReport; + fn benchmark(&self) -> BenchmarkReport; + } + +``ProviderRegistry``:: + + OnceLock>>> + fn register(name, provider) + fn get(name) -> Option> + fn list() -> Vec<&'static str> + +Step 3 — wolfSSL Submodule + ``ccc-crypto-wolfssl`` + +wolfSSL is vendored as a git submodule pinned to ``v5.7.2-stable``. +The crate uses ``cmake`` + ``bindgen`` in ``build.rs`` to build and bind it. +A ``stub_ffi`` feature bypasses the C build for fast unit-test cycles. + +wolfSSL Phase 4 Algorithm Coverage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +=================== =========================================== +Category Algorithms +=================== =========================================== +AEAD AES-256-GCM, ChaCha20-Poly1305, + XChaCha20-Poly1305 +KDF HKDF-SHA256/384/512, Argon2id, BLAKE2b-KDF +MAC HMAC-SHA256/384/512, BLAKE2b-MAC +Hash SHA-256/384/512, SHA3-256/512, BLAKE2b-512 +KEM X25519, X448 +KEM (Phase 5) ML-KEM-768, ML-KEM-1024, Classic McEliece +=================== =========================================== + +Capability Probe Strategy +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``WolfSslProvider::capabilities()`` runs a minimal probe call (encrypt 1 byte; +decrypt; compare) per algorithm at startup. Sets ``available = probe_succeeded``. +If the wolfSSL build omits PQ support, ML-KEM entries report +``available: false`` gracefully. + +Benchmark Strategy +~~~~~~~~~~~~~~~~~~ + +``WolfSslProvider::benchmark()`` encrypts a 1 MB buffer × 100 iterations per +AEAD algorithm, measures wall-clock throughput, normalises to a 0–100 +``efficiency_score``. Run once at library init and cached. + + +Step 4 — Conformance Test Suite + +Location: ``tests/conformance/src/main.rs`` + +Run with ``cargo run -p ccc-conformance-tests`` and ``cargo test --workspace``. + +========================= ================================ +Test Source +========================= ================================ +AES-256-GCM NIST SP 800-38D vectors +ChaCha20-Poly1305 RFC 8439 vectors +XChaCha20-Poly1305 Extended nonce vectors +HKDF-SHA256/512 RFC 5869 vectors +HMAC-SHA256/512 RFC 4231 vectors +SHA-256/512, SHA3, BLAKE2b FIPS / reference vectors +X25519 DH RFC 7748 vectors +X448 DH RFC 7748 vectors +========================= ================================ + +**Gate**: ``ALL VECTORS PASSED`` must print before Milestone 1 is tagged. + + +Step 5 — Architecture Documentation + +``docs/ccc_rust_milestone1.rst`` covers: + +* Crate dependency graph (ASCII) +* "How to add a new provider" — 7-step trait checklist +* ``algo: u32`` → cipher constant mapping table +* Milestone 2 hand-off contract (API surface Milestone 2 must implement against) + + +Milestone 1 Verification Gate + +All of the following must pass before the ``v0.1.0`` tag is cut and Milestone 2 +work begins: + +* ``cargo test --workspace`` — all unit tests pass +* ``cargo run -p ccc-conformance-tests`` — ``ALL VECTORS PASSED`` +* ``cargo build --target aarch64-apple-ios`` — compiles +* ``cargo build --target aarch64-linux-android`` — compiles +* No ``flutter_rust_bridge``, Dart, or Flutter dependency anywhere in the workspace +* ``cargo audit`` — no known CVEs in dependency tree + + +Milestone 2 — ``ccc_dart_plugin`` (separate repository) + +*(Planned — not started. Work begins after Milestone 1 gate passes.)* + +A separate Dart/Flutter plugin package repository. It contains: + +* A small Rust bridge crate that references ``ccc_rust`` via git tag: + + .. code-block:: toml + + [dependencies] + ccc-crypto-core = { git = "https://github.com/letusmsg/ccc_rust", tag = "v0.1.0" } + ccc-crypto-wolfssl = { git = "https://github.com/letusmsg/ccc_rust", tag = "v0.1.0" } + flutter_rust_bridge = "2" + +* ``flutter_rust_bridge_codegen generate`` output (``frb_generated.rs``, Dart bindings) +* Flutter plugin scaffold: ``ios/``, ``android/``, ``macos/`` +* Dart API surface: ``CccCrypto``, ``CccSelfTest``, ``CccProviderCatalog`` +* Flutter integration tests (roundtrip encrypt/decrypt, self-test harness) + + +Milestone 3 — LetUsMsg App Integration (existing repository) + +*(Planned — not started. Work begins after Milestone 2 gate passes.)* + +The existing ``letusmsg`` Flutter app adds ``ccc_dart_plugin`` as a pubspec +dependency. Changes are confined to: + +* ``crypto_wolfssl.dart`` — replace ``UnimplementedError`` stubs with plugin calls +* ``ccc_provider_spec.dart`` — populate ``CccProviderCatalog`` at runtime +* ``main.dart`` — call ``CccCrypto.cccInit()`` at startup +* App debug screen — expose ``CccSelfTest.runAll()`` results + +No Rust changes and no bridge changes are made in Milestone 3. + + +Phase 8 — Stretch Goal Providers (Future) + +*(Out of scope for Phase 4. Tracked here for future scheduling.)* + +================== ===================================================== +Library Rust crate / approach +================== ===================================================== +libsodium ``sodiumoxide`` or ``safe_libsodium`` +OpenSSL ``openssl`` crate +BoringSSL ``boring`` crate +RustCrypto Pure-Rust trait impls; no native dep +liboqs Open Quantum Safe — ML-KEM, BIKE, HQC, Falcon, + Dilithium, SPHINCS+ +Signal libsignal ``libsignal`` (Apache-2 subset) +Botan ``botan`` crate +mbedTLS ``mbedtls`` crate +Nettle ``nettle-sys`` crate +================== ===================================================== + diff --git a/docs/ccc_rust_plan_phases.rst b/docs/ccc_rust_plan_phases.rst new file mode 100644 index 0000000..044a78c --- /dev/null +++ b/docs/ccc_rust_plan_phases.rst @@ -0,0 +1,264 @@ +============================================== +CCC Rust Implementation — Phase Tracking +============================================== + +:Last Updated: 2026-02-25 + +Legend +------ + +* ``[ ]`` Not started +* ``[~]`` In progress +* ``[x]`` Complete +* ``[!]`` Blocked + +---- + +Three-Milestone Overview +------------------------ + +============= =================================== ============================ +Milestone Repository Status +============= =================================== ============================ +**1 (this)** ``ccc_rust`` Complete +**2** ``ccc_cryptography`` Not started +**3** ``letusmsg`` (existing app) Not started +============= =================================== ============================ + +Milestone 1 Verification Gate is now passing. +Milestone 2 may begin when scheduled. +Milestone 3 does not start until the Milestone 2 gate passes. + +---- + +============================================================ +Milestone 1 — ``ccc_rust`` Pure Rust Crypto Library +============================================================ + +Phase 1 — Cargo Workspace Scaffold +---------------------------------- + +* ``[x]`` Create ``Cargo.toml`` (workspace manifest, 3 members — no bridge crate) +* ``[x]`` Create ``rust-toolchain.toml`` (channel = "stable") +* ``[x]`` Create ``.cargo/config.toml`` (cross-compile target aliases) +* ``[x]`` Create ``vendors/README.md`` + +---- + +Phase 2 — ``ccc-crypto-core`` Trait Crate +----------------------------------------- + +* ``[x]`` Create ``crates/ccc-crypto-core/Cargo.toml`` +* ``[x]`` ``algorithms.rs`` — AeadAlgorithm, KdfAlgorithm, MacAlgorithm, + HashAlgorithm, KemAlgorithm enums (values == cipher_constants.dart) +* ``[x]`` ``capabilities.rs`` — AlgorithmCapability, ProviderCapabilities +* ``[x]`` ``error.rs`` — CryptoError enum +* ``[x]`` ``types.rs`` — KemKeyPair, SelfTestReport, BenchmarkReport, + AlgoTestResult +* ``[x]`` ``provider.rs`` — AeadProvider, KdfProvider, MacProvider, + HashProvider, KemProvider traits; CryptoProvider umbrella trait +* ``[x]`` ``registry.rs`` — ProviderRegistry (OnceLock>), + register(), get(), list() +* ``[x]`` ``lib.rs`` — re-exports all public items +* ``[x]`` Unit tests for registry (5 passing) + +---- + +Phase 3 — wolfSSL Submodule + ``ccc-crypto-wolfssl`` +----------------------------------------------------- + +* ``[x]`` ``git submodule add`` wolfSSL → ``vendors/wolfssl`` +* ``[x]`` Pin submodule to ``v5.7.2-stable`` +* ``[x]`` Document pin in ``vendors/README.md`` +* ``[x]`` Create ``crates/ccc-crypto-wolfssl/Cargo.toml`` +* ``[x]`` ``build.rs`` — cmake build + bindgen; stub_ffi feature bypasses C build +* ``[x]`` ``aead.rs`` — AES-256-GCM implementation + + * ``[x]`` encrypt_aead (AES-256-GCM) + * ``[x]`` decrypt_aead (AES-256-GCM) + * ``[x]`` encrypt_aead (ChaCha20-Poly1305) + * ``[x]`` decrypt_aead (ChaCha20-Poly1305) + * ``[x]`` encrypt_aead (XChaCha20-Poly1305 via HChaCha20) + * ``[x]`` decrypt_aead (XChaCha20-Poly1305) + +* ``[x]`` ``kdf.rs`` — KDF implementations + + * ``[x]`` HKDF-SHA256 + * ``[x]`` HKDF-SHA384 + * ``[x]`` HKDF-SHA512 + * ``[x]`` Argon2id (64 MB / 3 iter / 4 threads — matches DEFAULT_CIPHER_PARAMS) + * ``[x]`` BLAKE2b-512 KDF + +* ``[x]`` ``mac.rs`` — MAC implementations + + * ``[x]`` HMAC-SHA256 + * ``[x]`` HMAC-SHA384 + * ``[x]`` HMAC-SHA512 + * ``[x]`` BLAKE2b-MAC (keyed) + * ``[x]`` Constant-time verify + +* ``[x]`` ``hash.rs`` — Hash implementations + + * ``[x]`` SHA-256 / SHA-384 / SHA-512 + * ``[x]`` SHA3-256 / SHA3-512 + * ``[x]`` BLAKE2b-512 + +* ``[x]`` ``kem.rs`` — KEM implementations + + * ``[x]`` X25519 (keygen + DH encap/decap) + * ``[x]`` X448 (keygen + DH encap/decap) + * ``[ ]`` ML-KEM-768 (deferred to Phase 5) + * ``[ ]`` ML-KEM-1024 (deferred to Phase 5) + * ``[ ]`` Classic McEliece (deferred to Phase 5) + +* ``[x]`` ``capabilities.rs`` — probe-at-startup per algorithm +* ``[x]`` ``capabilities.rs`` — benchmark() throughput micro-bench +* ``[x]`` ``provider.rs`` — WolfSslProvider: CryptoProvider impl +* ``[x]`` ``provider.rs`` — self_test() with embedded NIST vectors (AES-256-GCM, ChaCha20-Poly1305) +* ``[x]`` Register WolfSslProvider in ProviderRegistry via init() +* ``[x]`` Full native build verified (cmake builds clean, all conformance tests pass) + +---- + +Phase 4 — Conformance Test Suite +--------------------------------- + +* ``[x]`` NIST AES-256-GCM vectors (2 vectors) +* ``[x]`` RFC 8439 ChaCha20-Poly1305 vectors +* ``[x]`` RFC 5869 HKDF-SHA256 vectors (2 vectors) +* ``[x]`` RFC 4231 HMAC-SHA256 vectors (2 vectors) +* ``[x]`` FIPS hash vectors (SHA-256/512, SHA3-256, BLAKE2b-512) +* ``[x]`` RFC 7748 X25519 DH test vectors +* ``[x]`` RFC 7748 X448 DH test vectors +* ``[x]`` XChaCha20-Poly1305 extended-nonce vectors +* ``[x]`` ``cargo run -p ccc-conformance-tests`` passes (all current vectors) + +---- + +Phase 5 — Architecture Documentation +-------------------------------------- + +* ``[x]`` Create ``docs/ccc_rust_milestone1.rst`` +* ``[x]`` Crate dependency graph (ASCII diagram) +* ``[x]`` "How to add a new provider" — 7-step trait checklist +* ``[x]`` ``algo: u32`` → cipher constant mapping table +* ``[x]`` Milestone 2 hand-off contract documented + +---- + +Milestone 1 Verification Gate +------------------------------ + +*All items must be checked before the* ``v0.1.0`` *tag is cut.* + +* ``[x]`` ``cargo test --workspace`` — all pass +* ``[x]`` ``cargo run -p ccc-conformance-tests`` — ALL VECTORS PASSED +* ``[x]`` ``cargo build --target aarch64-apple-ios`` — success +* ``[x]`` ``cargo build --target aarch64-linux-android`` — success +* ``[x]`` No ``flutter_rust_bridge`` / Dart / Flutter dependency in workspace +* ``[x]`` ``cargo audit`` — no known CVEs + +---- + +============================================================ +Milestone 2 — ``ccc_cryptography`` Flutter Plugin +=========================================================== + +*(Not started — begins after Milestone 1 gate passes)* + +Phase 1 — New Repository Setup +------------------------------- + +* ``[ ]`` Create ``ccc_cryptography`` repository +* ``[ ]`` Flutter plugin scaffold (``pubspec.yaml``, ``ios/``, ``android/``, ``macos/``) +* ``[ ]`` Rust bridge crate with ``crate-type = ["cdylib", "staticlib"]`` +* ``[ ]`` Add ``flutter_rust_bridge = "2"`` dependency +* ``[ ]`` Reference ``ccc_rust`` via git tag ``v0.1.0`` + +---- + +Phase 2 — Bridge Crate +---------------------- + +* ``[ ]`` ``dto.rs`` — CapabilitiesDto, KemKeyPairDto, KemEncapDto, + SelfTestDto, AlgoTestResultDto; From impls +* ``[ ]`` ``bridge.rs`` — ccc_init() +* ``[ ]`` ``bridge.rs`` — ccc_list_providers() +* ``[ ]`` ``bridge.rs`` — ccc_capabilities() / ccc_available_algorithms() +* ``[ ]`` ``bridge.rs`` — ccc_aead_encrypt() / ccc_aead_decrypt() +* ``[ ]`` ``bridge.rs`` — ccc_kdf_derive() +* ``[ ]`` ``bridge.rs`` — ccc_mac_compute() / ccc_mac_verify() +* ``[ ]`` ``bridge.rs`` — ccc_hash() +* ``[ ]`` ``bridge.rs`` — ccc_kem_generate_keypair() +* ``[ ]`` ``bridge.rs`` — ccc_kem_encapsulate() / ccc_kem_decapsulate() +* ``[ ]`` ``bridge.rs`` — ccc_self_test() + +---- + +Phase 3 — Codegen + Plugin Build +--------------------------------- + +* ``[ ]`` Run ``flutter_rust_bridge_codegen generate`` +* ``[ ]`` Verify generated Dart bindings compile +* ``[ ]`` ``flutter build ios`` succeeds (static lib linked) +* ``[ ]`` ``flutter build apk`` succeeds (cdylib linked) +* ``[ ]`` ``flutter build macos`` succeeds + +---- + +Phase 4 — Dart API Layer +------------------------ + +* ``[ ]`` ``CccCrypto`` class (wraps all bridge calls) +* ``[ ]`` ``CccSelfTest`` class (wraps ccc_self_test()) +* ``[ ]`` ``CccProviderCatalog`` (runtime-populated from ccc_capabilities()) + +---- + +Phase 5 — Flutter Integration Tests +------------------------------------ + +* ``[ ]`` Roundtrip encrypt/decrypt 1 KB (AES-256-GCM) +* ``[ ]`` Roundtrip encrypt/decrypt 1 KB (ChaCha20-Poly1305) +* ``[ ]`` ``CccSelfTest.runAll()`` — all-pass + +---- + +Milestone 2 Verification Gate +------------------------------ + +* ``[ ]`` All Flutter integration tests pass on iOS simulator +* ``[ ]`` All Flutter integration tests pass on Android emulator +* ``[ ]`` Package published / tagged ``v0.1.0`` + +---- + +============================================================ +Milestone 3 — LetUsMsg App Integration +============================================================ + +*(Not started — begins after Milestone 2 gate passes)* + +* ``[ ]`` Add ``ccc_cryptography`` to ``letusmsg`` `pubspec.yaml`` +* ``[ ]`` Wire ``crypto_wolfssl.dart`` encrypt/decrypt → bridge calls +* ``[ ]`` Call ``CccCrypto.cccInit()`` at app startup +* ``[ ]`` Populate ``CccProviderCatalog`` from runtime capabilities +* ``[ ]`` Expose ``CccSelfTest.runAll()`` in app debug screen +* ``[ ]`` End-to-end integration test (send + receive encrypted message) + +---- + +Phase 8 — Stretch Goal Providers (Future) +------------------------------------------ + +*(Out of scope for Phase 4. Tracked here for future scheduling.)* + +* ``[ ]`` libsodium (``sodiumoxide`` / ``safe_libsodium``) +* ``[ ]`` OpenSSL (``openssl`` crate) +* ``[ ]`` BoringSSL (``boring`` crate) +* ``[ ]`` RustCrypto (pure-Rust, no native dep) +* ``[ ]`` liboqs — ML-KEM, BIKE, HQC, Falcon, Dilithium, SPHINCS+ +* ``[ ]`` Signal ``libsignal`` +* ``[ ]`` Botan +* ``[ ]`` mbedTLS +* ``[ ]`` Nettle diff --git a/example/integration_test/simple_test.dart b/example/integration_test/simple_test.dart new file mode 100644 index 0000000..5f78e2e --- /dev/null +++ b/example/integration_test/simple_test.dart @@ -0,0 +1,11 @@ +import 'package:integration_test/integration_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ccc_cryptography/ccc_cryptography.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + setUpAll(() async => await RustLib.init()); + test('Can call rust function', () async { + expect(greet(name: "Tom"), "Hello, Tom!"); + }); +} diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig index 592ceee..ec97fc6 100644 --- a/example/ios/Flutter/Debug.xcconfig +++ b/example/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig index 592ceee..c4855bf 100644 --- a/example/ios/Flutter/Release.xcconfig +++ b/example/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile new file mode 100644 index 0000000..620e46e --- /dev/null +++ b/example/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/example/lib/main.dart b/example/lib/main.dart index 4e00d92..a0766b0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'dart:async'; +import 'package:ccc_cryptography/src/rust/api/simple.dart'; +import 'package:ccc_cryptography/src/rust/frb_generated.dart'; -import 'package:ccc_cryptography/ccc_cryptography.dart' as ccc_cryptography; - -void main() { +Future main() async { + await RustLib.init(); runApp(const MyApp()); } @@ -15,57 +15,25 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - late int sumResult; - late Future sumAsyncResult; + late String greetResult; @override void initState() { super.initState(); - sumResult = ccc_cryptography.sum(1, 2); - sumAsyncResult = ccc_cryptography.sumAsync(3, 4); + greetResult = greet(name: 'Flutter'); } @override Widget build(BuildContext context) { const textStyle = TextStyle(fontSize: 25); - const spacerSmall = SizedBox(height: 10); return MaterialApp( home: Scaffold( - appBar: AppBar( - title: const Text('Native Packages'), - ), - body: SingleChildScrollView( - child: Container( - padding: const .all(10), - child: Column( - children: [ - const Text( - 'This calls a native function through FFI that is shipped as source in the package. ' - 'The native code is built as part of the Flutter Runner build.', - style: textStyle, - textAlign: .center, - ), - spacerSmall, - Text( - 'sum(1, 2) = $sumResult', - style: textStyle, - textAlign: .center, - ), - spacerSmall, - FutureBuilder( - future: sumAsyncResult, - builder: (BuildContext context, AsyncSnapshot value) { - final displayValue = - (value.hasData) ? value.data : 'loading'; - return Text( - 'await sumAsync(3, 4) = $displayValue', - style: textStyle, - textAlign: .center, - ); - }, - ), - ], - ), + appBar: AppBar(title: const Text('ccc_cryptography')), + body: Center( + child: Text( + greetResult, + style: textStyle, + textAlign: TextAlign.center, ), ), ), diff --git a/example/macos/Flutter/Flutter-Debug.xcconfig b/example/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b..4b81f9b 100644 --- a/example/macos/Flutter/Flutter-Debug.xcconfig +++ b/example/macos/Flutter/Flutter-Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/example/macos/Flutter/Flutter-Release.xcconfig b/example/macos/Flutter/Flutter-Release.xcconfig index c2efd0b..5caa9d1 100644 --- a/example/macos/Flutter/Flutter-Release.xcconfig +++ b/example/macos/Flutter/Flutter-Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/example/macos/Podfile b/example/macos/Podfile new file mode 100644 index 0000000..ff5ddb3 --- /dev/null +++ b/example/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 5d7fcac..3511abe 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + C9D9D80953306779817A01D7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 038972E62E6D13C2A55A0B7F /* Pods_Runner.framework */; }; + CC6FDE117C14C0F98D1BA8BB /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5AA6C665A590100A722C2D2 /* Pods_RunnerTests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -60,11 +62,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 038972E62E6D13C2A55A0B7F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0988C826A2FD255462F9808A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* ccc_cryptography_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ccc_cryptography_example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* ccc_cryptography_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ccc_cryptography_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -77,7 +81,13 @@ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 86D70DA30699567E710A0459 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + 9D35F14235952B671983F7E0 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + A5B81D3E19756CB2D0C8B009 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + A81A44EB7B90A16EAADE4FA6 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + BA626D8003BA6E48536EE306 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + D5AA6C665A590100A722C2D2 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,6 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CC6FDE117C14C0F98D1BA8BB /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,6 +103,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C9D9D80953306779817A01D7 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -125,6 +137,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + DE0D4D416823266B5CAAEDA7 /* Pods */, ); sourceTree = ""; }; @@ -175,10 +188,26 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 038972E62E6D13C2A55A0B7F /* Pods_Runner.framework */, + D5AA6C665A590100A722C2D2 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; }; + DE0D4D416823266B5CAAEDA7 /* Pods */ = { + isa = PBXGroup; + children = ( + 0988C826A2FD255462F9808A /* Pods-Runner.debug.xcconfig */, + 86D70DA30699567E710A0459 /* Pods-Runner.release.xcconfig */, + BA626D8003BA6E48536EE306 /* Pods-Runner.profile.xcconfig */, + A81A44EB7B90A16EAADE4FA6 /* Pods-RunnerTests.debug.xcconfig */, + 9D35F14235952B671983F7E0 /* Pods-RunnerTests.release.xcconfig */, + A5B81D3E19756CB2D0C8B009 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -186,6 +215,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 086D907707E0A9BB81BA038A /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -204,11 +234,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + C86250B37FA1453AAEC9A1C2 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 78F7E7C7FE2E75BBB3819847 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -291,6 +323,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 086D907707E0A9BB81BA038A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -329,6 +383,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 78F7E7C7FE2E75BBB3819847 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + C86250B37FA1453AAEC9A1C2 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -380,6 +473,7 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = A81A44EB7B90A16EAADE4FA6 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -394,6 +488,7 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 9D35F14235952B671983F7E0 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -408,6 +503,7 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = A5B81D3E19756CB2D0C8B009 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; diff --git a/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/example/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/example/pubspec.yaml b/example/pubspec.yaml index faf508f..a5179f6 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -53,6 +53,8 @@ dev_dependencies: # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^6.0.0 + integration_test: + sdk: flutter # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/ffigen.yaml b/ffigen.yaml deleted file mode 100644 index 18fd78b..0000000 --- a/ffigen.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Run with `dart run ffigen --config ffigen.yaml`. -name: CccCryptographyBindings -description: | - Bindings for `src/ccc_cryptography.h`. - - Regenerate bindings with `dart run ffigen --config ffigen.yaml`. -output: 'lib/ccc_cryptography_bindings_generated.dart' -headers: - entry-points: - - 'src/ccc_cryptography.h' - include-directives: - - 'src/ccc_cryptography.h' -preamble: | - // ignore_for_file: always_specify_types - // ignore_for_file: camel_case_types - // ignore_for_file: non_constant_identifier_names -comments: - style: any - length: full diff --git a/flutter_rust_bridge.yaml b/flutter_rust_bridge.yaml new file mode 100644 index 0000000..c4c79c0 --- /dev/null +++ b/flutter_rust_bridge.yaml @@ -0,0 +1,3 @@ +rust_input: crate::api +dart_output: lib/src/rust +rust_root: rust/ diff --git a/ios/Classes/ccc_cryptography.c b/ios/Classes/ccc_cryptography.c deleted file mode 100644 index be218f7..0000000 --- a/ios/Classes/ccc_cryptography.c +++ /dev/null @@ -1,3 +0,0 @@ -// Relative import to be able to reuse the C sources. -// See the comment in ../ccc_cryptography.podspec for more information. -#include "../../src/ccc_cryptography.c" diff --git a/ios/Classes/dummy_file.c b/ios/Classes/dummy_file.c new file mode 100644 index 0000000..e06dab9 --- /dev/null +++ b/ios/Classes/dummy_file.c @@ -0,0 +1 @@ +// This is an empty file to force CocoaPods to create a framework. diff --git a/ios/ccc_cryptography.podspec b/ios/ccc_cryptography.podspec index e952f74..7816120 100644 --- a/ios/ccc_cryptography.podspec +++ b/ios/ccc_cryptography.podspec @@ -20,9 +20,26 @@ A new Flutter FFI plugin project. s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' - s.platform = :ios, '13.0' + s.platform = :ios, '11.0' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.swift_version = '5.0' -end + + s.script_phase = { + :name => 'Build Rust library', + # First argument is relative path to the `rust` folder, second is name of rust library + :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../rust ccc_cryptography', + :execution_position => :before_compile, + :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], + # Let XCode know that the static library referenced in -force_load below is + # created by this build step. + :output_files => ["${BUILT_PRODUCTS_DIR}/libccc_cryptography.a"], + } + s.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES', + # Flutter.framework does not contain a i386 slice. + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/libccc_cryptography.a', + } +end \ No newline at end of file diff --git a/lib/ccc_cryptography.dart b/lib/ccc_cryptography.dart index 506c4bf..72a1f4a 100644 --- a/lib/ccc_cryptography.dart +++ b/lib/ccc_cryptography.dart @@ -1,131 +1,147 @@ +// The original content is temporarily commented out to allow generating a self-contained demo - feel free to uncomment later. -import 'dart:async'; -import 'dart:ffi'; -import 'dart:io'; -import 'dart:isolate'; +// // The original content is temporarily commented out to allow generating a self-contained demo - feel free to uncomment later. +// +// // +// // import 'dart:async'; +// // import 'dart:ffi'; +// // import 'dart:io'; +// // import 'dart:isolate'; +// // +// // import 'ccc_cryptography_bindings_generated.dart'; +// // +// // /// A very short-lived native function. +// // /// +// // /// For very short-lived functions, it is fine to call them on the main isolate. +// // /// They will block the Dart execution while running the native function, so +// // /// only do this for native functions which are guaranteed to be short-lived. +// // int sum(int a, int b) => _bindings.sum(a, b); +// // +// // /// A longer lived native function, which occupies the thread calling it. +// // /// +// // /// Do not call these kind of native functions in the main isolate. They will +// // /// block Dart execution. This will cause dropped frames in Flutter applications. +// // /// Instead, call these native functions on a separate isolate. +// // /// +// // /// Modify this to suit your own use case. Example use cases: +// // /// +// // /// 1. Reuse a single isolate for various different kinds of requests. +// // /// 2. Use multiple helper isolates for parallel execution. +// // Future sumAsync(int a, int b) async { +// // final SendPort helperIsolateSendPort = await _helperIsolateSendPort; +// // final int requestId = _nextSumRequestId++; +// // final _SumRequest request = _SumRequest(requestId, a, b); +// // final Completer completer = Completer(); +// // _sumRequests[requestId] = completer; +// // helperIsolateSendPort.send(request); +// // return completer.future; +// // } +// // +// // const String _libName = 'ccc_cryptography'; +// // +// // /// The dynamic library in which the symbols for [CccCryptographyBindings] can be found. +// // final DynamicLibrary _dylib = () { +// // if (Platform.isMacOS || Platform.isIOS) { +// // return DynamicLibrary.open('$_libName.framework/$_libName'); +// // } +// // if (Platform.isAndroid || Platform.isLinux) { +// // return DynamicLibrary.open('lib$_libName.so'); +// // } +// // if (Platform.isWindows) { +// // return DynamicLibrary.open('$_libName.dll'); +// // } +// // throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}'); +// // }(); +// // +// // /// The bindings to the native functions in [_dylib]. +// // final CccCryptographyBindings _bindings = CccCryptographyBindings(_dylib); +// // +// // +// // /// A request to compute `sum`. +// // /// +// // /// Typically sent from one isolate to another. +// // class _SumRequest { +// // final int id; +// // final int a; +// // final int b; +// // +// // const _SumRequest(this.id, this.a, this.b); +// // } +// // +// // /// A response with the result of `sum`. +// // /// +// // /// Typically sent from one isolate to another. +// // class _SumResponse { +// // final int id; +// // final int result; +// // +// // const _SumResponse(this.id, this.result); +// // } +// // +// // /// Counter to identify [_SumRequest]s and [_SumResponse]s. +// // int _nextSumRequestId = 0; +// // +// // /// Mapping from [_SumRequest] `id`s to the completers corresponding to the correct future of the pending request. +// // final Map> _sumRequests = >{}; +// // +// // /// The SendPort belonging to the helper isolate. +// // Future _helperIsolateSendPort = () async { +// // // The helper isolate is going to send us back a SendPort, which we want to +// // // wait for. +// // final Completer completer = Completer(); +// // +// // // Receive port on the main isolate to receive messages from the helper. +// // // We receive two types of messages: +// // // 1. A port to send messages on. +// // // 2. Responses to requests we sent. +// // final ReceivePort receivePort = ReceivePort() +// // ..listen((dynamic data) { +// // if (data is SendPort) { +// // // The helper isolate sent us the port on which we can sent it requests. +// // completer.complete(data); +// // return; +// // } +// // if (data is _SumResponse) { +// // // The helper isolate sent us a response to a request we sent. +// // final Completer completer = _sumRequests[data.id]!; +// // _sumRequests.remove(data.id); +// // completer.complete(data.result); +// // return; +// // } +// // throw UnsupportedError('Unsupported message type: ${data.runtimeType}'); +// // }); +// // +// // // Start the helper isolate. +// // await Isolate.spawn((SendPort sendPort) async { +// // final ReceivePort helperReceivePort = ReceivePort() +// // ..listen((dynamic data) { +// // // On the helper isolate listen to requests and respond to them. +// // if (data is _SumRequest) { +// // final int result = _bindings.sum_long_running(data.a, data.b); +// // final _SumResponse response = _SumResponse(data.id, result); +// // sendPort.send(response); +// // return; +// // } +// // throw UnsupportedError('Unsupported message type: ${data.runtimeType}'); +// // }); +// // +// // // Send the port to the main isolate on which we can receive requests. +// // sendPort.send(helperReceivePort.sendPort); +// // }, receivePort.sendPort); +// // +// // // Wait until the helper isolate has sent us back the SendPort on which we +// // // can start sending requests. +// // return completer.future; +// // }(); +// // +// +// library ccc_cryptography; +// +// export 'src/rust/api/simple.dart'; +// export 'src/rust/frb_generated.dart' show RustLib; +// -import 'ccc_cryptography_bindings_generated.dart'; +library; -/// A very short-lived native function. -/// -/// For very short-lived functions, it is fine to call them on the main isolate. -/// They will block the Dart execution while running the native function, so -/// only do this for native functions which are guaranteed to be short-lived. -int sum(int a, int b) => _bindings.sum(a, b); - -/// A longer lived native function, which occupies the thread calling it. -/// -/// Do not call these kind of native functions in the main isolate. They will -/// block Dart execution. This will cause dropped frames in Flutter applications. -/// Instead, call these native functions on a separate isolate. -/// -/// Modify this to suit your own use case. Example use cases: -/// -/// 1. Reuse a single isolate for various different kinds of requests. -/// 2. Use multiple helper isolates for parallel execution. -Future sumAsync(int a, int b) async { - final SendPort helperIsolateSendPort = await _helperIsolateSendPort; - final int requestId = _nextSumRequestId++; - final _SumRequest request = _SumRequest(requestId, a, b); - final Completer completer = Completer(); - _sumRequests[requestId] = completer; - helperIsolateSendPort.send(request); - return completer.future; -} - -const String _libName = 'ccc_cryptography'; - -/// The dynamic library in which the symbols for [CccCryptographyBindings] can be found. -final DynamicLibrary _dylib = () { - if (Platform.isMacOS || Platform.isIOS) { - return DynamicLibrary.open('$_libName.framework/$_libName'); - } - if (Platform.isAndroid || Platform.isLinux) { - return DynamicLibrary.open('lib$_libName.so'); - } - if (Platform.isWindows) { - return DynamicLibrary.open('$_libName.dll'); - } - throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}'); -}(); - -/// The bindings to the native functions in [_dylib]. -final CccCryptographyBindings _bindings = CccCryptographyBindings(_dylib); - - -/// A request to compute `sum`. -/// -/// Typically sent from one isolate to another. -class _SumRequest { - final int id; - final int a; - final int b; - - const _SumRequest(this.id, this.a, this.b); -} - -/// A response with the result of `sum`. -/// -/// Typically sent from one isolate to another. -class _SumResponse { - final int id; - final int result; - - const _SumResponse(this.id, this.result); -} - -/// Counter to identify [_SumRequest]s and [_SumResponse]s. -int _nextSumRequestId = 0; - -/// Mapping from [_SumRequest] `id`s to the completers corresponding to the correct future of the pending request. -final Map> _sumRequests = >{}; - -/// The SendPort belonging to the helper isolate. -Future _helperIsolateSendPort = () async { - // The helper isolate is going to send us back a SendPort, which we want to - // wait for. - final Completer completer = Completer(); - - // Receive port on the main isolate to receive messages from the helper. - // We receive two types of messages: - // 1. A port to send messages on. - // 2. Responses to requests we sent. - final ReceivePort receivePort = ReceivePort() - ..listen((dynamic data) { - if (data is SendPort) { - // The helper isolate sent us the port on which we can sent it requests. - completer.complete(data); - return; - } - if (data is _SumResponse) { - // The helper isolate sent us a response to a request we sent. - final Completer completer = _sumRequests[data.id]!; - _sumRequests.remove(data.id); - completer.complete(data.result); - return; - } - throw UnsupportedError('Unsupported message type: ${data.runtimeType}'); - }); - - // Start the helper isolate. - await Isolate.spawn((SendPort sendPort) async { - final ReceivePort helperReceivePort = ReceivePort() - ..listen((dynamic data) { - // On the helper isolate listen to requests and respond to them. - if (data is _SumRequest) { - final int result = _bindings.sum_long_running(data.a, data.b); - final _SumResponse response = _SumResponse(data.id, result); - sendPort.send(response); - return; - } - throw UnsupportedError('Unsupported message type: ${data.runtimeType}'); - }); - - // Send the port to the main isolate on which we can receive requests. - sendPort.send(helperReceivePort.sendPort); - }, receivePort.sendPort); - - // Wait until the helper isolate has sent us back the SendPort on which we - // can start sending requests. - return completer.future; -}(); +export 'src/rust/api/simple.dart'; +export 'src/rust/frb_generated.dart' show RustLib; diff --git a/lib/ccc_cryptography_bindings_generated.dart b/lib/ccc_cryptography_bindings_generated.dart deleted file mode 100644 index f91e53e..0000000 --- a/lib/ccc_cryptography_bindings_generated.dart +++ /dev/null @@ -1,69 +0,0 @@ -// ignore_for_file: always_specify_types -// ignore_for_file: camel_case_types -// ignore_for_file: non_constant_identifier_names - -// AUTO GENERATED FILE, DO NOT EDIT. -// -// Generated by `package:ffigen`. -// ignore_for_file: type=lint -import 'dart:ffi' as ffi; - -/// Bindings for `src/ccc_cryptography.h`. -/// -/// Regenerate bindings with `dart run ffigen --config ffigen.yaml`. -/// -class CccCryptographyBindings { - /// Holds the symbol lookup function. - final ffi.Pointer Function(String symbolName) - _lookup; - - /// The symbols are looked up in [dynamicLibrary]. - CccCryptographyBindings(ffi.DynamicLibrary dynamicLibrary) - : _lookup = dynamicLibrary.lookup; - - /// The symbols are looked up with [lookup]. - CccCryptographyBindings.fromLookup( - ffi.Pointer Function(String symbolName) - lookup) - : _lookup = lookup; - - /// A very short-lived native function. - /// - /// For very short-lived functions, it is fine to call them on the main isolate. - /// They will block the Dart execution while running the native function, so - /// only do this for native functions which are guaranteed to be short-lived. - int sum( - int a, - int b, - ) { - return _sum( - a, - b, - ); - } - - late final _sumPtr = - _lookup>('sum'); - late final _sum = _sumPtr.asFunction(); - - /// A longer lived native function, which occupies the thread calling it. - /// - /// Do not call these kind of native functions in the main isolate. They will - /// block Dart execution. This will cause dropped frames in Flutter applications. - /// Instead, call these native functions on a separate isolate. - int sum_long_running( - int a, - int b, - ) { - return _sum_long_running( - a, - b, - ); - } - - late final _sum_long_runningPtr = - _lookup>( - 'sum_long_running'); - late final _sum_long_running = - _sum_long_runningPtr.asFunction(); -} diff --git a/lib/src/rust/api/simple.dart b/lib/src/rust/api/simple.dart new file mode 100644 index 0000000..b632d8b --- /dev/null +++ b/lib/src/rust/api/simple.dart @@ -0,0 +1,10 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +String greet({required String name}) => + RustLib.instance.api.crateApiSimpleGreet(name: name); diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart new file mode 100644 index 0000000..c9faaa9 --- /dev/null +++ b/lib/src/rust/frb_generated.dart @@ -0,0 +1,242 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field + +import 'api/simple.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'frb_generated.dart'; +import 'frb_generated.io.dart' + if (dart.library.js_interop) 'frb_generated.web.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +/// Main entrypoint of the Rust API +class RustLib extends BaseEntrypoint { + @internal + static final instance = RustLib._(); + + RustLib._(); + + /// Initialize flutter_rust_bridge + static Future init({ + RustLibApi? api, + BaseHandler? handler, + ExternalLibrary? externalLibrary, + bool forceSameCodegenVersion = true, + }) async { + await instance.initImpl( + api: api, + handler: handler, + externalLibrary: externalLibrary, + forceSameCodegenVersion: forceSameCodegenVersion, + ); + } + + /// Initialize flutter_rust_bridge in mock mode. + /// No libraries for FFI are loaded. + static void initMock({required RustLibApi api}) { + instance.initMockImpl(api: api); + } + + /// Dispose flutter_rust_bridge + /// + /// The call to this function is optional, since flutter_rust_bridge (and everything else) + /// is automatically disposed when the app stops. + static void dispose() => instance.disposeImpl(); + + @override + ApiImplConstructor get apiImplConstructor => + RustLibApiImpl.new; + + @override + WireConstructor get wireConstructor => + RustLibWire.fromExternalLibrary; + + @override + Future executeRustInitializers() async { + await api.crateApiSimpleInitApp(); + } + + @override + ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => + kDefaultExternalLibraryLoaderConfig; + + @override + String get codegenVersion => '2.11.1'; + + @override + int get rustContentHash => -1918914929; + + static const kDefaultExternalLibraryLoaderConfig = + ExternalLibraryLoaderConfig( + stem: 'ccc_cryptography', + ioDirectory: 'rust/target/release/', + webPrefix: 'pkg/', + ); +} + +abstract class RustLibApi extends BaseApi { + String crateApiSimpleGreet({required String name}); + + Future crateApiSimpleInitApp(); +} + +class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { + RustLibApiImpl({ + required super.handler, + required super.wire, + required super.generalizedFrbRustBinding, + required super.portManager, + }); + + @override + String crateApiSimpleGreet({required String name}) { + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(name, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 1)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: null, + ), + constMeta: kCrateApiSimpleGreetConstMeta, + argValues: [name], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiSimpleGreetConstMeta => + const TaskConstMeta(debugName: "greet", argNames: ["name"]); + + @override + Future crateApiSimpleInitApp() { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 2, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiSimpleInitAppConstMeta, + argValues: [], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiSimpleInitAppConstMeta => + const TaskConstMeta(debugName: "init_app", argNames: []); + + @protected + String dco_decode_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as String; + } + + @protected + Uint8List dco_decode_list_prim_u_8_strict(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as Uint8List; + } + + @protected + int dco_decode_u_8(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as int; + } + + @protected + void dco_decode_unit(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return; + } + + @protected + String sse_decode_String(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var inner = sse_decode_list_prim_u_8_strict(deserializer); + return utf8.decoder.convert(inner); + } + + @protected + Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var len_ = sse_decode_i_32(deserializer); + return deserializer.buffer.getUint8List(len_); + } + + @protected + int sse_decode_u_8(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint8(); + } + + @protected + void sse_decode_unit(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + } + + @protected + int sse_decode_i_32(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getInt32(); + } + + @protected + bool sse_decode_bool(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint8() != 0; + } + + @protected + void sse_encode_String(String self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer); + } + + @protected + void sse_encode_list_prim_u_8_strict( + Uint8List self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + serializer.buffer.putUint8List(self); + } + + @protected + void sse_encode_u_8(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint8(self); + } + + @protected + void sse_encode_unit(void self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + } + + @protected + void sse_encode_i_32(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putInt32(self); + } + + @protected + void sse_encode_bool(bool self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint8(self ? 1 : 0); + } +} diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart new file mode 100644 index 0000000..d797351 --- /dev/null +++ b/lib/src/rust/frb_generated.io.dart @@ -0,0 +1,86 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field + +import 'api/simple.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'dart:ffi' as ffi; +import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; + +abstract class RustLibApiImplPlatform extends BaseApiImpl { + RustLibApiImplPlatform({ + required super.handler, + required super.wire, + required super.generalizedFrbRustBinding, + required super.portManager, + }); + + @protected + String dco_decode_String(dynamic raw); + + @protected + Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + + @protected + int dco_decode_u_8(dynamic raw); + + @protected + void dco_decode_unit(dynamic raw); + + @protected + String sse_decode_String(SseDeserializer deserializer); + + @protected + Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + + @protected + int sse_decode_u_8(SseDeserializer deserializer); + + @protected + void sse_decode_unit(SseDeserializer deserializer); + + @protected + int sse_decode_i_32(SseDeserializer deserializer); + + @protected + bool sse_decode_bool(SseDeserializer deserializer); + + @protected + void sse_encode_String(String self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_8_strict( + Uint8List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_u_8(int self, SseSerializer serializer); + + @protected + void sse_encode_unit(void self, SseSerializer serializer); + + @protected + void sse_encode_i_32(int self, SseSerializer serializer); + + @protected + void sse_encode_bool(bool self, SseSerializer serializer); +} + +// Section: wire_class + +class RustLibWire implements BaseWire { + factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => + RustLibWire(lib.ffiDynamicLibrary); + + /// Holds the symbol lookup function. + final ffi.Pointer Function(String symbolName) + _lookup; + + /// The symbols are looked up in [dynamicLibrary]. + RustLibWire(ffi.DynamicLibrary dynamicLibrary) + : _lookup = dynamicLibrary.lookup; +} diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart new file mode 100644 index 0000000..431eaa9 --- /dev/null +++ b/lib/src/rust/frb_generated.web.dart @@ -0,0 +1,86 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field + +// Static analysis wrongly picks the IO variant, thus ignore this +// ignore_for_file: argument_type_not_assignable + +import 'api/simple.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart'; + +abstract class RustLibApiImplPlatform extends BaseApiImpl { + RustLibApiImplPlatform({ + required super.handler, + required super.wire, + required super.generalizedFrbRustBinding, + required super.portManager, + }); + + @protected + String dco_decode_String(dynamic raw); + + @protected + Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + + @protected + int dco_decode_u_8(dynamic raw); + + @protected + void dco_decode_unit(dynamic raw); + + @protected + String sse_decode_String(SseDeserializer deserializer); + + @protected + Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + + @protected + int sse_decode_u_8(SseDeserializer deserializer); + + @protected + void sse_decode_unit(SseDeserializer deserializer); + + @protected + int sse_decode_i_32(SseDeserializer deserializer); + + @protected + bool sse_decode_bool(SseDeserializer deserializer); + + @protected + void sse_encode_String(String self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_8_strict( + Uint8List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_u_8(int self, SseSerializer serializer); + + @protected + void sse_encode_unit(void self, SseSerializer serializer); + + @protected + void sse_encode_i_32(int self, SseSerializer serializer); + + @protected + void sse_encode_bool(bool self, SseSerializer serializer); +} + +// Section: wire_class + +class RustLibWire implements BaseWire { + RustLibWire.fromExternalLibrary(ExternalLibrary lib); +} + +@JS('wasm_bindgen') +external RustLibWasmModule get wasmModule; + +@JS() +@anonymous +extension type RustLibWasmModule._(JSObject _) implements JSObject {} diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index b8b278e..2763f01 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -7,16 +7,13 @@ cmake_minimum_required(VERSION 3.10) set(PROJECT_NAME "ccc_cryptography") project(${PROJECT_NAME} LANGUAGES CXX) -# Invoke the build for native code shared with the other target platforms. -# This can be changed to accommodate different builds. -add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared") +include("../cargokit/cmake/cargokit.cmake") +apply_cargokit(${PROJECT_NAME} ../rust ccc_cryptography "") # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an # external build triggered from this build file. set(ccc_cryptography_bundled_libraries - # Defined in ../src/CMakeLists.txt. - # This can be changed to accommodate different builds. - $ + "${${PROJECT_NAME}_cargokit_lib}" PARENT_SCOPE ) diff --git a/macos/Classes/ccc_cryptography.c b/macos/Classes/ccc_cryptography.c deleted file mode 100644 index be218f7..0000000 --- a/macos/Classes/ccc_cryptography.c +++ /dev/null @@ -1,3 +0,0 @@ -// Relative import to be able to reuse the C sources. -// See the comment in ../ccc_cryptography.podspec for more information. -#include "../../src/ccc_cryptography.c" diff --git a/macos/Classes/dummy_file.c b/macos/Classes/dummy_file.c new file mode 100644 index 0000000..e06dab9 --- /dev/null +++ b/macos/Classes/dummy_file.c @@ -0,0 +1 @@ +// This is an empty file to force CocoaPods to create a framework. diff --git a/macos/ccc_cryptography.podspec b/macos/ccc_cryptography.podspec index 937f623..d9ba811 100644 --- a/macos/ccc_cryptography.podspec +++ b/macos/ccc_cryptography.podspec @@ -18,17 +18,27 @@ A new Flutter FFI plugin project. # paths, so Classes contains a forwarder C file that relatively imports # `../src/*` so that the C sources can be shared among all target platforms. s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - - # If your plugin requires a privacy manifest, for example if it collects user - # data, update the PrivacyInfo.xcprivacy file to describe your plugin's - # privacy impact, and then uncomment this line. For more information, - # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files - # s.resource_bundles = {'ccc_cryptography_privacy' => ['Resources/PrivacyInfo.xcprivacy']} - + s.source_files = 'Classes/**/*' s.dependency 'FlutterMacOS' s.platform = :osx, '10.11' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } s.swift_version = '5.0' -end + + s.script_phase = { + :name => 'Build Rust library', + # First argument is relative path to the `rust` folder, second is name of rust library + :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../rust ccc_cryptography', + :execution_position => :before_compile, + :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], + # Let XCode know that the static library referenced in -force_load below is + # created by this build step. + :output_files => ["${BUILT_PRODUCTS_DIR}/libccc_cryptography.a"], + } + s.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES', + # Flutter.framework does not contain a i386 slice. + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/libccc_cryptography.a', + } +end \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index ce432e5..6c3b3bd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: ccc_cryptography description: "Copius Cipher Chain Cryptography" +publish_to: 'none' version: 0.0.1 -homepage: environment: sdk: ^3.10.1 @@ -11,13 +11,19 @@ dependencies: flutter: sdk: flutter plugin_platform_interface: ^2.0.2 + flutter_rust_bridge: 2.11.1 + freezed_annotation: ^2.4.1 + meta: ^1.11.0 dev_dependencies: ffi: ^2.1.3 - ffigen: ^13.0.0 flutter_test: sdk: flutter flutter_lints: ^6.0.0 + build_runner: ^2.4.8 + freezed: ^2.5.2 + integration_test: + sdk: flutter flutter: plugin: diff --git a/rust/.gitignore b/rust/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/rust/.gitignore @@ -0,0 +1 @@ +/target diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 0000000..ca167cd --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "ccc_cryptography" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "staticlib"] + +[dependencies] +# Local dev paths — switch to git deps for CI/release: +# ccc-crypto-core = { git = "ssh://git@10.0.5.109/j3g/lum_ccc_rust.git", rev = "971f1ae" } +# ccc-crypto-wolfssl = { git = "ssh://git@10.0.5.109/j3g/lum_ccc_rust.git", rev = "971f1ae" } +ccc-crypto-core = { path = "/Volumes/LUM/source/letusmsg_proj/app/lum_ccc_rust/crates/ccc-crypto-core" } +ccc-crypto-wolfssl = { path = "/Volumes/LUM/source/letusmsg_proj/app/lum_ccc_rust/crates/ccc-crypto-wolfssl" } +flutter_rust_bridge = "=2.11.1" diff --git a/rust/src/api/mod.rs b/rust/src/api/mod.rs new file mode 100644 index 0000000..b252f36 --- /dev/null +++ b/rust/src/api/mod.rs @@ -0,0 +1 @@ +pub mod simple; diff --git a/rust/src/api/simple.rs b/rust/src/api/simple.rs new file mode 100644 index 0000000..4360c82 --- /dev/null +++ b/rust/src/api/simple.rs @@ -0,0 +1,10 @@ +#[flutter_rust_bridge::frb(sync)] // Synchronous mode for simplicity of the demo +pub fn greet(name: String) -> String { + format!("Hello, {name}!") +} + +#[flutter_rust_bridge::frb(init)] +pub fn init_app() { + // Default utilities - feel free to customize + flutter_rust_bridge::setup_default_user_utils(); +} diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs new file mode 100644 index 0000000..4f41c47 --- /dev/null +++ b/rust/src/frb_generated.rs @@ -0,0 +1,276 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +#![allow( + non_camel_case_types, + unused, + non_snake_case, + clippy::needless_return, + clippy::redundant_closure_call, + clippy::redundant_closure, + clippy::useless_conversion, + clippy::unit_arg, + clippy::unused_unit, + clippy::double_parens, + clippy::let_and_return, + clippy::too_many_arguments, + clippy::match_single_binding, + clippy::clone_on_copy, + clippy::let_unit_value, + clippy::deref_addrof, + clippy::explicit_auto_deref, + clippy::borrow_deref_ref, + clippy::needless_borrow +)] + +// Section: imports + +use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; +use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; +use flutter_rust_bridge::{Handler, IntoIntoDart}; + +// Section: boilerplate + +flutter_rust_bridge::frb_generated_boilerplate!( + default_stream_sink_codec = SseCodec, + default_rust_opaque = RustOpaqueMoi, + default_rust_auto_opaque = RustAutoOpaqueMoi, +); +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1"; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1918914929; + +// Section: executor + +flutter_rust_bridge::frb_generated_default_handler!(); + +// Section: wire_funcs + +fn wire__crate__api__simple__greet_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "greet", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_name = ::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse::<_, ()>((move || { + let output_ok = Result::<_, ()>::Ok(crate::api::simple::greet(api_name))?; + Ok(output_ok) + })()) + }, + ) +} +fn wire__crate__api__simple__init_app_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "init_app", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let output_ok = Result::<_, ()>::Ok({ + crate::api::simple::init_app(); + })?; + Ok(output_ok) + })()) + } + }, + ) +} + +// Section: dart2rust + +impl SseDecode for String { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = >::sse_decode(deserializer); + return String::from_utf8(inner).unwrap(); + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for u8 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u8().unwrap() + } +} + +impl SseDecode for () { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {} +} + +impl SseDecode for i32 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_i32::().unwrap() + } +} + +impl SseDecode for bool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u8().unwrap() != 0 + } +} + +fn pde_ffi_dispatcher_primary_impl( + func_id: i32, + port: flutter_rust_bridge::for_generated::MessagePort, + ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len: i32, + data_len: i32, +) { + // Codec=Pde (Serialization + dispatch), see doc to use other codecs + match func_id { + 2 => wire__crate__api__simple__init_app_impl(port, ptr, rust_vec_len, data_len), + _ => unreachable!(), + } +} + +fn pde_ffi_dispatcher_sync_impl( + func_id: i32, + ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len: i32, + data_len: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + // Codec=Pde (Serialization + dispatch), see doc to use other codecs + match func_id { + 1 => wire__crate__api__simple__greet_impl(ptr, rust_vec_len, data_len), + _ => unreachable!(), + } +} + +// Section: rust2dart + +impl SseEncode for String { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.into_bytes(), serializer); + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for u8 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_u8(self).unwrap(); + } +} + +impl SseEncode for () { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {} +} + +impl SseEncode for i32 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_i32::(self).unwrap(); + } +} + +impl SseEncode for bool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_u8(self as _).unwrap(); + } +} + +#[cfg(not(target_family = "wasm"))] +mod io { + // This file is automatically generated, so please do not edit it. + // @generated by `flutter_rust_bridge`@ 2.11.1. + + // Section: imports + + use super::*; + use flutter_rust_bridge::for_generated::byteorder::{ + NativeEndian, ReadBytesExt, WriteBytesExt, + }; + use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; + use flutter_rust_bridge::{Handler, IntoIntoDart}; + + // Section: boilerplate + + flutter_rust_bridge::frb_generated_boilerplate_io!(); +} +#[cfg(not(target_family = "wasm"))] +pub use io::*; + +/// cbindgen:ignore +#[cfg(target_family = "wasm")] +mod web { + // This file is automatically generated, so please do not edit it. + // @generated by `flutter_rust_bridge`@ 2.11.1. + + // Section: imports + + use super::*; + use flutter_rust_bridge::for_generated::byteorder::{ + NativeEndian, ReadBytesExt, WriteBytesExt, + }; + use flutter_rust_bridge::for_generated::wasm_bindgen; + use flutter_rust_bridge::for_generated::wasm_bindgen::prelude::*; + use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; + use flutter_rust_bridge::{Handler, IntoIntoDart}; + + // Section: boilerplate + + flutter_rust_bridge::frb_generated_boilerplate_web!(); +} +#[cfg(target_family = "wasm")] +pub use web::*; diff --git a/rust/src/lib.rs b/rust/src/lib.rs new file mode 100644 index 0000000..4673c13 --- /dev/null +++ b/rust/src/lib.rs @@ -0,0 +1,2 @@ +mod api; +mod frb_generated; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index cd35cb4..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# The Flutter tooling requires that developers have CMake 3.10 or later -# installed. You should not increase this version, as doing so will cause -# the plugin to fail to compile for some customers of the plugin. -cmake_minimum_required(VERSION 3.10) - -project(ccc_cryptography_library VERSION 0.0.1 LANGUAGES C) - -add_library(ccc_cryptography SHARED - "ccc_cryptography.c" -) - -set_target_properties(ccc_cryptography PROPERTIES - PUBLIC_HEADER ccc_cryptography.h - OUTPUT_NAME "ccc_cryptography" -) - -target_compile_definitions(ccc_cryptography PUBLIC DART_SHARED_LIB) - -if (ANDROID) - # Support Android 15 16k page size - target_link_options(ccc_cryptography PRIVATE "-Wl,-z,max-page-size=16384") -endif() diff --git a/src/ccc_cryptography.c b/src/ccc_cryptography.c deleted file mode 100644 index 0be68eb..0000000 --- a/src/ccc_cryptography.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "ccc_cryptography.h" - -// A very short-lived native function. -// -// For very short-lived functions, it is fine to call them on the main isolate. -// They will block the Dart execution while running the native function, so -// only do this for native functions which are guaranteed to be short-lived. -FFI_PLUGIN_EXPORT int sum(int a, int b) { return a + b; } - -// A longer-lived native function, which occupies the thread calling it. -// -// Do not call these kind of native functions in the main isolate. They will -// block Dart execution. This will cause dropped frames in Flutter applications. -// Instead, call these native functions on a separate isolate. -FFI_PLUGIN_EXPORT int sum_long_running(int a, int b) { - // Simulate work. -#if _WIN32 - Sleep(5000); -#else - usleep(5000 * 1000); -#endif - return a + b; -} diff --git a/src/ccc_cryptography.h b/src/ccc_cryptography.h deleted file mode 100644 index 7944459..0000000 --- a/src/ccc_cryptography.h +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -#if _WIN32 -#include -#else -#include -#include -#endif - -#if _WIN32 -#define FFI_PLUGIN_EXPORT __declspec(dllexport) -#else -#define FFI_PLUGIN_EXPORT -#endif - -// A very short-lived native function. -// -// For very short-lived functions, it is fine to call them on the main isolate. -// They will block the Dart execution while running the native function, so -// only do this for native functions which are guaranteed to be short-lived. -FFI_PLUGIN_EXPORT int sum(int a, int b); - -// A longer lived native function, which occupies the thread calling it. -// -// Do not call these kind of native functions in the main isolate. They will -// block Dart execution. This will cause dropped frames in Flutter applications. -// Instead, call these native functions on a separate isolate. -FFI_PLUGIN_EXPORT int sum_long_running(int a, int b); diff --git a/test_driver/integration_test.dart b/test_driver/integration_test.dart new file mode 100644 index 0000000..b38629c --- /dev/null +++ b/test_driver/integration_test.dart @@ -0,0 +1,3 @@ +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index e002bb4..54d1504 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -8,16 +8,13 @@ cmake_minimum_required(VERSION 3.14) set(PROJECT_NAME "ccc_cryptography") project(${PROJECT_NAME} LANGUAGES CXX) -# Invoke the build for native code shared with the other target platforms. -# This can be changed to accommodate different builds. -add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared") +include("../cargokit/cmake/cargokit.cmake") +apply_cargokit(${PROJECT_NAME} ../rust ccc_cryptography "") # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an # external build triggered from this build file. set(ccc_cryptography_bundled_libraries - # Defined in ../src/CMakeLists.txt. - # This can be changed to accommodate different builds. - $ + "${${PROJECT_NAME}_cargokit_lib}" PARENT_SCOPE )