typeshare
repository·main·Indexed 25 days ago
https://github.com/1password/typeshareA tool that converts Rust types into equivalent forms in Swift, Go, Python, Kotlin, Scala, and TypeScript to facilitate safe FFI communication. It uses the #[typeshare] attribute to mark types for generation and leverages serde for serialization and deserialization to keep cross-language codebases in sync.
What's inside typeshare
- Typeshare is a tool designed to generate type definitions in various programming languages based on type definitions defined in Rust. It is primarily used for Foreign Function Interface (FFI) scenarios where types are passed as fully serialized blobs and subsequently decoded in the target language.
Use typeshare-lib for interacting with generated types
mainThetypeshare-libpackage provides library-level helper functions designed to facilitate interaction with types that have been generated by the Typeshare toolchain.Add and update snapshot tests in typeshare-core
mainTypeshare uses snapshot testing. To declare a new test, use the macro defined in
tests/snapshot_tests.rs.To initialize a new test and generate the necessary directory structure and starter files in
data/tests, run:env UPDATE_EXPECT=1 cargo test -p typeshare-coreAfter running this, place your Rust source input into the
input.rsfile within the newly created test folder. To update the expected output files with Typeshare's current generation results, run the same command again:env UPDATE_EXPECT=1 cargo test -p typeshare-coreIf you need to update expectations for a specific test only, use the following command (replacing the last argument with your test name):
env UPDATE_EXPECT=1 cargo test -p typeshare-core --test snapshot_tests -- <test_name>Generate FFI definitions using the Typeshare CLI
mainUse the
typeshareCLI tool to generate type definitions for specific target languages based on annotated Rust code.To generate definitions, you must provide:
- The directory containing your Rust code (the CLI will recursively search this directory tree for annotated types).
- The
--langoption to specify the target language. - The
--output-fileoption to specify the destination file for the generated definitions.
Supported languages include:
- Kotlin
- Typescript
- Swift
- Scala
- Go
typeshare ./my_rust_project --lang=kotlin --output-file=my_kotlin_definitions.kt typeshare ./my_rust_project --lang=swift --output-file=my_swift_definitions.swift typeshare ./my_rust_project --lang=typescript --output-file=my_typescript_definitions.ts typeshare ./my_rust_project --lang=scala --output-file=my_scala_definitions.scalaUse `target_os` conditional compilation in Rust
mainYou can use standard Rust
#[cfg]attributes to control which types are included in the generated output. Typeshare evaluates these attributes against the values provided in the--target-osCLI flag.Supported Patterns
- Simple standalone:
#[cfg(target_os = "android")]will only be generated ifandroidis in the--target-oslist. - Simple not rule:
#[cfg(not(target_os = "android"))]will only be generated ifandroidis not in the--target-oslist. - Multiple not any rule:
#[cfg(not(any(target_os = "android", target_os = "ios")))]will only be generated if neitherandroidnoriosare in the--target-oslist.
Note: Typeshare only considers
target_osattributes. It does not evaluate othercfgattributes likefeature. If acfgattribute combinestarget_oswith another attribute (e.g.,#[cfg(any(target_os = "android", feature = "android-test"))]), the type will be generated if thetarget_oscondition is met, regardless of the other attribute's state.- Simple standalone:
Run tests for typeshare-core
mainYou can run the standard test suite for the
typeshare-corepackage using cargo. This runs tests without updating any snapshot expectations.cargo test -p typeshare-coreAnnotate Rust types with #[typeshare]
mainTo include a struct or enum in the code generation process, annotate it with the
#[typeshare]attribute. Typeshare leveragesserdefor serialization and deserialization logic, so you can use standardserdeattributes (like#[serde(tag = ...)]) to control how enums are represented in the target language.// Rust type definitions #[typeshare] struct MyStruct { my_name: String, my_age: u32, } #[typeshare] #[serde(tag = "type", content = "content")] enum MyEnum { MyVariant(bool), MyOtherVariant, MyNumber(u32), }Install Typeshare CLI and dependency
mainTo use Typeshare, you must install the CLI tool via cargo and add the
typesharecrate to your Rust project's dependencies.Note that while the package name is
typeshare-cli, the command used in the terminal istypeshare.Ensure well-formatted output in Typeshare
mainTypeshare generates "best-effort" code output and then runs it through language-specific formatting tools to ensure the generated code meets language standards. To receive beautifully formatted output, you must have the appropriate formatting tools for each target language installed and available in your environment when running Typeshare. If these tools are missing, Typeshare will fall back to its default, less-formatted output.Install the typeshare CLI
mainInstall the
typeshareCLI tool usingcargo installto enable code generation from Rust type definitions.cargo install typeshareGenerate code from Rust files with typeshare
mainUse the
typesharecommand to generate code in various target languages from a specific Rust file. Use the--langflag to specify the target language. Some languages likekotlinandscalaalso support a package name flag.typeshare --lang=typescript some/file.rs typeshare --lang=swift some/file.rs typeshare --lang=kotlin --java-package=com.some.package.name some/file.rs typeshare --lang=scala --scala-package=com.some.package.name some/file.rsAdd the typeshare dependency to Cargo.toml
mainTo use the
#[typeshare]annotation on your Rust types, you must addtypeshareas a dependency in your project'sCargo.tomlfile.[dependencies] typeshare = "1.0.0" # Use whichever version is the most recent