use std::error::Error;
use std::fmt;
use qubit_budget::BudgetError;
use qubit_budget::MeasuredBudgetError;
use qubit_budget::QuantityConversionError;
use qubit_budget::json::JsonResource;
use qubit_json::decode::JsonDecodeError;
use qubit_json::decode::JsonDecodeErrorSource;
use qubit_json::decode::JsonSyntaxError;
use serde::de::Error as DeError;
use crate::MetadataError;
#[derive(Debug)]
#[non_exhaustive]
#[must_use]
pub enum MetadataWireDecodeError {
Domain(MetadataError),
UnsupportedVersion {
expected: u8,
actual: u8,
},
Budget(BudgetError<JsonResource, usize>),
Quantity {
resource: JsonResource,
source: QuantityConversionError,
},
Syntax(JsonSyntaxError),
InvalidLimits(serde_json::Error),
#[cfg(feature = "filter")]
Filter(MetadataError),
InvalidJson(
serde_json::Error,
),
}
impl fmt::Display for MetadataWireDecodeError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Domain(error) => fmt::Display::fmt(error, formatter),
Self::UnsupportedVersion { expected, actual } => write!(
formatter,
"Unsupported metadata wire version {actual}; expected {expected}"
),
Self::Budget(error) => fmt::Display::fmt(error, formatter),
Self::Quantity { source, .. } => fmt::Display::fmt(source, formatter),
Self::Syntax(error) => fmt::Display::fmt(error, formatter),
Self::InvalidLimits(error) => fmt::Display::fmt(error, formatter),
#[cfg(feature = "filter")]
Self::Filter(error) => fmt::Display::fmt(error, formatter),
Self::InvalidJson(error) => fmt::Display::fmt(error, formatter),
}
}
}
impl Error for MetadataWireDecodeError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Domain(error) => Some(error),
Self::UnsupportedVersion { .. } => None,
Self::Budget(error) => Some(error),
Self::Quantity { source, .. } => Some(source),
Self::Syntax(error) => Some(error),
Self::InvalidLimits(error) => Some(error),
#[cfg(feature = "filter")]
Self::Filter(error) => Some(error),
Self::InvalidJson(error) => Some(error),
}
}
}
impl From<JsonDecodeError<JsonResource>> for MetadataWireDecodeError {
fn from(error: JsonDecodeError<JsonResource>) -> Self {
let kind = error.kind();
let line = error.line().unwrap_or(0);
let column = error.column().unwrap_or(0);
match error.into_source() {
JsonDecodeErrorSource::Budget { source, .. } => match source {
MeasuredBudgetError::Budget(error) => Self::Budget(error),
MeasuredBudgetError::Quantity { resource, source } => Self::Quantity { resource, source },
},
JsonDecodeErrorSource::InvalidJson { syntax, .. } => Self::Syntax(syntax),
JsonDecodeErrorSource::EmptyInput { .. }
| JsonDecodeErrorSource::InvalidUtf8 { .. }
| JsonDecodeErrorSource::UnexpectedTopLevel { .. }
| JsonDecodeErrorSource::Deserialize { .. } => Self::InvalidJson(<serde_json::Error as DeError>::custom(
format_args!("JSON decoding failed ({kind:?}) at line {line}, column {column}",),
)),
}
}
}