use crate::family::Family;
use crate::gid::ParseGidError;
use crate::hex::HexError;
use crate::varint::VarintError;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ObjectError {
BadMagic,
UnknownEncodingVersion { found: u8 },
UnknownFamily { code: u8 },
UnknownSchemaVersion { family: Family, found: u8 },
ReservedFlags { found: u8 },
LengthMismatch,
TrailingBytes,
NonCanonicalInteger,
IntegerOverflow,
InvalidBoolean { byte: u8 },
InvalidUtf8,
InvalidGid { len: usize },
UnsortedFields { tag: u64, prev: u64 },
DuplicateField { tag: u64 },
ReservedTag { tag: u64 },
UnknownMandatoryField { family: Family, tag: u64 },
ExtensionNotPermitted { family: Family, tag: u64 },
ValueLengthMismatch,
MissingRequiredField {
family: Family,
tag: u8,
name: &'static str,
},
LimitExceeded {
kind: &'static str,
limit: u64,
found: u64,
},
InvalidPath { path: String },
InvalidEnumValue { field: &'static str, found: String },
FamilyMismatch { expected: Family, found: Family },
TypeMismatch { tag: u64, expected: &'static str },
BodyKindMismatch { family: Family },
UnexpectedRawValue { tag: u64 },
ExtensionMustBeRaw { tag: u64 },
InvalidTreeMode { mode: u64 },
InvalidTreeTargetFamily { name: String, mode: u64 },
InvalidTreeOrder { name: String },
InvalidTreeName { name: String },
UndeclaredOperationTag { op_type: String, tag: u64 },
EmptyPredicate,
MappingFabricatedNonEmpty,
RefCountExceeded { limit: usize, found: usize },
UnknownFieldName { tag: u64 },
Varint(VarintError),
Hex(HexError),
GidParse(String),
DigestLength { len: usize },
}
impl fmt::Display for ObjectError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ObjectError::BadMagic => write!(f, "bad envelope magic"),
ObjectError::UnknownEncodingVersion { found } => {
write!(f, "unknown encoding version {found}")
}
ObjectError::UnknownFamily { code } => write!(f, "unknown family code 0x{code:02x}"),
ObjectError::UnknownSchemaVersion { family, found } => {
write!(f, "unsupported schema version {found} for family {family}")
}
ObjectError::ReservedFlags { found } => {
write!(f, "reserved envelope flags 0x{found:02x}")
}
ObjectError::LengthMismatch => write!(f, "declared length does not match input"),
ObjectError::TrailingBytes => write!(f, "trailing bytes after object body"),
ObjectError::NonCanonicalInteger => write!(f, "non-canonical integer encoding"),
ObjectError::IntegerOverflow => write!(f, "integer overflow"),
ObjectError::InvalidBoolean { byte } => write!(f, "invalid boolean byte 0x{byte:02x}"),
ObjectError::InvalidUtf8 => write!(f, "invalid UTF-8 in string field"),
ObjectError::InvalidGid { len } => write!(f, "invalid gid length {len} (expected 33)"),
ObjectError::UnsortedFields { tag, prev } => {
write!(f, "unsorted fields: tag {tag} after {prev}")
}
ObjectError::DuplicateField { tag } => write!(f, "duplicate field tag {tag}"),
ObjectError::ReservedTag { tag } => write!(f, "reserved field tag {tag}"),
ObjectError::UnknownMandatoryField { family, tag } => {
write!(f, "unknown mandatory field tag {tag} for family {family}")
}
ObjectError::ExtensionNotPermitted { family, tag } => {
write!(f, "extension tag {tag} not permitted for family {family}")
}
ObjectError::ValueLengthMismatch => write!(f, "value length mismatch"),
ObjectError::MissingRequiredField { family, tag, name } => {
write!(
f,
"missing required field {name} (tag {tag}) for family {family}"
)
}
ObjectError::LimitExceeded { kind, limit, found } => {
write!(f, "limit exceeded: {kind} (limit {limit}, found {found})")
}
ObjectError::InvalidPath { path } => write!(f, "invalid canonical path: {path:?}"),
ObjectError::InvalidEnumValue { field, found } => {
write!(f, "invalid enum value {found:?} for {field}")
}
ObjectError::FamilyMismatch { expected, found } => {
write!(f, "gid family mismatch: expected {expected}, found {found}")
}
ObjectError::TypeMismatch { tag, expected } => {
write!(f, "value for tag {tag} is not {expected}")
}
ObjectError::BodyKindMismatch { family } => {
write!(f, "object body kind does not match family {family}")
}
ObjectError::UnexpectedRawValue { tag } => {
write!(f, "opaque raw value for schema field tag {tag}")
}
ObjectError::ExtensionMustBeRaw { tag } => {
write!(f, "extension tag {tag} must carry an opaque raw value")
}
ObjectError::InvalidTreeMode { mode } => write!(f, "invalid tree entry mode {mode:#o}"),
ObjectError::InvalidTreeTargetFamily { name, mode } => {
write!(
f,
"tree entry {name:?} target family does not match mode {mode:#o}"
)
}
ObjectError::InvalidTreeOrder { name } => {
write!(f, "tree entries out of order at {name:?}")
}
ObjectError::InvalidTreeName { name } => write!(f, "invalid tree entry name {name:?}"),
ObjectError::UndeclaredOperationTag { op_type, tag } => {
write!(f, "operation tag {tag} undeclared for op_type {op_type:?}")
}
ObjectError::EmptyPredicate => write!(f, "claim predicate must be non-empty"),
ObjectError::MappingFabricatedNonEmpty => {
write!(f, "mapping loss.fabricated must be empty")
}
ObjectError::RefCountExceeded { limit, found } => {
write!(
f,
"object reference count exceeds limit (limit {limit}, found {found})"
)
}
ObjectError::UnknownFieldName { tag } => write!(f, "no field name known for tag {tag}"),
ObjectError::Varint(e) => write!(f, "varint error: {e}"),
ObjectError::Hex(e) => write!(f, "hex error: {e:?}"),
ObjectError::GidParse(e) => write!(f, "gid parse error: {e}"),
ObjectError::DigestLength { len } => write!(f, "digest length {len} (expected 32)"),
}
}
}
impl std::error::Error for ObjectError {}
impl From<VarintError> for ObjectError {
fn from(e: VarintError) -> Self {
match e {
VarintError::NonCanonical => ObjectError::NonCanonicalInteger,
VarintError::Overflow => ObjectError::IntegerOverflow,
other => ObjectError::Varint(other),
}
}
}
impl From<HexError> for ObjectError {
fn from(e: HexError) -> Self {
ObjectError::Hex(e)
}
}
impl From<ParseGidError> for ObjectError {
fn from(e: ParseGidError) -> Self {
ObjectError::GidParse(e.to_string())
}
}