-
Notifications
You must be signed in to change notification settings - Fork 48
feat: add Metadata language
#264
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
base: master
Are you sure you want to change the base?
feat: add Metadata language
#264
Conversation
requires nightly
|
This PR supersedes #258 |
Metadata language
# Conflicts: # src/vec.rs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds a new Metadata language to safer_ffi that generates JSON metadata files containing detailed type information about FFI declarations. This metadata enhances C header exports with information lost during C translation, specifically for generating Kotlin Multiplatform bindings.
Key Changes:
- Added
Language::Metadataenum variant and correspondingmetadata.rslanguage implementation - Implemented
metadata_type_usage()method across allCTypeimplementations to generate JSON type descriptions - Introduced wrapper types
OptionCLayoutandNonNullCLayoutto preserve semantic information in metadata - Added
ffi_metadataattribute macro for annotating special container types (Vector, DynamicArray)
Reviewed Changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_kotlin.rs | Comprehensive test file demonstrating metadata generation with various FFI types |
| src/headers/languages/metadata.rs | Core implementation of metadata language with JSON output formatting |
| src/layout/impls.rs | Added metadata_type_usage() implementations for primitives, pointers, functions, and arrays; introduced NonNullCLayout wrapper |
| src/layout/niche.rs | Introduced OptionCLayout wrapper to preserve Optional semantics in metadata |
| src/headers/_mod.rs | Integrated Metadata language into header generation pipeline |
| src/layout/_mod.rs | Added metadata_type_usage() to CType trait; fixed typo "trully" → "truly" |
| src/proc_macro/derives/c_type/struct_.rs | Added metadata generation logic for structs with ffi_metadata attribute support |
| src/slice.rs, src/vec.rs | Applied ffi_metadata attributes to slice and vector types |
| src/proc_macro/_mod.rs | Added ffi_metadata procedural macro attribute |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
067709b to
a9fc308
Compare
a9fc308 to
95c9d56
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 25 out of 26 changed files in this pull request and generated 1 comment.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
|
Fixed CI, build issues with |
|
@danielhenrymantilla & @hamchapman Could I get your eyes on this PR? |
|
To be candid, I started to review it but there were so many changes I had questions about (little changes around using transmute rather than cast, etc etc) that I got bogged down. I will try and just focus on the bigger parts later today and get a review in. |
hamchapman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be good to wait for @danielhenrymantilla's review if possible but this LGTM
| call(data, c!("Hello, World!").to_str().as_ptr().cast()); | ||
| call( | ||
| data, | ||
| ::std::mem::transmute(c!("Hello, World!").to_str().as_ptr()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the need for the change here?
| unsafe impl Send for ThreadTiedJsFunction {} | ||
| unsafe impl Sync for ThreadTiedJsFunction {} | ||
|
|
||
| impl Drop for ThreadTiedJsFunction { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did something prompt this to be moved?
| out!(("\"kind\": \"Enum\",")); | ||
|
|
||
| self.emit_docs(ctx, docs, indent)?; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I picked a random line but the whitespacing in this file is kinda weird. Lots of newlines without any discernible consistent pattern for when to have a newline or not, at least to my eyes.
| } | ||
|
|
||
| #[derive(Debug, Clone, Copy)] | ||
| pub struct NonNullCLayout<T: CType> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some documentation around this and OptionCLayout would be a good idea. What guarantees are there, etc
Resolves SDKS-1053
Co-authored by: @phatblat
This PR adds a
Metadata"language" which is a JSON file containing Rust type metadata for external tools. This metadata is used to enhance the types with information lost in the export to a C header.Type Metadata
Metadata attributes included in the JSON file:
nametype namerustName(e.g.Leroy)cName(e.g.WOW_LEROY)kindexamples:boolchari8i32u8u16voidCommentConstantDynamicArrayEnumFunctionNonNullOpaqueOptionalPointerStructisMutablerust mutabilityvalueParametersfunction parameter names and typesreturnTypefunction return typescommentdoc comment stringsExample
[ { "kind": "Enum", "name": "Wow", "cases": [ { "rustName": "Leroy", "cName": "WOW_LEROY" }, { "rustName": "Jenkins", "cName": "WOW_JENKINS" } ], "backingType": { "kind": "u8" } } ,{ "kind": "Struct", "name": "AnUnusedStruct", "fields": [ { "name": "are_you_still_there", "type": { "kind": "Enum", "name": "Wow" } } ] } ,{ "kind": "Constant", "name": "FOO", "type": { "kind": "i32" } }Purpose
This type metadata information is passed to external tools in order to generate safer Kotlin bindings vs using a C header with
cinterop. Specifically, we're generating kotlin types for Ditto's new Kotlin Multiplatform (KMP) SDK (now in preview).Our build process goes through the following steps:
dittoffi.h) from the Ditto Rust code.cinteropuses thedittoffi.hC header to generate Kotlin bindings (dittoffi_native.ktin diagram below).dittoffi.kt)The Kotlin types generated from this metadata add in nullability, change enum names, add doc comments, etc.
The arrows in the above diagram show build order.