@@ -176,19 +176,25 @@ impl Properties {
176176
177177 /// Tries to get a property.
178178 ///
179- /// Returns an error if the property doesn't exist or the value has the wrong type.
180- pub fn try_get < T : PropertyType > ( & self , property : Property ) -> Result < T , PropertyError > {
179+ /// Returns `None` if the property doesn't exits and an error if the value has the wrong type.
180+ pub fn try_get < T : PropertyType > (
181+ & self ,
182+ property : Property ,
183+ ) -> Result < Option < T > , PropertyTypeError > {
181184 self . try_get_by_name ( & property. to_string ( ) )
182185 }
183186
184187 /// Tries to get a property by name.
185188 ///
186- /// Returns an error if the property doesn't exist or the value has the wrong type.
187- pub fn try_get_by_name < T : PropertyType > ( & self , name : & str ) -> Result < T , PropertyError > {
189+ /// Returns `None` if the property doesn't exits and an error if the value has the wrong type.
190+ pub fn try_get_by_name < T : PropertyType > (
191+ & self ,
192+ name : & str ,
193+ ) -> Result < Option < T > , PropertyTypeError > {
188194 self . properties
189195 . get ( name)
190- . ok_or_else ( || PropertyError :: Undefined ( name . to_string ( ) ) )
191- . and_then ( TryFrom :: try_from )
196+ . map ( |value| value . try_into ( ) )
197+ . transpose ( )
192198 }
193199
194200 /// Returns `true` if no properties exist.
@@ -200,12 +206,13 @@ impl Properties {
200206/// Marker trait for property value types.
201207pub trait PropertyType
202208where
203- Self : for < ' a > TryFrom < & ' a PropertyValue , Error = PropertyError > ,
209+ Self : for < ' a > TryFrom < & ' a PropertyValue , Error = PropertyTypeError > ,
204210{
205211}
206212
207213impl PropertyType for String { }
208214impl PropertyType for i32 { }
215+ impl PropertyType for u32 { }
209216
210217#[ derive( Debug , Clone , PartialEq , Eq ) ]
211218pub enum PropertyValue {
@@ -214,38 +221,43 @@ pub enum PropertyValue {
214221}
215222
216223impl TryFrom < & PropertyValue > for String {
217- type Error = PropertyError ;
224+ type Error = PropertyTypeError ;
218225
219226 fn try_from ( value : & PropertyValue ) -> Result < Self , Self :: Error > {
220227 match value {
221228 PropertyValue :: Text ( text) => Ok ( text. clone ( ) ) ,
222- _ => Err ( PropertyError :: WrongType ) ,
229+ _ => Err ( PropertyTypeError ) ,
223230 }
224231 }
225232}
226233
227234impl TryFrom < & PropertyValue > for i32 {
228- type Error = PropertyError ;
235+ type Error = PropertyTypeError ;
229236
230237 fn try_from ( value : & PropertyValue ) -> Result < Self , Self :: Error > {
231238 match value {
232239 PropertyValue :: Int ( int) => Ok ( * int) ,
233- _ => Err ( PropertyError :: WrongType ) ,
240+ _ => Err ( PropertyTypeError ) ,
234241 }
235242 }
236243}
237244
238- /// Error returned by property getters.
239- # [ derive ( Debug , Error , PartialEq , Eq , PartialOrd , Ord ) ]
240- pub enum PropertyError {
241- /// Undefined property.
242- # [ error ( "property \" {0} \" is undefined" ) ]
243- Undefined ( String ) ,
244- /// Wrong property type.
245- # [ error ( "wrong property type" ) ]
246- WrongType ,
245+ impl TryFrom < & PropertyValue > for u32 {
246+ type Error = PropertyTypeError ;
247+
248+ fn try_from ( value : & PropertyValue ) -> Result < Self , Self :: Error > {
249+ match value {
250+ PropertyValue :: Int ( int ) if * int >= 0 => Ok ( * int as u32 ) ,
251+ _ => Err ( PropertyTypeError ) ,
252+ }
253+ }
247254}
248255
256+ /// Invalid property type error.
257+ #[ derive( Debug , Error , PartialEq , Eq , PartialOrd , Ord ) ]
258+ #[ error( "invalid property type" ) ]
259+ pub struct PropertyTypeError ;
260+
249261#[ cfg( test) ]
250262mod tests {
251263 use super :: * ;
@@ -271,7 +283,7 @@ mod tests {
271283 ] {
272284 assert_eq ! (
273285 properties. try_get_by_name:: <String >( key) . unwrap( ) ,
274- expected. to_string( ) ,
286+ Some ( expected. to_string( ) ) ,
275287 "key=\" {key}\" "
276288 ) ;
277289 }
@@ -289,16 +301,19 @@ mod tests {
289301 let mut lines = Lines :: new ( INPUT ) ;
290302 let properties = Properties :: parse ( & mut lines) . unwrap ( ) ;
291303
292- for ( key, expected) in [
293- ( "POS_INT" , 10 ) , //
294- ( "NEG_INT" , -20 ) ,
295- ] {
296- assert_eq ! (
297- properties. try_get_by_name:: <i32 >( key) . unwrap( ) ,
298- expected,
299- "key=\" {key}\" "
300- ) ;
301- }
304+ assert_eq ! ( properties. try_get_by_name:: <i32 >( "POS_INT" ) , Ok ( Some ( 10 ) ) ) ;
305+ assert_eq ! ( properties. try_get_by_name:: <i32 >( "NEG_INT" ) , Ok ( Some ( -20 ) ) ) ;
306+
307+ assert_eq ! ( properties. try_get_by_name:: <u32 >( "POS_INT" ) , Ok ( Some ( 10 ) ) ) ;
308+ assert_eq ! (
309+ properties. try_get_by_name:: <u32 >( "NEG_INT" ) ,
310+ Err ( PropertyTypeError )
311+ ) ;
312+
313+ assert_eq ! (
314+ properties. try_get_by_name:: <String >( "POS_INT" ) ,
315+ Err ( PropertyTypeError )
316+ ) ;
302317 }
303318
304319 #[ test]
0 commit comments