AvroSchemaComponent

Trait AvroSchemaComponent 

Source
pub trait AvroSchemaComponent {
    // Required method
    fn get_schema_in_ctxt(
        named_schemas: &mut HashSet<Name>,
        enclosing_namespace: &Namespace,
    ) -> Schema;

    // Provided method
    fn get_record_fields_in_ctxt(
        first_field_position: usize,
        named_schemas: &mut HashSet<Name>,
        enclosing_namespace: &Namespace,
    ) -> Option<Vec<RecordField>> { ... }
}
Expand description

Trait for types that serve as fully defined components inside an Avro data model.

This trait can be derived with #[derive(AvroSchema)] when the derive feature is enabled.

§Implementation guide

§Implementation for returning primitive types

When the schema you want to return is a primitive type (a type without a name), the function arguments can be ignored.

For example, you have a custom integer type:

// Make sure to implement `Serialize` and `Deserialize` to use the right serialization methods
pub struct U24([u8; 3]);
impl AvroSchemaComponent for U24 {
    fn get_schema_in_ctxt(_: &mut HashSet<Name>, _: &Namespace) -> Schema {
        Schema::Int
    }

    fn get_record_fields_in_ctxt(_: usize, _: &mut HashSet<Name>, _: &Namespace) -> Option<Vec<RecordField>> {
        None // A Schema::Int is not a Schema::Record so there are no fields to return
    }
}

§Passthrough implementation

To construct a schema for a type is “transparent”, such as for smart pointers, simply pass through the arguments to the inner type:

#[derive(Serialize, Deserialize)]
#[serde(transparent)] // This attribute is important for all passthrough implementations!
pub struct Transparent<T>(T);
impl<T: AvroSchemaComponent> AvroSchemaComponent for Transparent<T> {
    fn get_schema_in_ctxt(named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace) -> Schema {
        T::get_schema_in_ctxt(named_schemas, enclosing_namespace)
    }

    fn get_record_fields_in_ctxt(first_field_position: usize, named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace) -> Option<Vec<RecordField>> {
        T::get_record_fields_in_ctxt(first_field_position, named_schemas, enclosing_namespace)
    }
}

§Implementation for complex types

When the schema you want to return is a complex type (a type with a name), special care has to be taken to avoid duplicate type definitions and getting the correct namespace.

Things to keep in mind:

  • If the fully qualified name already exists, return a Schema::Ref
  • Use the AvroSchemaComponent implementations to get the schemas for the subtypes
  • The ordering of fields in the schema must match with the ordering in Serde
  • Implement get_record_fields_in_ctxt as the default implementation has to be implemented with backtracking and a lot of cloning.
    • Even if your schema is not a record, still implement the function and just return None
pub struct Foo {
    one: String,
    two: i32,
    three: Option<Duration>
}

impl AvroSchemaComponent for Foo {
    fn get_schema_in_ctxt(named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace) -> Schema {
        // Create the fully qualified name for your type given the enclosing namespace
        let name = Name::new("Foo").unwrap().fully_qualified_name(enclosing_namespace);
        if named_schemas.contains(&name) {
            Schema::Ref { name }
        } else {
            let enclosing_namespace = &name.namespace;
            // Do this before you start creating the schema, as otherwise recursive types will cause infinite recursion.
            named_schemas.insert(name.clone());
            let schema = Schema::Record(RecordSchema::builder()
                .name(name.clone())
                .fields(Self::get_record_fields_in_ctxt(0, named_schemas, enclosing_namespace).expect("Impossible!"))
                .build()
            );
            schema
        }
    }

    fn get_record_fields_in_ctxt(first_field_position: usize, named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace) -> Option<Vec<RecordField>> {
        Some(vec![
            RecordField::builder()
                .name("one")
                .schema(String::get_schema_in_ctxt(named_schemas, enclosing_namespace))
                .position(first_field_position)
                .build(),
            RecordField::builder()
                .name("two")
                .schema(i32::get_schema_in_ctxt(named_schemas, enclosing_namespace))
                .position(first_field_position+1)
                .build(),
            RecordField::builder()
                .name("three")
                .schema(<Option<Duration>>::get_schema_in_ctxt(named_schemas, enclosing_namespace))
                .position(first_field_position+2)
                .build(),
        ])
    }
}

Required Methods§

Source

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Get the schema for this component

Provided Methods§

Source

fn get_record_fields_in_ctxt( first_field_position: usize, named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Option<Vec<RecordField>>

Get the fields of this schema if it is a record.

This returns None if the schema is not a record.

The default implementation has to do a lot of extra work, so it is strongly recommended to implement this function when manually implementing this trait.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl AvroSchemaComponent for bool

Source§

impl AvroSchemaComponent for char

Source§

impl AvroSchemaComponent for f32

Source§

impl AvroSchemaComponent for f64

Source§

impl AvroSchemaComponent for i8

Source§

impl AvroSchemaComponent for i16

Source§

impl AvroSchemaComponent for i32

Source§

impl AvroSchemaComponent for i64

Source§

impl AvroSchemaComponent for i128

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

The schema is Schema::Fixed of size 16 with the name i128.

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl AvroSchemaComponent for str

Source§

impl AvroSchemaComponent for u8

Source§

impl AvroSchemaComponent for u16

Source§

impl AvroSchemaComponent for u32

Source§

impl AvroSchemaComponent for u64

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

The schema is Schema::Fixed of size 8 with the name u64.

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl AvroSchemaComponent for u128

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

The schema is Schema::Fixed of size 16 with the name u128.

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl AvroSchemaComponent for String

Source§

impl AvroSchemaComponent for Duration

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

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.

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T> AvroSchemaComponent for Option<T>

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T> AvroSchemaComponent for HashMap<String, T>

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T: AvroSchemaComponent + ToOwned + ?Sized> AvroSchemaComponent for Cow<'_, T>

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( first_field_position: usize, named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T: AvroSchemaComponent + ?Sized> AvroSchemaComponent for &T

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( first_field_position: usize, named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T: AvroSchemaComponent + ?Sized> AvroSchemaComponent for &mut T

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( first_field_position: usize, named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T: AvroSchemaComponent + ?Sized> AvroSchemaComponent for Box<T>

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( first_field_position: usize, named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T: AvroSchemaComponent + ?Sized> AvroSchemaComponent for Mutex<T>

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( first_field_position: usize, named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T: AvroSchemaComponent> AvroSchemaComponent for [T]

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<T: AvroSchemaComponent> AvroSchemaComponent for Vec<T>

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Source§

impl<const N: usize, T> AvroSchemaComponent for [T; N]

Source§

fn get_schema_in_ctxt( named_schemas: &mut HashSet<Name>, enclosing_namespace: &Namespace, ) -> Schema

Source§

fn get_record_fields_in_ctxt( _: usize, _: &mut HashSet<Name>, _: &Namespace, ) -> Option<Vec<RecordField>>

Implementors§