pub mod backend; pub use crate::backend::*; pub mod buildable; pub use crate::buildable::*; pub mod collection_builder; pub use crate::collection_builder::*; pub mod error; pub use crate::error::*; pub mod value_builder; pub use crate::value_builder::*; #[cfg(test)] mod dummy_bool_test { use super::*; struct DummyBackend; impl Backend for DummyBackend { fn bool_builder(&self) -> Box> { Box::new(BoolValBuilder) } fn u8_builder(&self) -> Box> { unimplemented!() } fn u16_builder(&self) -> Box> { unimplemented!() } fn u32_builder(&self) -> Box> { unimplemented!() } fn u64_builder(&self) -> Box> { unimplemented!() } fn u128_builder(&self) -> Box> { unimplemented!() } fn i8_builder(&self) -> Box> { unimplemented!() } fn i16_builder(&self) -> Box> { unimplemented!() } fn i32_builder(&self) -> Box> { unimplemented!() } fn i64_builder(&self) -> Box> { unimplemented!() } fn i128_builder(&self) -> Box> { unimplemented!() } fn usize_builder(&self) -> Box> { unimplemented!() } fn isize_builder(&self) -> Box> { unimplemented!() } fn f32_builder(&self) -> Box> { unimplemented!() } fn f64_builder(&self) -> Box> { unimplemented!() } fn char_builder(&self) -> Box> { unimplemented!() } fn string_builder(&self) -> Box> { unimplemented!() } fn option_builder(&self) -> Box>> { unimplemented!() } fn vec_builder(&self) -> Box>> where T: 'static + BuildableValue { unimplemented!() } fn struct_builder(&self) -> Box> { unimplemented!() } } struct BoolValBuilder; impl ValueBuilder for BoolValBuilder { type Output = bool; fn build_value(&self, _question: &str) -> Result { Ok(true) } } #[test] fn test_build_value() { let v = bool::builder(DummyBackend).build_value("Are you sure?").unwrap(); assert!(v); } } #[cfg(test)] mod vec_test { use super::*; struct DummyBackend; impl Backend for DummyBackend { fn bool_builder(&self) -> Box> { Box::new(BoolValBuilder) } fn u8_builder(&self) -> Box> { unimplemented!() } fn u16_builder(&self) -> Box> { unimplemented!() } fn u32_builder(&self) -> Box> { unimplemented!() } fn u64_builder(&self) -> Box> { unimplemented!() } fn u128_builder(&self) -> Box> { unimplemented!() } fn i8_builder(&self) -> Box> { unimplemented!() } fn i16_builder(&self) -> Box> { unimplemented!() } fn i32_builder(&self) -> Box> { unimplemented!() } fn i64_builder(&self) -> Box> { unimplemented!() } fn i128_builder(&self) -> Box> { unimplemented!() } fn usize_builder(&self) -> Box> { unimplemented!() } fn isize_builder(&self) -> Box> { unimplemented!() } fn f32_builder(&self) -> Box> { unimplemented!() } fn f64_builder(&self) -> Box> { unimplemented!() } fn char_builder(&self) -> Box> { unimplemented!() } fn string_builder(&self) -> Box> { unimplemented!() } fn option_builder(&self) -> Box>> { unimplemented!() } fn vec_builder(&self) -> Box>> where T: 'static + BuildableValue { Box::new(VecBuilder::(std::marker::PhantomData)) } fn struct_builder(&self) -> Box> { unimplemented!() } } struct BoolValBuilder; impl ValueBuilder for BoolValBuilder { type Output = bool; fn build_value(&self, _question: &str) -> Result { Ok(true) } } pub struct VecBuilder(std::marker::PhantomData); impl CollectionBuilder for VecBuilder { type Output = Vec; fn build_collection(&self, value_desc: &str) -> Result { 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) } } #[test] fn test_build_vec() { let v = Vec::::builder(DummyBackend).build_collection("flag").unwrap(); 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> { Box::new(BoolValBuilder) } fn u8_builder(&self) -> Box> { Box::new(U8ValueBuilder) } fn u16_builder(&self) -> Box> { unimplemented!() } fn u32_builder(&self) -> Box> { unimplemented!() } fn u64_builder(&self) -> Box> { unimplemented!() } fn u128_builder(&self) -> Box> { unimplemented!() } fn i8_builder(&self) -> Box> { unimplemented!() } fn i16_builder(&self) -> Box> { unimplemented!() } fn i32_builder(&self) -> Box> { unimplemented!() } fn i64_builder(&self) -> Box> { unimplemented!() } fn i128_builder(&self) -> Box> { unimplemented!() } fn usize_builder(&self) -> Box> { unimplemented!() } fn isize_builder(&self) -> Box> { unimplemented!() } fn f32_builder(&self) -> Box> { unimplemented!() } fn f64_builder(&self) -> Box> { unimplemented!() } fn char_builder(&self) -> Box> { unimplemented!() } fn string_builder(&self) -> Box> { unimplemented!() } fn option_builder(&self) -> Box>> { unimplemented!() } fn vec_builder(&self) -> Box>> where T: 'static + BuildableValue { Box::new(VecBuilder::(std::marker::PhantomData)) } fn struct_builder(&self) -> Box> where T: 'static + BuildableCollection { Box::new(StructBuilder::(std::marker::PhantomData)) } } struct BoolValBuilder; impl ValueBuilder for BoolValBuilder { type Output = bool; fn build_value(&self, _question: &str) -> Result { Ok(true) } } struct U8ValueBuilder; impl ValueBuilder for U8ValueBuilder { type Output = u8; fn build_value(&self, _question: &str) -> Result { Ok(42) } } pub struct VecBuilder(std::marker::PhantomData); impl CollectionBuilder for VecBuilder { type Output = Vec; fn build_collection(&self, value_desc: &str) -> Result { 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(std::marker::PhantomData); impl CollectionBuilder for StructBuilder { type Output = T; fn build_collection(&self, value_desc: &str) -> Result { T::builder(DummyBackend).build_collection(value_desc) } } pub struct Configuration { verbose: bool, values: Vec, } impl BuildableCollection for Configuration { fn builder(_backend: B) -> Box> where B: Backend { Box::new(ConfigStructBuilder) } } pub struct ConfigStructBuilder; impl CollectionBuilder for ConfigStructBuilder { type Output = Configuration; fn build_collection(&self, value_desc: &str) -> Result { println!("Building {}", value_desc); let verbose = bool::builder(DummyBackend).build_value(value_desc)?; let values = Vec::::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]); } }