lib

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

commit 9364af59dc39a4b25021c0d9fb33da30499ef832
parent e3859f4d4b41f1aa3d396f1f378060f704719573
Author: triesap <tyson@radroots.org>
Date:   Wed, 24 Jun 2026 08:30:26 +0000

trade: inventory dto source roots

Diffstat:
MCargo.lock | 2++
Mcrates/trade/Cargo.toml | 10++++++++++
Acrates/trade/src/dto.rs | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/trade/src/lib.rs | 2++
Mcrates/trade/src/listing/model.rs | 2++
Mcrates/trade/src/listing/validation.rs | 1+
6 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -4820,6 +4820,8 @@ name = "radroots_trade" version = "0.1.0-alpha.2" dependencies = [ "base64 0.22.1", + "dto_bindgen", + "dto_bindgen_core", "hex", "radroots_authority", "radroots_core", diff --git a/crates/trade/Cargo.toml b/crates/trade/Cargo.toml @@ -14,6 +14,14 @@ readme = "README" [features] default = ["std", "serde", "serde_json"] +dto-bindgen = [ + "std", + "serde_json", + "dep:dto_bindgen", + "dep:dto_bindgen_core", + "radroots_core/dto-bindgen", + "radroots_events/dto-bindgen", +] std = [ "radroots_authority/std", "radroots_core/std", @@ -49,6 +57,8 @@ radroots_events = { workspace = true, default-features = false } radroots_events_codec = { workspace = true, default-features = false } radroots_event_store = { workspace = true, optional = true, default-features = false } base64 = { workspace = true, optional = true } +dto_bindgen = { workspace = true, optional = true } +dto_bindgen_core = { workspace = true, optional = true } hex = { workspace = true, optional = true } serde = { workspace = true, default-features = false, features = [ "alloc", diff --git a/crates/trade/src/dto.rs b/crates/trade/src/dto.rs @@ -0,0 +1,110 @@ +use dto_bindgen_core::RootDescriptor; + +use crate::listing::{ + model::{RadrootsTradeListingSubtotal, RadrootsTradeListingTotal}, + validation::RadrootsTradeListing, +}; + +pub fn dto_roots() -> [RootDescriptor; 3] { + [ + RootDescriptor::new::<RadrootsTradeListing>(), + RootDescriptor::new::<RadrootsTradeListingSubtotal>(), + RootDescriptor::new::<RadrootsTradeListingTotal>(), + ] +} + +#[cfg(test)] +mod tests { + use dto_bindgen_core::{Registry, TypeDef, build_registry}; + + use super::dto_roots; + + const TRADE_SOURCE_ROOTS: &[&str] = &[ + "RadrootsTradeListing", + "RadrootsTradeListingSubtotal", + "RadrootsTradeListingTotal", + ]; + const TRADE_IMPORTED_SOURCE_DEPENDENCIES: &[&str] = &[ + "RadrootsCoreDecimal", + "RadrootsCoreDiscount", + "RadrootsCoreDiscountScope", + "RadrootsCoreDiscountThreshold", + "RadrootsCoreDiscountValue", + "RadrootsCoreMoney", + "RadrootsCorePercent", + "RadrootsCoreQuantity", + "RadrootsCoreQuantityPrice", + "RadrootsCoreUnit", + "RadrootsFarmRef", + "RadrootsListing", + "RadrootsListingAvailability", + "RadrootsListingBin", + "RadrootsListingDeliveryMethod", + "RadrootsListingImage", + "RadrootsListingImageSize", + "RadrootsListingLocation", + "RadrootsListingProduct", + "RadrootsListingStatus", + "RadrootsPlotRef", + "RadrootsResourceAreaRef", + ]; + + #[test] + fn trade_descriptor_roots_build_registry() { + let registry = build_registry(dto_roots()); + + assert!( + !registry.has_errors(), + "trade registry has diagnostics: {:?}", + registry.diagnostics + ); + assert_eq!(registry.roots.len(), dto_roots().len()); + } + + #[test] + fn trade_source_roots_are_deterministic() { + let registry = build_registry(dto_roots()); + + assert_eq!(root_export_names(&registry), TRADE_SOURCE_ROOTS); + } + + #[test] + fn trade_source_dependencies_are_explicit() { + let registry = build_registry(dto_roots()); + let mut dependencies = type_export_names(&registry) + .into_iter() + .filter(|name| !TRADE_SOURCE_ROOTS.contains(name)) + .collect::<Vec<_>>(); + dependencies.sort(); + + assert_eq!(dependencies, TRADE_IMPORTED_SOURCE_DEPENDENCIES); + } + + fn root_export_names(registry: &Registry) -> Vec<&str> { + registry + .roots + .iter() + .map(|type_id| { + registry + .type_def(*type_id) + .map(type_export_name) + .expect("root type") + }) + .collect() + } + + fn type_export_names(registry: &Registry) -> Vec<&str> { + registry + .types_by_id + .values() + .map(type_export_name) + .collect::<Vec<_>>() + } + + fn type_export_name(def: &TypeDef) -> &str { + match def { + TypeDef::Struct(def) => def.export_name.as_str(), + TypeDef::Enum(def) => def.export_name.as_str(), + } + } +} diff --git a/crates/trade/src/lib.rs b/crates/trade/src/lib.rs @@ -3,6 +3,8 @@ #[cfg(not(feature = "std"))] extern crate alloc; +#[cfg(feature = "dto-bindgen")] +pub mod dto; pub mod listing; pub mod order; pub mod prelude; diff --git a/crates/trade/src/listing/model.rs b/crates/trade/src/listing/model.rs @@ -1,3 +1,4 @@ +#[cfg_attr(feature = "dto-bindgen", derive(dto_bindgen::Dto))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq, Eq)] pub struct RadrootsTradeListingSubtotal { @@ -7,6 +8,7 @@ pub struct RadrootsTradeListingSubtotal { pub quantity_unit: radroots_core::RadrootsCoreUnit, } +#[cfg_attr(feature = "dto-bindgen", derive(dto_bindgen::Dto))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq, Eq)] pub struct RadrootsTradeListingTotal { diff --git a/crates/trade/src/listing/validation.rs b/crates/trade/src/listing/validation.rs @@ -20,6 +20,7 @@ use radroots_events::{ use crate::listing::codec::listing_from_event_parts; +#[cfg_attr(feature = "dto-bindgen", derive(dto_bindgen::Dto))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug)] pub struct RadrootsTradeListing {