use core::fmt;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[non_exhaustive]
pub enum Invariant {
Depth,
Unsupported,
Arrays,
Buffers,
Rows,
ChildLength,
NullCount,
Validity,
BufferLength,
Size,
OffsetOrder,
OffsetRange,
DictionaryIndex,
ViewBuffer,
}
impl Invariant {
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::Depth => "nesting depth",
Self::Unsupported => "known types",
Self::Arrays => "array count",
Self::Buffers => "buffer count",
Self::Rows => "row count",
Self::ChildLength => "child length",
Self::NullCount => "null count",
Self::Validity => "validity length",
Self::BufferLength => "buffer length",
Self::Size => "addressable size",
Self::OffsetOrder => "offset order",
Self::OffsetRange => "offset range",
Self::DictionaryIndex => "dictionary index",
Self::ViewBuffer => "view buffer",
}
}
}
impl fmt::Display for Invariant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
#[derive(Clone, PartialEq, Eq, Debug, thiserror::Error)]
#[error("{path} breaks the {invariant} rule: {detail}")]
pub struct Violation {
pub invariant: Invariant,
pub path: String,
pub detail: String,
}
impl Violation {
pub(crate) fn at(invariant: Invariant, path: &str, detail: impl Into<String>) -> Self {
Self {
invariant,
path: if path.is_empty() {
"the batch".to_owned()
} else {
path.to_owned()
},
detail: detail.into(),
}
}
}
pub type Result<T> = core::result::Result<T, Violation>;