lib

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

commit 1d393dc92f495943e15b2c3cdd70f0d1b1e1dc86
parent a8ba1104fc03467f457c8a4d6166c8dd222f9851
Author: triesap <tyson@radroots.org>
Date:   Sat, 21 Feb 2026 15:47:45 +0000

contract: enforce `radroots-core` unit dimension variant order



- add source contract guard for radrootscoreunitdimension variant declaration order
- require count mass volume sequence in crates/core/src/unit.rs during sdk validation
- integrate ordering guard into xtask contract validation path used by ci
- add parser-focused xtask tests for expected and mismatched enum ordering

Diffstat:
Mcrates/xtask/src/contract.rs | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 119 insertions(+), 0 deletions(-)

diff --git a/crates/xtask/src/contract.rs b/crates/xtask/src/contract.rs @@ -98,6 +98,88 @@ fn contract_root(workspace_root: &Path) -> PathBuf { workspace_root.join("contract") } +const CORE_UNIT_DIMENSION_ENUM: &str = "RadrootsCoreUnitDimension"; +const CORE_UNIT_DIMENSION_ORDER: [&str; 3] = ["Count", "Mass", "Volume"]; + +fn extract_enum_body<'a>(source: &'a str, enum_name: &str) -> Result<&'a str, String> { + let marker = format!("pub enum {enum_name}"); + let enum_start = source + .find(&marker) + .ok_or_else(|| format!("missing enum {enum_name}"))?; + let after_start = &source[enum_start..]; + let open_rel = after_start + .find('{') + .ok_or_else(|| format!("missing opening brace for enum {enum_name}"))?; + let open_idx = enum_start + open_rel; + let mut depth = 0usize; + for (offset, ch) in source[open_idx..].char_indices() { + if ch == '{' { + depth += 1; + continue; + } + if ch != '}' { + continue; + } + depth = depth.saturating_sub(1); + if depth == 0 { + let close_idx = open_idx + offset; + return Ok(&source[(open_idx + 1)..close_idx]); + } + } + Err(format!("missing closing brace for enum {enum_name}")) +} + +fn parse_enum_variants(enum_body: &str) -> Vec<String> { + enum_body + .lines() + .filter_map(|line| { + let trimmed = line.trim(); + if trimmed.is_empty() || trimmed.starts_with('#') || trimmed.starts_with("//") { + return None; + } + let before_comma = trimmed.split_once(',').map_or(trimmed, |(head, _)| head).trim(); + if before_comma.is_empty() { + return None; + } + let before_discriminant = before_comma + .split_once('=') + .map_or(before_comma, |(head, _)| head) + .trim(); + if before_discriminant.is_empty() { + return None; + } + let ident = before_discriminant + .split_whitespace() + .next() + .unwrap_or_default(); + if ident.is_empty() { + return None; + } + Some(ident.to_string()) + }) + .collect() +} + +fn validate_core_unit_dimension_variant_order(workspace_root: &Path) -> Result<(), String> { + let source_path = workspace_root.join("crates").join("core").join("src").join("unit.rs"); + let source = + fs::read_to_string(&source_path).map_err(|e| format!("read {}: {e}", source_path.display()))?; + let enum_body = extract_enum_body(&source, CORE_UNIT_DIMENSION_ENUM)?; + let variants = parse_enum_variants(enum_body); + let expected = CORE_UNIT_DIMENSION_ORDER + .iter() + .map(|item| (*item).to_string()) + .collect::<Vec<_>>(); + if variants != expected { + return Err(format!( + "core unit dimension variant order must be {} but was {}", + CORE_UNIT_DIMENSION_ORDER.join(", "), + variants.join(", ") + )); + } + Ok(()) +} + pub fn load_contract_bundle(workspace_root: &Path) -> Result<ContractBundle, String> { let root = contract_root(workspace_root); let manifest = parse_toml::<ContractManifest>(&root.join("manifest.toml"))?; @@ -215,6 +297,11 @@ pub fn validate_contract_bundle(bundle: &ContractBundle) -> Result<(), String> { { return Err("contract policy flags must all be true".to_string()); } + let workspace_root = bundle + .root + .parent() + .ok_or_else(|| "failed to resolve workspace root from contract root".to_string())?; + validate_core_unit_dimension_variant_order(workspace_root)?; Ok(()) } @@ -296,4 +383,36 @@ mod tests { assert_eq!(mapped, expected); } } + + #[test] + fn parses_enum_variants_in_declared_order() { + let source = r#" +pub enum RadrootsCoreUnitDimension { + Count, + Mass, + Volume, +} +"#; + let enum_body = extract_enum_body(source, "RadrootsCoreUnitDimension").expect("enum body"); + let variants = parse_enum_variants(enum_body); + assert_eq!(variants, vec!["Count", "Mass", "Volume"]); + } + + #[test] + fn fails_when_enum_order_does_not_match_contract() { + let source = r#" +pub enum RadrootsCoreUnitDimension { + Mass, + Count, + Volume, +} +"#; + let enum_body = extract_enum_body(source, "RadrootsCoreUnitDimension").expect("enum body"); + let variants = parse_enum_variants(enum_body); + let expected = CORE_UNIT_DIMENSION_ORDER + .iter() + .map(|item| (*item).to_string()) + .collect::<Vec<_>>(); + assert_ne!(variants, expected); + } }