@@ -25,7 +25,7 @@ use crate::{
2525 schema:: { Name , NamesRef , Namespace , RecordField , RecordSchema , Schema } ,
2626} ;
2727use bigdecimal:: BigDecimal ;
28- use serde:: { Serialize , ser} ;
28+ use serde:: ser;
2929use std:: { borrow:: Cow , io:: Write , str:: FromStr } ;
3030
3131const COLLECTION_SERIALIZER_ITEM_LIMIT : usize = 1024 ;
@@ -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 : Vec < ( usize , Vec < u8 > ) > ,
254+ next_field : 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 : Vec :: new ( ) ,
267+ next_field : 0 ,
263268 bytes_written : 0 ,
264269 }
265270 }
@@ -268,19 +273,86 @@ 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) ?;
276+ if field. position == self . next_field {
277+ // If we receive fields in order, write them directly to the main writer
278+ let mut value_ser = SchemaAwareWriteSerializer :: new (
279+ & mut * self . ser . writer ,
280+ & field. schema ,
281+ self . ser . names ,
282+ self . ser . enclosing_namespace . clone ( ) ,
283+ ) ;
284+ self . bytes_written += value. serialize ( & mut value_ser) ?;
279285
286+ self . next_field += 1 ;
287+ while let Some ( index) = self
288+ . field_cache
289+ . iter ( )
290+ . position ( |( pos, _) | pos == & self . next_field )
291+ {
292+ let ( _, bytes) = self . field_cache . remove ( index) ;
293+ self . ser
294+ . writer
295+ . write_all ( & bytes)
296+ . map_err ( Details :: WriteBytes ) ?;
297+ self . bytes_written += bytes. len ( ) ;
298+ self . next_field += 1 ;
299+ }
300+ } else {
301+ // This field is in the wrong order, write it to a temporary buffer so we can add it at the right time
302+ let mut bytes = Vec :: new ( ) ;
303+ let mut value_ser = SchemaAwareWriteSerializer :: new (
304+ & mut bytes,
305+ & field. schema ,
306+ self . ser . names ,
307+ self . ser . enclosing_namespace . clone ( ) ,
308+ ) ;
309+ value. serialize ( & mut value_ser) ?;
310+ self . field_cache . push ( ( field. position , bytes) ) ;
311+ }
280312 Ok ( ( ) )
281313 }
282314
283- fn end ( self ) -> Result < usize , Error > {
315+ fn end ( mut self ) -> Result < usize , Error > {
316+ // Write any fields that are `serde(skip)` or `serde(skip_serializing)`
317+ while self . next_field != self . record_schema . fields . len ( ) {
318+ let field_info = & self . record_schema . fields [ self . next_field ] ;
319+ if let Some ( index) = self
320+ . field_cache
321+ . iter ( )
322+ . position ( |( pos, _) | pos == & self . next_field )
323+ {
324+ let ( _, bytes) = self . field_cache . remove ( index) ;
325+ self . ser
326+ . writer
327+ . write_all ( & bytes)
328+ . map_err ( Details :: WriteBytes ) ?;
329+ self . bytes_written += bytes. len ( ) ;
330+ self . next_field += 1 ;
331+ } else if let Some ( default) = & field_info. default {
332+ self . serialize_next_field ( field_info, default)
333+ . map_err ( |e| Details :: SerializeRecordFieldWithSchema {
334+ field_name : field_info. name . clone ( ) ,
335+ record_schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
336+ error : Box :: new ( e) ,
337+ } ) ?;
338+ } else {
339+ return Err ( Details :: MissingDefaultForSkippedField {
340+ field_name : field_info. name . clone ( ) ,
341+ schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
342+ }
343+ . into ( ) ) ;
344+ }
345+ }
346+
347+ // Check if all fields were written
348+ if self . next_field != self . record_schema . fields . len ( ) {
349+ let name = self . record_schema . fields [ self . next_field ] . name . clone ( ) ;
350+ return Err ( Details :: GetField ( name) . into ( ) ) ;
351+ }
352+ assert ! (
353+ self . field_cache. is_empty( ) ,
354+ "There should be no more unwritten fields at this point"
355+ ) ;
284356 Ok ( self . bytes_written )
285357 }
286358}
@@ -304,7 +376,7 @@ impl<W: Write> ser::SerializeStruct for SchemaAwareWriteSerializeStruct<'_, '_,
304376 // self.item_count += 1;
305377 self . serialize_next_field ( field, value) . map_err ( |e| {
306378 Details :: SerializeRecordFieldWithSchema {
307- field_name : key,
379+ field_name : key. to_string ( ) ,
308380 record_schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
309381 error : Box :: new ( e) ,
310382 }
@@ -323,15 +395,20 @@ impl<W: Write> ser::SerializeStruct for SchemaAwareWriteSerializeStruct<'_, '_,
323395 . and_then ( |idx| self . record_schema . fields . get ( * idx) ) ;
324396
325397 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- ) ) ?;
398+ if let Some ( default) = & skipped_field. default {
399+ self . serialize_next_field ( skipped_field, default)
400+ . map_err ( |e| Details :: SerializeRecordFieldWithSchema {
401+ field_name : key. to_string ( ) ,
402+ record_schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
403+ error : Box :: new ( e) ,
404+ } ) ?;
405+ } else {
406+ return Err ( Details :: MissingDefaultForSkippedField {
407+ field_name : key. to_string ( ) ,
408+ schema : Schema :: Record ( self . record_schema . clone ( ) ) ,
409+ }
410+ . into ( ) ) ;
411+ }
335412 } else {
336413 return Err ( Details :: GetField ( key. to_string ( ) ) . into ( ) ) ;
337414 }
@@ -1741,12 +1818,13 @@ impl<'a, 's, W: Write> ser::Serializer for &'a mut SchemaAwareWriteSerializer<'s
17411818mod tests {
17421819 use super :: * ;
17431820 use crate :: {
1744- Days , Duration , Millis , Months , decimal:: Decimal , error:: Details , schema:: ResolvedSchema ,
1821+ Days , Duration , Millis , Months , Reader , Writer , decimal:: Decimal , error:: Details ,
1822+ from_value, schema:: ResolvedSchema ,
17451823 } ;
17461824 use apache_avro_test_helper:: TestResult ;
17471825 use bigdecimal:: BigDecimal ;
17481826 use num_bigint:: { BigInt , Sign } ;
1749- use serde:: Serialize ;
1827+ use serde:: { Deserialize , Serialize } ;
17501828 use serde_bytes:: { ByteArray , Bytes } ;
17511829 use std:: {
17521830 collections:: { BTreeMap , HashMap } ,
@@ -2900,4 +2978,50 @@ mod tests {
29002978 string_record. serialize ( & mut serializer) ?;
29012979 Ok ( ( ) )
29022980 }
2981+
2982+ #[ test]
2983+ fn different_field_order_serde_vs_schema ( ) -> TestResult {
2984+ #[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
2985+ struct Foo {
2986+ a : String ,
2987+ b : String ,
2988+ }
2989+ let schema = Schema :: parse_str (
2990+ r#"
2991+ {
2992+ "type":"record",
2993+ "name":"Foo",
2994+ "fields": [
2995+ {
2996+ "name":"b",
2997+ "type":"string"
2998+ },
2999+ {
3000+ "name":"a",
3001+ "type":"string"
3002+ }
3003+ ]
3004+ }
3005+ "# ,
3006+ ) ?;
3007+
3008+ let mut writer = Writer :: new ( & schema, Vec :: new ( ) ) ?;
3009+ if let Err ( e) = writer. append_ser ( Foo {
3010+ a : "Hello" . into ( ) ,
3011+ b : "World" . into ( ) ,
3012+ } ) {
3013+ panic ! ( "{e:?}" ) ;
3014+ }
3015+ let encoded = writer. into_inner ( ) ?;
3016+ let mut reader = Reader :: with_schema ( & schema, & encoded[ ..] ) ?;
3017+ let decoded = from_value :: < Foo > ( & reader. next ( ) . unwrap ( ) ?) ?;
3018+ assert_eq ! (
3019+ decoded,
3020+ Foo {
3021+ a: "Hello" . into( ) ,
3022+ b: "World" . into( ) ,
3023+ }
3024+ ) ;
3025+ Ok ( ( ) )
3026+ }
29033027}
0 commit comments