summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2021-04-24 14:04:36 +0200
committerMatthias Beyer <mail@beyermatthias.de>2021-04-24 17:18:01 +0200
commitfd62a6064b265678b0da67a53a110fccee6e134c (patch)
treea1259db85ae57dbed51cfccbcad4ba6079d45034
parentfb2bc2e64cda462a8be0acb19863796647d180d6 (diff)
Struct support
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r--src/backend/dialoguer.rs18
-rw-r--r--src/backend/mod.rs4
-rw-r--r--src/lib.rs166
3 files changed, 188 insertions, 0 deletions
diff --git a/src/backend/dialoguer.rs b/src/backend/dialoguer.rs
index ec1f5b8..6b08507 100644
--- a/src/backend/dialoguer.rs
+++ b/src/backend/dialoguer.rs
@@ -1,6 +1,7 @@
use crate::error::Result;
use crate::Backend;
use crate::BuildableValue;
+use crate::BuildableCollection;
use crate::CollectionBuilder;
use crate::ValueBuilder;
@@ -84,6 +85,12 @@ impl Backend for DialoguerBackend {
fn option_builder<T: 'static + BuildableValue>(&self) -> Box<dyn CollectionBuilder<Output = Option<T>>> {
Box::new(DialoguerOptionValueBuilder::<T>(std::marker::PhantomData))
}
+
+ fn struct_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = T>>
+ where T: 'static + BuildableCollection
+ {
+ Box::new(DialoguerStructBuilder::<T>(std::marker::PhantomData))
+ }
}
pub struct DialoguerValueBuilder<T: Sized>(std::marker::PhantomData<T>);
@@ -144,3 +151,14 @@ impl<T> CollectionBuilder for DialoguerVecBuilder<T>
}
}
+
+pub struct DialoguerStructBuilder<T: 'static + BuildableCollection>(std::marker::PhantomData<T>);
+impl<T> CollectionBuilder for DialoguerStructBuilder<T>
+ where T: 'static + BuildableCollection
+{
+ type Output = T;
+
+ fn build_collection(&self, value_desc: &str) -> Result<Self::Output> {
+ T::builder(DialoguerBackend).build_collection(value_desc)
+ }
+}
diff --git a/src/backend/mod.rs b/src/backend/mod.rs
index 5884726..bd5bc58 100644
--- a/src/backend/mod.rs
+++ b/src/backend/mod.rs
@@ -1,6 +1,7 @@
pub mod dialoguer;
use crate::BuildableValue;
+use crate::BuildableCollection;
use crate::CollectionBuilder;
use crate::ValueBuilder;
@@ -28,6 +29,9 @@ pub trait Backend {
fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>>>
where T: 'static + BuildableValue;
+
+ fn struct_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = T>>
+ where T: 'static + BuildableCollection;
}
diff --git a/src/lib.rs b/src/lib.rs
index 9a89f37..c649ed8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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]);
+ }
+}