Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions avro/src/documentation/serde_data_model_to_avro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
//! - `bool` => [`Schema::Boolean`]
//! - `i8`, `i16`, `i32`, `u8`, `u16` => [`Schema::Int`]
//! - `i64`, `u32` => [`Schema::Long`]
//! - `u64` => [`Schema::Fixed`]`(name: "u64", size: 8)`
//! - `u64` => [`Schema::Fixed`]`(name: "org.apache.avro.rust.u64", size: 8)`
//! - This is not a `Schema::Long` as that is a signed number of maximum 64 bits.
//! - `i128` => [`Schema::Fixed`]`(name: "i128", size: 16)`
//! - `u128` => [`Schema::Fixed`]`(name: "u128", size: 16)`
//! - `i128` => [`Schema::Fixed`]`(name: "org.apache.avro.rust.i128", size: 16)`
//! - `u128` => [`Schema::Fixed`]`(name: "org.apache.avro.rust.u128", size: 16)`
//! - `f32` => [`Schema::Float`]
//! - `f64` => [`Schema::Double`]
//! - `char` => [`Schema::String`]
Expand Down
6 changes: 6 additions & 0 deletions avro/src/schema/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@ impl Debug for Name {
}
}

impl AsRef<str> for Name {
fn as_ref(&self) -> &str {
self.namespace_and_name.as_ref()
}
}

impl Display for Name {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
assert!(
Expand Down
27 changes: 27 additions & 0 deletions avro/src/schema/union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,33 @@ impl UnionSchema {
Ok(None)
}

/// Get the index and schema for the provided Rust type name.
///
/// Will use `names` to resolve references.
pub(crate) fn find_fully_qualified_named_schema<'s>(
&'s self,
full_name: &str,
names: &'s HashMap<Name, impl Borrow<Schema>>,
) -> Result<Option<(usize, &'s Schema)>, Error> {
for index in self.named_index.iter().copied() {
let schema = &self.schemas[index];
if let Some(schema_name) = schema.name()
&& schema_name.as_ref() == full_name
{
let schema = if let Schema::Ref { name } = schema {
names
.get(name)
.ok_or_else(|| Details::SchemaResolutionError(name.clone()))?
.borrow()
} else {
schema
};
return Ok(Some((index, schema)));
}
}
Ok(None)
}

/// Find a [`Schema::Fixed`] with the given size.
///
/// Will use `names` to resolve references.
Expand Down
68 changes: 26 additions & 42 deletions avro/src/serde/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,17 +613,16 @@ where
}

impl AvroSchemaComponent for core::time::Duration {
/// The schema is [`Schema::Record`] with the name `Duration`.
/// The schema is [`Schema::Record`] with the name `org.apache.avro.rust.Duration`.
///
/// It has two fields:
/// - `secs` with the schema `Schema::Fixed(name: "u64", size: 8)`
/// - `secs` with the schema `Schema::Fixed(name: "org.apache.avro.rust.u64", size: 8)`
/// - `nanos` with the schema `Schema::Long`
fn get_schema_in_ctxt(
named_schemas: &mut HashSet<Name>,
enclosing_namespace: NamespaceRef,
) -> Schema {
let name = Name::new_with_enclosing_namespace("Duration", enclosing_namespace)
.expect("Name is valid");
let name = Name::new("org.apache.avro.rust.Duration").expect("Name is valid");
if named_schemas.contains(&name) {
Schema::Ref { name }
} else {
Expand Down Expand Up @@ -657,17 +656,13 @@ impl AvroSchemaComponent for core::time::Duration {
}

impl AvroSchemaComponent for uuid::Uuid {
/// The schema is [`Schema::Uuid`] with the name `uuid`.
/// The schema is [`Schema::Uuid`] with the name `org.apache.avro.rust.Uuid`.
///
/// The underlying schema is [`Schema::Fixed`] with a size of 16.
///
/// If you're using `human_readable: true` you need to override this schema with a `Schema::String`.
fn get_schema_in_ctxt(
named_schemas: &mut HashSet<Name>,
enclosing_namespace: NamespaceRef,
) -> Schema {
let name =
Name::new_with_enclosing_namespace("uuid", enclosing_namespace).expect("Name is valid");
fn get_schema_in_ctxt(named_schemas: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
let name = Name::new("org.apache.avro.rust.Uuid").expect("Name is valid");
if named_schemas.contains(&name) {
Schema::Ref { name }
} else {
Expand All @@ -692,13 +687,9 @@ impl AvroSchemaComponent for uuid::Uuid {
}

impl AvroSchemaComponent for u64 {
/// The schema is [`Schema::Fixed`] of size 8 with the name `u64`.
fn get_schema_in_ctxt(
named_schemas: &mut HashSet<Name>,
enclosing_namespace: NamespaceRef,
) -> Schema {
let name =
Name::new_with_enclosing_namespace("u64", enclosing_namespace).expect("Name is valid");
/// The schema is [`Schema::Fixed`] of size 8 with the name `org.apache.avro.rust.u64`.
fn get_schema_in_ctxt(named_schemas: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
let name = Name::new("org.apache.avro.rust.u64").expect("Name is valid");
if named_schemas.contains(&name) {
Schema::Ref { name }
} else {
Expand All @@ -723,13 +714,9 @@ impl AvroSchemaComponent for u64 {
}

impl AvroSchemaComponent for u128 {
/// The schema is [`Schema::Fixed`] of size 16 with the name `u128`.
fn get_schema_in_ctxt(
named_schemas: &mut HashSet<Name>,
enclosing_namespace: NamespaceRef,
) -> Schema {
let name =
Name::new_with_enclosing_namespace("u128", enclosing_namespace).expect("Name is valid");
/// The schema is [`Schema::Fixed`] of size 16 with the name `org.apache.avro.rust.u128`.
fn get_schema_in_ctxt(named_schemas: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
let name = Name::new("org.apache.avro.rust.u128").expect("Name is valid");
if named_schemas.contains(&name) {
Schema::Ref { name }
} else {
Expand All @@ -754,13 +741,9 @@ impl AvroSchemaComponent for u128 {
}

impl AvroSchemaComponent for i128 {
/// The schema is [`Schema::Fixed`] of size 16 with the name `i128`.
fn get_schema_in_ctxt(
named_schemas: &mut HashSet<Name>,
enclosing_namespace: NamespaceRef,
) -> Schema {
let name =
Name::new_with_enclosing_namespace("i128", enclosing_namespace).expect("Name is valid");
/// The schema is [`Schema::Fixed`] of size 16 with the name `org.apache.avro.rust.i128`.
fn get_schema_in_ctxt(named_schemas: &mut HashSet<Name>, _: NamespaceRef) -> Schema {
let name = Name::new("org.apache.avro.rust.i128").expect("Name is valid");
if named_schemas.contains(&name) {
Schema::Ref { name }
} else {
Expand Down Expand Up @@ -1028,7 +1011,7 @@ mod tests {
assert_eq!(
schema,
Schema::Fixed(FixedSchema {
name: Name::new("u64")?,
name: Name::new("org.apache.avro.rust.u64")?,
aliases: None,
doc: None,
size: 8,
Expand All @@ -1045,7 +1028,7 @@ mod tests {
assert_eq!(
schema,
Schema::Fixed(FixedSchema {
name: Name::new("i128")?,
name: Name::new("org.apache.avro.rust.i128")?,
aliases: None,
doc: None,
size: 16,
Expand All @@ -1062,7 +1045,7 @@ mod tests {
assert_eq!(
schema,
Schema::Fixed(FixedSchema {
name: Name::new("u128")?,
name: Name::new("org.apache.avro.rust.u128")?,
aliases: None,
doc: None,
size: 16,
Expand Down Expand Up @@ -1103,8 +1086,9 @@ mod tests {
r#"{
"type": "record",
"name": "Duration",
"namespace": "org.apache.avro.rust",
"fields": [
{ "name": "secs", "type": {"type": "fixed", "name": "u64", "size": 8} },
{ "name": "secs", "type": {"type": "fixed", "name": "u64", "namespace": "org.apache.avro.rust", "size": 8} },
{ "name": "nanos", "type": "long" }
]
}"#,
Expand Down Expand Up @@ -1166,10 +1150,10 @@ mod tests {
let schema = Schema::parse_str(
r#"{
"type": "record",
"name": "A2_u2_n_r4_uuid",
"name": "A2_u2_n_r25_org_apache_avro_rust_Uuid",
"fields": [
{ "name": "field_0", "type": ["null", {"type": "fixed", "logicalType": "uuid", "size": 16, "name": "uuid"}], "default": null },
{ "name": "field_1", "type": ["null", "uuid"], "default": null }
{ "name": "field_0", "type": ["null", {"type": "fixed", "logicalType": "uuid", "size": 16, "name": "Uuid", "namespace": "org.apache.avro.rust"}], "default": null },
{ "name": "field_1", "type": ["null", "org.apache.avro.rust.Uuid"], "default": null }
]
}"#,
)?;
Expand Down Expand Up @@ -1211,10 +1195,10 @@ mod tests {
let schema = Schema::parse_str(
r#"{
"type": "record",
"name": "T3_u2_n_r4_uuid_r4_uuid_s",
"name": "T3_u2_n_r25_org_apache_avro_rust_Uuid_r25_org_apache_avro_rust_Uuid_s",
"fields": [
{ "name": "field_0", "type": ["null", {"type": "fixed", "logicalType": "uuid", "size": 16, "name": "uuid"}], "default": null },
{ "name": "field_1", "type": "uuid" },
{ "name": "field_0", "type": ["null", {"type": "fixed", "logicalType": "uuid", "size": 16, "name": "Uuid", "namespace": "org.apache.avro.rust"}], "default": null },
{ "name": "field_1", "type": "org.apache.avro.rust.Uuid" },
{ "name": "field_2", "type": "string" }
]
}"#,
Expand Down
28 changes: 22 additions & 6 deletions avro/src/serde/deser_schema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,16 @@ impl<'de, 's, 'r, R: Read, S: Borrow<Schema>> Deserializer<'de>
V: Visitor<'de>,
{
match self.schema {
Schema::Fixed(fixed) if fixed.size == 16 && fixed.name.name() == "i128" => {
Schema::Fixed(fixed)
if fixed.size == 16 && fixed.name.as_ref() == "org.apache.avro.rust.i128" =>
{
visitor.visit_i128(i128::from_le_bytes(self.read_array()?))
}
Schema::Union(union) => self.with_union(union)?.deserialize_i128(visitor),
_ => Err(self.error("i128", r#"Expected Schema::Fixed(name: "i128", size: 16)"#)),
_ => Err(self.error(
"i128",
r#"Expected Schema::Fixed(name: "org.apache.avro.rust.i128", size: 16)"#,
)),
}
}

Expand Down Expand Up @@ -405,11 +410,16 @@ impl<'de, 's, 'r, R: Read, S: Borrow<Schema>> Deserializer<'de>
V: Visitor<'de>,
{
match self.schema {
Schema::Fixed(fixed) if fixed.size == 8 && fixed.name.name() == "u64" => {
Schema::Fixed(fixed)
if fixed.size == 8 && fixed.name.as_ref() == "org.apache.avro.rust.u64" =>
{
visitor.visit_u64(u64::from_le_bytes(self.read_array()?))
}
Schema::Union(union) => self.with_union(union)?.deserialize_u64(visitor),
_ => Err(self.error("u64", r#"Expected Schema::Fixed(name: "u64", size: 8)"#)),
_ => Err(self.error(
"u64",
r#"Expected Schema::Fixed(name: "org.apache.avro.rust.u64", size: 8)"#,
)),
}
}

Expand All @@ -418,11 +428,16 @@ impl<'de, 's, 'r, R: Read, S: Borrow<Schema>> Deserializer<'de>
V: Visitor<'de>,
{
match self.schema {
Schema::Fixed(fixed) if fixed.size == 16 && fixed.name.name() == "u128" => {
Schema::Fixed(fixed)
if fixed.size == 16 && fixed.name.as_ref() == "org.apache.avro.rust.u128" =>
{
visitor.visit_u128(u128::from_le_bytes(self.read_array()?))
}
Schema::Union(union) => self.with_union(union)?.deserialize_u128(visitor),
_ => Err(self.error("u128", r#"Expected Schema::Fixed(name: "u128", size: 16)"#)),
_ => Err(self.error(
"u128",
r#"Expected Schema::Fixed(name: "org.apache.avro.rust.u128", size: 16)"#,
)),
}
}

Expand Down Expand Up @@ -1199,6 +1214,7 @@ mod tests {
"type": {
"type": "fixed",
"name": "u64",
"namespace": "org.apache.avro.rust",
"size": 8
}
}]
Expand Down
Loading
Loading