in avro/src/de.rs [1332:1539]
fn test_from_value_with_union() -> TestResult {
// AVRO-3232 test for deserialize_any on missing fields on the destination struct:
// Error: DeserializeValue("Unsupported union")
// Error: DeserializeValue("incorrect value of type: String")
#[derive(Debug, Deserialize, PartialEq, Eq)]
struct RecordInUnion {
record_in_union: i32,
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
enum EnumInStruct {
Val1,
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
struct StructWithMissingFields {
a_string: String,
a_record: Option<RecordInUnion>,
an_array: Option<[bool; 2]>,
a_union_map: Option<HashMap<String, i64>>,
an_enum: EnumInStruct,
}
let raw_map: HashMap<String, i64> = [
("long_one".to_string(), 1),
("long_two".to_string(), 2),
("long_three".to_string(), 3),
("time_micros_a".to_string(), 123),
("timestamp_millis_b".to_string(), 234),
("timestamp_micros_c".to_string(), 345),
("timestamp_nanos_d".to_string(), 345_001),
("local_timestamp_millis_d".to_string(), 678),
("local_timestamp_micros_e".to_string(), 789),
("local_timestamp_nanos_f".to_string(), 345_002),
]
.iter()
.cloned()
.collect();
let value_map = raw_map
.iter()
.map(|(k, v)| match k {
key if key.starts_with("long_") => (k.clone(), Value::Long(*v)),
key if key.starts_with("time_micros_") => (k.clone(), Value::TimeMicros(*v)),
key if key.starts_with("timestamp_millis_") => {
(k.clone(), Value::TimestampMillis(*v))
}
key if key.starts_with("timestamp_micros_") => {
(k.clone(), Value::TimestampMicros(*v))
}
key if key.starts_with("timestamp_nanos_") => {
(k.clone(), Value::TimestampNanos(*v))
}
key if key.starts_with("local_timestamp_millis_") => {
(k.clone(), Value::LocalTimestampMillis(*v))
}
key if key.starts_with("local_timestamp_micros_") => {
(k.clone(), Value::LocalTimestampMicros(*v))
}
key if key.starts_with("local_timestamp_nanos_") => {
(k.clone(), Value::LocalTimestampNanos(*v))
}
_ => unreachable!("unexpected key: {:?}", k),
})
.collect();
let record = Value::Record(vec![
(
"a_string".to_string(),
Value::String("a valid message field".to_string()),
),
(
"a_non_existing_string".to_string(),
Value::String("a string".to_string()),
),
(
"a_union_string".to_string(),
Value::Union(0, Box::new(Value::String("a union string".to_string()))),
),
(
"a_union_long".to_string(),
Value::Union(0, Box::new(Value::Long(412))),
),
(
"a_union_long".to_string(),
Value::Union(0, Box::new(Value::Long(412))),
),
(
"a_time_micros".to_string(),
Value::Union(0, Box::new(Value::TimeMicros(123))),
),
(
"a_non_existing_time_micros".to_string(),
Value::Union(0, Box::new(Value::TimeMicros(-123))),
),
(
"a_timestamp_millis".to_string(),
Value::Union(0, Box::new(Value::TimestampMillis(234))),
),
(
"a_non_existing_timestamp_millis".to_string(),
Value::Union(0, Box::new(Value::TimestampMillis(-234))),
),
(
"a_timestamp_micros".to_string(),
Value::Union(0, Box::new(Value::TimestampMicros(345))),
),
(
"a_non_existing_timestamp_micros".to_string(),
Value::Union(0, Box::new(Value::TimestampMicros(-345))),
),
(
"a_timestamp_nanos".to_string(),
Value::Union(0, Box::new(Value::TimestampNanos(345))),
),
(
"a_non_existing_timestamp_nanos".to_string(),
Value::Union(0, Box::new(Value::TimestampNanos(-345))),
),
(
"a_local_timestamp_millis".to_string(),
Value::Union(0, Box::new(Value::LocalTimestampMillis(678))),
),
(
"a_non_existing_local_timestamp_millis".to_string(),
Value::Union(0, Box::new(Value::LocalTimestampMillis(-678))),
),
(
"a_local_timestamp_micros".to_string(),
Value::Union(0, Box::new(Value::LocalTimestampMicros(789))),
),
(
"a_non_existing_local_timestamp_micros".to_string(),
Value::Union(0, Box::new(Value::LocalTimestampMicros(-789))),
),
(
"a_local_timestamp_nanos".to_string(),
Value::Union(0, Box::new(Value::LocalTimestampNanos(789))),
),
(
"a_non_existing_local_timestamp_nanos".to_string(),
Value::Union(0, Box::new(Value::LocalTimestampNanos(-789))),
),
(
"a_record".to_string(),
Value::Union(
0,
Box::new(Value::Record(vec![(
"record_in_union".to_string(),
Value::Int(-2),
)])),
),
),
(
"a_non_existing_record".to_string(),
Value::Union(
0,
Box::new(Value::Record(vec![("blah".to_string(), Value::Int(-22))])),
),
),
(
"an_array".to_string(),
Value::Union(
0,
Box::new(Value::Array(vec![
Value::Boolean(true),
Value::Boolean(false),
])),
),
),
(
"a_non_existing_array".to_string(),
Value::Union(
0,
Box::new(Value::Array(vec![
Value::Boolean(false),
Value::Boolean(true),
])),
),
),
(
"a_union_map".to_string(),
Value::Union(0, Box::new(Value::Map(value_map))),
),
(
"a_non_existing_union_map".to_string(),
Value::Union(0, Box::new(Value::Map(HashMap::new()))),
),
("an_enum".to_string(), Value::Enum(0, "Val1".to_owned())),
(
"a_non_existing_enum".to_string(),
Value::Enum(0, "AnotherVariant".to_owned()),
),
]);
let deserialized: StructWithMissingFields = crate::from_value(&record)?;
let reference = StructWithMissingFields {
a_string: "a valid message field".to_string(),
a_record: Some(RecordInUnion {
record_in_union: -2,
}),
an_array: Some([true, false]),
a_union_map: Some(raw_map),
an_enum: EnumInStruct::Val1,
};
assert_eq!(deserialized, reference);
Ok(())
}