use std::cell::RefCell;
use qubit_budget::ResourceQuantity;
use qubit_budget::json::JsonContainerKind;
use qubit_budget::json::JsonMeasurement;
use serde::Serialize;
use serde::ser::Error;
use serde::ser::SerializeMap;
use serde::ser::SerializeSeq;
use serde::ser::SerializeStruct;
use serde::ser::SerializeStructVariant;
use serde::ser::SerializeTuple;
use serde::ser::SerializeTupleStruct;
use serde::ser::SerializeTupleVariant;
use super::super::serde_compat::PrivateStructKind;
use super::budgeted_key::BudgetedKey;
use super::budgeted_private_value::BudgetedPrivateValue;
use super::budgeted_value::BudgetedValue;
use super::json_encode_context::JsonEncodeContext;
use crate::encode::JsonSerializationErrorKind;
use crate::encode::JsonSerializerStateError;
pub(in crate::encode) struct JsonEncodeCompound<'transaction, 'budget, 'context, C, R, Q, const VALUE_LIMITS: bool>
where
Q: ResourceQuantity,
{
inner: C,
context: &'context RefCell<JsonEncodeContext<'transaction, 'budget, R, Q>>,
child_depth: usize,
observed: usize,
map_key_pending: bool,
private_kind: Option<PrivateStructKind>,
}
impl<'transaction, 'budget, 'context, C, R, Q, const VALUE_LIMITS: bool>
JsonEncodeCompound<'transaction, 'budget, 'context, C, R, Q, VALUE_LIMITS>
where
R: Clone,
Q: ResourceQuantity,
{
#[inline]
pub(super) const fn new(
inner: C,
context: &'context RefCell<JsonEncodeContext<'transaction, 'budget, R, Q>>,
child_depth: usize,
) -> Self {
Self {
inner,
context,
child_depth,
observed: 0,
map_key_pending: false,
private_kind: None,
}
}
pub(super) const fn raw_value(
inner: C,
context: &'context RefCell<JsonEncodeContext<'transaction, 'budget, R, Q>>,
depth: usize,
) -> Self {
Self {
inner,
context,
child_depth: depth,
observed: 0,
map_key_pending: false,
private_kind: Some(PrivateStructKind::RawValue),
}
}
#[inline(always)]
fn next_sequence<E>(&mut self) -> Result<(), E>
where
E: Error,
{
if !VALUE_LIMITS {
return Ok(());
}
let next = self
.observed
.checked_add(1)
.ok_or_else(|| E::custom("JSON sequence item count overflowed usize"))?;
self.context
.borrow_mut()
.check_container_count(JsonContainerKind::Sequence, next)?;
self.observed = next;
Ok(())
}
#[inline(always)]
fn next_map_entry<E>(&mut self) -> Result<(), E>
where
E: Error,
{
if !VALUE_LIMITS {
return Ok(());
}
let next = self
.observed
.checked_add(1)
.ok_or_else(|| E::custom("JSON map entry count overflowed usize"))?;
self.context
.borrow_mut()
.check_container_count(JsonContainerKind::Map, next)?;
self.observed = next;
Ok(())
}
fn finish_sequence<E>(&mut self) -> Result<(), E>
where
E: Error,
{
Ok(())
}
fn finish_map<E>(&mut self) -> Result<(), E>
where
E: Error,
{
if self.map_key_pending {
return Err(self.serialization_error(JsonSerializerStateError::MapEndedWithPendingKey));
}
Ok(())
}
fn serialization_error<E>(&self, reason: JsonSerializerStateError) -> E
where
E: Error,
{
self.context
.borrow_mut()
.serialization_error(JsonSerializationErrorKind::InvalidSerializerState { reason })
}
}
impl<C, R, Q, const VALUE_LIMITS: bool> SerializeSeq for JsonEncodeCompound<'_, '_, '_, C, R, Q, VALUE_LIMITS>
where
C: SerializeSeq,
R: Clone,
Q: ResourceQuantity,
{
type Ok = C::Ok;
type Error = C::Error;
#[inline(always)]
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.next_sequence()?;
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_element(&value)
}
#[inline(always)]
fn end(mut self) -> Result<Self::Ok, Self::Error> {
self.finish_sequence()?;
self.inner.end()
}
}
impl<C, R, Q, const VALUE_LIMITS: bool> SerializeTuple for JsonEncodeCompound<'_, '_, '_, C, R, Q, VALUE_LIMITS>
where
C: SerializeTuple,
R: Clone,
Q: ResourceQuantity,
{
type Ok = C::Ok;
type Error = C::Error;
#[inline(always)]
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.next_sequence()?;
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_element(&value)
}
#[inline(always)]
fn end(mut self) -> Result<Self::Ok, Self::Error> {
self.finish_sequence()?;
self.inner.end()
}
}
impl<C, R, Q, const VALUE_LIMITS: bool> SerializeTupleStruct for JsonEncodeCompound<'_, '_, '_, C, R, Q, VALUE_LIMITS>
where
C: SerializeTupleStruct,
R: Clone,
Q: ResourceQuantity,
{
type Ok = C::Ok;
type Error = C::Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.next_sequence()?;
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_field(&value)
}
#[inline(always)]
fn end(mut self) -> Result<Self::Ok, Self::Error> {
self.finish_sequence()?;
self.inner.end()
}
}
impl<C, R, Q, const VALUE_LIMITS: bool> SerializeTupleVariant for JsonEncodeCompound<'_, '_, '_, C, R, Q, VALUE_LIMITS>
where
C: SerializeTupleVariant,
R: Clone,
Q: ResourceQuantity,
{
type Ok = C::Ok;
type Error = C::Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.next_sequence()?;
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_field(&value)
}
#[inline(always)]
fn end(mut self) -> Result<Self::Ok, Self::Error> {
self.finish_sequence()?;
self.inner.end()
}
}
impl<C, R, Q, const VALUE_LIMITS: bool> SerializeMap for JsonEncodeCompound<'_, '_, '_, C, R, Q, VALUE_LIMITS>
where
C: SerializeMap,
R: Clone,
Q: ResourceQuantity,
{
type Ok = C::Ok;
type Error = C::Error;
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
if self.map_key_pending {
return Err(self.serialization_error(JsonSerializerStateError::MapKeyAlreadyPending));
}
self.next_map_entry()?;
let key = BudgetedKey::<_, _, _, VALUE_LIMITS>::new(key, self.context);
self.inner.serialize_key(&key)?;
self.map_key_pending = true;
Ok(())
}
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
if !self.map_key_pending {
return Err(self.serialization_error(JsonSerializerStateError::MapValueWithoutKey));
}
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_value(&value)?;
self.map_key_pending = false;
Ok(())
}
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
where
K: Serialize + ?Sized,
V: Serialize + ?Sized,
{
self.serialize_key(key)?;
self.serialize_value(value)
}
#[inline(always)]
fn end(mut self) -> Result<Self::Ok, Self::Error> {
self.finish_map()?;
self.inner.end()
}
}
impl<C, R, Q, const VALUE_LIMITS: bool> SerializeStruct for JsonEncodeCompound<'_, '_, '_, C, R, Q, VALUE_LIMITS>
where
C: SerializeStruct,
R: Clone,
Q: ResourceQuantity,
{
type Ok = C::Ok;
type Error = C::Error;
#[inline(always)]
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
match self.private_kind {
Some(PrivateStructKind::RawValue) => {
let value = BudgetedPrivateValue::raw_value(value, self.context, self.child_depth);
return self.inner.serialize_field(key, &value);
}
None => self.next_map_entry()?,
}
if VALUE_LIMITS {
self.context
.borrow_mut()
.admit(JsonMeasurement::Key { bytes: key.len() })?;
}
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_field(key, &value)
}
#[inline(always)]
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
self.inner.skip_field(key)
}
#[inline(always)]
fn end(mut self) -> Result<Self::Ok, Self::Error> {
if self.private_kind.is_none() {
self.finish_map()?;
}
self.inner.end()
}
}
impl<C, R, Q, const VALUE_LIMITS: bool> SerializeStructVariant for JsonEncodeCompound<'_, '_, '_, C, R, Q, VALUE_LIMITS>
where
C: SerializeStructVariant,
R: Clone,
Q: ResourceQuantity,
{
type Ok = C::Ok;
type Error = C::Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize + ?Sized,
{
self.next_map_entry()?;
if VALUE_LIMITS {
self.context
.borrow_mut()
.admit(JsonMeasurement::Key { bytes: key.len() })?;
}
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_field(key, &value)
}
#[inline(always)]
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
self.inner.skip_field(key)
}
#[inline(always)]
fn end(mut self) -> Result<Self::Ok, Self::Error> {
self.finish_map()?;
self.inner.end()
}
}