[ https://issues.apache.org/jira/browse/AVRO-3507?focusedWorklogId=767711&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-767711 ]
ASF GitHub Bot logged work on AVRO-3507: ---------------------------------------- Author: ASF GitHub Bot Created on: 08/May/22 19:45 Start Date: 08/May/22 19:45 Worklog Time Spent: 10m Work Description: martin-g commented on code in PR #1681: URL: https://github.com/apache/avro/pull/1681#discussion_r867534037 ########## lang/rust/avro/src/reader.rs: ########## @@ -569,4 +663,158 @@ mod tests { let reader = Reader::new(&result[..]).unwrap(); assert_eq!(reader.user_metadata(), &user_meta_data); } + + #[derive(Deserialize, Clone, PartialEq, Debug)] + struct TestSingleObjectReader { + a: i64, + b: f64, + c: Vec<String>, + } + + impl AvroSchema for TestSingleObjectReader { + fn get_schema() -> Schema { + let schema = r#" + { + "type":"record", + "name":"TestSingleObjectWrtierSerialize", + "fields":[ + { + "name":"a", + "type":"long" + }, + { + "name":"b", + "type":"double" + }, + { + "name":"c", + "type":{ + "type":"array", + "items":"string" + } + } + ] + } + "#; + Schema::parse_str(schema).unwrap() + } + } + + impl From<Value> for TestSingleObjectReader { + fn from(obj: Value) -> TestSingleObjectReader { + if let Value::Record(fields) = obj { + let mut a = None; + let mut b = None; + let mut c = vec![]; + for (field_name, v) in fields { + match (field_name.as_str(), v) { + ("a", Value::Long(i)) => a = Some(i), + ("b", Value::Double(d)) => b = Some(d), + ("c", Value::Array(v)) => { + for inner_val in v { + if let Value::String(s) = inner_val { + c.push(s); + } + } + } + _ => panic!("Unexpected pair"), Review Comment: ```suggestion (key, value) => panic!("Unexpected pair: {:?} -> {:?}", key, value), ``` ########## lang/rust/avro/examples/test_interop_single_object_encoding.rs: ########## @@ -58,3 +63,15 @@ fn main() { .expect("Should encode"); assert_eq!(file_message, generated_encoding) } + +fn test_read() { + let file_message = std::fs::read(format!("{}/test_message.bin", RESOURCES_FOLDER)) Review Comment: Is this `read` really needed ? ########## lang/rust/avro/src/reader.rs: ########## @@ -569,4 +663,158 @@ mod tests { let reader = Reader::new(&result[..]).unwrap(); assert_eq!(reader.user_metadata(), &user_meta_data); } + + #[derive(Deserialize, Clone, PartialEq, Debug)] + struct TestSingleObjectReader { + a: i64, + b: f64, + c: Vec<String>, + } + + impl AvroSchema for TestSingleObjectReader { + fn get_schema() -> Schema { + let schema = r#" + { + "type":"record", + "name":"TestSingleObjectWrtierSerialize", + "fields":[ + { + "name":"a", + "type":"long" + }, + { + "name":"b", + "type":"double" + }, + { + "name":"c", + "type":{ + "type":"array", + "items":"string" + } + } + ] + } + "#; + Schema::parse_str(schema).unwrap() + } + } + + impl From<Value> for TestSingleObjectReader { + fn from(obj: Value) -> TestSingleObjectReader { + if let Value::Record(fields) = obj { + let mut a = None; + let mut b = None; + let mut c = vec![]; + for (field_name, v) in fields { + match (field_name.as_str(), v) { + ("a", Value::Long(i)) => a = Some(i), + ("b", Value::Double(d)) => b = Some(d), + ("c", Value::Array(v)) => { + for inner_val in v { + if let Value::String(s) = inner_val { + c.push(s); + } + } + } + _ => panic!("Unexpected pair"), + } + } + TestSingleObjectReader { + a: a.unwrap(), + b: b.unwrap(), + c, + } + } else { + panic!("Should be record value") Review Comment: ```suggestion panic!("Should be record value: {:?}", obj) ``` ########## lang/rust/avro/src/reader.rs: ########## @@ -569,4 +663,158 @@ mod tests { let reader = Reader::new(&result[..]).unwrap(); assert_eq!(reader.user_metadata(), &user_meta_data); } + + #[derive(Deserialize, Clone, PartialEq, Debug)] + struct TestSingleObjectReader { + a: i64, + b: f64, + c: Vec<String>, + } + + impl AvroSchema for TestSingleObjectReader { + fn get_schema() -> Schema { + let schema = r#" + { + "type":"record", + "name":"TestSingleObjectWrtierSerialize", + "fields":[ + { + "name":"a", + "type":"long" + }, + { + "name":"b", + "type":"double" + }, + { + "name":"c", + "type":{ + "type":"array", + "items":"string" + } + } + ] + } + "#; + Schema::parse_str(schema).unwrap() + } + } + + impl From<Value> for TestSingleObjectReader { + fn from(obj: Value) -> TestSingleObjectReader { + if let Value::Record(fields) = obj { + let mut a = None; + let mut b = None; + let mut c = vec![]; + for (field_name, v) in fields { + match (field_name.as_str(), v) { + ("a", Value::Long(i)) => a = Some(i), + ("b", Value::Double(d)) => b = Some(d), + ("c", Value::Array(v)) => { + for inner_val in v { + if let Value::String(s) = inner_val { + c.push(s); + } + } + } + _ => panic!("Unexpected pair"), + } + } + TestSingleObjectReader { + a: a.unwrap(), + b: b.unwrap(), + c, + } + } else { + panic!("Should be record value") + } + } + } + + impl From<TestSingleObjectReader> for Value { + fn from(obj: TestSingleObjectReader) -> Value { + Value::Record(vec![ + ("a".into(), obj.a.into()), + ("b".into(), obj.b.into()), + ( + "c".into(), + Value::Array(obj.c.into_iter().map(|s| s.into()).collect()), + ), + ]) + } + } + + #[test] + fn test_single_object_reader() { + let obj = TestSingleObjectReader { + a: 42, + b: 3.33, + c: vec!["cat".into(), "dog".into()], + }; + let mut to_read = Vec::<u8>::new(); + to_read.extend_from_slice(&[0xC3, 0x01]); + to_read.extend_from_slice( + &TestSingleObjectReader::get_schema() + .fingerprint::<Rabin>() + .bytes[..], + ); + encode( + &obj.clone().into(), + &TestSingleObjectReader::get_schema(), + &mut to_read, + ) + .expect("Encode should succeed"); + let mut to_read = &to_read[..]; + let generic_reader = GenericSingleObjectReader::new(TestSingleObjectReader::get_schema()) + .expect("Schema should resolve"); + let val = generic_reader + .read_value(&mut to_read) + .expect("Should read"); + let expected_value: Value = obj.into(); + assert_eq!(expected_value, val); + } + + #[test] + fn test_reader_parity() { Review Comment: ```suggestion fn test_avro_3507_reader_parity() { ``` ########## lang/rust/avro/src/reader.rs: ########## @@ -569,4 +663,158 @@ mod tests { let reader = Reader::new(&result[..]).unwrap(); assert_eq!(reader.user_metadata(), &user_meta_data); } + + #[derive(Deserialize, Clone, PartialEq, Debug)] + struct TestSingleObjectReader { + a: i64, + b: f64, + c: Vec<String>, + } + + impl AvroSchema for TestSingleObjectReader { + fn get_schema() -> Schema { + let schema = r#" + { + "type":"record", + "name":"TestSingleObjectWrtierSerialize", + "fields":[ + { + "name":"a", + "type":"long" + }, + { + "name":"b", + "type":"double" + }, + { + "name":"c", + "type":{ + "type":"array", + "items":"string" + } + } + ] + } + "#; + Schema::parse_str(schema).unwrap() + } + } + + impl From<Value> for TestSingleObjectReader { + fn from(obj: Value) -> TestSingleObjectReader { + if let Value::Record(fields) = obj { + let mut a = None; + let mut b = None; + let mut c = vec![]; + for (field_name, v) in fields { + match (field_name.as_str(), v) { + ("a", Value::Long(i)) => a = Some(i), + ("b", Value::Double(d)) => b = Some(d), + ("c", Value::Array(v)) => { + for inner_val in v { + if let Value::String(s) = inner_val { + c.push(s); + } + } + } + _ => panic!("Unexpected pair"), + } + } + TestSingleObjectReader { + a: a.unwrap(), + b: b.unwrap(), + c, + } + } else { + panic!("Should be record value") + } + } + } + + impl From<TestSingleObjectReader> for Value { + fn from(obj: TestSingleObjectReader) -> Value { + Value::Record(vec![ + ("a".into(), obj.a.into()), + ("b".into(), obj.b.into()), + ( + "c".into(), + Value::Array(obj.c.into_iter().map(|s| s.into()).collect()), + ), + ]) + } + } + + #[test] + fn test_single_object_reader() { Review Comment: ```suggestion fn test_avro_3507_single_object_reader() { ``` ########## lang/rust/avro/src/error.rs: ########## @@ -337,6 +337,9 @@ pub enum Error { #[error("wrong magic in header")] HeaderMagic, + #[error("Message Header mismatch. Expected: {0:?}. Actual: {1:?}")] + MessageHeaderMismatch([u8; 10], [u8; 10]), Review Comment: SingleObjectHeaderMismatch ?! Issue Time Tracking ------------------- Worklog Id: (was: 767711) Time Spent: 20m (was: 10m) > [rust] Implement Single Object Reader > ------------------------------------- > > Key: AVRO-3507 > URL: https://issues.apache.org/jira/browse/AVRO-3507 > Project: Apache Avro > Issue Type: New Feature > Reporter: Jack Klamer > Assignee: Jack Klamer > Priority: Major > Labels: pull-request-available > Time Spent: 20m > Remaining Estimate: 0h > > The spec contains a definition for Single object Encoding: > https://avro.apache.org/docs/current/spec.html#single_object_encoding > Rust should have a compatible reader -- This message was sent by Atlassian Jira (v8.20.7#820007)