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::BudgetedKey;
use super::BudgetedPrivateValue;
use super::BudgetedValue;
use super::JsonEncodeContext;
use crate::encode::JsonSerializationErrorKind;
use crate::encode::JsonSerializerStateError;
use crate::internal::JsonPrivateProtocolKind;
use crate::internal::JsonPrivateProtocolState;
use crate::internal::SERDE_JSON_RAW_VALUE_TOKEN;
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,
declared_empty: bool,
map_key_pending: bool,
private_kind: Option<JsonPrivateProtocolKind>,
private_state: Option<JsonPrivateProtocolState>,
}
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,
{
#[must_use]
#[inline]
pub(super) const fn new(
inner: C,
context: &'context RefCell<JsonEncodeContext<'transaction, 'budget, R, Q>>,
child_depth: usize,
declared_empty: bool,
) -> Self {
Self {
inner,
context,
child_depth,
observed: 0,
declared_empty,
map_key_pending: false,
private_kind: None,
private_state: None,
}
}
#[must_use]
pub(super) const fn private(
inner: C,
context: &'context RefCell<JsonEncodeContext<'transaction, 'budget, R, Q>>,
depth: usize,
kind: JsonPrivateProtocolKind,
state: JsonPrivateProtocolState,
) -> Self {
Self {
inner,
context,
child_depth: depth,
observed: 0,
declared_empty: false,
map_key_pending: false,
private_kind: Some(kind),
private_state: Some(state),
}
}
#[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_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 })
}
#[inline(always)]
fn reject_empty_callback<E>(&self) -> Result<(), E>
where
E: Error,
{
if self.declared_empty {
return Err(self.serialization_error(JsonSerializerStateError::UnexpectedCompound));
}
Ok(())
}
fn private_protocol_error<E>(&self) -> E
where
E: Error,
{
let kind = self.private_kind.expect("private protocol kind must exist");
self.context
.borrow_mut()
.serialization_error(JsonSerializationErrorKind::InvalidSerializerState {
reason: kind.invalid_state(),
})
}
}
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.reject_empty_callback()?;
self.next_sequence()?;
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_element(&value)
}
#[inline(always)]
fn end(self) -> Result<Self::Ok, Self::Error> {
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.reject_empty_callback()?;
self.next_sequence()?;
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_element(&value)
}
#[inline(always)]
fn end(self) -> Result<Self::Ok, Self::Error> {
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.reject_empty_callback()?;
self.next_sequence()?;
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_field(&value)
}
#[inline(always)]
fn end(self) -> Result<Self::Ok, Self::Error> {
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.reject_empty_callback()?;
self.next_sequence()?;
let value = BudgetedValue::<_, _, _, VALUE_LIMITS>::new(value, self.context, self.child_depth);
self.inner.serialize_field(&value)
}
#[inline(always)]
fn end(self) -> Result<Self::Ok, Self::Error> {
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,
{
self.reject_empty_callback()?;
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,
{
self.reject_empty_callback()?;
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.reject_empty_callback()?;
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,
{
self.reject_empty_callback()?;
if let Some(kind) = self.private_kind {
let state = self.private_state.as_mut().expect("private state must exist");
if state.begin(key).is_err() {
return Err(self.private_protocol_error());
}
let payload = match kind {
JsonPrivateProtocolKind::RawValue => {
BudgetedPrivateValue::raw_value(value, self.context, self.child_depth)
}
JsonPrivateProtocolKind::Number => BudgetedPrivateValue::number(value, self.context, self.child_depth),
};
let inner_key = if kind == JsonPrivateProtocolKind::Number {
SERDE_JSON_RAW_VALUE_TOKEN
} else {
key
};
if let Err(error) = self.inner.serialize_field(inner_key, &payload) {
self.private_state.as_mut().expect("private state must exist").fail();
let _: Self::Error = self.private_protocol_error();
return Err(error);
}
if self
.private_state
.as_mut()
.expect("private state must exist")
.complete()
.is_err()
{
return Err(self.private_protocol_error());
}
return Ok(());
}
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> {
if let Some(state) = self.private_state.as_mut() {
state.fail();
return Err(self.private_protocol_error());
}
self.inner.skip_field(key)
}
#[inline(always)]
fn end(mut self) -> Result<Self::Ok, Self::Error> {
if let Some(state) = self.private_state.take() {
if state.finish().is_err() {
return Err(self.private_protocol_error());
}
} else {
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.reject_empty_callback()?;
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()
}
}