in avro/src/types.rs [1103:1168]
fn resolve_record<S: Borrow<Schema> + Debug>(
self,
fields: &[RecordField],
names: &HashMap<Name, S>,
enclosing_namespace: &Namespace,
) -> Result<Self, Error> {
let mut items = match self {
Value::Map(items) => Ok(items),
Value::Record(fields) => Ok(fields.into_iter().collect::<HashMap<_, _>>()),
other => Err(Error::GetRecord {
expected: fields
.iter()
.map(|field| (field.name.clone(), field.schema.clone().into()))
.collect(),
other,
}),
}?;
let new_fields = fields
.iter()
.map(|field| {
let value = match items.remove(&field.name) {
Some(value) => value,
None => match field.default {
Some(ref value) => match field.schema {
Schema::Enum(EnumSchema {
ref symbols,
ref default,
..
}) => Value::from(value.clone()).resolve_enum(
symbols,
default,
&field.default.clone(),
)?,
Schema::Union(ref union_schema) => {
let first = &union_schema.variants()[0];
// NOTE: this match exists only to optimize null defaults for large
// backward-compatible schemas with many nullable fields
match first {
Schema::Null => Value::Union(0, Box::new(Value::Null)),
_ => Value::Union(
0,
Box::new(Value::from(value.clone()).resolve_internal(
first,
names,
enclosing_namespace,
&field.default,
)?),
),
}
}
_ => Value::from(value.clone()),
},
None => {
return Err(Error::GetField(field.name.clone()));
}
},
};
value
.resolve_internal(&field.schema, names, enclosing_namespace, &field.default)
.map(|value| (field.name.clone(), value))
})
.collect::<Result<Vec<_>, _>>()?;
Ok(Value::Record(new_fields))
}