use std::fmt;
use qubit_datatype::DataType;
use qubit_value::ValueError;
#[cfg(feature = "filter")]
use crate::FilterLimitKind;
use crate::MetadataWireLimitKind;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
#[must_use]
pub enum MetadataError {
ValueAccess {
key: String,
source: Box<ValueError>,
},
MissingKey(
String,
),
TypeMismatch {
key: String,
expected: DataType,
actual: DataType,
message: String,
},
WireLimitExceeded {
kind: MetadataWireLimitKind,
value: usize,
maximum: usize,
},
#[cfg(feature = "schema")]
MissingRequiredField {
key: String,
expected: DataType,
},
#[cfg(feature = "schema")]
UnknownField {
key: String,
},
#[cfg(feature = "schema")]
UnknownFilterField {
key: String,
},
#[cfg(feature = "schema")]
InvalidFilterOperator {
key: String,
operator: &'static str,
data_type: DataType,
message: String,
},
#[cfg(feature = "filter")]
InvalidFilterExpression {
message: String,
},
#[cfg(feature = "filter")]
InvalidFilterOperand {
operator: &'static str,
data_type: DataType,
message: String,
},
#[cfg(feature = "filter")]
MissingFilterExpression,
#[cfg(feature = "filter")]
InvalidFilterLimit {
kind: FilterLimitKind,
value: usize,
maximum: usize,
},
#[cfg(feature = "filter")]
FilterLimitExceeded {
kind: FilterLimitKind,
value: usize,
maximum: usize,
},
#[cfg(feature = "schema")]
DuplicateSchemaField {
key: String,
},
}
impl MetadataError {
#[cfg(feature = "schema")]
#[inline]
pub(crate) fn type_mismatch(key: &str, expected: DataType, actual: DataType) -> Self {
Self::TypeMismatch {
key: key.to_string(),
expected,
actual,
message: format!("expected {expected}, got {actual}"),
}
}
}
impl fmt::Display for MetadataError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ValueAccess { key, source } => {
write!(formatter, "Metadata key '{key}': {source}")
}
Self::MissingKey(key) => {
write!(formatter, "Metadata key not found: {key}")
}
Self::TypeMismatch {
key,
expected,
actual,
message,
} => write!(
formatter,
"Metadata key '{key}' expected {expected} but actual {actual}: {message}"
),
Self::WireLimitExceeded { kind, value, maximum } => write!(
formatter,
"Metadata wire {kind:?} value {value} exceeds the maximum of {maximum}"
),
#[cfg(feature = "schema")]
Self::MissingRequiredField { key, expected } => {
write!(
formatter,
"Required metadata key '{key}' is missing (expected {expected})"
)
}
#[cfg(feature = "schema")]
Self::UnknownField { key } => {
write!(formatter, "Metadata key '{key}' is not defined in schema")
}
#[cfg(feature = "schema")]
Self::UnknownFilterField { key } => {
write!(
formatter,
"Metadata filter references key '{key}' not defined in schema"
)
}
#[cfg(feature = "schema")]
Self::InvalidFilterOperator {
key,
operator,
data_type,
message,
} => write!(
formatter,
"Metadata filter operator '{operator}' is invalid for key '{key}' with type {data_type}: {message}"
),
#[cfg(feature = "filter")]
Self::InvalidFilterExpression { message } => {
write!(formatter, "Metadata filter expression is invalid: {message}")
}
#[cfg(feature = "filter")]
Self::InvalidFilterOperand {
operator,
data_type,
message,
} => write!(
formatter,
"Metadata filter operator '{operator}' cannot use {data_type}: {message}"
),
#[cfg(feature = "filter")]
Self::MissingFilterExpression => {
write!(formatter, "Metadata filter requires an expression")
}
#[cfg(feature = "filter")]
Self::InvalidFilterLimit { kind, value, maximum } => write!(
formatter,
"Metadata filter {kind:?} limit {value} is outside 1..={maximum}"
),
#[cfg(feature = "filter")]
Self::FilterLimitExceeded { kind, value, maximum } => write!(
formatter,
"Metadata filter {kind:?} value {value} exceeds the maximum of {maximum}"
),
#[cfg(feature = "schema")]
Self::DuplicateSchemaField { key } => {
write!(formatter, "Metadata schema declares field '{key}' more than once")
}
}
}
}
impl std::error::Error for MetadataError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::ValueAccess { source, .. } => Some(source.as_ref()),
_ => None,
}
}
}