This is an automated email from the ASF dual-hosted git repository. mgrigorov pushed a commit to branch avro-3821-fix-encoding-of-records in repository https://gitbox.apache.org/repos/asf/avro.git
commit ccde2e5d76b5091a0dcd5ffdba3b5427ab4c2d60 Author: Martin Tzvetanov Grigorov <[email protected]> AuthorDate: Fri Aug 4 15:22:20 2023 +0300 AVRO-3821: [Rust] Encoding records should follow the schema When encoding Value::Record the logic should use the order of the fields in the schema instead of the order in the Value::Record Signed-off-by: Martin Tzvetanov Grigorov <[email protected]> --- lang/rust/avro/src/encode.rs | 34 ++++++++++++++++++++-------------- lang/rust/avro/tests/schema.rs | 11 +++++++++-- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/lang/rust/avro/src/encode.rs b/lang/rust/avro/src/encode.rs index 94436b86f..e8080f04b 100644 --- a/lang/rust/avro/src/encode.rs +++ b/lang/rust/avro/src/encode.rs @@ -196,33 +196,39 @@ pub(crate) fn encode_internal<S: Borrow<Schema>>( }); } } - Value::Record(fields) => { + Value::Record(value_fields) => { if let Schema::Record(RecordSchema { ref name, fields: ref schema_fields, - ref lookup, .. }) = *schema { let record_namespace = name.fully_qualified_name(enclosing_namespace).namespace; - for (name, value) in fields.iter() { - match lookup.get(name) { - Some(idx) => { - encode_internal( - value, - &schema_fields[*idx].schema, - names, - &record_namespace, - buffer, - )?; - } + + let mut lookup = HashMap::new(); + value_fields.iter().for_each(|(name, field)| { + lookup.insert(name, field); + }); + + for schema_field in schema_fields.iter() { + let name = &schema_field.name; + let value = match lookup.get(name) { + Some(value) => value, None => { return Err(Error::NoEntryInLookupTable( name.clone(), format!("{lookup:?}"), )); } - } + }; + + encode_internal( + value, + &schema_field.schema, + names, + &record_namespace, + buffer, + )?; } } else { error!("invalid schema type for Record: {:?}", schema); diff --git a/lang/rust/avro/tests/schema.rs b/lang/rust/avro/tests/schema.rs index 00be0ab01..58e95e8cc 100644 --- a/lang/rust/avro/tests/schema.rs +++ b/lang/rust/avro/tests/schema.rs @@ -18,6 +18,7 @@ use std::io::{Cursor, Read}; use apache_avro::{ + from_avro_datum, from_value, schema::{EnumSchema, FixedSchema, Name, RecordField, RecordSchema}, to_avro_datum, to_value, types::{Record, Value}, @@ -1452,7 +1453,7 @@ fn avro_old_issue_47() -> TestResult { use serde::{Deserialize, Serialize}; - #[derive(Deserialize, Serialize)] + #[derive(Deserialize, Serialize, Debug, Clone, PartialEq)] pub struct MyRecord { b: String, a: i64, @@ -1463,7 +1464,13 @@ fn avro_old_issue_47() -> TestResult { a: 1, }; - let _ = to_avro_datum(&schema, to_value(record)?)?; + let ser_value = to_value(record.clone())?; + let serialized_bytes = to_avro_datum(&schema, ser_value)?; + + let de_value = &from_avro_datum(&schema, &mut &*serialized_bytes, None)?; + let deserialized_record = from_value::<MyRecord>(de_value)?; + + assert_eq!(record, deserialized_record); Ok(()) }
