-
Notifications
You must be signed in to change notification settings - Fork 206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Equality check on records when arrays are involved in Kotlin #1985
Comments
Or phrasing it differently: As a Kotlin UniFFI consumer we expect two instances of If we agree that the above expectation is reasonable and valid - then UniFFI wrt to Records containing So we propose UniFFI convert |
We can note that there wasn't really any discussion regarding the potential problems of |
I'm slightly confused here. The first comment says:
But then:
So I must be missing something because they seem contradictory? The second statement implies you really just want to revert #1543 - but we introduced bytes for use-cases where having contiguous memory was important. I don't think I think what should actually happen here is some way to make #1696 optional - ie, to not have procmacros treat every |
@mhammond Yes @micbakos-rdx phrased it badly, i think:
I think Michael meant: "If we are the only ones who need UniFFI to change, WE at RDX Works cannot rely on Mozilla changing UniFFI to our needs". @mhammond Thank you for link to #1696 and #1638 , with discussions, I also had the idea of field attached macros, I love the syntax: #[uniffi(type = bytes)] @mhammond you wrote:
So here is my presenting a credible use-case: ✨ Reason why we must use `Record` HERE ✨The reason why we MUST use
This is why we have completely fallen in love with UniFFI 😍 we are about to move not only implementation of the Profile models, but also the non-trivial (read: complex) logic involving mutating them into one place, Rust and exposed to iOS and Android wallets using UniFFI. Those wallets are used published on Apple App Store / Google Play Store with tens of thousands of users, holding many millions of USD in crypto. We need a gradual migration from Profile in Swift on iOS and in Kotlin on Android to be using Profile in Rust exposed via UniFFI. Our plan is:
I've recently finalised implementation of the models (and a little bit of the logic) @ ~12,000 - 15,000 lines of Rust code (trying to not count 10k+ lines of huge string literals in Rust, part of JSON roundtrip tests of models). I had already written Swift bindgen tests and Michael is now writing Kotlin bindgen tests, where we unexpectedly saw So for Phase 2 we must continue to use the logic implemented as is in Swift and Kotlin, therefor we must do a minimal change to the models. Changing them all to be reference types is a huge change, and just not feasible. Our UI layer would be completely broken on iOS since we use TCA which requires that state is only containing value types. So this is the reason why we MUST use Also, today in wallet repos, we rely on all our values types impl of So Ofc, if the UniFFI team - in this thread - tell us "you will have to live with ByteArray in Kotlin for Records for the unforseeable future", I will update all our methods and functions to use TL;DR; So syntax #[uniffi(type = bytes)] Was primary tricky due to uncertain how to handle |
And what @micbakos-rdx wrote above:
Him and I have a hard time seeming a good place to put it... it would be strange for it to be macro code next to the struct in Rust file, so would probably be in |
The details are murky, but "not feasible" was probably more like "not obvious" - ie, if there was an easy path it would have been taken, but I don't think we exhausted all possibilities.
Another possibility would be to have a simple boolean in this file, meaning this entire crate simply opts out of having a |
Yes, that is a good solution too, especially if it can be a per language setting? Just like EDIT: that was a bit unclear... I meant to say I would love for Swift bindings to still get |
yeah, it would want to be a per-language setting IMO. |
Hello, I am in the process of verifying the usage of this library with Kotlin built by @Sajjon that uses UniFFI.
During testing, we encountered a situation that, while not a UniFFI issue, could impact our development and its resolution.
The
hex_32bytes.rs
is a simple struct that holds abytes: Vec<u8>
. It uses theuniffi::Record
so it is converted into a data class in Kotlin like so:Which is correct.
In Kotlin, two arrays with the same structure and data are not considered equal when using the built-in equals method:
Now, when the Hex32Bytes class is used inside other generated data classes like:
Since these classes are generated, there is no way to enforce the usage of contentEquals when comparing the two byte arrays. An extension equals method cannot be used since it will always be shadowed by the built-in equals method.
Considering the need to use records, there are a few options:
Change the implementation of Hex32Bytes and create a custom implementation (e.g.,
BagOfBytes
) instead of usingVec<u8>
. Instruct UniFFI to convert it to aList<UByte>
. This is being explored in a pull request by @Sajjon. Lists in Kotlin follow structural equality, resolving the mentioned problems.Explore the possibility of instructing UniFFI to override the equals method of the generated data class, allowing it to follow the equality check in Rust. This would involve defining a method in Rust's struct and annotating it to override the equals method on the Kotlin side.
Consider changing how
Vec<u8>
is translated in Kotlin. However, this solution is only valid for our use case. So we are not considering this.The text was updated successfully, but these errors were encountered: