This is an automated email from the ASF dual-hosted git repository.
mgrigorov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/master by this push:
new d05ca14e7 AVRO-3821: [Rust] Encoding records should follow the schema
(#2417)
d05ca14e7 is described below
commit d05ca14e7de4281f5db464546dbc89537db1bcb1
Author: Martin Grigorov <[email protected]>
AuthorDate: Fri Aug 4 15:40:19 2023 +0300
AVRO-3821: [Rust] Encoding records should follow the schema (#2417)
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(())
}