This is an automated email from the ASF dual-hosted git repository.

kriskras99 pushed a commit to branch feat/namespace_for_named_types
in repository https://gitbox.apache.org/repos/asf/avro-rs.git

commit 6f2a27b638ac2a5fc1b1416db34d8c442ac49e14
Author: Kriskras99 <[email protected]>
AuthorDate: Thu Apr 9 08:32:20 2026 +0200

    wip: Namespace for named types defined by this library
---
 avro/src/schema/name.rs            |  6 ++++++
 avro/src/schema/union.rs           | 27 +++++++++++++++++++++++++
 avro/src/serde/derive.rs           | 41 ++++++++++++++------------------------
 avro/src/serde/deser_schema/mod.rs | 27 +++++++++++++++++++------
 avro/src/serde/ser_schema/mod.rs   | 27 +++++++++++++++++++------
 avro/src/serde/ser_schema/union.rs | 15 +++++++++++---
 avro_derive/tests/derive.rs        | 10 +++++++---
 7 files changed, 109 insertions(+), 44 deletions(-)

diff --git a/avro/src/schema/name.rs b/avro/src/schema/name.rs
index 31a5f1e..c03e58b 100644
--- a/avro/src/schema/name.rs
+++ b/avro/src/schema/name.rs
@@ -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!(
diff --git a/avro/src/schema/union.rs b/avro/src/schema/union.rs
index 9a2a1f3..1561c11 100644
--- a/avro/src/schema/union.rs
+++ b/avro/src/schema/union.rs
@@ -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.
diff --git a/avro/src/serde/derive.rs b/avro/src/serde/derive.rs
index 573b6b3..8c722cf 100644
--- a/avro/src/serde/derive.rs
+++ b/avro/src/serde/derive.rs
@@ -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 {
@@ -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 {
@@ -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 {
@@ -723,13 +714,12 @@ impl AvroSchemaComponent for u64 {
 }
 
 impl AvroSchemaComponent for u128 {
-    /// The schema is [`Schema::Fixed`] of size 16 with the name `u128`.
+    /// 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>,
-        enclosing_namespace: NamespaceRef,
+        _: NamespaceRef,
     ) -> Schema {
-        let name =
-            Name::new_with_enclosing_namespace("u128", 
enclosing_namespace).expect("Name is valid");
+        let name = Name::new("org.apache.avro.rust.u128").expect("Name is 
valid");
         if named_schemas.contains(&name) {
             Schema::Ref { name }
         } else {
@@ -754,13 +744,12 @@ impl AvroSchemaComponent for u128 {
 }
 
 impl AvroSchemaComponent for i128 {
-    /// The schema is [`Schema::Fixed`] of size 16 with the name `i128`.
+    /// 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>,
-        enclosing_namespace: NamespaceRef,
+        _: NamespaceRef,
     ) -> Schema {
-        let name =
-            Name::new_with_enclosing_namespace("i128", 
enclosing_namespace).expect("Name is valid");
+        let name = Name::new("org.apache.avro.rust.i128").expect("Name is 
valid");
         if named_schemas.contains(&name) {
             Schema::Ref { name }
         } else {
diff --git a/avro/src/serde/deser_schema/mod.rs 
b/avro/src/serde/deser_schema/mod.rs
index ba8590c..0ece35b 100644
--- a/avro/src/serde/deser_schema/mod.rs
+++ b/avro/src/serde/deser_schema/mod.rs
@@ -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)"#,
+            )),
         }
     }
 
@@ -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)"#,
+            )),
         }
     }
 
@@ -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)"#,
+            )),
         }
     }
 
diff --git a/avro/src/serde/ser_schema/mod.rs b/avro/src/serde/ser_schema/mod.rs
index d6975e2..b4daf3a 100644
--- a/avro/src/serde/ser_schema/mod.rs
+++ b/avro/src/serde/ser_schema/mod.rs
@@ -249,13 +249,18 @@ impl<'s, 'w, W: Write, S: Borrow<Schema>> Serializer for 
SchemaAwareSerializer<'
 
     fn serialize_i128(mut self, v: i128) -> Result<Self::Ok, Self::Error> {
         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" =>
+            {
                 self.write_array(v.to_le_bytes())
             }
             Schema::Union(union) => {
                 UnionSerializer::new(self.writer, union, 
self.config).serialize_i128(v)
             }
-            _ => 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)"#,
+            )),
         }
     }
 
@@ -273,25 +278,35 @@ impl<'s, 'w, W: Write, S: Borrow<Schema>> Serializer for 
SchemaAwareSerializer<'
 
     fn serialize_u64(mut self, v: u64) -> Result<Self::Ok, Self::Error> {
         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" =>
+            {
                 self.write_array(v.to_le_bytes())
             }
             Schema::Union(union) => {
                 UnionSerializer::new(self.writer, union, 
self.config).serialize_u64(v)
             }
-            _ => 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)"#,
+            )),
         }
     }
 
     fn serialize_u128(mut self, v: u128) -> Result<Self::Ok, Self::Error> {
         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" =>
+            {
                 self.write_array(v.to_le_bytes())
             }
             Schema::Union(union) => {
                 UnionSerializer::new(self.writer, union, 
self.config).serialize_u128(v)
             }
-            _ => 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)"#,
+            )),
         }
     }
 
diff --git a/avro/src/serde/ser_schema/union.rs 
b/avro/src/serde/ser_schema/union.rs
index d1aa73e..8b5d468 100644
--- a/avro/src/serde/ser_schema/union.rs
+++ b/avro/src/serde/ser_schema/union.rs
@@ -166,7 +166,10 @@ impl<'s, 'w, W: Write, S: Borrow<Schema>> Serializer for 
UnionSerializer<'s, 'w,
     }
 
     fn serialize_i128(mut self, v: i128) -> Result<Self::Ok, Self::Error> {
-        match self.union.find_named_schema("i128", self.config.names)? {
+        match self
+            .union
+            .find_fully_qualified_named_schema("org.apache.avro.rust.i128", 
self.config.names)?
+        {
             Some((index, Schema::Fixed(FixedSchema { size: 16, .. }))) => {
                 let mut bytes_written = zig_i32(index as i32, &mut 
*self.writer)?;
                 bytes_written += self.write_array(v.to_le_bytes())?;
@@ -192,7 +195,10 @@ impl<'s, 'w, W: Write, S: Borrow<Schema>> Serializer for 
UnionSerializer<'s, 'w,
     }
 
     fn serialize_u64(mut self, v: u64) -> Result<Self::Ok, Self::Error> {
-        match self.union.find_named_schema("u64", self.config.names)? {
+        match self
+            .union
+            .find_fully_qualified_named_schema("org.apache.avro.rust.u64", 
self.config.names)?
+        {
             Some((index, Schema::Fixed(FixedSchema { size: 8, .. }))) => {
                 let mut bytes_written = zig_i32(index as i32, &mut 
*self.writer)?;
                 bytes_written += self.write_array(v.to_le_bytes())?;
@@ -206,7 +212,10 @@ impl<'s, 'w, W: Write, S: Borrow<Schema>> Serializer for 
UnionSerializer<'s, 'w,
     }
 
     fn serialize_u128(mut self, v: u128) -> Result<Self::Ok, Self::Error> {
-        match self.union.find_named_schema("u128", self.config.names)? {
+        match self
+            .union
+            .find_fully_qualified_named_schema("org.apache.avro.rust.u128", 
self.config.names)?
+        {
             Some((index, Schema::Fixed(FixedSchema { size: 16, .. }))) => {
                 let mut bytes_written = zig_i32(index as i32, &mut 
*self.writer)?;
                 bytes_written += self.write_array(v.to_le_bytes())?;
diff --git a/avro_derive/tests/derive.rs b/avro_derive/tests/derive.rs
index 42835db..e2509c3 100644
--- a/avro_derive/tests/derive.rs
+++ b/avro_derive/tests/derive.rs
@@ -1954,7 +1954,8 @@ fn avro_rs_397_uuid() {
                 "type":{
                     "type":"fixed",
                     "logicalType":"uuid",
-                    "name":"uuid",
+                    "name":"Uuid",
+                    "namespace": "org.apache.avro.rust",
                     
"default":"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000",
                     "size":16
                 }
@@ -2140,6 +2141,7 @@ fn avro_rs_414_round_trip_char_u64_u128_i128() {
             "name": "b",
             "type": {
                 "name": "u64",
+                "namespace": "org.apache.avro.rust",
                 "type": "fixed",
                 "size": 8
             }
@@ -2148,6 +2150,7 @@ fn avro_rs_414_round_trip_char_u64_u128_i128() {
             "name": "c",
             "type": {
                 "name": "u128",
+                "namespace": "org.apache.avro.rust",
                 "type": "fixed",
                 "size": 16
             }
@@ -2156,6 +2159,7 @@ fn avro_rs_414_round_trip_char_u64_u128_i128() {
             "name": "d",
             "type": {
                 "name": "i128",
+                "namespace": "org.apache.avro.rust",
                 "type": "fixed",
                 "size": 16
             }
@@ -2420,7 +2424,7 @@ fn avro_rs_476_field_default() {
     let schema = Foo::get_schema();
     assert_eq!(
         serde_json::to_string(&schema).unwrap(),
-        
r#"{"type":"record","name":"Foo","fields":[{"name":"_a","type":"boolean"},{"name":"_b","type":"int"},{"name":"_c","type":"int"},{"name":"_d","type":"int"},{"name":"_e","type":"long"},{"name":"_f","type":"int"},{"name":"_g","type":"int"},{"name":"_h","type":"long"},{"name":"_i","type":"float"},{"name":"_j","type":"double"},{"name":"_k","type":"string"},{"name":"_l","type":"string"},{"name":"_m","type":"string"},{"name":"_n","type":{"type":"record","name":"Spam","fields":[{"name":"
 [...]
+        
r#"{"type":"record","name":"Foo","fields":[{"name":"_a","type":"boolean"},{"name":"_b","type":"int"},{"name":"_c","type":"int"},{"name":"_d","type":"int"},{"name":"_e","type":"long"},{"name":"_f","type":"int"},{"name":"_g","type":"int"},{"name":"_h","type":"long"},{"name":"_i","type":"float"},{"name":"_j","type":"double"},{"name":"_k","type":"string"},{"name":"_l","type":"string"},{"name":"_m","type":"string"},{"name":"_n","type":{"type":"record","name":"Spam","fields":[{"name":"
 [...]
     );
 }
 
@@ -2531,7 +2535,7 @@ fn avro_rs_476_field_default_provided() {
     let schema = Foo::get_schema();
     assert_eq!(
         serde_json::to_string(&schema).unwrap(),
-        
r#"{"type":"record","name":"Foo","fields":[{"name":"_a","type":"boolean","default":true},{"name":"_b","type":"int","default":42},{"name":"_c","type":"int","default":42},{"name":"_d","type":"int","default":42},{"name":"_e","type":"long","default":42},{"name":"_f","type":"int","default":42},{"name":"_g","type":"int","default":42},{"name":"_h","type":"long","default":42},{"name":"_i","type":"float","default":42.0},{"name":"_j","type":"double","default":42.0},{"name":"_k","type":"str
 [...]
+        
r#"{"type":"record","name":"Foo","fields":[{"name":"_a","type":"boolean","default":true},{"name":"_b","type":"int","default":42},{"name":"_c","type":"int","default":42},{"name":"_d","type":"int","default":42},{"name":"_e","type":"long","default":42},{"name":"_f","type":"int","default":42},{"name":"_g","type":"int","default":42},{"name":"_h","type":"long","default":42},{"name":"_i","type":"float","default":42.0},{"name":"_j","type":"double","default":42.0},{"name":"_k","type":"str
 [...]
     );
 }
 

Reply via email to