mod canonical_form;
mod check_for_cycles;
mod parsing;
mod rabin;
mod serialize;
use super::{Fixed, Name, SchemaError};
pub use check_for_cycles::UnconditionalCycle;
#[derive(Clone, Debug)]
pub struct SchemaMut {
pub(super) nodes: Vec<SchemaNode>,
pub(super) schema_json: Option<String>,
}
impl SchemaMut {
pub fn nodes(&self) -> &[SchemaNode] {
&self.nodes
}
pub fn nodes_mut(&mut self) -> &mut Vec<SchemaNode> {
self.schema_json = None;
&mut self.nodes
}
pub fn root(&self) -> &SchemaNode {
self.nodes.first().expect(
"Schema should have nodes - have you updated it \
in such a way that all of its nodes were removed?",
)
}
pub fn from_nodes(nodes: Vec<SchemaNode>) -> Self {
Self {
nodes,
schema_json: None,
}
}
pub fn freeze(self) -> Result<super::Schema, SchemaError> {
self.try_into()
}
pub fn get(&self, key: SchemaKey) -> Option<&SchemaNode> {
self.nodes.get(key.idx)
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SchemaKey {
pub(super) idx: usize,
}
impl SchemaKey {
pub const fn from_idx(idx: usize) -> Self {
Self { idx }
}
pub const fn idx(self) -> usize {
self.idx
}
pub const fn root() -> Self {
Self { idx: 0 }
}
}
impl std::ops::Index<SchemaKey> for SchemaMut {
type Output = SchemaNode;
fn index(&self, key: SchemaKey) -> &Self::Output {
&self.nodes[key.idx]
}
}
impl std::fmt::Debug for SchemaKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.idx, f)
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct SchemaNode {
pub type_: RegularType,
pub logical_type: Option<LogicalType>,
}
impl SchemaNode {
pub fn new(type_: RegularType) -> Self {
type_.into()
}
pub fn with_logical_type(type_: RegularType, logical_type: LogicalType) -> Self {
Self {
type_,
logical_type: Some(logical_type),
}
}
}
#[derive(Clone, Debug)]
pub enum RegularType {
Null,
Boolean,
Int,
Long,
Float,
Double,
Bytes,
String,
Array(Array),
Map(Map),
Union(Union),
Record(Record),
Enum(Enum),
Fixed(Fixed),
}
impl RegularType {
pub fn name(&self) -> Option<&Name> {
match self {
RegularType::Record(record) => Some(&record.name),
RegularType::Enum(enum_) => Some(&enum_.name),
RegularType::Fixed(fixed) => Some(&fixed.name),
RegularType::Null
| RegularType::Boolean
| RegularType::Int
| RegularType::Long
| RegularType::Float
| RegularType::Double
| RegularType::Bytes
| RegularType::String
| RegularType::Array(_)
| RegularType::Map(_)
| RegularType::Union(_) => None,
}
}
pub fn name_mut(&mut self) -> Option<&mut Name> {
match self {
RegularType::Record(record) => Some(&mut record.name),
RegularType::Enum(enum_) => Some(&mut enum_.name),
RegularType::Fixed(fixed) => Some(&mut fixed.name),
RegularType::Null
| RegularType::Boolean
| RegularType::Int
| RegularType::Long
| RegularType::Float
| RegularType::Double
| RegularType::Bytes
| RegularType::String
| RegularType::Array(_)
| RegularType::Map(_)
| RegularType::Union(_) => None,
}
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Array {
pub items: SchemaKey,
}
impl Array {
pub fn new(items: SchemaKey) -> Self {
Self { items }
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Map {
pub values: SchemaKey,
}
impl Map {
pub fn new(values: SchemaKey) -> Self {
Self { values }
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Union {
pub variants: Vec<SchemaKey>,
}
impl Union {
pub fn new(variants: Vec<SchemaKey>) -> Self {
Self { variants }
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Record {
pub fields: Vec<RecordField>,
pub name: Name,
}
impl Record {
pub fn new(name: Name, fields: Vec<RecordField>) -> Self {
Self { fields, name }
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct RecordField {
pub name: String,
pub type_: SchemaKey,
}
impl RecordField {
pub fn new(name: impl Into<String>, schema: SchemaKey) -> Self {
Self {
name: name.into(),
type_: schema,
}
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Enum {
pub symbols: Vec<String>,
pub name: Name,
}
impl Enum {
pub fn new(name: Name, symbols: Vec<String>) -> Self {
Self { symbols, name }
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum LogicalType {
Decimal(Decimal),
Uuid,
Date,
TimeMillis,
TimeMicros,
TimestampMillis,
TimestampMicros,
Duration,
BigDecimal,
Unknown(UnknownLogicalType),
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Decimal {
pub scale: u32,
pub precision: usize,
}
impl Decimal {
pub fn new(scale: u32, precision: usize) -> Self {
Self { precision, scale }
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct UnknownLogicalType {
pub logical_type_name: String,
}
impl UnknownLogicalType {
pub fn new(logical_type_name: impl Into<String>) -> Self {
Self {
logical_type_name: logical_type_name.into(),
}
}
pub fn as_str(&self) -> &str {
&self.logical_type_name
}
}
impl LogicalType {
pub fn as_str(&self) -> &str {
match self {
LogicalType::Decimal(_) => "decimal",
LogicalType::Uuid => "uuid",
LogicalType::Date => "date",
LogicalType::TimeMillis => "time-millis",
LogicalType::TimeMicros => "time-micros",
LogicalType::TimestampMillis => "timestamp-millis",
LogicalType::TimestampMicros => "timestamp-micros",
LogicalType::Duration => "duration",
LogicalType::BigDecimal => "big-decimal",
LogicalType::Unknown(unknown_logical_type) => &unknown_logical_type.logical_type_name,
}
}
}
impl From<RegularType> for SchemaNode {
fn from(regular_type: RegularType) -> Self {
Self {
type_: regular_type,
logical_type: None,
}
}
}
macro_rules! impl_froms_for_regular_type {
($($variant: ident)*) => {
$(
impl From<$variant> for RegularType {
fn from(variant: $variant) -> Self {
Self::$variant(variant)
}
}
impl From<$variant> for SchemaNode {
fn from(variant: $variant) -> Self {
Self {
type_: RegularType::$variant(variant),
logical_type: None,
}
}
}
)*
};
}
impl_froms_for_regular_type! { Array Map Union Record Enum Fixed }