1- use serde:: { Deserialize , Serialize } ;
1+ use serde:: { Deserialize , Deserializer , Serialize } ;
22use std:: {
33 convert:: Infallible ,
44 fmt:: { Display , Formatter } ,
@@ -13,7 +13,7 @@ use std::{
1313/// them are in results. Frequently, not all fields in an Item are used, so this
1414/// specification provides a mechanism for clients to request that servers to
1515/// explicitly include or exclude certain fields.
16- #[ derive( Clone , Debug , Serialize , Deserialize , Default , PartialEq ) ]
16+ #[ derive( Clone , Debug , Serialize , Default , PartialEq ) ]
1717pub struct Fields {
1818 /// Fields to include.
1919 #[ serde( skip_serializing_if = "Vec::is_empty" , default ) ]
@@ -24,22 +24,59 @@ pub struct Fields {
2424 pub exclude : Vec < String > ,
2525}
2626
27- impl FromStr for Fields {
28- type Err = Infallible ;
29-
30- fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
27+ impl Fields {
28+ fn from_iter < I > ( fields : I ) -> Fields
29+ where
30+ I : IntoIterator < Item = String > ,
31+ {
3132 let mut include = Vec :: new ( ) ;
3233 let mut exclude = Vec :: new ( ) ;
33- for field in s . split ( ',' ) . filter ( |s| !s . is_empty ( ) ) {
34+ for field in fields {
3435 if let Some ( field) = field. strip_prefix ( '-' ) {
3536 exclude. push ( field. to_string ( ) ) ;
3637 } else if let Some ( field) = field. strip_prefix ( '+' ) {
3738 include. push ( field. to_string ( ) ) ;
3839 } else {
39- include. push ( field. to_string ( ) ) ;
40+ include. push ( field) ;
4041 }
4142 }
42- Ok ( Fields { include, exclude } )
43+ Fields { include, exclude }
44+ }
45+ }
46+
47+ impl FromStr for Fields {
48+ type Err = Infallible ;
49+
50+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
51+ Ok ( Fields :: from_iter (
52+ s. split ( ',' )
53+ . filter ( |s| !s. is_empty ( ) )
54+ . map ( ToString :: to_string) ,
55+ ) )
56+ }
57+ }
58+
59+ impl < ' de > Deserialize < ' de > for Fields {
60+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
61+ where
62+ D : Deserializer < ' de > ,
63+ {
64+ #[ derive( Deserialize ) ]
65+ #[ serde( untagged) ]
66+ enum Repr {
67+ List ( Vec < String > ) ,
68+ Struct {
69+ #[ serde( default ) ]
70+ include : Vec < String > ,
71+ #[ serde( default ) ]
72+ exclude : Vec < String > ,
73+ } ,
74+ }
75+
76+ Ok ( match Repr :: deserialize ( deserializer) ? {
77+ Repr :: List ( fields) => Fields :: from_iter ( fields) ,
78+ Repr :: Struct { include, exclude } => Fields { include, exclude } ,
79+ } )
4380 }
4481}
4582
@@ -136,4 +173,31 @@ mod tests {
136173 fn permissive_deserialization ( ) {
137174 let _ = serde_json:: from_str :: < Fields > ( "{}" ) . unwrap ( ) ;
138175 }
176+
177+ #[ test]
178+ fn deserialize_struct ( ) {
179+ assert_eq ! (
180+ Fields {
181+ include: vec![ "foo" . to_string( ) ] ,
182+ exclude: vec![ "bar" . to_string( ) ] ,
183+ } ,
184+ serde_json:: from_str( r#"{"include": ["foo"], "exclude": ["bar"]}"# ) . unwrap( )
185+ ) ;
186+ }
187+
188+ #[ test]
189+ fn deserialize_list ( ) {
190+ assert_eq ! (
191+ Fields {
192+ include: vec![ "foo" . to_string( ) , "baz" . to_string( ) ] ,
193+ exclude: vec![ "bar" . to_string( ) ] ,
194+ } ,
195+ serde_json:: from_str( r#"["foo", "-bar", "+baz"]"# ) . unwrap( )
196+ ) ;
197+ }
198+
199+ #[ test]
200+ fn deserialize_empty_list ( ) {
201+ assert_eq ! ( Fields :: default ( ) , serde_json:: from_str( "[]" ) . unwrap( ) ) ;
202+ }
139203}
0 commit comments