From cabb017f4e559195ab4220ff84e1afc833c8e5b1 Mon Sep 17 00:00:00 2001 From: Zaba505 Date: Thu, 10 Sep 2020 02:08:31 -0400 Subject: [PATCH] feat(value): pass set errors up --- src/lib.rs | 44 +++++++++++++++++++++++++------------------- src/value.rs | 40 ++++++++++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6025073..8424777 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,12 @@ //! pflag is a port of spf13s' amazing Go package by the same name. -#![feature(associated_type_bounds)] #![feature(type_name_of_val)] mod value; pub use value::Slice; pub use value::Value; +pub use value::ValueError; use std::collections::BTreeMap; use std::fmt; @@ -51,7 +51,7 @@ pub struct Flag { } impl Flag { - pub fn set(&mut self, val: String) -> Result<(), String> { + pub fn set(&mut self, val: String) -> Result<(), ValueError> { self.value.set(val) } @@ -534,9 +534,9 @@ impl FlagSet { builtin_flag_val!(socket_addr_v6, SocketAddrV6); /// value_of retrieves the value for the given flags name. - pub fn value_of>(&self, name: &str) -> T { + pub fn value_of(&self, name: &str) -> Result { let i = self.formal.get(name).unwrap(); - self.flags[*i].value.value().parse().unwrap() + self.flags[*i].value.value().parse() } } @@ -651,7 +651,10 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("hello"), "world".to_string()); + assert_eq!( + flags.value_of::("hello").unwrap(), + "world".to_string() + ); } #[test] @@ -663,7 +666,10 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("hello"), "world".to_string()); + assert_eq!( + flags.value_of::("hello").unwrap(), + "world".to_string() + ); } #[test] @@ -675,7 +681,7 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("hello"), true); + assert_eq!(flags.value_of::("hello").unwrap(), true); } #[test] @@ -687,7 +693,7 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("hello"), true); + assert_eq!(flags.value_of::("hello").unwrap(), true); } #[test] @@ -699,7 +705,7 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("help"), true); + assert_eq!(flags.value_of::("help").unwrap(), true); } #[test] @@ -711,7 +717,7 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("help"), true); + assert_eq!(flags.value_of::("help").unwrap(), true); } #[test] @@ -724,8 +730,8 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("help"), true); - assert_eq!(flags.value_of::("verbose"), true); + assert_eq!(flags.value_of::("help").unwrap(), true); + assert_eq!(flags.value_of::("verbose").unwrap(), true); } #[test] @@ -738,8 +744,8 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("help"), false); - assert_eq!(flags.value_of::("verbose"), true); + assert_eq!(flags.value_of::("help").unwrap(), false); + assert_eq!(flags.value_of::("verbose").unwrap(), true); } #[test] @@ -751,7 +757,7 @@ mod tests { panic!(err); } - assert_eq!(flags.value_of::("port"), 8080); + assert_eq!(flags.value_of::("port").unwrap(), 8080); } #[test] @@ -791,7 +797,7 @@ mod tests { panic!(err); } - let bools = flags.value_of::>("bools"); + let bools = flags.value_of::>("bools").unwrap(); assert_eq!(bools.len(), 3); } @@ -804,7 +810,7 @@ mod tests { panic!(err); } - let bools = flags.value_of::>("bools"); + let bools = flags.value_of::>("bools").unwrap(); assert_eq!(bools.len(), 3); } @@ -817,7 +823,7 @@ mod tests { panic!(err); } - let bools = flags.value_of::>("bools"); + let bools = flags.value_of::>("bools").unwrap(); assert_eq!(bools.len(), 3); } @@ -830,7 +836,7 @@ mod tests { panic!(err); } - let bools = flags.value_of::>("bools"); + let bools = flags.value_of::>("bools").unwrap(); assert_eq!(bools.len(), 1); } } diff --git a/src/value.rs b/src/value.rs index 7f9eade..8de2064 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,11 +1,23 @@ +use std::error::Error; use std::fmt; use std::str; use std::string; +#[derive(Debug)] +pub struct ValueError(Box); + +impl fmt::Display for ValueError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "unexpected error while setting value: {}", &self.0) + } +} + +impl Error for ValueError {} + /// Value is a trait representing the value stored in a flag. pub trait Value { /// set sets the underlying value. - fn set(&mut self, val: string::String) -> Result<(), string::String>; + fn set(&mut self, val: string::String) -> Result<(), ValueError>; /// value retrieves the current value as a String. fn value(&self) -> string::String; @@ -21,7 +33,11 @@ pub trait Value { } } -impl> Value for T { +impl Value for T +where + E: Error + 'static, + T: string::ToString + str::FromStr, +{ // typ is reimplemeted in order to leverage any::type_name, which // is currently whereas any::type_name_of_val is not. fn typ(&self) -> &str { @@ -33,14 +49,14 @@ impl> Value for T { + 1) as usize..] } - fn set(&mut self, val: string::String) -> Result<(), string::String> { + fn set(&mut self, val: string::String) -> Result<(), ValueError> { let res = val.as_str().parse::(); match res { Ok(v) => { *self = v; Ok(()) } - Err(err) => Err(format!("unexpected error while parsing: {:?}", err)), + Err(err) => Err(ValueError(Box::new(err))), } } @@ -94,7 +110,11 @@ impl>> From for Slice { } } -impl> Value for Slice { +impl Value for Slice +where + E: Error + 'static, + T: string::ToString + str::FromStr, +{ fn typ(&self) -> &str { let type_name = std::any::type_name::(); &type_name[(type_name @@ -104,7 +124,7 @@ impl> Value for Slice { + 1) as usize..] } - fn set(&mut self, val: string::String) -> Result<(), string::String> { + fn set(&mut self, val: string::String) -> Result<(), ValueError> { if !self.changed { self.vals = Vec::with_capacity(self.vals.capacity()); } @@ -115,7 +135,7 @@ impl> Value for Slice { self.vals.push(v); Ok(()) } - Err(err) => Err(format!("unexpected error while parsing: {:?}", err)), + Err(err) => Err(ValueError(Box::new(err))), } }) } @@ -135,7 +155,11 @@ impl> Value for Slice { } } -impl> str::FromStr for Slice { +impl str::FromStr for Slice +where + E: Error + 'static, + T: str::FromStr, +{ type Err = T::Err; fn from_str(s: &str) -> Result {