diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 166 |
1 files changed, 166 insertions, 0 deletions
@@ -81,6 +81,10 @@ mod dummy_bool_test { { unimplemented!() } + + fn struct_builder<T: Sized>(&self) -> Box<dyn CollectionBuilder<Output = T>> { + unimplemented!() + } } struct BoolValBuilder; @@ -165,6 +169,9 @@ mod vec_test { { Box::new(VecBuilder::<T>(std::marker::PhantomData)) } + fn struct_builder<T: Sized>(&self) -> Box<dyn CollectionBuilder<Output = T>> { + unimplemented!() + } } struct BoolValBuilder; @@ -202,3 +209,162 @@ mod vec_test { assert_eq!(v, vec![true, true, true]); } } + + +#[cfg(test)] +mod struct_test { + use super::*; + + struct DummyBackend; + impl Backend for DummyBackend { + fn bool_builder(&self) -> Box<dyn ValueBuilder<Output = bool>> { + Box::new(BoolValBuilder) + } + fn u8_builder(&self) -> Box<dyn ValueBuilder<Output = u8>> { + Box::new(U8ValueBuilder) + } + fn u16_builder(&self) -> Box<dyn ValueBuilder<Output = u16>> { + unimplemented!() + } + fn u32_builder(&self) -> Box<dyn ValueBuilder<Output = u32>> { + unimplemented!() + } + fn u64_builder(&self) -> Box<dyn ValueBuilder<Output = u64>> { + unimplemented!() + } + fn u128_builder(&self) -> Box<dyn ValueBuilder<Output = u128>> { + unimplemented!() + } + fn i8_builder(&self) -> Box<dyn ValueBuilder<Output = i8>> { + unimplemented!() + } + fn i16_builder(&self) -> Box<dyn ValueBuilder<Output = i16>> { + unimplemented!() + } + fn i32_builder(&self) -> Box<dyn ValueBuilder<Output = i32>> { + unimplemented!() + } + fn i64_builder(&self) -> Box<dyn ValueBuilder<Output = i64>> { + unimplemented!() + } + fn i128_builder(&self) -> Box<dyn ValueBuilder<Output = i128>> { + unimplemented!() + } + fn usize_builder(&self) -> Box<dyn ValueBuilder<Output = usize>> { + unimplemented!() + } + fn isize_builder(&self) -> Box<dyn ValueBuilder<Output = isize>> { + unimplemented!() + } + fn f32_builder(&self) -> Box<dyn ValueBuilder<Output = f32>> { + unimplemented!() + } + fn f64_builder(&self) -> Box<dyn ValueBuilder<Output = f64>> { + unimplemented!() + } + fn char_builder(&self) -> Box<dyn ValueBuilder<Output = char>> { + unimplemented!() + } + fn string_builder(&self) -> Box<dyn ValueBuilder<Output = String>> { + unimplemented!() + } + fn option_builder<T: 'static + BuildableValue>(&self) -> Box<dyn CollectionBuilder<Output = Option<T>>> { + unimplemented!() + } + fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>>> + where T: 'static + BuildableValue + { + Box::new(VecBuilder::<T>(std::marker::PhantomData)) + } + + fn struct_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = T>> + where T: 'static + BuildableCollection + { + Box::new(StructBuilder::<T>(std::marker::PhantomData)) + } + } + + struct BoolValBuilder; + impl ValueBuilder for BoolValBuilder { + type Output = bool; + + fn build_value(&self, _question: &str) -> Result<Self::Output> { + Ok(true) + } + } + + struct U8ValueBuilder; + impl ValueBuilder for U8ValueBuilder { + type Output = u8; + + fn build_value(&self, _question: &str) -> Result<Self::Output> { + Ok(42) + } + } + + pub struct VecBuilder<T: 'static + BuildableValue>(std::marker::PhantomData<T>); + impl<T: BuildableValue> CollectionBuilder for VecBuilder<T> { + type Output = Vec<T>; + + fn build_collection(&self, value_desc: &str) -> Result<Self::Output> { + let mut buf = vec![]; + + loop { + let v: T = T::builder(DummyBackend).build_value(value_desc)?; + buf.push(v); + + if buf.len() == 3 { + break + } + } + + Ok(buf) + } + } + + pub struct StructBuilder<T: BuildableCollection>(std::marker::PhantomData<T>); + impl<T: BuildableCollection> CollectionBuilder for StructBuilder<T> { + type Output = T; + + fn build_collection(&self, value_desc: &str) -> Result<Self::Output> { + T::builder(DummyBackend).build_collection(value_desc) + } + } + + pub struct Configuration { + verbose: bool, + values: Vec<u8>, + } + + impl BuildableCollection for Configuration { + fn builder<B>(_backend: B) -> Box<dyn CollectionBuilder<Output = Self>> + where B: Backend + { + Box::new(ConfigStructBuilder) + } + } + + pub struct ConfigStructBuilder; + impl CollectionBuilder for ConfigStructBuilder { + type Output = Configuration; + + fn build_collection(&self, value_desc: &str) -> Result<Self::Output> { + println!("Building {}", value_desc); + + let verbose = bool::builder(DummyBackend).build_value(value_desc)?; + let values = Vec::<u8>::builder(DummyBackend).build_collection(value_desc)?; + + Ok(Configuration { + verbose, + values, + }) + } + } + + #[test] + fn test_struct() { + let c = Configuration::builder(DummyBackend).build_collection("config").unwrap(); + assert!(c.verbose); + assert_eq!(c.values, [42, 42, 42]); + } +} |