Skip to content

Commit

Permalink
Merge branch 'feat/lifetime-support' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
pankcuf committed Feb 19, 2025
2 parents b28f6a7 + eec010c commit 9410d89
Show file tree
Hide file tree
Showing 200 changed files with 10,202 additions and 54,222 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,7 @@ So here we have 2 different approaches, in `OuterStruct_ctor` and in `create_out
Back in the days decisions were made from the point of view of efficiency, it would be better to always give pointer's ownership to the rust. But to do this, you will have to write code in rust only in an FFI-compatible style (which is ridiculous), or modify the `ferment` to the state where not only FFI-compatible methods/structures are fermented, but also the code itself inside them.
FAQ:
- if you see no opaque pointers in cbindgen header makes sure you did include crate-owner in the list in settings
60 changes: 21 additions & 39 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
- Need to catch this aliases at mod.rs level
```rust
pub use self::models::snapshot::LLMQSnapshot;
```
otherwise to support fermentation it needs to be imported as full path:
```rust
use crate::models::snapshot::LLMQSnapshot;
```
and this wouldn't work:
```rust
use crate::models::LLMQSnapshot;
```
- Now you can't specify field type as full or partially qualified (bug). So use this:
```rust
use example_simple::nested::HashID;
Expand All @@ -35,33 +23,21 @@
[0u8; 32]
}
```
- Need to fix "fermented::" hardcoded in type transposing although different name is specified in Config::with_mod_name()
- Async generic traits (decomposable) (epic)
- Other Languages Support (objc/java) - (at least DashSyncs boilerplate generation) (epic)
- Typealiases for paths (re-export types support)
- Path chunks support (when objects contains paths like this:

```rust
use example_simple::nested;
use crate::model::snapshot;
#[ferment_macro::export]
pub fn get_hash_id_form_snapshot(snapshot: snapshot::LLMQSnapshot) -> nested::HashID {
[0u8; 32]
}
```

- Fix: custom fermented module names (currently no matter what you specified in configit always expanding in crate::fermented scope)
- Fix: optional primitives (Now Option<bool> expanding to false when bool is really false, or when Option is None, same thing for Option<u32> becomes 0 if None)
- Handle mut vs const in methods arguments
- Expose tokio runtime constructor/destructor
- Improve `Self::` processing
- Somewhat happens while reexporting fermented types while using nested crates: it goes with dash_spv_masternode_processor::some_type::SomeStruct insted of dash_spv_masternode_processor::fermented::types::some_type::SomeStruct
- Custom structures named Result, Vec, HashMap, BTreeMap may not work properly. Need to add some logic to distinguish between std and custom types here
- Need support for paths containing super or super::super etc
- Minor issue with things like #[doc = "FFI-representation of the # [doc = \"FFI-representation of the crate :: identity :: identity_request :: GetIdentityRequest\"]"]
- TypeGroup support
- Algo for determine if type is simple enough to add it to the dictionary of registered types and use orginal one across the FFI
- Such enum has wrong fermentation:
- fix: "fermented::" hardcoded in type transposing although different name is specified in Config::with_mod_name()
- improve: async generic traits (decomposable) (epic)
- improve: other Languages Support (java) (epic)
- improve: typealiases for paths (re-export types support)
- improve: cross-crates re-exports support
- improve: internal crate reexports with gaps in the middle of hierarchy (like state_transitions::*)
- improve: support wildcard imports ("*")
- fix: custom fermented module names (currently no matter what you specified in configit always expanding in crate::fermented scope)
- improve: `Self::`, `&Self` processing
- improve: Need support for paths containing super or super::super etc
- fix: minor issue with things like #[doc = "FFI-representation of the # [doc = \"FFI-representation of the crate :: identity :: identity_request :: GetIdentityRequest\"]"]
- improve: TypeGroup support
- improve: public/private fields/mods visibility support + mod-based fermentation (epic)
- improve: algo for determine if type is simple enough to add it to the dictionary of registered types and use original one across the FFI (like we often have for type aliases)
- fix: such enum has wrong fermentation:
```rust
#[repr(u8)]
#[ferment_macro::export]
Expand All @@ -70,3 +46,9 @@
SingleContractDocumentType { id: Identifier, document_type_name: String } = 1,
}
```
- improve types wrapped into smart pointers (Box, etc) (in terms of memory use?)
- fix: Vec<&str> becomes Vec_, also can't use smth like ['a ['a str]]
- static methods for impls are broken (if they are non-opaque), so currently it's possible to use only instance methods
- fix: HashSet<[u8; 32]> becomes std_collections_HashSet_u8 instead of std_collections_HashSet_Arr_u8_32 (+)
- fix: opaque types which impl are exported can't use `fn some_fn(self)` (trying to dereference it)
- fix: Fn without non-receiver arguments is not supported
2 changes: 1 addition & 1 deletion ferment-example/entry-point/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ferment-macro = { path = "../../ferment-macro" }
tokio = { version = "1.34", features = ["full"] }

[build-dependencies]
cbindgen = "0.26.0"
cbindgen = "0.27.0"
ferment-sys = { path = "../../ferment-sys" }


Expand Down
5 changes: 3 additions & 2 deletions ferment-example/entry-point/src/entry/core.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::BTreeMap;
use std::sync::Arc;
use ferment::boxed;
use crate::entry::{BlockHashByHeight, ModelByHeight, SomeModel};
use crate::entry::processor::MasternodeProcessor;
Expand All @@ -18,7 +19,7 @@ impl DashSharedCore {
model_by_height: ModelByHeight,
context: *const std::os::raw::c_void) -> Self {
Self {
processor: boxed(MasternodeProcessor { provider: Box::new(FFIPtrCoreProvider { block_hash_by_height, model_by_height }) }),
processor: boxed(MasternodeProcessor { provider: Arc::new(FFIPtrCoreProvider { block_hash_by_height, model_by_height }) }),
cache: Default::default(),
context
}
Expand All @@ -30,7 +31,7 @@ impl DashSharedCore {
where {
Self {
processor: boxed(MasternodeProcessor {
provider: Box::new(FFITraitCoreProvider {
provider: Arc::new(FFITraitCoreProvider {
block_hash_by_height: Box::new(block_hash_by_height),
model_by_height: Box::new(model_by_height) }) }),
cache: Default::default(),
Expand Down
10 changes: 8 additions & 2 deletions ferment-example/entry-point/src/entry/processor.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::sync::Arc;
use crate::entry::provider::CoreProvider;

// #[ferment_macro::opaque]
#[ferment_macro::opaque]
pub struct MasternodeProcessor {
pub provider: Box<dyn CoreProvider>,
pub provider: Arc<dyn CoreProvider>,
}

#[ferment_macro::opaque]
Expand All @@ -13,3 +14,8 @@ pub struct FFICoreProvider {

}

impl MasternodeProcessor {
pub fn new(provider: Arc<dyn CoreProvider>) -> Self {
Self { provider }
}
}
5 changes: 3 additions & 2 deletions ferment-example/entry-point/src/entry/rnt.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::BTreeMap;
use std::sync::Arc;
use tokio::runtime::Runtime;
use crate::entry::{BlockHashByHeight, ModelByHeight, SomeModel};
use crate::entry::processor::MasternodeProcessor;
Expand All @@ -20,7 +21,7 @@ impl DashSharedCoreWithRuntime {
runtime: *mut Runtime,
context: *const std::os::raw::c_void) -> Self {
Self {
processor: ferment::boxed(MasternodeProcessor { provider: Box::new(FFIPtrCoreProvider { block_hash_by_height, model_by_height }) }),
processor: ferment::boxed(MasternodeProcessor { provider: Arc::new(FFIPtrCoreProvider { block_hash_by_height, model_by_height }) }),
cache: Default::default(),
runtime,
context
Expand All @@ -34,7 +35,7 @@ impl DashSharedCoreWithRuntime {
where {
Self {
processor: ferment::boxed(MasternodeProcessor {
provider: Box::new(FFITraitCoreProvider {
provider: Arc::new(FFITraitCoreProvider {
block_hash_by_height: Box::new(block_hash_by_height),
model_by_height: Box::new(model_by_height) }) }),
cache: Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion ferment-example/entry-point/src/fermented.rs

Large diffs are not rendered by default.

66 changes: 63 additions & 3 deletions ferment-example/nested/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,77 @@ edition = "2021"
build = "build.rs"

[dependencies]
anyhow = "1.0.95"
#dashcore = { path = "../../../rust-dashcore-fork", features = [
# "std",
# "secp-recovery",
# "rand",
# "signer",
# "serde",
#], default-features = false }
dashcore = { git = "https://github.com/pankcuf/rust-dashcore", features = [
"std",
"secp-recovery",
"rand",
"signer",
"serde",
], default-features = false, branch = "feat/ferment" }

ferment = { path = "../../ferment" }
ferment-macro = { path = "../../ferment-macro" }
example-simple = { path = "../simple" }
platform-value = { path = "../../../platform/packages/rs-platform-value" }
platform-version = { path = "../../../platform/packages/rs-platform-version" }
dpp = { path = "../../../platform/packages/rs-dpp" }

indexmap = "2.7.0"
regex = "1.11.1"
serde = { version = "1.0.215", features = ["derive"], optional = true }
serde_json = "1.0.85"
versioned-feature-core = "1.0.0"

[build-dependencies]
cbindgen = "0.26.0"
ferment-sys = { path = "../../ferment-sys", features = ["objc"] }
cbindgen = "0.28.0"
ferment-sys = { path = "../../ferment-sys" }
#ferment-sys = { path = "../../ferment-sys", features = ["objc"] }
#ferment-sys = { path = "../../ferment-sys", features = ["objc", "cbindgen_only"] }
toml = "0.8.8"

[features]
default = ["state-transitions"]

bls-signatures = ["dpp/bls-signatures"]
blsful = ["dashcore/blsful"]
cbor = ["platform-value/cbor", "dpp/cbor", "dpp/ciborium"]
core-types = ["dpp/core-types"]
data-contract-cbor-conversion = ["dpp/data-contract-cbor-conversion"]
data-contract-json-conversion = ["dpp/data-contract-json-conversion"]
data-contract-value-conversion = ["dpp/data-contract-value-conversion"]
document-cbor-conversion = ["dpp/document-cbor-conversion"]
document-json-conversion = ["dpp/document-json-conversion"]
document-value-conversion = ["dpp/document-value-conversion"]
extended-document = ["dpp/extended-document"]
factories = ["dpp/factories"]
fee-distribution = ["dpp/fee-distribution"]
fixtures-and-mocks = ["dpp/fixtures-and-mocks"]
identity-cbor-conversion = ["dpp/identity-cbor-conversion"]
identity-json-conversion = ["dpp/identity-json-conversion"]
identity-value-conversion = ["dpp/identity-value-conversion"]
json = ["platform-value/serde_json"]
json-object = ["dpp/json-object"]
json-schema-validation = ["dpp/json-schema-validation"]
message-signing = ["dpp/message-signing"]
mock-versions = ["platform-version/mock-versions"]
objc = ["ferment-sys/objc"]
cbindgen_only = ["ferment-sys/cbindgen_only"]
platform-value = ["dpp/platform-value"]
state-transitions = ["dpp/state-transitions"]
state-transition-json-conversion = ["dpp/state-transition-json-conversion"]
state-transition-validation = ["dpp/state-transition-validation"]
state-transition-signing = ["dpp/state-transition-signing"]
std = ["platform-value/std"]
system_contracts = ["dpp/system_contracts"]
validation = ["dpp/validation"]

[lib]
name = "example_nested"
crate-type = ["staticlib", "cdylib"]
47 changes: 26 additions & 21 deletions ferment-example/nested/build.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
extern crate cbindgen;
extern crate ferment_sys;

use std::process::Command;
use ferment_sys::{Ferment, Lang, ObjC, XCodeConfig};

pub const SELF_NAME: &str = "example_nested";
fn main() {
let c_header = format!("target/{}.h", SELF_NAME);
match Ferment::with_crate_name(SELF_NAME)
.with_default_mod_name()
.with_external_crates(vec!["example-simple"])
.with_languages(vec![
Lang::ObjC(ObjC::new(XCodeConfig { class_prefix: "DS".to_string(), framework_name: "Fermented".to_string() })),
])
.generate() {
Ok(()) => match Command::new("cbindgen")
.args(["--config", "cbindgen.toml", "-o", c_header.as_str()])
.status() {
Ok(status) => println!("[cbindgen] [ok] generated into {c_header} with status: {status}"),
Err(err) => panic!("[cbindgen] [error] {}", err)
}
Err(err) => panic!("[ferment-sys] Can't create FFI fermentate: {}", err)
}
}
const SELF_NAME: &str = "example_nested";
match ferment_sys::Ferment::with_crate_name(SELF_NAME)
.with_default_mod_name()
.with_cbindgen_config_from_file("cbindgen.toml")
.with_external_crates(vec![
"versioned-feature-core",
"example-simple",
"dashcore",
"dpp",
"platform-value",
"platform-version"
])
.with_languages(vec![
#[cfg(feature = "objc")]
ferment_sys::Lang::ObjC(ferment_sys::ObjC::new(ferment_sys::XCodeConfig {
class_prefix: "DS".to_string(),
framework_name: "DSExampleNested".to_string(),
header_name: SELF_NAME.to_string()
}
)),
])
.generate() {
Ok(_) => println!("[ferment] [ok]: {SELF_NAME}"),
Err(err) => panic!("[ferment] [err]: {}", err)
}
}
79 changes: 79 additions & 0 deletions ferment-example/nested/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash
echo "Building Dash Shared Core..."
pwd
compare_version() {
# shellcheck disable=SC2053
if [[ $1 == $2 ]]; then
return 1
fi
local IFS=.
# shellcheck disable=SC2206
local i a=(${1%%[^0-9.]*}) b=(${2%%[^0-9.]*})
local arem=${1#${1%%[^0-9.]*}} brem=${2#${2%%[^0-9.]*}}
for ((i=0; i<${#a[@]} || i<${#b[@]}; i++)); do
if ((10#${a[i]:-0} < 10#${b[i]:-0})); then
return 1
elif ((10#${a[i]:-0} > 10#${b[i]:-0})); then
return 0
fi
done
if [ "$arem" '<' "$brem" ]; then
return 1
elif [ "$arem" '>' "$brem" ]; then
return 0
fi
return 1
}
REQUIRED_VERSION=1.66.0
CURRENT_VERSION=$(rustc -V | awk '{sub(/-.*/,"");print $2}')
FRAMEWORK=DSExampleNested
HEADER=example_nested
echo "rustc -V: current ${CURRENT_VERSION} vs. required ${REQUIRED_VERSION}"
if compare_version "${REQUIRED_VERSION}" "${CURRENT_VERSION}"; then
echo "ERROR: rustc version ${CURRENT_VERSION} not supported, please upgrade to at least ${REQUIRED_VERSION}"
exit 1
fi

cargo install cargo-lipo
for target in "x86_64-apple-darwin" "aarch64-apple-darwin" "x86_64-apple-ios" "aarch64-apple-ios" "aarch64-apple-ios-sim"; do
if ! rustup target list | grep -q "${target} (installed)"; then
rustup target add "$target"
fi
done
rm -rf target/{framework,include,lib}
cargo lipo --release
build_targets=(
"x86_64-apple-ios"
"aarch64-apple-ios"
"aarch64-apple-ios-sim"
"x86_64-apple-darwin"
"aarch64-apple-darwin"

)
for target in "${build_targets[@]}"; do
if [ ! -f "../../target/$target/release/lib${HEADER}.a" ]; then
cargo build --target="$target" --release --no-default-features &
fi
done
wait
mkdir -p target/{framework,include,lib/{ios,ios-simulator,macos}}
lipo -create ../../target/x86_64-apple-darwin/release/lib${HEADER}.a \
../../target/aarch64-apple-darwin/release/lib${HEADER}.a \
-output target/lib/macos/lib${HEADER}_macos.a &
cp -r -p ../../target/aarch64-apple-ios/release/lib${HEADER}.a target/lib/ios/lib${HEADER}_ios.a &
lipo -create ../../target/x86_64-apple-ios/release/lib${HEADER}.a \
../../target/aarch64-apple-ios-sim/release/lib${HEADER}.a \
-output target/lib/ios-simulator/lib${HEADER}_ios.a &
wait
wait

if which clang-format >/dev/null; then
find "target/include" -name 'objc_wrapper.h' -print0 | xargs -0 clang-format -i -style=file
else
echo "warning: clang-format not installed, install it by running $(brew install clang-format)"
fi

xcodebuild -create-xcframework \
-library target/lib/ios/lib${HEADER}_ios.a -headers target/include \
-library target/lib/ios-simulator/lib${HEADER}_ios.a -headers target/include \
-output target/framework/${FRAMEWORK}.xcframework
Loading

0 comments on commit 9410d89

Please sign in to comment.