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(())
 }
 

Reply via email to