1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
use ion::Value; pub trait FromIon<T>: Sized { type Err; fn from_ion(&T) -> Result<Self, Self::Err>; } impl FromIon<Value> for String { type Err = (); fn from_ion(value: &Value) -> Result<Self, Self::Err> { value.as_string().map(|s| s.to_owned()).ok_or(()) } } impl FromIon<Value> for Option<String> { type Err = (); fn from_ion(value: &Value) -> Result<Self, Self::Err> { value.as_string() .map(|s| if s.is_empty() { None } else { Some(s.to_owned()) }) .ok_or(()) } } macro_rules! from_ion_value_int_impl { ($($t:ty)*) => {$( impl FromIon<Value> for $t { type Err = ::std::num::ParseIntError; fn from_ion(value: &Value) -> Result<Self, Self::Err> { match value.as_string() { Some(s) => Ok(s.parse()?), None => "".parse() } } } )*} } from_ion_value_int_impl!{ isize i8 i16 i32 i64 usize u8 u16 u32 u64 } impl FromIon<Value> for bool { type Err = ::std::str::ParseBoolError; fn from_ion(value: &Value) -> Result<Self, Self::Err> { match value.as_string() { Some(s) => Ok(s.parse()?), None => "".parse(), } } } #[cfg(test)] mod tests { use std::str::FromStr; use ion::{FromIon, Section, Value}; #[test] fn string() { let v = Value::String("foo".to_owned()); let s = String::from_ion(&v).unwrap(); assert_eq!("foo", s); let s: String = v.from_ion().unwrap(); assert_eq!("foo", s); } #[test] fn option_string() { let v = Value::from_str("foo").unwrap(); let os: Option<String> = v.from_ion().unwrap(); assert_eq!(Some("foo".to_owned()), os); let v = Value::from_str("").unwrap(); let os: Option<String> = v.from_ion().unwrap(); assert_eq!(None, os); } #[test] fn u32() { let v = Value::from_str("16").unwrap(); let u: u32 = v.from_ion().unwrap(); assert_eq!(16, u); } #[test] fn bool() { let v = Value::from_str("true").unwrap(); let u: bool = v.from_ion().unwrap(); assert_eq!(true, u); let v = Value::from_str("false").unwrap(); let u: bool = v.from_ion().unwrap(); assert_eq!(false, u); let v = Value::from_str("").unwrap(); let u: Result<bool, _> = v.from_ion(); assert!(u.is_err()); } struct Foo { a: u32, b: String, } impl FromIon<Section> for Foo { type Err = (); fn from_ion(_section: &Section) -> Result<Self, Self::Err> { Ok(Foo { a: 1, b: "foo".to_owned(), }) } } #[test] fn from_ion_section() { let section = Section::new(); let foo: Foo = section.parse().unwrap(); assert_eq!(1, foo.a); assert_eq!("foo", foo.b); } }