Skip to content

Commit

Permalink
use Bens fork with mozilla/uniffi-rs#2087 and the BagOfBytes works! c…
Browse files Browse the repository at this point in the history
…an be used in other crates than declaring crate.
  • Loading branch information
Sajjon committed May 20, 2024
1 parent 32e5740 commit 8d3eb60
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 14 deletions.
45 changes: 35 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion crates/chef/src/chef.udl
Original file line number Diff line number Diff line change
@@ -1 +1 @@
namespace chef {};
namespace chef {};
2 changes: 2 additions & 0 deletions crates/chef/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::ops::AddAssign;
pub struct Chef {
pub name: String,
pub money: RwLock<Money>,
pub bag_of_bytes: BagOfBytes,
}

#[uniffi::export]
Expand All @@ -16,6 +17,7 @@ impl Chef {
Arc::new(Self {
name,
money: RwLock::new(money),
bag_of_bytes: BagOfBytes::from(vec![0xde, 0xad, 0xbe, 0xef]),
})
}

Expand Down
1 change: 1 addition & 0 deletions crates/kitchen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ build = "build.rs"

[dependencies]
uniffi = { workspace = true, features = ["cli"] }
money = { path = "../money" }
farm = { path = "../farm" }

[build-dependencies]
Expand Down
1 change: 1 addition & 0 deletions crates/kitchen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod prelude {
pub use crate::models::*;

pub(crate) use farm::prelude::*;
pub(crate) use money::prelude::*;
}

pub use prelude::*;
Expand Down
4 changes: 3 additions & 1 deletion crates/kitchen/src/models.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
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 {
Self {
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]),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/money/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"
build = "build.rs"

[dependencies]
itertools = "0.13.0"
uniffi = { workspace = true, features = ["cli"] }

[build-dependencies]
Expand Down
83 changes: 83 additions & 0 deletions crates/money/src/models.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,88 @@
use itertools::*;
use std::ops::{AddAssign, SubAssign};

#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct BagOfBytes {
pub bytes: Vec<u8>,
}

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<u8> {
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<Vec<u8>> for BagOfBytes {
fn from(value: Vec<u8>) -> 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<i8>`, unfortunately we cannot
use `sequence<u8>` 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<i8>` (`Vec<i8>`) 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<i8> -> Vec<u8>, meaning Kotlin and Swift actually
never see the `i8`, and only works with u8.
So we translate:
Kotlin: `Rust[BagOfBytes <:2's comp.:> Vec<i8>] <:2's comp:> [Kotlin]List<UByte>`
Swift: `Rust[BagOfBytes <:2's comp.:> Vec<i8>] <:2's comp:> [Swift]Foundation.Data`
*/
uniffi::custom_type!(BagOfBytes, Vec<i8>, {
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,
Expand Down
11 changes: 10 additions & 1 deletion crates/money/src/money.udl
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
namespace money {};
namespace money {};

// HERE BE DRAGONS
// Due to Kotlin equals being broken for ByteArray
// Which otherwise UniFFI converts `Vec<u8>` to, we MUST use
// our own "bag of bytes" which we convert to a Kotlin `List<Byte>`
// which DOES have a working equals!
// HERE BE DRAGONS
[Custom]
typedef sequence<i8> BagOfBytes;
13 changes: 13 additions & 0 deletions crates/money/uniffi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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<UByte>"
imports = []
into_custom = "{}.map({ it.toUByte() })"
from_custom = "{}.map({ it.toByte() })"

0 comments on commit 8d3eb60

Please sign in to comment.