11use crate :: {
22 scheme:: { Field , List , Scheme , SchemeMismatchError } ,
33 types:: { GetType , LhsValue , LhsValueSeed , Type , TypeMismatchError } ,
4- ListMatcher ,
4+ ListMatcher , UnknownFieldError ,
55} ;
66use serde:: de:: { self , DeserializeSeed , Deserializer , MapAccess , Visitor } ;
77use serde:: ser:: { SerializeMap , SerializeSeq , Serializer } ;
@@ -16,11 +16,15 @@ use thiserror::Error;
1616pub enum SetFieldValueError {
1717 /// An error that occurs when trying to assign a value of the wrong type to a field.
1818 #[ error( "{0}" ) ]
19- TypeMismatchError ( #[ source] TypeMismatchError ) ,
19+ TypeMismatch ( #[ source] TypeMismatchError ) ,
2020
2121 /// An error that occurs when trying to set the value of a field from a different scheme.
2222 #[ error( "{0}" ) ]
23- SchemeMismatchError ( #[ source] SchemeMismatchError ) ,
23+ SchemeMismatch ( #[ source] SchemeMismatchError ) ,
24+
25+ /// An error that occurs when specifying an unknown field name.
26+ #[ error( "{0}" ) ]
27+ UnknownField ( #[ source] UnknownFieldError ) ,
2428}
2529
2630/// An error that occurs when previously defined list gets redefined.
@@ -82,7 +86,7 @@ impl<'e, U> ExecutionContext<'e, U> {
8286 value : V ,
8387 ) -> Result < Option < LhsValue < ' e > > , SetFieldValueError > {
8488 if !std:: ptr:: eq ( self . scheme , field. scheme ( ) ) {
85- return Err ( SetFieldValueError :: SchemeMismatchError ( SchemeMismatchError ) ) ;
89+ return Err ( SetFieldValueError :: SchemeMismatch ( SchemeMismatchError ) ) ;
8690 }
8791 let value = value. into ( ) ;
8892
@@ -92,7 +96,32 @@ impl<'e, U> ExecutionContext<'e, U> {
9296 if field_type == value_type {
9397 Ok ( self . values [ field. index ( ) ] . replace ( value) )
9498 } else {
95- Err ( SetFieldValueError :: TypeMismatchError ( TypeMismatchError {
99+ Err ( SetFieldValueError :: TypeMismatch ( TypeMismatchError {
100+ expected : field_type. into ( ) ,
101+ actual : value_type,
102+ } ) )
103+ }
104+ }
105+
106+ /// Sets a runtime value for a given field name.
107+ pub fn set_field_value_from_name < ' v : ' e , V : Into < LhsValue < ' v > > > (
108+ & mut self ,
109+ name : & str ,
110+ value : V ,
111+ ) -> Result < Option < LhsValue < ' e > > , SetFieldValueError > {
112+ let field = self
113+ . scheme
114+ . get_field ( name)
115+ . map_err ( SetFieldValueError :: UnknownField ) ?;
116+ let value = value. into ( ) ;
117+
118+ let field_type = field. get_type ( ) ;
119+ let value_type = value. get_type ( ) ;
120+
121+ if field_type == value_type {
122+ Ok ( self . values [ field. index ( ) ] . replace ( value) )
123+ } else {
124+ Err ( SetFieldValueError :: TypeMismatch ( TypeMismatchError {
96125 expected : field_type. into ( ) ,
97126 actual : value_type,
98127 } ) )
@@ -138,13 +167,25 @@ impl<'e, U> ExecutionContext<'e, U> {
138167 & * self . list_matchers [ list. index ( ) ]
139168 }
140169
170+ /// Get the list matcher object for the specified type.
171+ pub fn get_list_matcher_from_type ( & self , ty : & Type ) -> Option < & dyn ListMatcher > {
172+ let list = self . scheme . get_list ( ty) ?;
173+ Some ( & * self . list_matchers [ list. index ( ) ] )
174+ }
175+
141176 /// Get the list matcher object for the specified list type.
142177 pub fn get_list_matcher_mut ( & mut self , list : List < ' _ > ) -> & mut dyn ListMatcher {
143178 assert ! ( self . scheme( ) == list. scheme( ) ) ;
144179
145180 & mut * self . list_matchers [ list. index ( ) ]
146181 }
147182
183+ /// Get the list matcher object for the specified type.
184+ pub fn get_list_matcher_mut_from_type ( & mut self , ty : & Type ) -> Option < & mut dyn ListMatcher > {
185+ let list = self . scheme . get_list ( ty) ?;
186+ Some ( & mut * self . list_matchers [ list. index ( ) ] )
187+ }
188+
148189 /// Get immutable reference to user data stored in
149190 /// this execution context with [`ExecutionContext::new_with`].
150191 #[ inline]
@@ -285,18 +326,18 @@ impl<'de, U> DeserializeSeed<'de> for &mut ExecutionContext<'de, U> {
285326 . map_err ( |_| de:: Error :: custom ( format ! ( "unknown field: {key}" ) ) ) ?;
286327 let value = access
287328 . next_value_seed :: < LhsValueSeed < ' _ > > ( LhsValueSeed ( & field. get_type ( ) ) ) ?;
288- let field = self
289- . 0
290- . scheme ( )
291- . get_field ( & key )
292- . map_err ( |_| de:: Error :: custom ( format ! ( "unknown field: {key}" ) ) ) ? ;
293- self . 0 . set_field_value ( field , value ) . map_err ( |e| match e {
294- SetFieldValueError :: TypeMismatchError ( e) => de:: Error :: custom ( format ! (
295- "invalid type: {:?}, expected {:?}" ,
296- e. actual, e. expected
297- ) ) ,
298- SetFieldValueError :: SchemeMismatchError ( _) => unreachable ! ( ) ,
299- } ) ?;
329+ self . 0
330+ . set_field_value_from_name ( & key , value )
331+ . map_err ( |e| match e {
332+ SetFieldValueError :: UnknownField ( UnknownFieldError ) => {
333+ de:: Error :: custom ( format ! ( "unknown field name ` {key}`" , ) )
334+ }
335+ SetFieldValueError :: TypeMismatch ( e) => de:: Error :: custom ( format ! (
336+ "invalid type: {:?}, expected {:?}" ,
337+ e. actual, e. expected
338+ ) ) ,
339+ SetFieldValueError :: SchemeMismatch ( _) => unreachable ! ( ) ,
340+ } ) ?;
300341 }
301342 }
302343
@@ -361,7 +402,7 @@ fn test_field_value_type_mismatch() {
361402
362403 assert_eq ! (
363404 ctx. set_field_value( scheme. get_field( "foo" ) . unwrap( ) , LhsValue :: Bool ( false ) ) ,
364- Err ( SetFieldValueError :: TypeMismatchError ( TypeMismatchError {
405+ Err ( SetFieldValueError :: TypeMismatch ( TypeMismatchError {
365406 expected: Type :: Int . into( ) ,
366407 actual: Type :: Bool ,
367408 } ) )
@@ -378,9 +419,7 @@ fn test_scheme_mismatch() {
378419
379420 assert_eq ! (
380421 ctx. set_field_value( scheme2. get_field( "foo" ) . unwrap( ) , LhsValue :: Bool ( false ) ) ,
381- Err ( SetFieldValueError :: SchemeMismatchError (
382- SchemeMismatchError { }
383- ) )
422+ Err ( SetFieldValueError :: SchemeMismatch ( SchemeMismatchError { } ) )
384423 ) ;
385424}
386425
0 commit comments