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_json::Error as JsonError;
use serde_json::error::Category;
use thiserror::Error;
#[non_exhaustive]
#[must_use]
#[derive(Debug, Error)]
pub enum ValueWireDecodeError {
#[error("V1 JSON wire resource budget exceeded: {0}")]
Budget(
#[source]
BudgetError<JsonResource, usize>,
),
#[error("V1 JSON wire resource quantity conversion failed for {resource:?}: {source}")]
Quantity {
resource: JsonResource,
#[source]
source: QuantityConversionError,
},
#[error("invalid V1 JSON wire syntax: {0}")]
Syntax(
#[source]
JsonSyntaxError,
),
#[error("unsupported qubit-value wire version {actual}; expected {expected}")]
UnsupportedVersion {
expected: u8,
actual: u8,
},
#[error("failed to decode V1 JSON wire input: {0}")]
InvalidJson(
#[source]
JsonError,
),
}
impl ValueWireDecodeError {
fn deserialize(category: Category, line: usize, column: usize) -> Self {
let error = <JsonError as serde::de::Error>::custom(format_args!(
"JSON deserialization failed ({category:?}) at line {line}, column {column}"
));
Self::InvalidJson(error)
}
}
impl From<JsonDecodeError<JsonResource, usize>> for ValueWireDecodeError {
#[inline]
fn from(error: JsonDecodeError<JsonResource>) -> Self {
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::deserialize(Category::Data, line, column),
}
}
}
impl From<JsonError> for ValueWireDecodeError {
#[inline]
fn from(error: JsonError) -> Self {
let category = error.classify();
let line = error.line();
let column = error.column();
Self::deserialize(category, line, column)
}
}