summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2021-04-24 13:30:22 +0200
committerMatthias Beyer <mail@beyermatthias.de>2021-04-24 13:30:22 +0200
commit2987c24a46f3895afd85edd5f3c262776e7fa47e (patch)
treed368de1354d41579372fd12fdc87ca22f2cb54c5
parenta834f3c5eb10de3dbc1fb51d017cbee4483830ff (diff)
parent053a8eb004a2d44505233bf37d7e8e85a0a2f1ce (diff)
Merge branch 'vec-example'
-rw-r--r--examples/vec.rs10
-rw-r--r--src/backend/dialoguer.rs31
-rw-r--r--src/backend/mod.rs6
-rw-r--r--src/buildable.rs21
-rw-r--r--src/collection_builder.rs2
-rw-r--r--src/lib.rs158
6 files changed, 227 insertions, 1 deletions
diff --git a/examples/vec.rs b/examples/vec.rs
new file mode 100644
index 0000000..6aa10c4
--- /dev/null
+++ b/examples/vec.rs
@@ -0,0 +1,10 @@
+use interactive_object_builder::*;
+use interactive_object_builder::backend::dialoguer::DialoguerBackend;
+
+fn main() -> Result<(), ()> {
+ let v = Vec::<bool>::builder(DialoguerBackend).build_collection("yes/no flag")
+ .map_err(|_| ())?;
+
+ println!("{:?}", v);
+ Ok(())
+}
diff --git a/src/backend/dialoguer.rs b/src/backend/dialoguer.rs
index 6689250..11d5349 100644
--- a/src/backend/dialoguer.rs
+++ b/src/backend/dialoguer.rs
@@ -1,5 +1,7 @@
use crate::Backend;
use crate::ValueBuilder;
+use crate::BuildableValue;
+use crate::CollectionBuilder;
pub struct DialoguerBackend;
@@ -80,6 +82,12 @@ impl Backend for DialoguerBackend {
Box::new(DialoguerValueBuilder::<String>(std::marker::PhantomData))
}
+ fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>, Error = Self::Error>>
+ where T: 'static + BuildableValue
+ {
+ Box::new(DialoguerVecBuilder::<T>(std::marker::PhantomData))
+ }
+
}
pub struct DialoguerValueBuilder<T: Sized>(std::marker::PhantomData<T>);
@@ -99,3 +107,26 @@ impl<T> ValueBuilder for DialoguerValueBuilder<T>
}
+pub struct DialoguerVecBuilder<T: 'static + BuildableValue>(std::marker::PhantomData<T>);
+impl<T> CollectionBuilder for DialoguerVecBuilder<T>
+ where T: 'static + BuildableValue
+{
+ type Output = Vec<T>;
+ type Error = DialoguerBackendError;
+
+ fn build_collection(&self, value_desc: &str) -> Result<Self::Output, Self::Error> {
+ let mut buf = vec![];
+
+ loop {
+ let v: T = T::builder(DialoguerBackend).build_value(value_desc)?;
+ buf.push(v);
+
+ if !dialoguer::Input::<bool>::new().with_prompt("Another one?").interact_text()? {
+ break
+ }
+ }
+
+ Ok(buf)
+ }
+}
+
diff --git a/src/backend/mod.rs b/src/backend/mod.rs
index dfd77c8..1353a6d 100644
--- a/src/backend/mod.rs
+++ b/src/backend/mod.rs
@@ -1,6 +1,8 @@
pub mod dialoguer;
use crate::ValueBuilder;
+use crate::BuildableValue;
+use crate::CollectionBuilder;
/// A backend can be used to get builders for specific types
pub trait Backend {
@@ -23,6 +25,10 @@ pub trait Backend {
fn f64_builder(&self) -> Box<dyn ValueBuilder<Output = f64, Error = Self::Error>>;
fn char_builder(&self) -> Box<dyn ValueBuilder<Output = char, Error = Self::Error>>;
fn string_builder(&self) -> Box<dyn ValueBuilder<Output = String, Error = Self::Error>>;
+
+ fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>, Error = Self::Error>>
+ where T: 'static + BuildableValue
+ ;
}
diff --git a/src/buildable.rs b/src/buildable.rs
index 22f6d0a..95382e7 100644
--- a/src/buildable.rs
+++ b/src/buildable.rs
@@ -1,4 +1,5 @@
use crate::ValueBuilder;
+use crate::CollectionBuilder;
use crate::Backend;
// A value that can be built interactively, using a Backend
@@ -162,3 +163,23 @@ impl BuildableValue for String {
}
}
+
+
+pub trait BuildableCollection {
+ fn builder<E, B>(backend: B) -> Box<dyn CollectionBuilder<Output = Self, Error = E>>
+ where E: Sized,
+ B: Backend<Error = E>
+ ;
+}
+
+impl<T> BuildableCollection for Vec<T>
+ where T: 'static + BuildableValue
+{
+ fn builder<E, B>(backend: B) -> Box<dyn CollectionBuilder<Output = Self, Error = E>>
+ where E: Sized,
+ B: Backend<Error = E>
+ {
+ backend.vec_builder::<T>()
+ }
+}
+
diff --git a/src/collection_builder.rs b/src/collection_builder.rs
index 3535ee2..70c1ae3 100644
--- a/src/collection_builder.rs
+++ b/src/collection_builder.rs
@@ -5,6 +5,6 @@ pub trait CollectionBuilder {
type Output: Sized;
type Error: Sized;
- fn build_collection(&self) -> Result<Self::Output, Self::Error>;
+ fn build_collection(&self, value_desc: &str) -> Result<Self::Output, Self::Error>;
}
diff --git a/src/lib.rs b/src/lib.rs
index e054fa1..21d5ab4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -22,6 +22,60 @@ mod dummy_bool_test {
fn bool_builder(&self) -> Box<dyn ValueBuilder<Output = bool, Error = Self::Error>> {
Box::new(BoolValBuilder)
}
+ fn u8_builder(&self) -> Box<dyn ValueBuilder<Output = u8, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn u16_builder(&self) -> Box<dyn ValueBuilder<Output = u16, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn u32_builder(&self) -> Box<dyn ValueBuilder<Output = u32, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn u64_builder(&self) -> Box<dyn ValueBuilder<Output = u64, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn u128_builder(&self) -> Box<dyn ValueBuilder<Output = u128, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i8_builder(&self) -> Box<dyn ValueBuilder<Output = i8, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i16_builder(&self) -> Box<dyn ValueBuilder<Output = i16, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i32_builder(&self) -> Box<dyn ValueBuilder<Output = i32, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i64_builder(&self) -> Box<dyn ValueBuilder<Output = i64, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i128_builder(&self) -> Box<dyn ValueBuilder<Output = i128, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn usize_builder(&self) -> Box<dyn ValueBuilder<Output = usize, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn isize_builder(&self) -> Box<dyn ValueBuilder<Output = isize, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn f32_builder(&self) -> Box<dyn ValueBuilder<Output = f32, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn f64_builder(&self) -> Box<dyn ValueBuilder<Output = f64, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn char_builder(&self) -> Box<dyn ValueBuilder<Output = char, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn string_builder(&self) -> Box<dyn ValueBuilder<Output = String, Error = Self::Error>> {
+ unimplemented!()
+ }
+
+ fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>, Error = Self::Error>>
+ where T: 'static + BuildableValue
+ {
+ unimplemented!()
+ }
}
struct BoolValBuilder;
@@ -41,3 +95,107 @@ mod dummy_bool_test {
}
}
+
+#[cfg(test)]
+mod vec_test {
+ use super::*;
+
+ struct DummyBackend;
+ impl Backend for DummyBackend {
+ type Error = ();
+
+ fn bool_builder(&self) -> Box<dyn ValueBuilder<Output = bool, Error = Self::Error>> {
+ Box::new(BoolValBuilder)
+ }
+ fn u8_builder(&self) -> Box<dyn ValueBuilder<Output = u8, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn u16_builder(&self) -> Box<dyn ValueBuilder<Output = u16, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn u32_builder(&self) -> Box<dyn ValueBuilder<Output = u32, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn u64_builder(&self) -> Box<dyn ValueBuilder<Output = u64, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn u128_builder(&self) -> Box<dyn ValueBuilder<Output = u128, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i8_builder(&self) -> Box<dyn ValueBuilder<Output = i8, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i16_builder(&self) -> Box<dyn ValueBuilder<Output = i16, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i32_builder(&self) -> Box<dyn ValueBuilder<Output = i32, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i64_builder(&self) -> Box<dyn ValueBuilder<Output = i64, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn i128_builder(&self) -> Box<dyn ValueBuilder<Output = i128, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn usize_builder(&self) -> Box<dyn ValueBuilder<Output = usize, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn isize_builder(&self) -> Box<dyn ValueBuilder<Output = isize, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn f32_builder(&self) -> Box<dyn ValueBuilder<Output = f32, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn f64_builder(&self) -> Box<dyn ValueBuilder<Output = f64, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn char_builder(&self) -> Box<dyn ValueBuilder<Output = char, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn string_builder(&self) -> Box<dyn ValueBuilder<Output = String, Error = Self::Error>> {
+ unimplemented!()
+ }
+ fn vec_builder<T>(&self) -> Box<dyn CollectionBuilder<Output = Vec<T>, Error = Self::Error>>
+ where T: 'static + BuildableValue
+ {
+ Box::new(VecBuilder::<T>(std::marker::PhantomData))
+ }
+ }
+
+ struct BoolValBuilder;
+ impl ValueBuilder for BoolValBuilder {
+ type Output = bool;
+ type Error = ();
+
+ fn build_value(&self, _question: &str) -> Result<Self::Output, Self::Error> {
+ Ok(true)
+ }
+ }
+
+ pub struct VecBuilder<T: 'static + BuildableValue>(std::marker::PhantomData<T>);
+ impl<T: BuildableValue> CollectionBuilder for VecBuilder<T> {
+ type Output = Vec<T>;
+ type Error = ();
+
+ fn build_collection(&self, value_desc: &str) -> Result<Self::Output, Self::Error> {
+ 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::<bool>::builder(DummyBackend).build_collection("flag").unwrap();
+ assert_eq!(v, vec![true, true, true]);
+ }
+}