You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by mg...@apache.org on 2023/05/19 13:06:38 UTC

[avro] 01/01: AVRO-3759: Add extra types for RecordSchema, EnumSchema, FixedSchema and DecimalSchema

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

mgrigorov pushed a commit to branch avro-3759-add-extra-types
in repository https://gitbox.apache.org/repos/asf/avro.git

commit a46786b4b409b9e293a4ed88552421ff854eb1a8
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
AuthorDate: Fri May 19 16:05:43 2023 +0300

    AVRO-3759: Add extra types for RecordSchema, EnumSchema, FixedSchema and DecimalSchema
    
    Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
---
 lang/rust/avro/src/decode.rs               |  33 ++--
 lang/rust/avro/src/encode.rs               |  15 +-
 lang/rust/avro/src/schema.rs               | 234 +++++++++++++++--------------
 lang/rust/avro/src/schema_compatibility.rs |  34 ++---
 lang/rust/avro/src/types.rs                |  94 ++++++------
 lang/rust/avro/src/writer.rs               |  18 +--
 lang/rust/avro/tests/schema.rs             |  26 ++--
 lang/rust/avro_derive/src/lib.rs           |   8 +-
 lang/rust/avro_derive/tests/derive.rs      |  48 +++---
 9 files changed, 270 insertions(+), 240 deletions(-)

diff --git a/lang/rust/avro/src/decode.rs b/lang/rust/avro/src/decode.rs
index 4f9e7e945..31b76243a 100644
--- a/lang/rust/avro/src/decode.rs
+++ b/lang/rust/avro/src/decode.rs
@@ -18,7 +18,10 @@
 use crate::{
     decimal::Decimal,
     duration::Duration,
-    schema::{Name, Namespace, ResolvedSchema, Schema},
+    schema::{
+        DecimalSchema, EnumSchema, FixedSchema, Name, Namespace, RecordSchema, ResolvedSchema,
+        Schema,
+    },
     types::Value,
     util::{safe_len, zag_i32, zag_i64},
     AvroResult, Error,
@@ -98,7 +101,7 @@ pub(crate) fn decode_internal<R: Read, S: Borrow<Schema>>(
                 }
             }
         }
-        Schema::Decimal { ref inner, .. } => match &**inner {
+        Schema::Decimal(DecimalSchema { ref inner, .. }) => match &**inner {
             Schema::Fixed { .. } => {
                 match decode_internal(inner, names, enclosing_namespace, reader)? {
                     Value::Fixed(_, bytes) => Ok(Value::Decimal(Decimal::from(bytes))),
@@ -164,7 +167,7 @@ pub(crate) fn decode_internal<R: Read, S: Borrow<Schema>>(
                 }
             }
         }
-        Schema::Fixed { size, .. } => {
+        Schema::Fixed(FixedSchema { size, .. }) => {
             let mut buf = vec![0u8; size];
             reader
                 .read_exact(&mut buf)
@@ -232,11 +235,11 @@ pub(crate) fn decode_internal<R: Read, S: Borrow<Schema>>(
             }
             Err(io_err) => Err(io_err),
         },
-        Schema::Record {
+        Schema::Record(RecordSchema {
             ref name,
             ref fields,
             ..
-        } => {
+        }) => {
             let fully_qualified_name = name.fully_qualified_name(enclosing_namespace);
             // Benchmarks indicate ~10% improvement using this method.
             let mut items = Vec::with_capacity(fields.len());
@@ -254,7 +257,7 @@ pub(crate) fn decode_internal<R: Read, S: Borrow<Schema>>(
             }
             Ok(Value::Record(items))
         }
-        Schema::Enum { ref symbols, .. } => {
+        Schema::Enum(EnumSchema { ref symbols, .. }) => {
             Ok(if let Value::Int(raw_index) = decode_int(reader)? {
                 let index = usize::try_from(raw_index)
                     .map_err(|e| Error::ConvertI32ToUsize(e, raw_index))?;
@@ -293,7 +296,7 @@ mod tests {
     use crate::{
         decode::decode,
         encode::{encode, tests::success},
-        schema::Schema,
+        schema::{DecimalSchema, FixedSchema, Schema},
         types::{
             Value,
             Value::{Array, Int, Map},
@@ -339,18 +342,18 @@ mod tests {
     fn test_negative_decimal_value() {
         use crate::{encode::encode, schema::Name};
         use num_bigint::ToBigInt;
-        let inner = Box::new(Schema::Fixed {
+        let inner = Box::new(Schema::Fixed(FixedSchema {
             size: 2,
             doc: None,
             name: Name::new("decimal").unwrap(),
             aliases: None,
             attributes: Default::default(),
-        });
-        let schema = Schema::Decimal {
+        }));
+        let schema = Schema::Decimal(DecimalSchema {
             inner,
             precision: 4,
             scale: 2,
-        };
+        });
         let bigint = (-423).to_bigint().unwrap();
         let value = Value::Decimal(Decimal::from(bigint.to_signed_bytes_be()));
 
@@ -366,18 +369,18 @@ mod tests {
     fn test_decode_decimal_with_bigger_than_necessary_size() {
         use crate::{encode::encode, schema::Name};
         use num_bigint::ToBigInt;
-        let inner = Box::new(Schema::Fixed {
+        let inner = Box::new(Schema::Fixed(FixedSchema {
             size: 13,
             name: Name::new("decimal").unwrap(),
             aliases: None,
             doc: None,
             attributes: Default::default(),
-        });
-        let schema = Schema::Decimal {
+        }));
+        let schema = Schema::Decimal(DecimalSchema {
             inner,
             precision: 4,
             scale: 2,
-        };
+        });
         let value = Value::Decimal(Decimal::from(
             ((-423).to_bigint().unwrap()).to_signed_bytes_be(),
         ));
diff --git a/lang/rust/avro/src/encode.rs b/lang/rust/avro/src/encode.rs
index 40f4ee0f7..94436b86f 100644
--- a/lang/rust/avro/src/encode.rs
+++ b/lang/rust/avro/src/encode.rs
@@ -16,7 +16,10 @@
 // under the License.
 
 use crate::{
-    schema::{Name, Namespace, ResolvedSchema, Schema, SchemaKind},
+    schema::{
+        DecimalSchema, EnumSchema, FixedSchema, Name, Namespace, RecordSchema, ResolvedSchema,
+        Schema, SchemaKind,
+    },
     types::{Value, ValueKind},
     util::{zig_i32, zig_i64},
     AvroResult, Error,
@@ -78,8 +81,8 @@ pub(crate) fn encode_internal<S: Borrow<Schema>>(
         Value::Float(x) => buffer.extend_from_slice(&x.to_le_bytes()),
         Value::Double(x) => buffer.extend_from_slice(&x.to_le_bytes()),
         Value::Decimal(decimal) => match schema {
-            Schema::Decimal { inner, .. } => match *inner.clone() {
-                Schema::Fixed { size, .. } => {
+            Schema::Decimal(DecimalSchema { inner, .. }) => match *inner.clone() {
+                Schema::Fixed(FixedSchema { size, .. }) => {
                     let bytes = decimal.to_sign_extended_bytes_with_len(size).unwrap();
                     let num_bytes = bytes.len();
                     if num_bytes != size {
@@ -125,7 +128,7 @@ pub(crate) fn encode_internal<S: Borrow<Schema>>(
             Schema::String | Schema::Uuid => {
                 encode_bytes(s, buffer);
             }
-            Schema::Enum { ref symbols, .. } => {
+            Schema::Enum(EnumSchema { ref symbols, .. }) => {
                 if let Some(index) = symbols.iter().position(|item| item == s) {
                     encode_int(index as i32, buffer);
                 } else {
@@ -194,12 +197,12 @@ pub(crate) fn encode_internal<S: Borrow<Schema>>(
             }
         }
         Value::Record(fields) => {
-            if let Schema::Record {
+            if let Schema::Record(RecordSchema {
                 ref name,
                 fields: ref schema_fields,
                 ref lookup,
                 ..
-            } = *schema
+            }) = *schema
             {
                 let record_namespace = name.fully_qualified_name(enclosing_namespace).namespace;
                 for (name, value) in fields.iter() {
diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs
index a035a55ca..e5f3c69cb 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -98,43 +98,14 @@ pub enum Schema {
     /// A `union` Avro schema.
     Union(UnionSchema),
     /// A `record` Avro schema.
-    ///
-    /// The `lookup` table maps field names to their position in the `Vec`
-    /// of `fields`.
-    Record {
-        name: Name,
-        aliases: Aliases,
-        doc: Documentation,
-        fields: Vec<RecordField>,
-        lookup: BTreeMap<String, usize>,
-        attributes: BTreeMap<String, Value>,
-    },
+    Record(RecordSchema),
     /// An `enum` Avro schema.
-    Enum {
-        name: Name,
-        aliases: Aliases,
-        doc: Documentation,
-        symbols: Vec<String>,
-        attributes: BTreeMap<String, Value>,
-    },
+    Enum(EnumSchema),
     /// A `fixed` Avro schema.
-    Fixed {
-        name: Name,
-        aliases: Aliases,
-        doc: Documentation,
-        size: usize,
-        attributes: BTreeMap<String, Value>,
-    },
+    Fixed(FixedSchema),
     /// Logical type which represents `Decimal` values. The underlying type is serialized and
     /// deserialized as `Schema::Bytes` or `Schema::Fixed`.
-    ///
-    /// `scale` defaults to 0 and is an integer greater than or equal to 0 and `precision` is an
-    /// integer greater than 0.
-    Decimal {
-        precision: DecimalMetadata,
-        scale: DecimalMetadata,
-        inner: Box<Schema>,
-    },
+    Decimal(DecimalSchema),
     /// A universally unique identifier, annotating a string.
     Uuid,
     /// Logical type which represents the number of days since the unix epoch.
@@ -452,7 +423,7 @@ impl<'s> ResolvedSchema<'s> {
                         Self::from_internal(vec![schema], names_ref, enclosing_namespace)?
                     }
                 }
-                Schema::Enum { name, .. } | Schema::Fixed { name, .. } => {
+                Schema::Enum(EnumSchema { name, .. }) | Schema::Fixed(FixedSchema { name, .. }) => {
                     let fully_qualified_name = name.fully_qualified_name(enclosing_namespace);
                     if names_ref
                         .insert(fully_qualified_name.clone(), schema)
@@ -461,7 +432,7 @@ impl<'s> ResolvedSchema<'s> {
                         return Err(Error::AmbiguousSchemaDefinition(fully_qualified_name));
                     }
                 }
-                Schema::Record { name, fields, .. } => {
+                Schema::Record(RecordSchema { name, fields, .. }) => {
                     let fully_qualified_name = name.fully_qualified_name(enclosing_namespace);
                     if names_ref
                         .insert(fully_qualified_name.clone(), schema)
@@ -530,7 +501,7 @@ impl ResolvedOwnedSchema {
                 }
                 Ok(())
             }
-            Schema::Enum { name, .. } | Schema::Fixed { name, .. } => {
+            Schema::Enum(EnumSchema { name, .. }) | Schema::Fixed(FixedSchema { name, .. }) => {
                 let fully_qualified_name = name.fully_qualified_name(enclosing_namespace);
                 if names
                     .insert(fully_qualified_name.clone(), schema.clone())
@@ -541,7 +512,7 @@ impl ResolvedOwnedSchema {
                     Ok(())
                 }
             }
-            Schema::Record { name, fields, .. } => {
+            Schema::Record(RecordSchema { name, fields, .. }) => {
                 let fully_qualified_name = name.fully_qualified_name(enclosing_namespace);
                 if names
                     .insert(fully_qualified_name.clone(), schema.clone())
@@ -666,6 +637,45 @@ impl RecordField {
     }
 }
 
+/// The `lookup` table maps field names to their position in the `Vec`
+/// of `fields`.
+#[derive(Debug, Clone)]
+pub struct RecordSchema {
+    pub name: Name,
+    pub aliases: Aliases,
+    pub doc: Documentation,
+    pub fields: Vec<RecordField>,
+    pub lookup: BTreeMap<String, usize>,
+    pub attributes: BTreeMap<String, Value>,
+}
+
+#[derive(Debug, Clone)]
+pub struct EnumSchema {
+    pub name: Name,
+    pub aliases: Aliases,
+    pub doc: Documentation,
+    pub symbols: Vec<String>,
+    pub attributes: BTreeMap<String, Value>,
+}
+
+#[derive(Debug, Clone)]
+pub struct FixedSchema {
+    pub name: Name,
+    pub aliases: Aliases,
+    pub doc: Documentation,
+    pub size: usize,
+    pub attributes: BTreeMap<String, Value>,
+}
+
+/// `scale` defaults to 0 and is an integer greater than or equal to 0 and `precision` is an
+/// integer greater than 0.
+#[derive(Debug, Clone)]
+pub struct DecimalSchema {
+    pub precision: DecimalMetadata,
+    pub scale: DecimalMetadata,
+    pub inner: Box<Schema>,
+}
+
 #[derive(Debug, Clone)]
 pub struct UnionSchema {
     pub(crate) schemas: Vec<Schema>,
@@ -851,9 +861,9 @@ impl Schema {
     /// Returns the custom attributes (metadata) if the schema supports them.
     pub fn custom_attributes(&self) -> Option<&BTreeMap<String, Value>> {
         match self {
-            Schema::Record { attributes, .. }
-            | Schema::Enum { attributes, .. }
-            | Schema::Fixed { attributes, .. } => Some(attributes),
+            Schema::Record(RecordSchema { attributes, .. })
+            | Schema::Enum(EnumSchema { attributes, .. })
+            | Schema::Fixed(FixedSchema { attributes, .. }) => Some(attributes),
             _ => None,
         }
     }
@@ -862,9 +872,9 @@ impl Schema {
     pub fn name(&self) -> Option<&Name> {
         match self {
             Schema::Ref { ref name, .. }
-            | Schema::Record { ref name, .. }
-            | Schema::Enum { ref name, .. }
-            | Schema::Fixed { ref name, .. } => Some(name),
+            | Schema::Record(RecordSchema { ref name, .. })
+            | Schema::Enum(EnumSchema { ref name, .. })
+            | Schema::Fixed(FixedSchema { ref name, .. }) => Some(name),
             _ => None,
         }
     }
@@ -960,9 +970,9 @@ impl Parser {
     ) -> AvroResult<Schema> {
         fn get_schema_ref(parsed: &Schema) -> Schema {
             match &parsed {
-                Schema::Record { ref name, .. }
-                | Schema::Enum { ref name, .. }
-                | Schema::Fixed { ref name, .. } => Schema::Ref { name: name.clone() },
+                Schema::Record(RecordSchema { ref name, .. })
+                | Schema::Enum(EnumSchema { ref name, .. })
+                | Schema::Fixed(FixedSchema { ref name, .. }) => Schema::Ref { name: name.clone() },
                 _ => parsed.clone(),
             }
         }
@@ -1116,11 +1126,11 @@ impl Parser {
 
                     let (precision, scale) = Self::parse_precision_and_scale(complex)?;
 
-                    return Ok(Schema::Decimal {
+                    return Ok(Schema::Decimal(DecimalSchema {
                         precision,
                         scale,
                         inner,
-                    });
+                    }));
                 }
                 "uuid" => {
                     logical_verify_type(complex, &[SchemaKind::String], self, enclosing_namespace)?;
@@ -1313,14 +1323,14 @@ impl Parser {
             }
         }
 
-        let schema = Schema::Record {
+        let schema = Schema::Record(RecordSchema {
             name,
             aliases: aliases.clone(),
             doc: complex.doc(),
             fields,
             lookup,
             attributes: self.get_custom_attributes(complex, vec!["fields"]),
-        };
+        });
 
         self.register_parsed_schema(&fully_qualified_name, &schema, &aliases);
         Ok(schema)
@@ -1387,13 +1397,13 @@ impl Parser {
             existing_symbols.insert(symbol);
         }
 
-        let schema = Schema::Enum {
+        let schema = Schema::Enum(EnumSchema {
             name,
             aliases: aliases.clone(),
             doc: complex.doc(),
             symbols,
             attributes: self.get_custom_attributes(complex, vec!["symbols"]),
-        };
+        });
 
         self.register_parsed_schema(&fully_qualified_name, &schema, &aliases);
 
@@ -1490,13 +1500,13 @@ impl Parser {
         let fully_qualified_name = name.fully_qualified_name(enclosing_namespace);
         let aliases = fix_aliases_namespace(complex.aliases(), &name.namespace);
 
-        let schema = Schema::Fixed {
+        let schema = Schema::Fixed(FixedSchema {
             name,
             aliases: aliases.clone(),
             doc,
             size: size as usize,
             attributes: self.get_custom_attributes(complex, vec!["size"]),
-        };
+        });
 
         self.register_parsed_schema(&fully_qualified_name, &schema, &aliases);
 
@@ -1573,13 +1583,13 @@ impl Serialize for Schema {
                 }
                 seq.end()
             }
-            Schema::Record {
+            Schema::Record(RecordSchema {
                 ref name,
                 ref aliases,
                 ref doc,
                 ref fields,
                 ..
-            } => {
+            }) => {
                 let mut map = serializer.serialize_map(None)?;
                 map.serialize_entry("type", "record")?;
                 if let Some(ref n) = name.namespace {
@@ -1595,12 +1605,12 @@ impl Serialize for Schema {
                 map.serialize_entry("fields", fields)?;
                 map.end()
             }
-            Schema::Enum {
+            Schema::Enum(EnumSchema {
                 ref name,
                 ref symbols,
                 ref aliases,
                 ..
-            } => {
+            }) => {
                 let mut map = serializer.serialize_map(None)?;
                 map.serialize_entry("type", "enum")?;
                 if let Some(ref n) = name.namespace {
@@ -1614,13 +1624,13 @@ impl Serialize for Schema {
                 }
                 map.end()
             }
-            Schema::Fixed {
+            Schema::Fixed(FixedSchema {
                 ref name,
                 ref doc,
                 ref size,
                 ref aliases,
                 ..
-            } => {
+            }) => {
                 let mut map = serializer.serialize_map(None)?;
                 map.serialize_entry("type", "fixed")?;
                 if let Some(ref n) = name.namespace {
@@ -1637,11 +1647,11 @@ impl Serialize for Schema {
                 }
                 map.end()
             }
-            Schema::Decimal {
+            Schema::Decimal(DecimalSchema {
                 ref scale,
                 ref precision,
                 ref inner,
-            } => {
+            }) => {
                 let mut map = serializer.serialize_map(None)?;
                 map.serialize_entry("type", &*inner.clone())?;
                 map.serialize_entry("logicalType", "decimal")?;
@@ -1690,13 +1700,13 @@ impl Serialize for Schema {
 
                 // the Avro doesn't indicate what the name of the underlying fixed type of a
                 // duration should be or typically is.
-                let inner = Schema::Fixed {
+                let inner = Schema::Fixed(FixedSchema {
                     name: Name::new("duration").unwrap(),
                     aliases: None,
                     doc: None,
                     size: 12,
                     attributes: Default::default(),
-                };
+                });
                 map.serialize_entry("type", &inner)?;
                 map.serialize_entry("logicalType", "duration")?;
                 map.end()
@@ -2185,7 +2195,7 @@ mod tests {
             .unwrap()
             .clone();
 
-        let schema_c_expected = Schema::Record {
+        let schema_c_expected = Schema::Record(RecordSchema {
             name: Name::new("C").unwrap(),
             aliases: None,
             doc: None,
@@ -2211,7 +2221,7 @@ mod tests {
             }],
             lookup: BTreeMap::from_iter(vec![("field_one".to_string(), 0)]),
             attributes: Default::default(),
-        };
+        });
 
         assert_eq!(schema_c, schema_c_expected);
     }
@@ -2237,7 +2247,7 @@ mod tests {
         let schema_a = list.first().unwrap().clone();
 
         match schema_a {
-            Schema::Record { fields, .. } => {
+            Schema::Record(RecordSchema { fields, .. }) => {
                 let f1 = fields.get(0);
 
                 let ref_schema = Schema::Ref {
@@ -2277,7 +2287,7 @@ mod tests {
             .unwrap()
             .clone();
 
-        let schema_option_a_expected = Schema::Record {
+        let schema_option_a_expected = Schema::Record(RecordSchema {
             name: Name::new("OptionA").unwrap(),
             aliases: None,
             doc: None,
@@ -2301,7 +2311,7 @@ mod tests {
             }],
             lookup: BTreeMap::from_iter(vec![("field_one".to_string(), 0)]),
             attributes: Default::default(),
-        };
+        });
 
         assert_eq!(schema_option_a, schema_option_a_expected);
     }
@@ -2326,7 +2336,7 @@ mod tests {
         lookup.insert("a".to_owned(), 0);
         lookup.insert("b".to_owned(), 1);
 
-        let expected = Schema::Record {
+        let expected = Schema::Record(RecordSchema {
             name: Name::new("test").unwrap(),
             aliases: None,
             doc: None,
@@ -2354,7 +2364,7 @@ mod tests {
             ],
             lookup,
             attributes: Default::default(),
-        };
+        });
 
         assert_eq!(parsed, expected);
     }
@@ -2390,7 +2400,7 @@ mod tests {
         node_lookup.insert("children".to_owned(), 1);
         node_lookup.insert("label".to_owned(), 0);
 
-        let expected = Schema::Record {
+        let expected = Schema::Record(RecordSchema {
             name: Name::new("test").unwrap(),
             aliases: None,
             doc: None,
@@ -2399,7 +2409,7 @@ mod tests {
                 doc: None,
                 default: None,
                 aliases: None,
-                schema: Schema::Record {
+                schema: Schema::Record(RecordSchema {
                     name: Name::new("Node").unwrap(),
                     aliases: None,
                     doc: None,
@@ -2429,14 +2439,14 @@ mod tests {
                     ],
                     lookup: node_lookup,
                     attributes: Default::default(),
-                },
+                }),
                 order: RecordFieldOrder::Ascending,
                 position: 0,
                 custom_attributes: Default::default(),
             }],
             lookup,
             attributes: Default::default(),
-        };
+        });
         assert_eq!(schema, expected);
 
         let canonical_form = &schema.canonical_form();
@@ -2566,7 +2576,7 @@ mod tests {
         lookup.insert("value".to_owned(), 0);
         lookup.insert("next".to_owned(), 1);
 
-        let expected = Schema::Record {
+        let expected = Schema::Record(RecordSchema {
             name: Name {
                 name: "LongList".to_owned(),
                 namespace: None,
@@ -2608,7 +2618,7 @@ mod tests {
             ],
             lookup,
             attributes: Default::default(),
-        };
+        });
         assert_eq!(schema, expected);
 
         let canonical_form = &schema.canonical_form();
@@ -2637,7 +2647,7 @@ mod tests {
         lookup.insert("value".to_owned(), 0);
         lookup.insert("next".to_owned(), 1);
 
-        let expected = Schema::Record {
+        let expected = Schema::Record(RecordSchema {
             name: Name {
                 name: "record".to_owned(),
                 namespace: None,
@@ -2673,7 +2683,7 @@ mod tests {
             ],
             lookup,
             attributes: Default::default(),
-        };
+        });
         assert_eq!(schema, expected);
 
         let canonical_form = &schema.canonical_form();
@@ -2706,7 +2716,7 @@ mod tests {
         lookup.insert("enum".to_owned(), 0);
         lookup.insert("next".to_owned(), 1);
 
-        let expected = Schema::Record {
+        let expected = Schema::Record(RecordSchema {
             name: Name {
                 name: "record".to_owned(),
                 namespace: None,
@@ -2719,7 +2729,7 @@ mod tests {
                     doc: None,
                     default: None,
                     aliases: None,
-                    schema: Schema::Enum {
+                    schema: Schema::Enum(EnumSchema {
                         name: Name {
                             name: "enum".to_owned(),
                             namespace: None,
@@ -2728,7 +2738,7 @@ mod tests {
                         doc: None,
                         symbols: vec!["one".to_string(), "two".to_string(), "three".to_string()],
                         attributes: Default::default(),
-                    },
+                    }),
                     order: RecordFieldOrder::Ascending,
                     position: 0,
                     custom_attributes: Default::default(),
@@ -2738,7 +2748,7 @@ mod tests {
                     doc: None,
                     default: None,
                     aliases: None,
-                    schema: Schema::Enum {
+                    schema: Schema::Enum(EnumSchema {
                         name: Name {
                             name: "enum".to_owned(),
                             namespace: None,
@@ -2747,7 +2757,7 @@ mod tests {
                         doc: None,
                         symbols: vec!["one".to_string(), "two".to_string(), "three".to_string()],
                         attributes: Default::default(),
-                    },
+                    }),
                     order: RecordFieldOrder::Ascending,
                     position: 1,
                     custom_attributes: Default::default(),
@@ -2755,7 +2765,7 @@ mod tests {
             ],
             lookup,
             attributes: Default::default(),
-        };
+        });
         assert_eq!(schema, expected);
 
         let canonical_form = &schema.canonical_form();
@@ -2788,7 +2798,7 @@ mod tests {
         lookup.insert("fixed".to_owned(), 0);
         lookup.insert("next".to_owned(), 1);
 
-        let expected = Schema::Record {
+        let expected = Schema::Record(RecordSchema {
             name: Name {
                 name: "record".to_owned(),
                 namespace: None,
@@ -2801,7 +2811,7 @@ mod tests {
                     doc: None,
                     default: None,
                     aliases: None,
-                    schema: Schema::Fixed {
+                    schema: Schema::Fixed(FixedSchema {
                         name: Name {
                             name: "fixed".to_owned(),
                             namespace: None,
@@ -2810,7 +2820,7 @@ mod tests {
                         doc: None,
                         size: 456,
                         attributes: Default::default(),
-                    },
+                    }),
                     order: RecordFieldOrder::Ascending,
                     position: 0,
                     custom_attributes: Default::default(),
@@ -2820,7 +2830,7 @@ mod tests {
                     doc: None,
                     default: None,
                     aliases: None,
-                    schema: Schema::Fixed {
+                    schema: Schema::Fixed(FixedSchema {
                         name: Name {
                             name: "fixed".to_owned(),
                             namespace: None,
@@ -2829,7 +2839,7 @@ mod tests {
                         doc: None,
                         size: 456,
                         attributes: Default::default(),
-                    },
+                    }),
                     order: RecordFieldOrder::Ascending,
                     position: 1,
                     custom_attributes: Default::default(),
@@ -2837,7 +2847,7 @@ mod tests {
             ],
             lookup,
             attributes: Default::default(),
-        };
+        });
         assert_eq!(schema, expected);
 
         let canonical_form = &schema.canonical_form();
@@ -2851,7 +2861,7 @@ mod tests {
             r#"{"type": "enum", "name": "Suit", "symbols": ["diamonds", "spades", "clubs", "hearts"]}"#,
         ).unwrap();
 
-        let expected = Schema::Enum {
+        let expected = Schema::Enum(EnumSchema {
             name: Name::new("Suit").unwrap(),
             aliases: None,
             doc: None,
@@ -2862,7 +2872,7 @@ mod tests {
                 "hearts".to_owned(),
             ],
             attributes: Default::default(),
-        };
+        });
 
         assert_eq!(expected, schema);
     }
@@ -2889,13 +2899,13 @@ mod tests {
     fn test_fixed_schema() {
         let schema = Schema::parse_str(r#"{"type": "fixed", "name": "test", "size": 16}"#).unwrap();
 
-        let expected = Schema::Fixed {
+        let expected = Schema::Fixed(FixedSchema {
             name: Name::new("test").unwrap(),
             aliases: None,
             doc: None,
             size: 16usize,
             attributes: Default::default(),
-        };
+        });
 
         assert_eq!(expected, schema);
     }
@@ -2907,13 +2917,13 @@ mod tests {
         )
         .unwrap();
 
-        let expected = Schema::Fixed {
+        let expected = Schema::Fixed(FixedSchema {
             name: Name::new("test").unwrap(),
             aliases: None,
             doc: Some(String::from("FixedSchema documentation")),
             size: 16usize,
             attributes: Default::default(),
-        };
+        });
 
         assert_eq!(expected, schema);
     }
@@ -2925,7 +2935,7 @@ mod tests {
                 .unwrap();
 
         let doc = match schema {
-            Schema::Enum { doc, .. } => doc,
+            Schema::Enum(EnumSchema { doc, .. }) => doc,
             _ => return,
         };
 
@@ -2939,7 +2949,7 @@ mod tests {
         ).unwrap();
 
         let doc = match schema {
-            Schema::Enum { doc, .. } => doc,
+            Schema::Enum(EnumSchema { doc, .. }) => doc,
             _ => None,
         };
 
@@ -3103,7 +3113,7 @@ mod tests {
     "#;
 
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, .. } = schema {
+        if let Schema::Record(RecordSchema { name, .. }) = schema {
             assert_eq!(name.name, "name");
             assert_eq!(name.namespace, Some("space".to_string()));
         } else {
@@ -3128,7 +3138,7 @@ mod tests {
     "#;
 
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, .. } = schema {
+        if let Schema::Record(RecordSchema { name, .. }) = schema {
             assert_eq!(name.namespace, Some("space1".to_string()));
         } else {
             panic!("Expected a record schema!");
@@ -3152,7 +3162,7 @@ mod tests {
     "#;
 
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, .. } = schema {
+        if let Schema::Record(RecordSchema { name, .. }) = schema {
             assert_eq!(name.namespace, Some("space2".to_string()));
         } else {
             panic!("Expected a record schema!");
@@ -3870,7 +3880,7 @@ mod tests {
         )
         .unwrap();
 
-        if let Schema::Record { ref aliases, .. } = schema {
+        if let Schema::Record(RecordSchema { ref aliases, .. }) = schema {
             assert_avro_3512_aliases(aliases);
         } else {
             panic!("The Schema should be a record: {schema:?}");
@@ -3894,7 +3904,7 @@ mod tests {
         )
         .unwrap();
 
-        if let Schema::Enum { ref aliases, .. } = schema {
+        if let Schema::Enum(EnumSchema { ref aliases, .. }) = schema {
             assert_avro_3512_aliases(aliases);
         } else {
             panic!("The Schema should be an enum: {schema:?}");
@@ -3916,7 +3926,7 @@ mod tests {
         )
         .unwrap();
 
-        if let Schema::Fixed { ref aliases, .. } = schema {
+        if let Schema::Fixed(FixedSchema { ref aliases, .. }) = schema {
             assert_avro_3512_aliases(aliases);
         } else {
             panic!("The Schema should be a fixed: {schema:?}");
@@ -4028,7 +4038,7 @@ mod tests {
         "#;
         let schema = Schema::parse_str(schema_str).unwrap();
 
-        if let Schema::Record { name, fields, .. } = schema {
+        if let Schema::Record(RecordSchema { name, fields, .. }) = schema {
             assert_eq!(name, Name::new("AccountEvent").unwrap());
 
             let field = &fields[0];
@@ -4187,7 +4197,7 @@ mod tests {
             Schema::parse_str(schema_str.replace("{{{}}}", CUSTOM_ATTRS_SUFFIX).as_str()).unwrap();
 
         match schema {
-            Schema::Record { name, fields, .. } => {
+            Schema::Record(RecordSchema { name, fields, .. }) => {
                 assert_eq!(name, Name::new("Rec").unwrap());
                 assert_eq!(fields.len(), 1);
                 let field = &fields[0];
@@ -4215,7 +4225,7 @@ mod tests {
         let schema = Schema::parse_str(&schema_str).unwrap();
 
         match schema {
-            Schema::Record { name, fields, .. } => {
+            Schema::Record(RecordSchema { name, fields, .. }) => {
                 assert_eq!(name, Name::new("union_schema_test").unwrap());
                 assert_eq!(fields.len(), 1);
                 let field = &fields[0];
@@ -4252,7 +4262,7 @@ mod tests {
         let schema = Schema::parse_str(&schema_str).unwrap();
 
         match schema {
-            Schema::Record { name, fields, .. } => {
+            Schema::Record(RecordSchema { name, fields, .. }) => {
                 assert_eq!(name, Name::new("union_schema_test").unwrap());
                 assert_eq!(fields.len(), 1);
                 let field = &fields[0];
@@ -4288,7 +4298,7 @@ mod tests {
         let schema = Schema::parse_str(&schema_str).unwrap();
 
         match schema {
-            Schema::Record { name, fields, .. } => {
+            Schema::Record(RecordSchema { name, fields, .. }) => {
                 assert_eq!(name, Name::new("union_schema_test").unwrap());
                 assert_eq!(fields.len(), 1);
                 let field = &fields[0];
@@ -4325,7 +4335,7 @@ mod tests {
         let schema = Schema::parse_str(&schema_str).unwrap();
 
         match schema {
-            Schema::Record { name, fields, .. } => {
+            Schema::Record(RecordSchema { name, fields, .. }) => {
                 assert_eq!(name, Name::new("union_schema_test").unwrap());
                 assert_eq!(fields.len(), 1);
                 let field = &fields[0];
@@ -4361,7 +4371,7 @@ mod tests {
         "#;
 
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { fields, .. } = schema {
+        if let Schema::Record(RecordSchema { fields, .. }) = schema {
             let num_field = &fields[0];
             assert_eq!(num_field.name, "num");
             assert_eq!(num_field.aliases, Some(vec!("num1".into(), "num2".into())));
diff --git a/lang/rust/avro/src/schema_compatibility.rs b/lang/rust/avro/src/schema_compatibility.rs
index b691041e5..aad8fde36 100644
--- a/lang/rust/avro/src/schema_compatibility.rs
+++ b/lang/rust/avro/src/schema_compatibility.rs
@@ -16,7 +16,7 @@
 // under the License.
 
 //! Logic for checking schema compatibility
-use crate::schema::{Schema, SchemaKind};
+use crate::schema::{EnumSchema, FixedSchema, RecordSchema, Schema, SchemaKind};
 use std::{
     collections::{hash_map::DefaultHasher, HashSet},
     hash::Hasher,
@@ -88,13 +88,13 @@ impl Checker {
             SchemaKind::Union => self.match_union_schemas(writers_schema, readers_schema),
             SchemaKind::Enum => {
                 // reader's symbols must contain all writer's symbols
-                if let Schema::Enum {
+                if let Schema::Enum(EnumSchema {
                     symbols: w_symbols, ..
-                } = writers_schema
+                }) = writers_schema
                 {
-                    if let Schema::Enum {
+                    if let Schema::Enum(EnumSchema {
                         symbols: r_symbols, ..
-                    } = readers_schema
+                    }) = readers_schema
                     {
                         return !w_symbols.iter().any(|e| !r_symbols.contains(e));
                     }
@@ -121,15 +121,15 @@ impl Checker {
             return false;
         }
 
-        if let Schema::Record {
+        if let Schema::Record(RecordSchema {
             fields: w_fields,
             lookup: w_lookup,
             ..
-        } = writers_schema
+        }) = writers_schema
         {
-            if let Schema::Record {
+            if let Schema::Record(RecordSchema {
                 fields: r_fields, ..
-            } = readers_schema
+            }) = readers_schema
             {
                 for field in r_fields.iter() {
                     if let Some(pos) = w_lookup.get(&field.name) {
@@ -219,8 +219,8 @@ impl SchemaCompatibility {
 
             match r_type {
                 SchemaKind::Record => {
-                    if let Schema::Record { name: w_name, .. } = writers_schema {
-                        if let Schema::Record { name: r_name, .. } = readers_schema {
+                    if let Schema::Record(RecordSchema { name: w_name, .. }) = writers_schema {
+                        if let Schema::Record(RecordSchema { name: r_name, .. }) = readers_schema {
                             return w_name.fullname(None) == r_name.fullname(None);
                         } else {
                             unreachable!("readers_schema should have been Schema::Record")
@@ -230,21 +230,21 @@ impl SchemaCompatibility {
                     }
                 }
                 SchemaKind::Fixed => {
-                    if let Schema::Fixed {
+                    if let Schema::Fixed(FixedSchema {
                         name: w_name,
                         aliases: _,
                         doc: _w_doc,
                         size: w_size,
                         attributes: _,
-                    } = writers_schema
+                    }) = writers_schema
                     {
-                        if let Schema::Fixed {
+                        if let Schema::Fixed(FixedSchema {
                             name: r_name,
                             aliases: _,
                             doc: _r_doc,
                             size: r_size,
                             attributes: _,
-                        } = readers_schema
+                        }) = readers_schema
                         {
                             return w_name.fullname(None) == r_name.fullname(None)
                                 && w_size == r_size;
@@ -256,8 +256,8 @@ impl SchemaCompatibility {
                     }
                 }
                 SchemaKind::Enum => {
-                    if let Schema::Enum { name: w_name, .. } = writers_schema {
-                        if let Schema::Enum { name: r_name, .. } = readers_schema {
+                    if let Schema::Enum(EnumSchema { name: w_name, .. }) = writers_schema {
+                        if let Schema::Enum(EnumSchema { name: r_name, .. }) = readers_schema {
                             return w_name.fullname(None) == r_name.fullname(None);
                         } else {
                             unreachable!("readers_schema should have been Schema::Enum")
diff --git a/lang/rust/avro/src/types.rs b/lang/rust/avro/src/types.rs
index ee322b331..d44826be1 100644
--- a/lang/rust/avro/src/types.rs
+++ b/lang/rust/avro/src/types.rs
@@ -20,8 +20,8 @@ use crate::{
     decimal::Decimal,
     duration::Duration,
     schema::{
-        Name, NamesRef, Namespace, Precision, RecordField, ResolvedSchema, Scale, Schema,
-        SchemaKind, UnionSchema,
+        DecimalSchema, EnumSchema, FixedSchema, Name, NamesRef, Namespace, Precision, RecordField,
+        RecordSchema, ResolvedSchema, Scale, Schema, SchemaKind, UnionSchema,
     },
     AvroResult, Error,
 };
@@ -221,11 +221,11 @@ impl<'a> Record<'a> {
     /// If the `Schema` is not a `Schema::Record` variant, `None` will be returned.
     pub fn new(schema: &Schema) -> Option<Record> {
         match *schema {
-            Schema::Record {
+            Schema::Record(RecordSchema {
                 fields: ref schema_fields,
                 lookup: ref schema_lookup,
                 ..
-            } => {
+            }) => {
                 let mut fields = Vec::with_capacity(schema_fields.len());
                 for schema_field in schema_fields.iter() {
                     fields.push((schema_field.name.clone(), Value::Null));
@@ -282,7 +282,7 @@ impl From<JsonValue> for Value {
 }
 
 /// Convert Avro values to Json values
-impl std::convert::TryFrom<Value> for JsonValue {
+impl TryFrom<Value> for JsonValue {
     type Error = crate::error::Error;
     fn try_from(value: Value) -> AvroResult<Self> {
         match value {
@@ -415,7 +415,7 @@ impl Value {
             (&Value::Bytes(_), &Schema::Decimal { .. }) => None,
             (&Value::String(_), &Schema::String) => None,
             (&Value::String(_), &Schema::Uuid) => None,
-            (&Value::Fixed(n, _), &Schema::Fixed { size, .. }) => {
+            (&Value::Fixed(n, _), &Schema::Fixed(FixedSchema { size, .. })) => {
                 if n != size {
                     Some(format!(
                         "The value's size ({n}) is different than the schema's size ({size})"
@@ -424,7 +424,7 @@ impl Value {
                     None
                 }
             }
-            (Value::Bytes(b), &Schema::Fixed { size, .. }) => {
+            (Value::Bytes(b), &Schema::Fixed(FixedSchema { size, .. })) => {
                 if b.len() != size {
                     Some(format!(
                         "The bytes' length ({}) is different than the schema's size ({})",
@@ -446,14 +446,14 @@ impl Value {
             }
             // TODO: check precision against n
             (&Value::Fixed(_n, _), &Schema::Decimal { .. }) => None,
-            (Value::String(s), Schema::Enum { symbols, .. }) => {
+            (Value::String(s), Schema::Enum(EnumSchema { symbols, .. })) => {
                 if !symbols.contains(s) {
                     Some(format!("'{s}' is not a member of the possible symbols"))
                 } else {
                     None
                 }
             }
-            (&Value::Enum(i, ref s), Schema::Enum { symbols, .. }) => symbols
+            (&Value::Enum(i, ref s), Schema::Enum(EnumSchema { symbols, .. })) => symbols
                 .get(i as usize)
                 .map(|ref symbol| {
                     if symbol != &s {
@@ -487,7 +487,7 @@ impl Value {
                     )
                 })
             }
-            (Value::Record(record_fields), Schema::Record { fields, lookup, .. }) => {
+            (Value::Record(record_fields), Schema::Record(RecordSchema { fields, lookup, .. })) => {
                 let non_nullable_fields_count =
                     fields.iter().filter(|&rf| !rf.is_nullable()).count();
 
@@ -527,7 +527,7 @@ impl Value {
                         }
                     })
             }
-            (Value::Map(items), Schema::Record { fields, .. }) => {
+            (Value::Map(items), Schema::Record(RecordSchema { fields, .. })) => {
                 fields.iter().fold(None, |acc, field| {
                     if let Some(item) = items.get(&field.name) {
                         let res = item.validate_internal(&field.schema, names, enclosing_namespace);
@@ -598,19 +598,19 @@ impl Value {
             Schema::Double => self.resolve_double(),
             Schema::Bytes => self.resolve_bytes(),
             Schema::String => self.resolve_string(),
-            Schema::Fixed { size, .. } => self.resolve_fixed(size),
+            Schema::Fixed(FixedSchema { size, .. }) => self.resolve_fixed(size),
             Schema::Union(ref inner) => self.resolve_union(inner, names, enclosing_namespace),
-            Schema::Enum { ref symbols, .. } => self.resolve_enum(symbols),
+            Schema::Enum(EnumSchema { ref symbols, .. }) => self.resolve_enum(symbols),
             Schema::Array(ref inner) => self.resolve_array(inner, names, enclosing_namespace),
             Schema::Map(ref inner) => self.resolve_map(inner, names, enclosing_namespace),
-            Schema::Record { ref fields, .. } => {
+            Schema::Record(RecordSchema { ref fields, .. }) => {
                 self.resolve_record(fields, names, enclosing_namespace)
             }
-            Schema::Decimal {
+            Schema::Decimal(DecimalSchema {
                 scale,
                 precision,
                 ref inner,
-            } => self.resolve_decimal(precision, scale, inner),
+            }) => self.resolve_decimal(precision, scale, inner),
             Schema::Date => self.resolve_date(),
             Schema::TimeMillis => self.resolve_time_millis(),
             Schema::TimeMicros => self.resolve_time_micros(),
@@ -657,7 +657,7 @@ impl Value {
             return Err(Error::GetScaleAndPrecision { scale, precision });
         }
         match inner {
-            &Schema::Fixed { size, .. } => {
+            &Schema::Fixed(FixedSchema { size, .. }) => {
                 if max_prec_for_len(size)? < precision {
                     return Err(Error::GetScaleWithFixedSize { size, precision });
                 }
@@ -960,7 +960,7 @@ impl Value {
                     Some(value) => value,
                     None => match field.default {
                         Some(ref value) => match field.schema {
-                            Schema::Enum { ref symbols, .. } => {
+                            Schema::Enum(EnumSchema { ref symbols, .. }) => {
                                 Value::from(value.clone()).resolve_enum(symbols)?
                             }
                             Schema::Union(ref union_schema) => {
@@ -1106,7 +1106,7 @@ mod tests {
             ),
             (
                 Value::Record(vec![("unknown_field_name".to_string(), Value::Null)]),
-                Schema::Record {
+                Schema::Record(RecordSchema {
                     name: Name::new("record_name").unwrap(),
                     aliases: None,
                     doc: None,
@@ -1122,13 +1122,13 @@ mod tests {
                     }],
                     lookup: Default::default(),
                     attributes: Default::default(),
-                },
+                }),
                 false,
-                r#"Invalid value: Record([("unknown_field_name", Null)]) for schema: Record { name: Name { name: "record_name", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "field_name", doc: None, aliases: None, default: None, schema: Int, order: Ignore, position: 0, custom_attributes: {} }], lookup: {}, attributes: {} }. Reason: There is no schema field for field 'unknown_field_name'"#,
+                r#"Invalid value: Record([("unknown_field_name", Null)]) for schema: Record(RecordSchema { name: Name { name: "record_name", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "field_name", doc: None, aliases: None, default: None, schema: Int, order: Ignore, position: 0, custom_attributes: {} }], lookup: {}, attributes: {} }). Reason: There is no schema field for field 'unknown_field_name'"#,
             ),
             (
                 Value::Record(vec![("field_name".to_string(), Value::Null)]),
-                Schema::Record {
+                Schema::Record(RecordSchema {
                     name: Name::new("record_name").unwrap(),
                     aliases: None,
                     doc: None,
@@ -1146,9 +1146,9 @@ mod tests {
                     }],
                     lookup: [("field_name".to_string(), 0)].iter().cloned().collect(),
                     attributes: Default::default(),
-                },
+                }),
                 false,
-                r#"Invalid value: Record([("field_name", Null)]) for schema: Record { name: Name { name: "record_name", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "field_name", doc: None, aliases: None, default: None, schema: Ref { name: Name { name: "missing", namespace: None } }, order: Ignore, position: 0, custom_attributes: {} }], lookup: {"field_name": 0}, attributes: {} }. Reason: Unresolved schema reference: 'Name { name: "missing", namespace: None } [...]
+                r#"Invalid value: Record([("field_name", Null)]) for schema: Record(RecordSchema { name: Name { name: "record_name", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "field_name", doc: None, aliases: None, default: None, schema: Ref { name: Name { name: "missing", namespace: None } }, order: Ignore, position: 0, custom_attributes: {} }], lookup: {"field_name": 0}, attributes: {} }). Reason: Unresolved schema reference: 'Name { name: "missing", nam [...]
             ),
         ];
 
@@ -1170,13 +1170,13 @@ mod tests {
 
     #[test]
     fn validate_fixed() {
-        let schema = Schema::Fixed {
+        let schema = Schema::Fixed(FixedSchema {
             size: 4,
             name: Name::new("some_fixed").unwrap(),
             aliases: None,
             doc: None,
             attributes: Default::default(),
-        };
+        });
 
         assert!(Value::Fixed(4, vec![0, 0, 0, 0]).validate(&schema));
         let value = Value::Fixed(5, vec![0, 0, 0, 0, 0]);
@@ -1203,7 +1203,7 @@ mod tests {
 
     #[test]
     fn validate_enum() {
-        let schema = Schema::Enum {
+        let schema = Schema::Enum(EnumSchema {
             name: Name::new("some_enum").unwrap(),
             aliases: None,
             doc: None,
@@ -1214,7 +1214,7 @@ mod tests {
                 "clubs".to_string(),
             ],
             attributes: Default::default(),
-        };
+        });
 
         assert!(Value::Enum(0, "spades".to_string()).validate(&schema));
         assert!(Value::String("spades".to_string()).validate(&schema));
@@ -1249,7 +1249,7 @@ mod tests {
             .as_str(),
         );
 
-        let other_schema = Schema::Enum {
+        let other_schema = Schema::Enum(EnumSchema {
             name: Name::new("some_other_enum").unwrap(),
             aliases: None,
             doc: None,
@@ -1260,7 +1260,7 @@ mod tests {
                 "spades".to_string(),
             ],
             attributes: Default::default(),
-        };
+        });
 
         let value = Value::Enum(0, "spades".to_string());
         assert!(!value.validate(&other_schema));
@@ -1287,7 +1287,7 @@ mod tests {
         //      }
         //    ]
         // }
-        let schema = Schema::Record {
+        let schema = Schema::Record(RecordSchema {
             name: Name::new("some_record").unwrap(),
             aliases: None,
             doc: None,
@@ -1334,7 +1334,7 @@ mod tests {
             .cloned()
             .collect(),
             attributes: Default::default(),
-        };
+        });
 
         assert!(Value::Record(vec![
             ("a".to_string(), Value::Long(42i64)),
@@ -1354,7 +1354,7 @@ mod tests {
         ]);
         assert!(!value.validate(&schema));
         assert_logged(
-            r#"Invalid value: Record([("a", Boolean(false)), ("b", String("foo"))]) for schema: Record { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, RecordField { name: "c",  [...]
+            r#"Invalid value: Record([("a", Boolean(false)), ("b", String("foo"))]) for schema: Record(RecordSchema { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, RecordField  [...]
         );
 
         let value = Value::Record(vec![
@@ -1363,7 +1363,7 @@ mod tests {
         ]);
         assert!(!value.validate(&schema));
         assert_logged(
-            r#"Invalid value: Record([("a", Long(42)), ("c", String("foo"))]) for schema: Record { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, RecordField { name: "c", doc: N [...]
+            r#"Invalid value: Record([("a", Long(42)), ("c", String("foo"))]) for schema: Record(RecordSchema { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, RecordField { name [...]
         );
         assert_not_logged(
             r#"Invalid value: String("foo") for schema: Int. Reason: Unsupported value-schema combination"#,
@@ -1375,7 +1375,7 @@ mod tests {
         ]);
         assert!(!value.validate(&schema));
         assert_logged(
-            r#"Invalid value: Record([("a", Long(42)), ("d", String("foo"))]) for schema: Record { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, RecordField { name: "c", doc: N [...]
+            r#"Invalid value: Record([("a", Long(42)), ("d", String("foo"))]) for schema: Record(RecordSchema { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, RecordField { name [...]
         );
 
         let value = Value::Record(vec![
@@ -1386,7 +1386,7 @@ mod tests {
         ]);
         assert!(!value.validate(&schema));
         assert_logged(
-            r#"Invalid value: Record([("a", Long(42)), ("b", String("foo")), ("c", Null), ("d", Null)]) for schema: Record { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, Recor [...]
+            r#"Invalid value: Record([("a", Long(42)), ("b", String("foo")), ("c", Null), ("d", Null)]) for schema: Record(RecordSchema { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes [...]
         );
 
         assert!(Value::Map(
@@ -1406,7 +1406,7 @@ mod tests {
         )
         .validate(&schema));
         assert_logged(
-            r#"Invalid value: Map({"d": Long(123)}) for schema: Record { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, RecordField { name: "c", doc: None, aliases: None, defaul [...]
+            r#"Invalid value: Map({"d": Long(123)}) for schema: Record(RecordSchema { name: Name { name: "some_record", namespace: None }, aliases: None, doc: None, fields: [RecordField { name: "a", doc: None, aliases: None, default: None, schema: Long, order: Ascending, position: 0, custom_attributes: {} }, RecordField { name: "b", doc: None, aliases: None, default: None, schema: String, order: Ascending, position: 1, custom_attributes: {} }, RecordField { name: "c", doc: None, aliases: [...]
 Field with name '"b"' is not a member of the map items"#,
         );
 
@@ -1473,11 +1473,11 @@ Field with name '"b"' is not a member of the map items"#,
         let value = Value::Decimal(Decimal::from(vec![1, 2]));
         value
             .clone()
-            .resolve(&Schema::Decimal {
+            .resolve(&Schema::Decimal(DecimalSchema {
                 precision: 10,
                 scale: 4,
                 inner: Box::new(Schema::Bytes),
-            })
+            }))
             .unwrap();
         assert!(value.resolve(&Schema::String).is_err());
     }
@@ -1486,11 +1486,11 @@ Field with name '"b"' is not a member of the map items"#,
     fn resolve_decimal_invalid_scale() {
         let value = Value::Decimal(Decimal::from(vec![1]));
         assert!(value
-            .resolve(&Schema::Decimal {
+            .resolve(&Schema::Decimal(DecimalSchema {
                 precision: 2,
                 scale: 3,
                 inner: Box::new(Schema::Bytes),
-            })
+            }))
             .is_err());
     }
 
@@ -1498,11 +1498,11 @@ Field with name '"b"' is not a member of the map items"#,
     fn resolve_decimal_invalid_precision_for_length() {
         let value = Value::Decimal(Decimal::from((1u8..=8u8).rev().collect::<Vec<_>>()));
         assert!(value
-            .resolve(&Schema::Decimal {
+            .resolve(&Schema::Decimal(DecimalSchema {
                 precision: 1,
                 scale: 0,
                 inner: Box::new(Schema::Bytes),
-            })
+            }))
             .is_err());
     }
 
@@ -1511,17 +1511,17 @@ Field with name '"b"' is not a member of the map items"#,
         let value = Value::Decimal(Decimal::from(vec![1, 2]));
         assert!(value
             .clone()
-            .resolve(&Schema::Decimal {
+            .resolve(&Schema::Decimal(DecimalSchema {
                 precision: 10,
                 scale: 1,
-                inner: Box::new(Schema::Fixed {
+                inner: Box::new(Schema::Fixed(FixedSchema {
                     name: Name::new("decimal").unwrap(),
                     aliases: None,
                     size: 20,
                     doc: None,
                     attributes: Default::default(),
-                })
-            })
+                }))
+            }))
             .is_ok());
         assert!(value.resolve(&Schema::String).is_err());
     }
diff --git a/lang/rust/avro/src/writer.rs b/lang/rust/avro/src/writer.rs
index 795fd09f2..58d13d40f 100644
--- a/lang/rust/avro/src/writer.rs
+++ b/lang/rust/avro/src/writer.rs
@@ -632,7 +632,7 @@ mod tests {
     use crate::{
         decimal::Decimal,
         duration::{Days, Duration, Millis, Months},
-        schema::Name,
+        schema::{DecimalSchema, FixedSchema, Name},
         types::Record,
         util::zig_i64,
     };
@@ -781,21 +781,21 @@ mod tests {
     #[test]
     fn decimal_fixed() -> TestResult<()> {
         let size = 30;
-        let inner = Schema::Fixed {
+        let inner = Schema::Fixed(FixedSchema {
             name: Name::new("decimal").unwrap(),
             aliases: None,
             doc: None,
             size,
             attributes: Default::default(),
-        };
+        });
         let value = vec![0u8; size];
         logical_type_test(
             r#"{"type": {"type": "fixed", "size": 30, "name": "decimal"}, "logicalType": "decimal", "precision": 20, "scale": 5}"#,
-            &Schema::Decimal {
+            &Schema::Decimal(DecimalSchema {
                 precision: 20,
                 scale: 5,
                 inner: Box::new(inner.clone()),
-            },
+            }),
             Value::Decimal(Decimal::from(value.clone())),
             &inner,
             Value::Fixed(size, value),
@@ -808,11 +808,11 @@ mod tests {
         let value = vec![0u8; 10];
         logical_type_test(
             r#"{"type": "bytes", "logicalType": "decimal", "precision": 4, "scale": 3}"#,
-            &Schema::Decimal {
+            &Schema::Decimal(DecimalSchema {
                 precision: 4,
                 scale: 3,
                 inner: Box::new(inner.clone()),
-            },
+            }),
             Value::Decimal(Decimal::from(value.clone())),
             &inner,
             value,
@@ -821,13 +821,13 @@ mod tests {
 
     #[test]
     fn duration() -> TestResult<()> {
-        let inner = Schema::Fixed {
+        let inner = Schema::Fixed(FixedSchema {
             name: Name::new("duration").unwrap(),
             aliases: None,
             doc: None,
             size: 12,
             attributes: Default::default(),
-        };
+        });
         let value = Value::Duration(Duration::new(
             Months::new(256),
             Days::new(512),
diff --git a/lang/rust/avro/tests/schema.rs b/lang/rust/avro/tests/schema.rs
index 95ba18c2f..5018dc5dd 100644
--- a/lang/rust/avro/tests/schema.rs
+++ b/lang/rust/avro/tests/schema.rs
@@ -16,7 +16,7 @@
 // under the License.
 
 use apache_avro::{
-    schema::{Name, RecordField},
+    schema::{EnumSchema, FixedSchema, Name, RecordField, RecordSchema},
     to_avro_datum, to_value,
     types::{Record, Value},
     Codec, Error, Reader, Schema, Writer,
@@ -634,21 +634,21 @@ fn test_correct_recursive_extraction() {
         ]
     }"#;
     let outer_schema = Schema::parse_str(raw_outer_schema).unwrap();
-    if let Schema::Record {
+    if let Schema::Record(RecordSchema {
         fields: outer_fields,
         ..
-    } = outer_schema
+    }) = outer_schema
     {
         let inner_schema = &outer_fields[0].schema;
-        if let Schema::Record {
+        if let Schema::Record(RecordSchema {
             fields: inner_fields,
             ..
-        } = inner_schema
+        }) = inner_schema
         {
-            if let Schema::Record {
+            if let Schema::Record(RecordSchema {
                 name: recursive_type,
                 ..
-            } = &inner_fields[0].schema
+            }) = &inner_fields[0].schema
             {
                 assert_eq!("X", recursive_type.name.as_str());
             }
@@ -880,14 +880,14 @@ fn test_parse_reused_record_schema_by_fullname() {
     let schema = Schema::parse_str(schema_str);
     assert!(schema.is_ok());
     match schema.unwrap() {
-        Schema::Record {
+        Schema::Record(RecordSchema {
             ref name,
             aliases: _,
             doc: _,
             ref fields,
             lookup: _,
             attributes: _,
-        } => {
+        }) => {
             assert_eq!(name.fullname(None), "test.Weather", "Name does not match!");
 
             assert_eq!(fields.len(), 3, "The number of the fields is not correct!");
@@ -1199,9 +1199,9 @@ fn test_doc_attributes() {
     init();
     fn assert_doc(schema: &Schema) {
         match schema {
-            Schema::Enum { doc, .. } => assert!(doc.is_some()),
-            Schema::Record { doc, .. } => assert!(doc.is_some()),
-            Schema::Fixed { doc, .. } => assert!(doc.is_some()),
+            Schema::Enum(EnumSchema { doc, .. }) => assert!(doc.is_some()),
+            Schema::Record(RecordSchema { doc, .. }) => assert!(doc.is_some()),
+            Schema::Fixed(FixedSchema { doc, .. }) => assert!(doc.is_some()),
             Schema::String => (),
             _ => unreachable!("Unexpected schema type: {:?}", schema),
         }
@@ -1210,7 +1210,7 @@ fn test_doc_attributes() {
     for (raw_schema, _) in DOC_EXAMPLES.iter() {
         let original_schema = Schema::parse_str(raw_schema).unwrap();
         assert_doc(&original_schema);
-        if let Schema::Record { fields, .. } = original_schema {
+        if let Schema::Record(RecordSchema { fields, .. }) = original_schema {
             for f in fields {
                 assert_doc(&f.schema)
             }
diff --git a/lang/rust/avro_derive/src/lib.rs b/lang/rust/avro_derive/src/lib.rs
index 5f900473c..5e80e70af 100644
--- a/lang/rust/avro_derive/src/lib.rs
+++ b/lang/rust/avro_derive/src/lib.rs
@@ -190,14 +190,14 @@ fn get_data_struct_schema_def(
             .iter()
             .map(|field| (field.name.to_owned(), field.position))
             .collect();
-        apache_avro::schema::Schema::Record {
+        apache_avro::schema::Schema::Record(apache_avro::schema::RecordSchema {
             name,
             aliases: #record_aliases,
             doc: #record_doc,
             fields: schema_fields,
             lookup,
             attributes: Default::default(),
-        }
+        })
     })
 }
 
@@ -217,13 +217,13 @@ fn get_data_enum_schema_def(
             .map(|variant| variant.ident.to_string())
             .collect();
         Ok(quote! {
-            apache_avro::schema::Schema::Enum {
+            apache_avro::schema::Schema::Enum(apache_avro::schema::EnumSchema {
                 name: apache_avro::schema::Name::new(#full_schema_name).expect(&format!("Unable to parse enum name for schema {}", #full_schema_name)[..]),
                 aliases: #enum_aliases,
                 doc: #doc,
                 symbols: vec![#(#symbols.to_owned()),*],
                 attributes: Default::default(),
-            }
+            })
         })
     } else {
         Err(vec![syn::Error::new(
diff --git a/lang/rust/avro_derive/tests/derive.rs b/lang/rust/avro_derive/tests/derive.rs
index dcf599092..3dc217b6a 100644
--- a/lang/rust/avro_derive/tests/derive.rs
+++ b/lang/rust/avro_derive/tests/derive.rs
@@ -30,7 +30,7 @@ extern crate serde;
 
 #[cfg(test)]
 mod test_derive {
-    use apache_avro::schema::Alias;
+    use apache_avro::schema::{Alias, EnumSchema, RecordSchema};
     use std::{
         borrow::{Borrow, Cow},
         sync::Mutex,
@@ -144,7 +144,7 @@ mod test_derive {
         "#;
         let schema = Schema::parse_str(schema).unwrap();
         assert_eq!(schema, TestBasicNamespace::get_schema());
-        if let Schema::Record { name, .. } = TestBasicNamespace::get_schema() {
+        if let Schema::Record(RecordSchema { name, .. }) = TestBasicNamespace::get_schema() {
             assert_eq!("com.testing.namespace".to_owned(), name.namespace.unwrap())
         } else {
             panic!("TestBasicNamespace schema must be a record schema")
@@ -191,7 +191,9 @@ mod test_derive {
         "#;
         let schema = Schema::parse_str(schema).unwrap();
         assert_eq!(schema, TestComplexNamespace::get_schema());
-        if let Schema::Record { name, fields, .. } = TestComplexNamespace::get_schema() {
+        if let Schema::Record(RecordSchema { name, fields, .. }) =
+            TestComplexNamespace::get_schema()
+        {
             assert_eq!(
                 "com.testing.complex.namespace".to_owned(),
                 name.namespace.unwrap()
@@ -201,7 +203,7 @@ mod test_derive {
                 .filter(|field| field.name == "a")
                 .map(|field| &field.schema)
                 .next();
-            if let Some(Schema::Record { name, .. }) = inner_schema {
+            if let Some(Schema::Record(RecordSchema { name, .. })) = inner_schema {
                 assert_eq!(
                     "com.testing.namespace".to_owned(),
                     name.namespace.clone().unwrap()
@@ -944,7 +946,9 @@ mod test_derive {
         }
         "#;
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, doc, .. } = TestBasicWithAttributes::get_schema() {
+        if let Schema::Record(RecordSchema { name, doc, .. }) =
+            TestBasicWithAttributes::get_schema()
+        {
             assert_eq!("com.testing.namespace".to_owned(), name.namespace.unwrap());
             assert_eq!("A Documented Record", doc.unwrap())
         } else {
@@ -987,7 +991,7 @@ mod test_derive {
         let schema = Schema::parse_str(schema).unwrap();
         let derived_schema = TestBasicWithOuterDocAttributes::get_schema();
         assert_eq!(&schema, &derived_schema);
-        if let Schema::Record { name, doc, .. } = derived_schema {
+        if let Schema::Record(RecordSchema { name, doc, .. }) = derived_schema {
             assert_eq!("com.testing.namespace".to_owned(), name.namespace.unwrap());
             assert_eq!("A Documented Record", doc.unwrap())
         } else {
@@ -1029,7 +1033,8 @@ mod test_derive {
         }
         "#;
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, doc, .. } = TestBasicWithLargeDoc::get_schema() {
+        if let Schema::Record(RecordSchema { name, doc, .. }) = TestBasicWithLargeDoc::get_schema()
+        {
             assert_eq!("com.testing.namespace".to_owned(), name.namespace.unwrap());
             assert_eq!(
                 "A Documented Record\nthat spans\nmultiple lines",
@@ -1069,7 +1074,7 @@ mod test_derive {
         let schema = Schema::parse_str(schema).unwrap();
         let derived_schema = TestBasicWithBool::get_schema();
 
-        if let Schema::Record { name, .. } = derived_schema {
+        if let Schema::Record(RecordSchema { name, .. }) = derived_schema {
             assert_eq!("TestBasicWithBool", name.fullname(None))
         } else {
             panic!("TestBasicWithBool schema must be a record schema")
@@ -1100,7 +1105,7 @@ mod test_derive {
         }
         "#;
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, .. } = TestBasicWithU32::get_schema() {
+        if let Schema::Record(RecordSchema { name, .. }) = TestBasicWithU32::get_schema() {
             assert_eq!("TestBasicWithU32", name.fullname(None))
         } else {
             panic!("TestBasicWithU32 schema must be a record schema")
@@ -1132,7 +1137,9 @@ mod test_derive {
         }
         "#;
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, aliases, .. } = TestBasicStructWithAliases::get_schema() {
+        if let Schema::Record(RecordSchema { name, aliases, .. }) =
+            TestBasicStructWithAliases::get_schema()
+        {
             assert_eq!("TestBasicStructWithAliases", name.fullname(None));
             assert_eq!(
                 Some(vec![
@@ -1174,7 +1181,9 @@ mod test_derive {
         }
         "#;
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, aliases, .. } = TestBasicStructWithAliases2::get_schema() {
+        if let Schema::Record(RecordSchema { name, aliases, .. }) =
+            TestBasicStructWithAliases2::get_schema()
+        {
             assert_eq!("TestBasicStructWithAliases2", name.fullname(None));
             assert_eq!(
                 Some(vec![
@@ -1213,7 +1222,9 @@ mod test_derive {
         }
         "#;
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Enum { name, aliases, .. } = TestBasicEnumWithAliases::get_schema() {
+        if let Schema::Enum(EnumSchema { name, aliases, .. }) =
+            TestBasicEnumWithAliases::get_schema()
+        {
             assert_eq!("TestBasicEnumWithAliases", name.fullname(None));
             assert_eq!(
                 Some(vec![
@@ -1254,7 +1265,9 @@ mod test_derive {
         }
         "#;
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Enum { name, aliases, .. } = TestBasicEnumWithAliases2::get_schema() {
+        if let Schema::Enum(EnumSchema { name, aliases, .. }) =
+            TestBasicEnumWithAliases2::get_schema()
+        {
             assert_eq!("TestBasicEnumWithAliases2", name.fullname(None));
             assert_eq!(
                 Some(vec![
@@ -1358,7 +1371,8 @@ mod test_derive {
         "#;
 
         let schema = Schema::parse_str(schema).unwrap();
-        if let Schema::Record { name, fields, .. } = TestBasicStructWithDefaultValues::get_schema()
+        if let Schema::Record(RecordSchema { name, fields, .. }) =
+            TestBasicStructWithDefaultValues::get_schema()
         {
             assert_eq!("TestBasicStructWithDefaultValues", name.fullname(None));
             use serde_json::json;
@@ -1455,7 +1469,7 @@ mod test_derive {
 
         let schema = Schema::parse_str(schema).unwrap();
         let derived_schema = TestBasicStructWithSkipAttribute::get_schema();
-        if let Schema::Record { name, fields, .. } = &derived_schema {
+        if let Schema::Record(RecordSchema { name, fields, .. }) = &derived_schema {
             assert_eq!("TestBasicStructWithSkipAttribute", name.fullname(None));
             for field in fields {
                 match field.name.as_str() {
@@ -1522,7 +1536,7 @@ mod test_derive {
 
         let schema = Schema::parse_str(schema).unwrap();
         let derived_schema = TestBasicStructWithRenameAttribute::get_schema();
-        if let Schema::Record { name, fields, .. } = &derived_schema {
+        if let Schema::Record(RecordSchema { name, fields, .. }) = &derived_schema {
             assert_eq!("TestBasicStructWithRenameAttribute", name.fullname(None));
             for field in fields {
                 match field.name.as_str() {
@@ -1553,7 +1567,7 @@ mod test_derive {
         }
 
         let derived_schema = TestRawIdent::get_schema();
-        if let Schema::Record { fields, .. } = derived_schema {
+        if let Schema::Record(RecordSchema { fields, .. }) = derived_schema {
             let field = fields.get(0).expect("TestRawIdent must contain a field");
             assert_eq!(field.name, "type");
         } else {