use qubit_budget::MeasuredBudgetError;
use qubit_budget::ResourceBudget;
use qubit_budget::ResourceQuantity;
use crate::decode::JsonSyntaxError;
use crate::encode::JsonSerializationError;
use crate::encode::JsonSerializationErrorKind;
pub(in crate::encode) struct JsonOutputAccounting<'a, R, Q>
where
Q: ResourceQuantity,
{
output: Option<&'a mut ResourceBudget<R, Q>>,
violation: Option<MeasuredBudgetError<R, Q>>,
syntax_error: Option<JsonSyntaxError>,
serialization_error: Option<JsonSerializationError>,
}
impl<'a, R, Q> JsonOutputAccounting<'a, R, Q>
where
Q: ResourceQuantity,
{
#[inline]
pub(in crate::encode) const fn new(output: Option<&'a mut ResourceBudget<R, Q>>) -> Self {
Self {
output,
violation: None,
syntax_error: None,
serialization_error: None,
}
}
#[must_use]
#[inline(always)]
pub(in crate::encode) const fn has_output_budget(&self) -> bool {
self.output.is_some()
}
#[must_use]
#[inline(always)]
pub(in crate::encode) fn remaining(&self) -> Option<Q> {
self.output.as_deref().map(ResourceBudget::remaining)
}
pub(in crate::encode) fn check_available(&self, amount: usize) -> Result<(), MeasuredBudgetError<R, Q>>
where
R: Clone,
{
self.output.as_deref().map_or(Ok(()), |output| {
let amount = Q::try_from_usize(amount)
.map_err(|source| MeasuredBudgetError::quantity(output.resource().clone(), source))?;
output.check_available(amount).map_err(MeasuredBudgetError::from)
})
}
pub(in crate::encode) fn consume(&mut self, amount: usize) -> Result<(), MeasuredBudgetError<R, Q>>
where
R: Clone,
{
self.output.as_deref_mut().map_or(Ok(()), |output| {
let amount = Q::try_from_usize(amount)
.map_err(|source| MeasuredBudgetError::quantity(output.resource().clone(), source))?;
output.try_consume(amount).map_err(MeasuredBudgetError::from)
})
}
pub(in crate::encode) fn record_violation(&mut self, error: MeasuredBudgetError<R, Q>) {
if self.violation.is_none() {
self.violation = Some(error);
}
}
#[must_use]
#[inline(always)]
pub(in crate::encode) fn take_violation(&mut self) -> Option<MeasuredBudgetError<R, Q>> {
self.violation.take()
}
pub(in crate::encode) fn record_syntax_error(&mut self, error: JsonSyntaxError) {
if self.syntax_error.is_none() {
self.syntax_error = Some(error);
}
}
#[must_use]
#[inline(always)]
pub(in crate::encode) fn take_syntax_error(&mut self) -> Option<JsonSyntaxError> {
self.syntax_error.take()
}
pub(in crate::encode) fn record_serialization_error(&mut self, error: JsonSerializationError) {
if self.serialization_error.is_none() {
self.serialization_error = Some(error);
}
}
#[must_use]
#[inline(always)]
pub(in crate::encode) fn take_serialization_error(&mut self) -> Option<JsonSerializationError> {
self.serialization_error.take()
}
pub(in crate::encode) fn take_serialization_error_or_custom(&mut self) -> JsonSerializationError {
self.take_serialization_error()
.unwrap_or_else(|| JsonSerializationError::new(JsonSerializationErrorKind::CustomSerialization))
}
}