This is an automated email from the ASF dual-hosted git repository. kriskras99 pushed a commit to branch feat/documentation in repository https://gitbox.apache.org/repos/asf/avro-rs.git
commit 75ca979af6b84d48e406219370b9256593e3e6b9 Author: Kriskras99 <[email protected]> AuthorDate: Sun Jan 18 11:49:47 2026 +0100 fix!: Move `AvroSchema` and `AvroSchemaComponent` to the `serde` module --- .../test_interop_single_object_encoding.rs | 2 +- avro/src/lib.rs | 4 +- avro/src/reader.rs | 4 +- avro/src/schema/mod.rs | 314 +------------------- avro/src/serde/derive.rs | 322 +++++++++++++++++++++ avro/src/serde/mod.rs | 3 + avro/src/writer.rs | 4 +- avro_derive/tests/derive.rs | 5 +- 8 files changed, 335 insertions(+), 323 deletions(-) diff --git a/avro/examples/test_interop_single_object_encoding.rs b/avro/examples/test_interop_single_object_encoding.rs index 61b1e6f..8a8b419 100644 --- a/avro/examples/test_interop_single_object_encoding.rs +++ b/avro/examples/test_interop_single_object_encoding.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use apache_avro::{schema::AvroSchema, types::Value}; +use apache_avro::{AvroSchema, types::Value}; use std::error::Error; struct InteropMessage; diff --git a/avro/src/lib.rs b/avro/src/lib.rs index 2d144ea..ac6d0bf 100644 --- a/avro/src/lib.rs +++ b/avro/src/lib.rs @@ -974,8 +974,8 @@ pub use reader::{ GenericSingleObjectReader, Reader, SpecificSingleObjectReader, from_avro_datum, from_avro_datum_reader_schemata, from_avro_datum_schemata, read_marker, }; -pub use schema::{AvroSchema, AvroSchemaComponent, Schema}; -pub use serde::{de::from_value, ser::to_value}; +pub use schema::Schema; +pub use serde::{AvroSchema, AvroSchemaComponent, de::from_value, ser::to_value}; pub use uuid::Uuid; pub use writer::{ GenericSingleObjectWriter, SpecificSingleObjectWriter, Writer, WriterBuilder, to_avro_datum, diff --git a/avro/src/reader.rs b/avro/src/reader.rs index 23af5db..d578a5f 100644 --- a/avro/src/reader.rs +++ b/avro/src/reader.rs @@ -17,13 +17,13 @@ //! Logic handling reading from Avro format at user level. use crate::{ - AvroResult, Codec, Error, + AvroResult, AvroSchema, Codec, Error, decode::{decode, decode_internal}, error::Details, from_value, headers::{HeaderBuilder, RabinFingerprintHeader}, schema::{ - AvroSchema, Names, ResolvedOwnedSchema, ResolvedSchema, Schema, resolve_names, + Names, ResolvedOwnedSchema, ResolvedSchema, Schema, resolve_names, resolve_names_with_schemata, }, types::Value, diff --git a/avro/src/schema/mod.rs b/avro/src/schema/mod.rs index 110d1d8..8ddd6f3 100644 --- a/avro/src/schema/mod.rs +++ b/avro/src/schema/mod.rs @@ -34,7 +34,7 @@ use serde::{ }; use serde_json::{Map, Value}; use std::{ - borrow::{Borrow, Cow}, + borrow::Borrow, collections::{BTreeMap, HashMap, HashSet}, fmt, fmt::Debug, @@ -2583,268 +2583,6 @@ fn field_ordering_position(field: &str) -> Option<usize> { .map(|pos| pos + 1) } -/// Trait for types that serve as an Avro data model. Derive implementation available -/// through `derive` feature. Do not implement directly! -/// Implement [`AvroSchemaComponent`] to get this trait -/// through a blanket implementation. -/// -/// Note: This trait is **not** implemented for `char` and `u64`. `char` is a 32-bit value -/// that does not have a logical mapping to an Avro schema. `u64` is too large to fit in a -/// Avro `long`. -pub trait AvroSchema { - fn get_schema() -> Schema; -} - -/// Trait for types that serve as fully defined components inside an Avro data model. Derive -/// implementation available through `derive` feature. This is what is implemented by -/// the `derive(AvroSchema)` macro. -/// -/// Note: This trait is **not** implemented for `char` and `u64`. `char` is a 32-bit value -/// that does not have a logical mapping to an Avro schema. `u64` is too large to fit in a -/// Avro `long`. -/// -/// # Implementation guide -/// -/// ### Simple implementation -/// To construct a non named simple schema, it is possible to ignore the input argument making the -/// general form implementation look like -/// ```ignore -/// impl AvroSchemaComponent for AType { -/// fn get_schema_in_ctxt(_: &mut Names, _: &Namespace) -> Schema { -/// Schema::? -/// } -///} -/// ``` -/// -/// ### Passthrough implementation -/// -/// To construct a schema for a Type that acts as in "inner" type, such as for smart pointers, simply -/// pass through the arguments to the inner type -/// ```ignore -/// impl AvroSchemaComponent for PassthroughType { -/// fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { -/// InnerType::get_schema_in_ctxt(named_schemas, enclosing_namespace) -/// } -///} -/// ``` -/// -/// ### Complex implementation -/// -/// To implement this for Named schema there is a general form needed to avoid creating invalid -/// schemas or infinite loops. -/// ```ignore -/// impl AvroSchemaComponent for ComplexType { -/// fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { -/// // Create the fully qualified name for your type given the enclosing namespace -/// let name = apache_avro::schema::Name::new("MyName") -/// .expect("Unable to parse schema name") -/// .fully_qualified_name(enclosing_namespace); -/// let enclosing_namespace = &name.namespace; -/// // Check, if your name is already defined, and if so, return a ref to that name -/// if named_schemas.contains_key(&name) { -/// apache_avro::schema::Schema::Ref{name: name.clone()} -/// } else { -/// named_schemas.insert(name.clone(), apache_avro::schema::Schema::Ref{name: name.clone()}); -/// // YOUR SCHEMA DEFINITION HERE with the name equivalent to "MyName". -/// // For non-simple sub types delegate to their implementation of AvroSchemaComponent -/// } -/// } -///} -/// ``` -pub trait AvroSchemaComponent { - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema; -} - -impl<T> AvroSchema for T -where - T: AvroSchemaComponent + ?Sized, -{ - fn get_schema() -> Schema { - T::get_schema_in_ctxt(&mut HashMap::default(), &None) - } -} - -macro_rules! impl_schema ( - ($type:ty, $variant_constructor:expr) => ( - impl AvroSchemaComponent for $type { - fn get_schema_in_ctxt(_: &mut Names, _: &Namespace) -> Schema { - $variant_constructor - } - } - ); -); - -impl_schema!(bool, Schema::Boolean); -impl_schema!(i8, Schema::Int); -impl_schema!(i16, Schema::Int); -impl_schema!(i32, Schema::Int); -impl_schema!(i64, Schema::Long); -impl_schema!(u8, Schema::Int); -impl_schema!(u16, Schema::Int); -impl_schema!(u32, Schema::Long); -impl_schema!(f32, Schema::Float); -impl_schema!(f64, Schema::Double); -impl_schema!(String, Schema::String); -impl_schema!(str, Schema::String); - -impl<T> AvroSchemaComponent for &T -where - T: AvroSchemaComponent + ?Sized, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - T::get_schema_in_ctxt(named_schemas, enclosing_namespace) - } -} - -impl<T> AvroSchemaComponent for &mut T -where - T: AvroSchemaComponent + ?Sized, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - T::get_schema_in_ctxt(named_schemas, enclosing_namespace) - } -} - -impl<T> AvroSchemaComponent for [T] -where - T: AvroSchemaComponent, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - Schema::array(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) - } -} - -impl<const N: usize, T> AvroSchemaComponent for [T; N] -where - T: AvroSchemaComponent, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - Schema::array(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) - } -} - -impl<T> AvroSchemaComponent for Vec<T> -where - T: AvroSchemaComponent, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - Schema::array(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) - } -} - -impl<T> AvroSchemaComponent for Option<T> -where - T: AvroSchemaComponent, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - let variants = vec![ - Schema::Null, - T::get_schema_in_ctxt(named_schemas, enclosing_namespace), - ]; - - Schema::Union( - UnionSchema::new(variants).expect("Option<T> must produce a valid (non-nested) union"), - ) - } -} - -impl<T> AvroSchemaComponent for Map<String, T> -where - T: AvroSchemaComponent, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - Schema::map(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) - } -} - -impl<T> AvroSchemaComponent for HashMap<String, T> -where - T: AvroSchemaComponent, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - Schema::map(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) - } -} - -impl<T> AvroSchemaComponent for Box<T> -where - T: AvroSchemaComponent, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - T::get_schema_in_ctxt(named_schemas, enclosing_namespace) - } -} - -impl<T> AvroSchemaComponent for std::sync::Mutex<T> -where - T: AvroSchemaComponent, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - T::get_schema_in_ctxt(named_schemas, enclosing_namespace) - } -} - -impl<T> AvroSchemaComponent for Cow<'_, T> -where - T: AvroSchemaComponent + Clone, -{ - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - T::get_schema_in_ctxt(named_schemas, enclosing_namespace) - } -} - -impl AvroSchemaComponent for core::time::Duration { - /// The schema is [`Schema::Duration`] with the name `duration`. - /// - /// This is a lossy conversion as this Avro type does not store the amount of nanoseconds. - #[expect(clippy::map_entry, reason = "We don't use the value from the map")] - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - let name = Name::new("duration") - .expect("Name is valid") - .fully_qualified_name(enclosing_namespace); - if named_schemas.contains_key(&name) { - Schema::Ref { name } - } else { - let schema = Schema::Duration(FixedSchema { - name: name.clone(), - aliases: None, - doc: None, - size: 12, - default: None, - attributes: Default::default(), - }); - named_schemas.insert(name, schema.clone()); - schema - } - } -} - -impl AvroSchemaComponent for uuid::Uuid { - /// The schema is [`Schema::Uuid`] with the name `uuid`. - /// - /// The underlying schema is [`Schema::Fixed`] with a size of 16. - #[expect(clippy::map_entry, reason = "We don't use the value from the map")] - fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { - let name = Name::new("uuid") - .expect("Name is valid") - .fully_qualified_name(enclosing_namespace); - if named_schemas.contains_key(&name) { - Schema::Ref { name } - } else { - let schema = Schema::Uuid(UuidSchema::Fixed(FixedSchema { - name: name.clone(), - aliases: None, - doc: None, - size: 16, - default: None, - attributes: Default::default(), - })); - named_schemas.insert(name, schema.clone()); - schema - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -7686,54 +7424,4 @@ mod tests { Ok(()) } - - #[test] - fn avro_rs_401_str() -> TestResult { - let schema = str::get_schema(); - assert_eq!(schema, Schema::String); - - Ok(()) - } - - #[test] - fn avro_rs_401_references() -> TestResult { - let schema_ref = <&str>::get_schema(); - let schema_ref_mut = <&mut str>::get_schema(); - - assert_eq!(schema_ref, Schema::String); - assert_eq!(schema_ref_mut, Schema::String); - - Ok(()) - } - - #[test] - fn avro_rs_401_slice() -> TestResult { - let schema = <[u8]>::get_schema(); - assert_eq!(schema, Schema::array(Schema::Int)); - - Ok(()) - } - - #[test] - fn avro_rs_401_array() -> TestResult { - let schema = <[u8; 55]>::get_schema(); - assert_eq!(schema, Schema::array(Schema::Int)); - - Ok(()) - } - - #[test] - fn avro_rs_401_option_ref_slice_array() -> TestResult { - let schema = <Option<&[[u8; 55]]>>::get_schema(); - assert_eq!( - schema, - Schema::union(vec![ - Schema::Null, - Schema::array(Schema::array(Schema::Int)) - ]) - .unwrap() - ); - - Ok(()) - } } diff --git a/avro/src/serde/derive.rs b/avro/src/serde/derive.rs new file mode 100644 index 0000000..0499897 --- /dev/null +++ b/avro/src/serde/derive.rs @@ -0,0 +1,322 @@ +use std::borrow::Cow; +use std::collections::HashMap; +use serde_json::Map; +use crate::Schema; +use crate::schema::{FixedSchema, Name, Names, Namespace, UnionSchema, UuidSchema}; + +/// Trait for types that serve as an Avro data model. Derive implementation available +/// through `derive` feature. Do not implement directly! +/// Implement [`AvroSchemaComponent`] to get this trait +/// through a blanket implementation. +/// +/// Note: This trait is **not** implemented for `char` and `u64`. `char` is a 32-bit value +/// that does not have a logical mapping to an Avro schema. `u64` is too large to fit in a +/// Avro `long`. +pub trait AvroSchema { + fn get_schema() -> Schema; +} + +/// Trait for types that serve as fully defined components inside an Avro data model. Derive +/// implementation available through `derive` feature. This is what is implemented by +/// the `derive(AvroSchema)` macro. +/// +/// Note: This trait is **not** implemented for `char` and `u64`. `char` is a 32-bit value +/// that does not have a logical mapping to an Avro schema. `u64` is too large to fit in a +/// Avro `long`. +/// +/// # Implementation guide +/// +/// ### Simple implementation +/// To construct a non named simple schema, it is possible to ignore the input argument making the +/// general form implementation look like +/// ```ignore +/// impl AvroSchemaComponent for AType { +/// fn get_schema_in_ctxt(_: &mut Names, _: &Namespace) -> Schema { +/// Schema::? +/// } +///} +/// ``` +/// +/// ### Passthrough implementation +/// +/// To construct a schema for a Type that acts as in "inner" type, such as for smart pointers, simply +/// pass through the arguments to the inner type +/// ```ignore +/// impl AvroSchemaComponent for PassthroughType { +/// fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { +/// InnerType::get_schema_in_ctxt(named_schemas, enclosing_namespace) +/// } +///} +/// ``` +/// +/// ### Complex implementation +/// +/// To implement this for Named schema there is a general form needed to avoid creating invalid +/// schemas or infinite loops. +/// ```ignore +/// impl AvroSchemaComponent for ComplexType { +/// fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { +/// // Create the fully qualified name for your type given the enclosing namespace +/// let name = apache_avro::schema::Name::new("MyName") +/// .expect("Unable to parse schema name") +/// .fully_qualified_name(enclosing_namespace); +/// let enclosing_namespace = &name.namespace; +/// // Check, if your name is already defined, and if so, return a ref to that name +/// if named_schemas.contains_key(&name) { +/// apache_avro::schema::Schema::Ref{name: name.clone()} +/// } else { +/// named_schemas.insert(name.clone(), apache_avro::schema::Schema::Ref{name: name.clone()}); +/// // YOUR SCHEMA DEFINITION HERE with the name equivalent to "MyName". +/// // For non-simple sub types delegate to their implementation of AvroSchemaComponent +/// } +/// } +///} +/// ``` +pub trait AvroSchemaComponent { + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema; +} + +impl<T> AvroSchema for T +where + T: AvroSchemaComponent + ?Sized, +{ + fn get_schema() -> Schema { + T::get_schema_in_ctxt(&mut HashMap::default(), &None) + } +} + +macro_rules! impl_schema ( + ($type:ty, $variant_constructor:expr) => ( + impl AvroSchemaComponent for $type { + fn get_schema_in_ctxt(_: &mut Names, _: &Namespace) -> Schema { + $variant_constructor + } + } + ); +); + +impl_schema!(bool, Schema::Boolean); +impl_schema!(i8, Schema::Int); +impl_schema!(i16, Schema::Int); +impl_schema!(i32, Schema::Int); +impl_schema!(i64, Schema::Long); +impl_schema!(u8, Schema::Int); +impl_schema!(u16, Schema::Int); +impl_schema!(u32, Schema::Long); +impl_schema!(f32, Schema::Float); +impl_schema!(f64, Schema::Double); +impl_schema!(String, Schema::String); +impl_schema!(str, Schema::String); + +impl<T> AvroSchemaComponent for &T +where + T: AvroSchemaComponent + ?Sized, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + T::get_schema_in_ctxt(named_schemas, enclosing_namespace) + } +} + +impl<T> AvroSchemaComponent for &mut T +where + T: AvroSchemaComponent + ?Sized, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + T::get_schema_in_ctxt(named_schemas, enclosing_namespace) + } +} + +impl<T> AvroSchemaComponent for [T] +where + T: AvroSchemaComponent, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + Schema::array(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) + } +} + +impl<const N: usize, T> AvroSchemaComponent for [T; N] +where + T: AvroSchemaComponent, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + Schema::array(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) + } +} + +impl<T> AvroSchemaComponent for Vec<T> +where + T: AvroSchemaComponent, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + Schema::array(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) + } +} + +impl<T> AvroSchemaComponent for Option<T> +where + T: AvroSchemaComponent, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + let variants = vec![ + Schema::Null, + T::get_schema_in_ctxt(named_schemas, enclosing_namespace), + ]; + + Schema::Union( + UnionSchema::new(variants).expect("Option<T> must produce a valid (non-nested) union"), + ) + } +} + +impl<T> AvroSchemaComponent for Map<String, T> +where + T: AvroSchemaComponent, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + Schema::map(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) + } +} + +impl<T> AvroSchemaComponent for HashMap<String, T> +where + T: AvroSchemaComponent, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + Schema::map(T::get_schema_in_ctxt(named_schemas, enclosing_namespace)) + } +} + +impl<T> AvroSchemaComponent for Box<T> +where + T: AvroSchemaComponent, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + T::get_schema_in_ctxt(named_schemas, enclosing_namespace) + } +} + +impl<T> AvroSchemaComponent for std::sync::Mutex<T> +where + T: AvroSchemaComponent, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + T::get_schema_in_ctxt(named_schemas, enclosing_namespace) + } +} + +impl<T> AvroSchemaComponent for Cow<'_, T> +where + T: AvroSchemaComponent + Clone, +{ + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + T::get_schema_in_ctxt(named_schemas, enclosing_namespace) + } +} + +impl AvroSchemaComponent for core::time::Duration { + /// The schema is [`Schema::Duration`] with the name `duration`. + /// + /// This is a lossy conversion as this Avro type does not store the amount of nanoseconds. + #[expect(clippy::map_entry, reason = "We don't use the value from the map")] + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + let name = Name::new("duration") + .expect("Name is valid") + .fully_qualified_name(enclosing_namespace); + if named_schemas.contains_key(&name) { + Schema::Ref { name } + } else { + let schema = Schema::Duration(FixedSchema { + name: name.clone(), + aliases: None, + doc: None, + size: 12, + default: None, + attributes: Default::default(), + }); + named_schemas.insert(name, schema.clone()); + schema + } + } +} + +impl AvroSchemaComponent for uuid::Uuid { + /// The schema is [`Schema::Uuid`] with the name `uuid`. + /// + /// The underlying schema is [`Schema::Fixed`] with a size of 16. + #[expect(clippy::map_entry, reason = "We don't use the value from the map")] + fn get_schema_in_ctxt(named_schemas: &mut Names, enclosing_namespace: &Namespace) -> Schema { + let name = Name::new("uuid") + .expect("Name is valid") + .fully_qualified_name(enclosing_namespace); + if named_schemas.contains_key(&name) { + Schema::Ref { name } + } else { + let schema = Schema::Uuid(UuidSchema::Fixed(FixedSchema { + name: name.clone(), + aliases: None, + doc: None, + size: 16, + default: None, + attributes: Default::default(), + })); + named_schemas.insert(name, schema.clone()); + schema + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use apache_avro_test_helper::TestResult; + + #[test] + fn avro_rs_401_str() -> TestResult { + let schema = str::get_schema(); + assert_eq!(schema, Schema::String); + + Ok(()) + } + + #[test] + fn avro_rs_401_references() -> TestResult { + let schema_ref = <&str>::get_schema(); + let schema_ref_mut = <&mut str>::get_schema(); + + assert_eq!(schema_ref, Schema::String); + assert_eq!(schema_ref_mut, Schema::String); + + Ok(()) + } + + #[test] + fn avro_rs_401_slice() -> TestResult { + let schema = <[u8]>::get_schema(); + assert_eq!(schema, Schema::array(Schema::Int)); + + Ok(()) + } + + #[test] + fn avro_rs_401_array() -> TestResult { + let schema = <[u8; 55]>::get_schema(); + assert_eq!(schema, Schema::array(Schema::Int)); + + Ok(()) + } + + #[test] + fn avro_rs_401_option_ref_slice_array() -> TestResult { + let schema = <Option<&[[u8; 55]]>>::get_schema(); + assert_eq!( + schema, + Schema::union(vec![ + Schema::Null, + Schema::array(Schema::array(Schema::Int)) + ])? + ); + + Ok(()) + } +} \ No newline at end of file diff --git a/avro/src/serde/mod.rs b/avro/src/serde/mod.rs index 3480a14..ef99a09 100644 --- a/avro/src/serde/mod.rs +++ b/avro/src/serde/mod.rs @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. +mod derive; mod util; mod with; @@ -22,5 +23,7 @@ pub mod de; pub mod ser; pub mod ser_schema; +#[doc(inline)] +pub use derive::{AvroSchema, AvroSchemaComponent}; #[doc(inline)] pub use with::{bytes, bytes_opt, fixed, fixed_opt, slice, slice_opt}; diff --git a/avro/src/writer.rs b/avro/src/writer.rs index 1c375d9..b9691a7 100644 --- a/avro/src/writer.rs +++ b/avro/src/writer.rs @@ -17,11 +17,11 @@ //! Logic handling writing in Avro format at user level. use crate::{ - AvroResult, Codec, Error, + AvroResult, AvroSchema, Codec, Error, encode::{encode, encode_internal, encode_to_vec}, error::Details, headers::{HeaderBuilder, RabinFingerprintHeader}, - schema::{AvroSchema, Name, ResolvedOwnedSchema, ResolvedSchema, Schema}, + schema::{Name, ResolvedOwnedSchema, ResolvedSchema, Schema}, serde::ser_schema::SchemaAwareWriteSerializer, types::Value, }; diff --git a/avro_derive/tests/derive.rs b/avro_derive/tests/derive.rs index a1e01ef..802e752 100644 --- a/avro_derive/tests/derive.rs +++ b/avro_derive/tests/derive.rs @@ -16,13 +16,12 @@ // under the License. use apache_avro::{ - Reader, Schema, Writer, from_value, + AvroSchema, AvroSchemaComponent, Reader, Schema, Writer, from_value, schema::{ - Alias, AvroSchema, AvroSchemaComponent, EnumSchema, FixedSchema, Name, Names, Namespace, + Alias, EnumSchema, FixedSchema, Name, Names, Namespace, RecordSchema, }, }; -use apache_avro_derive::*; use proptest::prelude::*; use serde::{Deserialize, Serialize, de::DeserializeOwned}; use std::{borrow::Cow, collections::HashMap, sync::Mutex};
