lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit cf9574b9e4e1d7338d1abcbc2f4f156494cfa551
parent 79fb1215883bea615a6b934f7f57508648927fb6
Author: triesap <tyson@radroots.org>
Date:   Thu,  6 Aug 2026 19:10:09 +0000

sdk: validate requested ffi artifact language

- scope FFI freshness checks to the requested artifact route
- preserve Kotlin schema inventory validation on Kotlin routes
- prove one language can refresh without stale sibling output
- retain complete native binding equivalence coverage

Diffstat:
Mtools/xtask/src/sdk_generation/bindings.rs | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mtools/xtask/src/sdk_generation/mod.rs | 2+-
2 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/tools/xtask/src/sdk_generation/bindings.rs b/tools/xtask/src/sdk_generation/bindings.rs @@ -169,24 +169,33 @@ fn normalize_generated_text(contents: &str) -> String { normalized } -pub fn check(source_root: &Path, consumer_root: &Path) -> Result<(), String> { - check_language( - source_root, - consumer_root, - "swift", - &[ - "radroots_sdk.swift", - "radroots_sdkFFI.h", - "radroots_sdkFFI.modulemap", - ], - )?; - check_language( - source_root, - consumer_root, - "kotlin", - &["uniffi/radroots_sdk/radroots_sdk.kt"], - )?; - check_kotlin_schema_inventory(consumer_root) +pub fn check_generated_language( + source_root: &Path, + consumer_root: &Path, + language: &str, +) -> Result<(), String> { + match language { + "swift" => check_language( + source_root, + consumer_root, + "swift", + &[ + "radroots_sdk.swift", + "radroots_sdkFFI.h", + "radroots_sdkFFI.modulemap", + ], + ), + "kotlin" => { + check_language( + source_root, + consumer_root, + "kotlin", + &["uniffi/radroots_sdk/radroots_sdk.kt"], + )?; + check_kotlin_schema_inventory(consumer_root) + } + _ => Err("SDK binding language must be swift or kotlin".to_owned()), + } } fn check_kotlin_schema_inventory(root: &Path) -> Result<(), String> { @@ -325,7 +334,47 @@ mod tests { use crate::build_control::Mode; - use super::{check, generate}; + use super::{ + BINDGEN_VERSION, FFI_PACKAGE, FFI_VERSION, SourceLock, check_generated_language, + ffi_source_sha256, generate, + }; + + #[test] + fn language_check_does_not_require_the_other_binding_tree() { + let consumer = tempfile::TempDir::new().expect("consumer fixture"); + let source = crate::workspace_root(); + let output_dir = consumer.path().join("generated/swift"); + fs::create_dir_all(&output_dir).expect("Swift output directory"); + let outputs = BTreeMap::from([ + ("radroots_sdk.swift".to_owned(), "swift\n"), + ("radroots_sdkFFI.h".to_owned(), "header\n"), + ("radroots_sdkFFI.modulemap".to_owned(), "module\n"), + ]); + for (name, contents) in &outputs { + fs::write(output_dir.join(name), contents).expect("Swift fixture output"); + } + let lock = SourceLock { + schema_version: 1, + source_package: FFI_PACKAGE.to_owned(), + source_version: FFI_VERSION.to_owned(), + source_sha256: ffi_source_sha256(&source).expect("FFI source digest"), + generator: "uniffi".to_owned(), + generator_version: BINDGEN_VERSION.to_owned(), + language: "swift".to_owned(), + outputs: outputs + .into_iter() + .map(|(name, contents)| { + (name, format!("{:x}", Sha256::digest(contents.as_bytes()))) + }) + .collect(), + }; + let mut rendered = serde_json::to_string_pretty(&lock).expect("source lock"); + rendered.push('\n'); + fs::write(output_dir.join("source.lock"), rendered).expect("source lock fixture"); + + check_generated_language(&source, consumer.path(), "swift").expect("Swift-only validation"); + assert!(check_generated_language(&source, consumer.path(), "kotlin").is_err()); + } #[test] #[ignore = "requires the native UniFFI bindgen toolchain"] @@ -334,7 +383,9 @@ mod tests { let source = crate::workspace_root(); generate(&source, consumer.path(), "swift", Mode::Write).expect("Swift generation"); generate(&source, consumer.path(), "kotlin", Mode::Write).expect("Kotlin generation"); - check(&source, consumer.path()).expect("fresh generated bindings"); + check_generated_language(&source, consumer.path(), "swift").expect("fresh Swift bindings"); + check_generated_language(&source, consumer.path(), "kotlin") + .expect("fresh Kotlin bindings"); let expected = BTreeMap::from([ ( diff --git a/tools/xtask/src/sdk_generation/mod.rs b/tools/xtask/src/sdk_generation/mod.rs @@ -32,7 +32,7 @@ pub fn artifact( } ("ffi", "swift" | "kotlin") => { bindings::generate(source_root, consumer_root, language, mode)?; - bindings::check(source_root, consumer_root)?; + bindings::check_generated_language(source_root, consumer_root, language)?; } _ => { return Err(format!(