diff --git a/Cargo.lock b/Cargo.lock index 6462518..ad1f411 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,6 +214,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + [[package]] name = "farm" version = "0.1.0" @@ -260,6 +266,15 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -271,6 +286,7 @@ name = "kitchen" version = "0.1.0" dependencies = [ "farm", + "money", "uniffi", ] @@ -344,6 +360,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" name = "money" version = "0.1.0" dependencies = [ + "itertools", "uniffi", ] @@ -363,6 +380,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "oneshot-uniffi" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c" + [[package]] name = "paste" version = "1.0.15" @@ -559,7 +582,7 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "uniffi" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "anyhow", "camino", @@ -573,12 +596,13 @@ dependencies = [ [[package]] name = "uniffi_bindgen" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "anyhow", "askama", "camino", "cargo_metadata", + "clap", "fs-err", "glob", "goblin", @@ -596,7 +620,7 @@ dependencies = [ [[package]] name = "uniffi_build" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "anyhow", "camino", @@ -606,7 +630,7 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "quote", "syn", @@ -615,13 +639,14 @@ dependencies = [ [[package]] name = "uniffi_core" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "anyhow", "bytes", "camino", "log", "once_cell", + "oneshot-uniffi", "paste", "static_assertions", ] @@ -629,7 +654,7 @@ dependencies = [ [[package]] name = "uniffi_macros" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "bincode", "camino", @@ -646,7 +671,7 @@ dependencies = [ [[package]] name = "uniffi_meta" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "anyhow", "bytes", @@ -657,7 +682,7 @@ dependencies = [ [[package]] name = "uniffi_testing" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "anyhow", "camino", @@ -669,7 +694,7 @@ dependencies = [ [[package]] name = "uniffi_udl" version = "0.27.1" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "anyhow", "textwrap", @@ -693,7 +718,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "weedle2" version = "5.0.0" -source = "git+https://github.com/mozilla/uniffi-rs/?rev=aa338ccb435d81d36f7adef8954bcffebdd4a7d1#aa338ccb435d81d36f7adef8954bcffebdd4a7d1" +source = "git+https://github.com/bendk/uniffi-rs/?rev=4b65c3796bc3743404e1ee2a7b4ab51e24589aa6#4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index f4622fb..a303507 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ members = [ ] [workspace.dependencies] -uniffi = { git = "https://github.com/mozilla/uniffi-rs/", rev = "aa338ccb435d81d36f7adef8954bcffebdd4a7d1" } +uniffi = { git = "https://github.com/bendk/uniffi-rs/", rev = "4b65c3796bc3743404e1ee2a7b4ab51e24589aa6" } [profile.release] incremental = false diff --git a/crates/chef/src/chef.udl b/crates/chef/src/chef.udl index c594cc3..386eefe 100644 --- a/crates/chef/src/chef.udl +++ b/crates/chef/src/chef.udl @@ -1 +1 @@ -namespace chef {}; \ No newline at end of file +namespace chef {}; diff --git a/crates/chef/src/models.rs b/crates/chef/src/models.rs index eea3cf4..ef41832 100644 --- a/crates/chef/src/models.rs +++ b/crates/chef/src/models.rs @@ -7,6 +7,7 @@ use std::ops::AddAssign; pub struct Chef { pub name: String, pub money: RwLock, + pub bag_of_bytes: BagOfBytes, } #[uniffi::export] @@ -16,6 +17,7 @@ impl Chef { Arc::new(Self { name, money: RwLock::new(money), + bag_of_bytes: BagOfBytes::from(vec![0xde, 0xad, 0xbe, 0xef]), }) } diff --git a/crates/kitchen/Cargo.toml b/crates/kitchen/Cargo.toml index 7a6eff3..a4e7760 100644 --- a/crates/kitchen/Cargo.toml +++ b/crates/kitchen/Cargo.toml @@ -6,6 +6,7 @@ build = "build.rs" [dependencies] uniffi = { workspace = true, features = ["cli"] } +money = { path = "../money" } farm = { path = "../farm" } [build-dependencies] diff --git a/crates/kitchen/src/lib.rs b/crates/kitchen/src/lib.rs index caf8578..bfabfed 100644 --- a/crates/kitchen/src/lib.rs +++ b/crates/kitchen/src/lib.rs @@ -4,6 +4,7 @@ pub mod prelude { pub use crate::models::*; pub(crate) use farm::prelude::*; + pub(crate) use money::prelude::*; } pub use prelude::*; diff --git a/crates/kitchen/src/models.rs b/crates/kitchen/src/models.rs index 1fc0394..eeb5f03 100644 --- a/crates/kitchen/src/models.rs +++ b/crates/kitchen/src/models.rs @@ -1,10 +1,11 @@ use crate::prelude::*; -#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, uniffi::Record)] +#[derive(Default, Clone, Debug, PartialEq, Eq, uniffi::Record)] pub struct Fridge { pub egg: EggBox, pub butter: ButterBlock, pub lemons: Lemons, + pub bag_of_bytes: BagOfBytes, } impl Fridge { pub fn stock_with(produce: farm::Produce) -> Self { @@ -12,6 +13,7 @@ impl Fridge { egg: EggBox::from(produce.clone()), butter: ButterBlock::from(produce.clone()), lemons: Lemons::from(produce.clone()), + bag_of_bytes: BagOfBytes::from(vec![0xde, 0xad, 0xbe, 0xef]), } } } diff --git a/crates/money/Cargo.toml b/crates/money/Cargo.toml index 2a688ae..6d2248e 100644 --- a/crates/money/Cargo.toml +++ b/crates/money/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" build = "build.rs" [dependencies] +itertools = "0.13.0" uniffi = { workspace = true, features = ["cli"] } [build-dependencies] diff --git a/crates/money/src/models.rs b/crates/money/src/models.rs index b1df354..143b7cb 100644 --- a/crates/money/src/models.rs +++ b/crates/money/src/models.rs @@ -1,5 +1,88 @@ +use itertools::*; use std::ops::{AddAssign, SubAssign}; +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct BagOfBytes { + pub bytes: Vec, +} + +impl BagOfBytes { + pub fn len(&self) -> usize { + self.bytes.len() + } + + pub fn is_empty(&self) -> bool { + self.bytes.is_empty() + } + + /// Returns a clone of the inner bytes as a `Vec`. + pub fn to_vec(&self) -> Vec { + Vec::from(self.bytes()) + } + + /// Returns a references to the inner array slice. + pub fn bytes(&self) -> &[u8] { + &self.bytes + } +} + +fn twos_complement_of_u8(u: u8) -> i8 { + // Yes, it is this easy, Rust does all the heavy lifting + u as i8 +} + +fn twos_complement_of_i8(i: i8) -> u8 { + // Yes, it is this easy, Rust does all the heavy lifting + i as u8 +} + +impl From> for BagOfBytes { + fn from(value: Vec) -> Self { + Self { bytes: value } + } +} + +impl From<&[u8]> for BagOfBytes { + /// Instantiates a new `BagOfBytes` from the bytes. + fn from(value: &[u8]) -> Self { + Self { + bytes: value.to_vec(), + } + } +} + +/* + Expose `BagOfBytes` to Uniffi as `sequence`, unfortunately we cannot + use `sequence` because it results in: + + /uniffi-rs-6f89edd2a1ffa4bd/fb8dd5c/uniffi_bindgen/src/interface/universe.rs:50:17: + assertion `left == right` failed + left: Custom { module_path: "profile", name: "BagOfBytes", builtin: Bytes } + right: Custom { module_path: "profile", name: "BagOfBytes", builtin: Sequence { inner_type: UInt8 } } + + So HACK HACK HACK we use `sequence` (`Vec`) instead as an intermediary `Builtin`. + + However, in `uniffi.toml` we provide `from_custom`` / `into_custom`` for Kotlin and Swift + which using two's complement maps back Vec -> Vec, meaning Kotlin and Swift actually + never see the `i8`, and only works with u8. + + So we translate: + Kotlin: `Rust[BagOfBytes <:2's comp.:> Vec] <:2's comp:> [Kotlin]List` + Swift: `Rust[BagOfBytes <:2's comp.:> Vec] <:2's comp:> [Swift]Foundation.Data` + +*/ +uniffi::custom_type!(BagOfBytes, Vec, { + from_custom: |s| s.to_vec() + .into_iter() + .map(twos_complement_of_u8) + .collect_vec(), + try_into_custom: |s| Ok(s + .into_iter() + .map(twos_complement_of_i8) + .collect_vec() + .into()), +}); + #[derive(uniffi::Record, Default, Clone, PartialEq, Eq, Copy, Debug)] pub struct Money { pub amount: u64, diff --git a/crates/money/src/money.udl b/crates/money/src/money.udl index 926def9..584341c 100644 --- a/crates/money/src/money.udl +++ b/crates/money/src/money.udl @@ -1 +1,10 @@ -namespace money {}; \ No newline at end of file +namespace money {}; + +// HERE BE DRAGONS +// Due to Kotlin equals being broken for ByteArray +// Which otherwise UniFFI converts `Vec` to, we MUST use +// our own "bag of bytes" which we convert to a Kotlin `List` +// which DOES have a working equals! +// HERE BE DRAGONS +[Custom] +typedef sequence BagOfBytes; \ No newline at end of file diff --git a/crates/money/uniffi.toml b/crates/money/uniffi.toml index 31a3586..e62574b 100644 --- a/crates/money/uniffi.toml +++ b/crates/money/uniffi.toml @@ -2,3 +2,16 @@ namespace = "money" [bindings.kotlin] package_name = "com.sajjon.money" + + +[bindings.swift.custom_types.BagOfBytes] +type_name = "Data" +imports = ["Foundation"] +into_custom = "{ Data({}.map({ i8 in UInt8(bitPattern: i8) })) }()" +from_custom = "{ {}.map({ u8 in Int8(bitPattern: u8) }) }()" + +[bindings.kotlin.custom_types.BagOfBytes] +type_name = "List" +imports = [] +into_custom = "{}.map({ it.toUByte() })" +from_custom = "{}.map({ it.toByte() })"