Skip to content

Commit

Permalink
feat(value): pass set errors up
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaba505 committed Sep 10, 2020
1 parent 689f31f commit cabb017
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 27 deletions.
44 changes: 25 additions & 19 deletions 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;
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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<T: std::str::FromStr<Err: fmt::Debug>>(&self, name: &str) -> T {
pub fn value_of<T: std::str::FromStr>(&self, name: &str) -> Result<T, T::Err> {
let i = self.formal.get(name).unwrap();
self.flags[*i].value.value().parse().unwrap()
self.flags[*i].value.value().parse()
}
}

Expand Down Expand Up @@ -651,7 +651,10 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<String>("hello"), "world".to_string());
assert_eq!(
flags.value_of::<String>("hello").unwrap(),
"world".to_string()
);
}

#[test]
Expand All @@ -663,7 +666,10 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<String>("hello"), "world".to_string());
assert_eq!(
flags.value_of::<String>("hello").unwrap(),
"world".to_string()
);
}

#[test]
Expand All @@ -675,7 +681,7 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<bool>("hello"), true);
assert_eq!(flags.value_of::<bool>("hello").unwrap(), true);
}

#[test]
Expand All @@ -687,7 +693,7 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<bool>("hello"), true);
assert_eq!(flags.value_of::<bool>("hello").unwrap(), true);
}

#[test]
Expand All @@ -699,7 +705,7 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<bool>("help"), true);
assert_eq!(flags.value_of::<bool>("help").unwrap(), true);
}

#[test]
Expand All @@ -711,7 +717,7 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<bool>("help"), true);
assert_eq!(flags.value_of::<bool>("help").unwrap(), true);
}

#[test]
Expand All @@ -724,8 +730,8 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<bool>("help"), true);
assert_eq!(flags.value_of::<bool>("verbose"), true);
assert_eq!(flags.value_of::<bool>("help").unwrap(), true);
assert_eq!(flags.value_of::<bool>("verbose").unwrap(), true);
}

#[test]
Expand All @@ -738,8 +744,8 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<bool>("help"), false);
assert_eq!(flags.value_of::<bool>("verbose"), true);
assert_eq!(flags.value_of::<bool>("help").unwrap(), false);
assert_eq!(flags.value_of::<bool>("verbose").unwrap(), true);
}

#[test]
Expand All @@ -751,7 +757,7 @@ mod tests {
panic!(err);
}

assert_eq!(flags.value_of::<u32>("port"), 8080);
assert_eq!(flags.value_of::<u32>("port").unwrap(), 8080);
}

#[test]
Expand Down Expand Up @@ -791,7 +797,7 @@ mod tests {
panic!(err);
}

let bools = flags.value_of::<Slice<bool>>("bools");
let bools = flags.value_of::<Slice<bool>>("bools").unwrap();
assert_eq!(bools.len(), 3);
}

Expand All @@ -804,7 +810,7 @@ mod tests {
panic!(err);
}

let bools = flags.value_of::<Slice<bool>>("bools");
let bools = flags.value_of::<Slice<bool>>("bools").unwrap();
assert_eq!(bools.len(), 3);
}

Expand All @@ -817,7 +823,7 @@ mod tests {
panic!(err);
}

let bools = flags.value_of::<value::Slice<bool>>("bools");
let bools = flags.value_of::<value::Slice<bool>>("bools").unwrap();
assert_eq!(bools.len(), 3);
}

Expand All @@ -830,7 +836,7 @@ mod tests {
panic!(err);
}

let bools = flags.value_of::<Slice<bool>>("bools");
let bools = flags.value_of::<Slice<bool>>("bools").unwrap();
assert_eq!(bools.len(), 1);
}
}
40 changes: 32 additions & 8 deletions 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<dyn Error>);

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;
Expand All @@ -21,7 +33,11 @@ pub trait Value {
}
}

impl<T: string::ToString + str::FromStr<Err: fmt::Debug>> Value for T {
impl<E, T> Value for T
where
E: Error + 'static,
T: string::ToString + str::FromStr<Err = E>,
{
// 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 {
Expand All @@ -33,14 +49,14 @@ impl<T: string::ToString + str::FromStr<Err: fmt::Debug>> 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::<T>();
match res {
Ok(v) => {
*self = v;
Ok(())
}
Err(err) => Err(format!("unexpected error while parsing: {:?}", err)),
Err(err) => Err(ValueError(Box::new(err))),
}
}

Expand Down Expand Up @@ -94,7 +110,11 @@ impl<T, V: Into<Vec<T>>> From<V> for Slice<T> {
}
}

impl<T: string::ToString + str::FromStr<Err: fmt::Debug>> Value for Slice<T> {
impl<E, T> Value for Slice<T>
where
E: Error + 'static,
T: string::ToString + str::FromStr<Err = E>,
{
fn typ(&self) -> &str {
let type_name = std::any::type_name::<T>();
&type_name[(type_name
Expand All @@ -104,7 +124,7 @@ impl<T: string::ToString + str::FromStr<Err: fmt::Debug>> Value for Slice<T> {
+ 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());
}
Expand All @@ -115,7 +135,7 @@ impl<T: string::ToString + str::FromStr<Err: fmt::Debug>> Value for Slice<T> {
self.vals.push(v);
Ok(())
}
Err(err) => Err(format!("unexpected error while parsing: {:?}", err)),
Err(err) => Err(ValueError(Box::new(err))),
}
})
}
Expand All @@ -135,7 +155,11 @@ impl<T: string::ToString + str::FromStr<Err: fmt::Debug>> Value for Slice<T> {
}
}

impl<T: str::FromStr<Err: fmt::Debug>> str::FromStr for Slice<T> {
impl<E, T> str::FromStr for Slice<T>
where
E: Error + 'static,
T: str::FromStr<Err = E>,
{
type Err = T::Err;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Expand Down

0 comments on commit cabb017

Please sign in to comment.