This is an automated email from the ASF dual-hosted git repository. mgrigorov pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/avro-rs.git
commit 4b2897ca85884f8050ac92d27ccb45958d46ce64 Author: Kriskras99 <[email protected]> AuthorDate: Wed Nov 12 13:43:14 2025 +0100 feat: Transform the `StructFieldEq` implementation into an exhaustive match This makes it a compiler error if we forget to compare a type. `rustfmt` has been disabled for this function as it does a poor job of formatting this code. --- avro/src/schema_equality.rs | 228 ++++++++++++++++++-------------------------- 1 file changed, 94 insertions(+), 134 deletions(-) diff --git a/avro/src/schema_equality.rs b/avro/src/schema_equality.rs index 1097594..6763a3a 100644 --- a/avro/src/schema_equality.rs +++ b/avro/src/schema_equality.rs @@ -22,7 +22,7 @@ use crate::{ UnionSchema, }, }; -use log::{debug, error}; +use log::debug; use std::{fmt::Debug, sync::OnceLock}; /// A trait that compares two schemata for equality. @@ -54,160 +54,120 @@ pub struct StructFieldEq { } impl SchemataEq for StructFieldEq { + #[rustfmt::skip] fn compare(&self, schema_one: &Schema, schema_two: &Schema) -> bool { - macro_rules! compare_primitive { - ($primitive:ident) => { - if let Schema::$primitive = schema_one { - if let Schema::$primitive = schema_two { - return true; - } - return false; - } - }; - } - if schema_one.name() != schema_two.name() { return false; } - compare_primitive!(Null); - compare_primitive!(Boolean); - compare_primitive!(Int); - compare_primitive!(Int); - compare_primitive!(Long); - compare_primitive!(Float); - compare_primitive!(Double); - compare_primitive!(Bytes); - compare_primitive!(String); - compare_primitive!(Uuid); - compare_primitive!(BigDecimal); - compare_primitive!(Date); - compare_primitive!(Duration); - compare_primitive!(TimeMicros); - compare_primitive!(TimeMillis); - compare_primitive!(TimestampMicros); - compare_primitive!(TimestampMillis); - compare_primitive!(TimestampNanos); - compare_primitive!(LocalTimestampMicros); - compare_primitive!(LocalTimestampMillis); - compare_primitive!(LocalTimestampNanos); - if self.include_attributes && schema_one.custom_attributes() != schema_two.custom_attributes() { return false; } - if let Schema::Record(RecordSchema { - fields: fields_one, .. - }) = schema_one - { - if let Schema::Record(RecordSchema { - fields: fields_two, .. - }) = schema_two - { - return self.compare_fields(fields_one, fields_two); + match (schema_one, schema_two) { + (Schema::Null, Schema::Null) => true, + (Schema::Null, _) => false, + (Schema::Boolean, Schema::Boolean) => true, + (Schema::Boolean, _) => false, + (Schema::Int, Schema::Int) => true, + (Schema::Int, _) => false, + (Schema::Long, Schema::Long) => true, + (Schema::Long, _) => false, + (Schema::Float, Schema::Float) => true, + (Schema::Float, _) => false, + (Schema::Double, Schema::Double) => true, + (Schema::Double, _) => false, + (Schema::Bytes, Schema::Bytes) => true, + (Schema::Bytes, _) => false, + (Schema::String, Schema::String) => true, + (Schema::String, _) => false, + (Schema::Uuid, Schema::Uuid) => true, + (Schema::Uuid, _) => false, + (Schema::BigDecimal, Schema::BigDecimal) => true, + (Schema::BigDecimal, _) => false, + (Schema::Date, Schema::Date) => true, + (Schema::Date, _) => false, + (Schema::Duration, Schema::Duration) => true, + (Schema::Duration, _) => false, + (Schema::TimeMicros, Schema::TimeMicros) => true, + (Schema::TimeMicros, _) => false, + (Schema::TimeMillis, Schema::TimeMillis) => true, + (Schema::TimeMillis, _) => false, + (Schema::TimestampMicros, Schema::TimestampMicros) => true, + (Schema::TimestampMicros, _) => false, + (Schema::TimestampMillis, Schema::TimestampMillis) => true, + (Schema::TimestampMillis, _) => false, + (Schema::TimestampNanos, Schema::TimestampNanos) => true, + (Schema::TimestampNanos, _) => false, + (Schema::LocalTimestampMicros, Schema::LocalTimestampMicros) => true, + (Schema::LocalTimestampMicros, _) => false, + (Schema::LocalTimestampMillis, Schema::LocalTimestampMillis) => true, + (Schema::LocalTimestampMillis, _) => false, + (Schema::LocalTimestampNanos, Schema::LocalTimestampNanos) => true, + (Schema::LocalTimestampNanos, _) => false, + ( + Schema::Record(RecordSchema { fields: fields_one, ..}), + Schema::Record(RecordSchema { fields: fields_two, ..}) + ) => { + self.compare_fields(fields_one, fields_two) } - return false; - } - - if let Schema::Enum(EnumSchema { - symbols: symbols_one, - .. - }) = schema_one - { - if let Schema::Enum(EnumSchema { - symbols: symbols_two, - .. - }) = schema_two - { - return symbols_one == symbols_two; + (Schema::Record(_), _) => false, + ( + Schema::Enum(EnumSchema { symbols: symbols_one, ..}), + Schema::Enum(EnumSchema { symbols: symbols_two, .. }) + ) => { + symbols_one == symbols_two } - return false; - } - - if let Schema::Fixed(FixedSchema { size: size_one, .. }) = schema_one { - if let Schema::Fixed(FixedSchema { size: size_two, .. }) = schema_two { - return size_one == size_two; + (Schema::Enum(_), _) => false, + ( + Schema::Fixed(FixedSchema { size: size_one, ..}), + Schema::Fixed(FixedSchema { size: size_two, .. }) + ) => { + size_one == size_two } - return false; - } - - if let Schema::Union(UnionSchema { - schemas: schemas_one, - .. - }) = schema_one - { - if let Schema::Union(UnionSchema { - schemas: schemas_two, - .. - }) = schema_two - { - return schemas_one.len() == schemas_two.len() + (Schema::Fixed(_), _) => false, + ( + Schema::Union(UnionSchema { schemas: schemas_one, ..}), + Schema::Union(UnionSchema { schemas: schemas_two, .. }) + ) => { + schemas_one.len() == schemas_two.len() && schemas_one - .iter() - .zip(schemas_two.iter()) - .all(|(s1, s2)| self.compare(s1, s2)); + .iter() + .zip(schemas_two.iter()) + .all(|(s1, s2)| self.compare(s1, s2)) } - return false; - } - - if let Schema::Decimal(DecimalSchema { - precision: precision_one, - scale: scale_one, - .. - }) = schema_one - { - if let Schema::Decimal(DecimalSchema { - precision: precision_two, - scale: scale_two, - .. - }) = schema_two - { - return precision_one == precision_two && scale_one == scale_two; + (Schema::Union(_), _) => false, + ( + Schema::Decimal(DecimalSchema { precision: precision_one, scale: scale_one, ..}), + Schema::Decimal(DecimalSchema { precision: precision_two, scale: scale_two, .. }) + ) => { + precision_one == precision_two && scale_one == scale_two } - return false; - } - - if let Schema::Array(ArraySchema { - items: items_one, .. - }) = schema_one - { - if let Schema::Array(ArraySchema { - items: items_two, .. - }) = schema_two - { - return items_one == items_two; + (Schema::Decimal(_), _) => false, + ( + Schema::Array(ArraySchema { items: items_one, ..}), + Schema::Array(ArraySchema { items: items_two, ..}) + ) => { + items_one == items_two } - return false; - } - - if let Schema::Map(MapSchema { - types: types_one, .. - }) = schema_one - { - if let Schema::Map(MapSchema { - types: types_two, .. - }) = schema_two - { - return self.compare(types_one, types_two); + (Schema::Array(_), _) => false, + ( + Schema::Map(MapSchema { types: types_one, ..}), + Schema::Map(MapSchema { types: types_two, ..}) + ) => { + self.compare(types_one, types_two) } - return false; - } - - if let Schema::Ref { name: name_one } = schema_one { - if let Schema::Ref { name: name_two } = schema_two { - return name_one == name_two; + (Schema::Map(_), _) => false, + ( + Schema::Ref { name: name_one }, + Schema::Ref { name: name_two } + ) => { + name_one == name_two } - return false; + (Schema::Ref { .. }, _) => false, } - - error!( - "This is a bug in schema_equality.rs! The following schemata types are not checked! \ - Please report it to the Avro library maintainers! \ - \n{schema_one:?}\n\n{schema_two:?}" - ); - false } }
