-
Notifications
You must be signed in to change notification settings - Fork 1
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
Isolate UniFFI #194
Comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Abstract
We plan to isolate the usage of UniFFI to a single wrapping crate, which hosts (iOS/Android wallet app) will use, which will allow us to convert Sargon (this repo) into using Cargo Workspace - which as seen in #143 leads to a massive speedup in compilation and build time.
Rationale
#143 is not mergeable since we hit issues with the complexities of UniFFI tag conversion between different crates. Even if we were to solve the issues preventing us from using the "naive" approach in #143, where many crates use UniFFI (e.g. by not using
uniffi::custom_newtype!(NonPrimitive, NewType)
but rather always use UniFFI primitive types such asString
,i8
etc), we still want to limit our dependency on UniFFI, if we ever want to use another bindgen tool some day.Another benefit of limiting the usage of UniFFI is that the restrictions put on the Rust code by UniFFI is lifted, such as lack of support of generics! Suddenly we can translate lots of our macro heavy code to use generics instead.
Vision
The vision, how we want it in the future, when we have migrated over to Cargo Workspace is many small crates, allowing us to get parallellisation and caching of builds, thanks to cargo and sccache.
Important
This issue is about completing the isolation of UniFFI into a single crate, which is the prerequisites of a proper splitting of code into crates. We dont have to create more than two crates part of this PR, if it is not deemed helpful.
Work
Unfortunately we note that there is a little bit of a chicken or the egg situation between isolating-UniFFI-into-single-crate work and refactor-logic-from-hosts-into-Sargon-and-use-SargonOS work, since if we had moved all the logic from hosts into Sargon, we could remove many of the models, since they need no longer be UniFFI exported. E.g.
Account
would not need to be UniFFI exported at all, instead a small "ViewModel"AccountForDisplay
would be enough for hosts. An end-goal is to not have to have Profile UniFFI exported at all, but just use drivers to load Profile JSON data from hosts and let Profile be fully internal and wrapped by Sargon. However, the work of moving logic from hosts into Sargon will greatly benefit from fast code completion, compilation and build times.Important
Since moving from hosts into Sargon spreads across 3 repos, compared to isolating UniFFI which means working in a single repo, we will do the work of isolating UniFFI into a single crate first.
Strategies
Strategy 1a
src
->crates/private
(except for CLIsrc/bindgen
perhaps). Since this touches all files we wanna do it directly as to mitigate merge conflicts with future changes to Sargon (and update thepath
of[lib]
inCargo.toml
).crates/sargon-uniffi
which is NOT a module/crate or known to Rust yet, only file level.#[derive(uniffi::Record)]
and remove that derive fromstruct Foo
incrates/private/.../foo.rs
, and having a newstruct Foo
incrates/sargon-uniffi/../foo.rs
and also implementFrom<T> for U
andFrom<U> for T
incrates/sargon-uniffi/../foo.rs
.crates/sargon-uniffi/../foo.rs
folder is still not compiled. We would typically want to migrate some types being defined by macros -> generics here.crates/private
, by moving all#[uniffi::export]
functions to thecrates/sargon-uniffi
folder (still not compiled).Cargo.toml
to declare a workspace and let all code incrates/private
be one single crate.Cargo.toml
declare an actual package forsargon-uniffi
, with thesargon-private
crate as a dependencyStrategy 1b
Just like
1a
but instead of creating one single crate in step 5, we declare many small ones and reference used dependencies fromsargon-uniffi
crateStrategy 2 #
Like Strategy
1
but more aggressive rewrite, instead of gradual translation of UniFFI instep 3
andstep 4
, we simply bring the axe and remove UniFFI completely. Steps:src
->crates/private
sccache
, but primarily it will be dictated by our structure of crates, if we manage to create a broad and shallow dependency tree or not.Strategy 2: Unknowns / Undecided:
#[uniffi::export]
annotated ? Or should we delete those? :thinking_face: Those contain no logic, maybe just noise, and will be quite easy - albeit cumbersome - to reintroduce.main
branch) and modify it to our needs.Unknowns / Uncertainties / Risks
I have a hard time seeing exactly how Radix-Engine-Toolkit fits in here. Specifically
ret::Decimal
, which today is wrapped by Sargon asDecimal192
which is UniFFI exported, which has quite a bit of complexity. We have different tactics here:Decimal Tactic 1
ret::Decimal
anywhere in code, by wrapping it inDecimal192
incrates/sargon-private
(probablycrates/private/decimal
) which ofc does NOT know anything about UniFFI.sargon_uniffi::Decimal192
which wrapssargon_private::Decimal192
and UniFFI exports it.Decimal Tactic 2
ret::Decimal
directly everywhere incrates/private/*
Decimal192
almost as-is incrates/sargon-uniffi
crateIf we use
Tactic 2
then how do we handle errors??? Hmm.... anywhere incrates/private
when we use any throwing method onret::Decimal
we would need to convert that error intoCommonError
which seems like a less elegant option than wrapping? However,Tactic 1
with its 3 type results in two layers ofFrom<T> for U
andFrom<U> for T
which seems very costly if we also wanna declare all methods on both layers. There are a LOT of methods.The text was updated successfully, but these errors were encountered: