@@ -25,8 +25,8 @@ use crate::{
2525 schema:: { Name , NamesRef , Namespace , RecordField , RecordSchema , Schema } ,
2626} ;
2727use bigdecimal:: BigDecimal ;
28- use serde:: { Serialize , ser} ;
29- use std:: { borrow:: Cow , io:: Write , str:: FromStr } ;
28+ use serde:: ser;
29+ use std:: { borrow:: Cow , cmp :: Ordering , collections :: HashMap , io:: Write , str:: FromStr } ;
3030
3131const COLLECTION_SERIALIZER_ITEM_LIMIT : usize = 1024 ;
3232const COLLECTION_SERIALIZER_DEFAULT_INIT_ITEM_CAPACITY : usize = 32 ;
@@ -249,6 +249,9 @@ impl<W: Write> ser::SerializeMap for SchemaAwareWriteSerializeMap<'_, '_, W> {
249249pub struct SchemaAwareWriteSerializeStruct < ' a , ' s , W : Write > {
250250 ser : & ' a mut SchemaAwareWriteSerializer < ' s , W > ,
251251 record_schema : & ' s RecordSchema ,
252+ /// Fields we received in the wrong order
253+ field_cache : HashMap < usize , Vec < u8 > > ,
254+ field_position : usize ,
252255 bytes_written : usize ,
253256}
254257
@@ -260,6 +263,8 @@ impl<'a, 's, W: Write> SchemaAwareWriteSerializeStruct<'a, 's, W> {
260263 SchemaAwareWriteSerializeStruct {
261264 ser,
262265 record_schema,
266+ field_cache : HashMap :: new ( ) ,
267+ field_position : 0 ,
263268 bytes_written : 0 ,
264269 }
265270 }
@@ -268,19 +273,85 @@ impl<'a, 's, W: Write> SchemaAwareWriteSerializeStruct<'a, 's, W> {
268273 where
269274 T : ?Sized + ser:: Serialize ,
270275 {
271- // If we receive fields in order, write them directly to the main writer
272- let mut value_ser = SchemaAwareWriteSerializer :: new (
273- & mut * self . ser . writer ,
274- & field. schema ,
275- self . ser . names ,
276- self . ser . enclosing_namespace . clone ( ) ,
277- ) ;
278- self . bytes_written += value. serialize ( & mut value_ser) ?;
279-
280- Ok ( ( ) )
276+ match self . field_position . cmp ( & field. position ) {
277+ Ordering :: Equal => {
278+ // If we receive fields in order, write them directly to the main writer
279+ let mut value_ser = SchemaAwareWriteSerializer :: new (
280+ & mut * self . ser . writer ,
281+ & field. schema ,
282+ self . ser . names ,
283+ self . ser . enclosing_namespace . clone ( ) ,
284+ ) ;
285+ self . bytes_written += value. serialize ( & mut value_ser) ?;
286+
287+ self . field_position += 1 ;
288+ while let Some ( bytes) = self . field_cache . remove ( & self . field_position ) {
289+ self . ser
290+ . writer
291+ . write_all ( & bytes)
292+ . map_err ( Details :: WriteBytes ) ?;
293+ self . bytes_written += bytes. len ( ) ;
294+ self . field_position += 1 ;
295+ }
296+ Ok ( ( ) )
297+ }
298+ Ordering :: Less => {
299+ // Current field position is smaller than this field position,
300+ // so we're still missing at least one field, save this field temporarily
301+ let mut bytes = Vec :: new ( ) ;
302+ let mut value_ser = SchemaAwareWriteSerializer :: new (
303+ & mut bytes,
304+ & field. schema ,
305+ self . ser . names ,
306+ self . ser . enclosing_namespace . clone ( ) ,
307+ ) ;
308+ value. serialize ( & mut value_ser) ?;
309+ if self . field_cache . insert ( field. position , bytes) . is_some ( ) {
310+ Err ( Details :: FieldNameDuplicate ( field. name . clone ( ) ) . into ( ) )
311+ } else {
312+ Ok ( ( ) )
313+ }
314+ }
315+ Ordering :: Greater => {
316+ // Current field position is greater than this field position,
317+ // so we've already had this field
318+ Err ( Details :: FieldNameDuplicate ( field. name . clone ( ) ) . into ( ) )
319+ }
320+ }
281321 }
282322
283- fn end ( self ) -> Result < usize , Error > {
323+ fn end ( mut self ) -> Result < usize , Error > {
324+ // Write any fields that are `serde(skip)` or `serde(skip_serializing)`
325+ while self . field_position != self . record_schema . fields . len ( ) {
326+ let field_info = & self . record_schema . fields [ self . field_position ] ;
327+ if let Some ( bytes) = self . field_cache . remove ( & self . field_position ) {
328+ self . ser
329+ . writer
330+ . write_all ( & bytes)
331+ . map_err ( Details :: WriteBytes ) ?;
332+ self . bytes_written += bytes. len ( ) ;
333+ self . field_position += 1 ;
334+ } else if let Some ( default) = & field_info. default {
335+ self . serialize_next_field ( field_info, default)
336+ . map_err ( |e| Details :: SerializeRecordFieldWithSchema {
337+ field_name : field_info. name . clone ( ) ,
338+ record_schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
339+ error : Box :: new ( e) ,
340+ } ) ?;
341+ } else {
342+ return Err ( Details :: MissingDefaultForSkippedField {
343+ field_name : field_info. name . clone ( ) ,
344+ schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
345+ }
346+ . into ( ) ) ;
347+ }
348+ }
349+
350+ debug_assert ! (
351+ self . field_cache. is_empty( ) ,
352+ "There should be no more unwritten fields at this point: {:?}" ,
353+ self . field_cache
354+ ) ;
284355 Ok ( self . bytes_written )
285356 }
286357}
@@ -304,7 +375,7 @@ impl<W: Write> ser::SerializeStruct for SchemaAwareWriteSerializeStruct<'_, '_,
304375 // self.item_count += 1;
305376 self . serialize_next_field ( field, value) . map_err ( |e| {
306377 Details :: SerializeRecordFieldWithSchema {
307- field_name : key,
378+ field_name : key. to_string ( ) ,
308379 record_schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
309380 error : Box :: new ( e) ,
310381 }
@@ -323,15 +394,20 @@ impl<W: Write> ser::SerializeStruct for SchemaAwareWriteSerializeStruct<'_, '_,
323394 . and_then ( |idx| self . record_schema . fields . get ( * idx) ) ;
324395
325396 if let Some ( skipped_field) = skipped_field {
326- // self.item_count += 1;
327- skipped_field
328- . default
329- . serialize ( & mut SchemaAwareWriteSerializer :: new (
330- self . ser . writer ,
331- & skipped_field. schema ,
332- self . ser . names ,
333- self . ser . enclosing_namespace . clone ( ) ,
334- ) ) ?;
397+ if let Some ( default) = & skipped_field. default {
398+ self . serialize_next_field ( skipped_field, default)
399+ . map_err ( |e| Details :: SerializeRecordFieldWithSchema {
400+ field_name : key. to_string ( ) ,
401+ record_schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
402+ error : Box :: new ( e) ,
403+ } ) ?;
404+ } else {
405+ return Err ( Details :: MissingDefaultForSkippedField {
406+ field_name : key. to_string ( ) ,
407+ schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
408+ }
409+ . into ( ) ) ;
410+ }
335411 } else {
336412 return Err ( Details :: GetField ( key. to_string ( ) ) . into ( ) ) ;
337413 }
@@ -1741,12 +1817,13 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut SchemaAwareWriteSerializer<'s
17411817mod tests {
17421818 use super :: * ;
17431819 use crate :: {
1744- Days , Duration , Millis , Months , decimal:: Decimal , error:: Details , schema:: ResolvedSchema ,
1820+ Days , Duration , Millis , Months , Reader , Writer , decimal:: Decimal , error:: Details ,
1821+ from_value, schema:: ResolvedSchema ,
17451822 } ;
17461823 use apache_avro_test_helper:: TestResult ;
17471824 use bigdecimal:: BigDecimal ;
17481825 use num_bigint:: { BigInt , Sign } ;
1749- use serde:: Serialize ;
1826+ use serde:: { Deserialize , Serialize } ;
17501827 use serde_bytes:: { ByteArray , Bytes } ;
17511828 use std:: {
17521829 collections:: { BTreeMap , HashMap } ,
@@ -2900,4 +2977,69 @@ mod tests {
29002977 string_record. serialize ( & mut serializer) ?;
29012978 Ok ( ( ) )
29022979 }
2980+
2981+ #[ test]
2982+ fn avro_rs_351_different_field_order_serde_vs_schema ( ) -> TestResult {
2983+ #[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
2984+ struct Foo {
2985+ a : String ,
2986+ b : String ,
2987+ c : usize ,
2988+ d : f64 ,
2989+ e : usize ,
2990+ }
2991+ let schema = Schema :: parse_str (
2992+ r#"
2993+ {
2994+ "type":"record",
2995+ "name":"Foo",
2996+ "fields": [
2997+ {
2998+ "name":"b",
2999+ "type":"string"
3000+ },
3001+ {
3002+ "name":"a",
3003+ "type":"string"
3004+ },
3005+ {
3006+ "name":"d",
3007+ "type":"double"
3008+ },
3009+ {
3010+ "name":"e",
3011+ "type":"long"
3012+ },
3013+ {
3014+ "name":"c",
3015+ "type":"long"
3016+ }
3017+ ]
3018+ }
3019+ "# ,
3020+ ) ?;
3021+
3022+ let mut writer = Writer :: new ( & schema, Vec :: new ( ) ) ?;
3023+ writer. append_ser ( Foo {
3024+ a : "Hello" . into ( ) ,
3025+ b : "World" . into ( ) ,
3026+ c : 42 ,
3027+ d : std:: f64:: consts:: PI ,
3028+ e : 5 ,
3029+ } ) ?;
3030+ let encoded = writer. into_inner ( ) ?;
3031+ let mut reader = Reader :: with_schema ( & schema, & encoded[ ..] ) ?;
3032+ let decoded = from_value :: < Foo > ( & reader. next ( ) . unwrap ( ) ?) ?;
3033+ assert_eq ! (
3034+ decoded,
3035+ Foo {
3036+ a: "Hello" . into( ) ,
3037+ b: "World" . into( ) ,
3038+ c: 42 ,
3039+ d: std:: f64 :: consts:: PI ,
3040+ e: 5
3041+ }
3042+ ) ;
3043+ Ok ( ( ) )
3044+ }
29033045}
0 commit comments