@@ -8,6 +8,35 @@ use sonic_rs::JsonNumberTrait;
88use sonic_rs:: JsonValue ;
99use sonic_rs:: { to_array_iter, to_array_iter_unchecked, to_object_iter, to_object_iter_unchecked} ;
1010
11+ macro_rules! test_struct {
12+ ( $ty: ty, $data: expr) => {
13+ match serde_json:: from_slice:: <$ty>( $data) {
14+ Ok ( jv) => {
15+ let sv = sonic_rs:: from_slice:: <$ty>( $data) . expect( & format!(
16+ "parse valid json {:?} failed for type {}" ,
17+ $data,
18+ stringify!( $ty)
19+ ) ) ;
20+ assert_eq!( sv, jv) ;
21+
22+ // fuzz the struct to_string
23+ let sout = sonic_rs:: to_string( & sv) . unwrap( ) ;
24+ let jout = serde_json:: to_string( & jv) . unwrap( ) ;
25+ let sv = sonic_rs:: from_str:: <$ty>( & sout) . unwrap( ) ;
26+ let jv = serde_json:: from_str:: <$ty>( & jout) . unwrap( ) ;
27+ assert_eq!( sv, jv) ;
28+ }
29+ Err ( _) => {
30+ let _ = sonic_rs:: from_slice:: <$ty>( $data) . expect_err( & format!(
31+ "parse invalid json {:?} wrong for type {}" ,
32+ $data,
33+ stringify!( $ty)
34+ ) ) ;
35+ }
36+ }
37+ } ;
38+ }
39+
1140fuzz_target ! ( |data: & [ u8 ] | {
1241 match serde_json:: from_slice:: <JValue >( data) {
1342 Ok ( jv) => {
@@ -66,6 +95,12 @@ fuzz_target!(|data: &[u8]| {
6695 let _ = dom_from_slice( data) . unwrap_err( ) ;
6796 }
6897 }
98+
99+ test_struct!( TestStruct , data) ;
100+ test_struct!( Foo , data) ;
101+ test_struct!( Enum , data) ;
102+ test_struct!( String , data) ;
103+ test_struct!( f64 , data) ;
69104} ) ;
70105
71106fn compare_lazyvalue ( jv : & JValue , sv : & sonic_rs:: LazyValue ) {
@@ -120,3 +155,97 @@ fn compare_value(jv: &JValue, sv: &sonic_rs::Value) -> bool {
120155 }
121156 true
122157}
158+
159+ use faststr:: FastStr ;
160+ use serde:: { Deserialize , Serialize } ;
161+ use std:: borrow:: Cow ;
162+ use std:: { collections:: HashMap , hash:: Hash , marker:: PhantomData } ;
163+
164+ #[ derive( Debug , Deserialize , Serialize , PartialEq ) ]
165+ struct Foo {
166+ name : FastStr ,
167+ id : u64 ,
168+ }
169+
170+ #[ derive( Debug , Deserialize , Serialize , Hash , Eq , PartialEq ) ]
171+ enum Enum {
172+ Zero = 0 ,
173+ One = 1 ,
174+ Two = 2 ,
175+ }
176+
177+ #[ derive( Debug , Deserialize , Serialize , PartialEq ) ]
178+ enum FieldEnum {
179+ Integer ( i8 ) ,
180+ Tuple ( ( FastStr , i32 ) ) ,
181+ Struct ( Foo ) ,
182+ Unit ,
183+ }
184+
185+ #[ derive( Debug , Deserialize , Serialize , PartialEq ) ]
186+ enum FieldlessEnum {
187+ Tuple ( ) ,
188+ Struct { } ,
189+ Unit ,
190+ }
191+
192+ #[ derive( Debug , Deserialize , Serialize , PartialEq ) ]
193+ struct Wrapper < ' a > ( & ' a str ) ;
194+
195+ // A unit struct
196+ #[ derive( Debug , Deserialize , Serialize , PartialEq ) ]
197+ struct Unit ;
198+
199+ // A uint struct
200+ #[ derive( Debug , Deserialize , Serialize , PartialEq ) ]
201+ struct Phan < T > {
202+ phan : String ,
203+ _data : PhantomData < T > ,
204+ }
205+
206+ // A tuple struct
207+ #[ derive( Debug , Deserialize , Serialize , PartialEq ) ]
208+ struct Pair ( i32 , f32 ) ;
209+
210+ #[ derive( Debug , Deserialize , Serialize , PartialEq ) ]
211+ struct TestStruct < ' a > {
212+ fieldless : FieldlessEnum ,
213+ enummap : HashMap < Enum , FieldlessEnum > ,
214+ enum_ : Enum ,
215+
216+ // basic types
217+ boolean : bool ,
218+ integer : i32 ,
219+ float : f64 ,
220+ int128 : i128 ,
221+ uint128 : u128 ,
222+ char_ : char ,
223+
224+ // string or bytes
225+ str_ : & ' a str ,
226+ // bytes_: &'a [u8],
227+ string : String ,
228+ faststr : FastStr ,
229+ #[ serde( borrow) ]
230+ cow : Cow < ' a , str > ,
231+
232+ // containers
233+ vector : Vec < u32 > ,
234+ array : [ u32 ; 1 ] ,
235+ empty_array : [ u8 ; 0 ] ,
236+ map : HashMap < FastStr , f64 > ,
237+ map_opkey : HashMap < Option < FastStr > , f64 > ,
238+
239+ // enum types
240+ option : Option < String > ,
241+ fieldenum : FieldEnum ,
242+
243+ // tuple or struct
244+ tuple : ( u64 , String ) ,
245+ tuple_struct : Pair ,
246+ unit_struct : Unit ,
247+
248+ #[ serde( borrow) ]
249+ wrapper : Wrapper < ' a > ,
250+ phan_struct : Phan < ( ) > ,
251+ }
0 commit comments