use std::cell::RefCell;
use std::fmt::Display;
use qubit_budget::ResourceQuantity;
use qubit_budget::json::JsonMeasurement;
use serde::Serialize;
use serde::Serializer;
use super::super::display_budget_kind::DisplayBudgetKind;
use super::super::json_encode_context::JsonEncodeContext;
use crate::encode::JsonMapKeyKind;
use crate::encode::JsonSerializationErrorKind;
use crate::internal::JsonLexemeLength;
use crate::internal::JsonMapKey;
pub(in crate::encode::serializer) struct JsonKeyBudgetSerializer<
'context,
'transaction,
'budget,
S,
R,
Q,
const VALUE_LIMITS: bool,
> where
Q: ResourceQuantity,
{
pub(in crate::encode::serializer) inner: S,
pub(in crate::encode::serializer) context: &'context RefCell<JsonEncodeContext<'transaction, 'budget, R, Q>>,
}
impl<S, R, Q, const VALUE_LIMITS: bool> JsonKeyBudgetSerializer<'_, '_, '_, S, R, Q, VALUE_LIMITS>
where
S: Serializer,
R: Clone,
Q: ResourceQuantity,
{
fn check(&self, bytes: usize) -> Result<(), S::Error> {
if !VALUE_LIMITS {
return Ok(());
}
self.context.borrow_mut().admit(JsonMeasurement::Key { bytes })
}
fn unsupported(&self, kind: JsonMapKeyKind) -> S::Error {
self.context
.borrow_mut()
.serialization_error(JsonSerializationErrorKind::UnsupportedMapKey { kind })
}
fn non_finite(&self) -> S::Error {
self.context
.borrow_mut()
.serialization_error(JsonSerializationErrorKind::NonFiniteFloat)
}
}
macro_rules! serialize_key_number {
($name:ident, signed $type:ty) => {
#[doc = "Checks the serialized signed key length before forwarding it."]
fn $name(self, value: $type) -> Result<Self::Ok, Self::Error> {
if VALUE_LIMITS {
self.check(JsonLexemeLength::signed_integer(value.into()))?;
}
self.inner.$name(value)
}
};
($name:ident, unsigned $type:ty) => {
#[doc = "Checks the serialized unsigned key length before forwarding it."]
fn $name(self, value: $type) -> Result<Self::Ok, Self::Error> {
if VALUE_LIMITS {
self.check(JsonLexemeLength::unsigned_integer(value.into()))?;
}
self.inner.$name(value)
}
};
}
impl<'context, 'transaction, 'budget, S, R, Q, const VALUE_LIMITS: bool> Serializer
for JsonKeyBudgetSerializer<'context, 'transaction, 'budget, S, R, Q, VALUE_LIMITS>
where
S: Serializer,
R: Clone,
Q: ResourceQuantity,
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = S::SerializeSeq;
type SerializeTuple = S::SerializeTuple;
type SerializeTupleStruct = S::SerializeTupleStruct;
type SerializeTupleVariant = S::SerializeTupleVariant;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
type SerializeStructVariant = S::SerializeStructVariant;
fn serialize_bool(self, value: bool) -> Result<Self::Ok, Self::Error> {
self.check(if value { 4 } else { 5 })?;
self.inner.serialize_bool(value)
}
serialize_key_number!(serialize_i8, signed i8);
serialize_key_number!(serialize_i16, signed i16);
serialize_key_number!(serialize_i32, signed i32);
serialize_key_number!(serialize_i64, signed i64);
serialize_key_number!(serialize_u8, unsigned u8);
serialize_key_number!(serialize_u16, unsigned u16);
serialize_key_number!(serialize_u32, unsigned u32);
serialize_key_number!(serialize_u64, unsigned u64);
fn serialize_i128(self, value: i128) -> Result<Self::Ok, Self::Error> {
let text = JsonMapKey::signed_wide(value);
if VALUE_LIMITS {
self.check(text.len())?;
}
self.inner.serialize_str(&text)
}
fn serialize_u128(self, value: u128) -> Result<Self::Ok, Self::Error> {
let text = JsonMapKey::unsigned_wide(value);
if VALUE_LIMITS {
self.check(text.len())?;
}
self.inner.serialize_str(&text)
}
fn serialize_f32(self, value: f32) -> Result<Self::Ok, Self::Error> {
if !value.is_finite() {
return Err(self.non_finite());
}
if VALUE_LIMITS {
self.check(JsonLexemeLength::finite_f32(value))?;
}
self.inner.serialize_f32(value)
}
fn serialize_f64(self, value: f64) -> Result<Self::Ok, Self::Error> {
if !value.is_finite() {
return Err(self.non_finite());
}
if VALUE_LIMITS {
self.check(JsonLexemeLength::finite_f64(value))?;
}
self.inner.serialize_f64(value)
}
fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
if VALUE_LIMITS {
self.check(value.len_utf8())?;
}
self.inner.serialize_char(value)
}
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
if VALUE_LIMITS {
self.check(value.len())?;
}
self.inner.serialize_str(value)
}
fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::Bytes))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::None))
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize + ?Sized,
{
value.serialize(self)
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::Unit))
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::UnitStruct))
}
fn serialize_unit_variant(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
if VALUE_LIMITS {
self.check(variant.len())?;
}
self.inner.serialize_unit_variant(name, variant_index, variant)
}
fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize + ?Sized,
{
value.serialize(self)
}
fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize + ?Sized,
{
Err(self.unsupported(JsonMapKeyKind::NewtypeVariant))
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::Sequence))
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::Tuple))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::TupleStruct))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::TupleVariant))
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::Map))
}
fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::Struct))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(self.unsupported(JsonMapKeyKind::StructVariant))
}
fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Display + ?Sized,
{
let text = JsonEncodeContext::collect_display::<S::Error, _>(self.context, value, DisplayBudgetKind::Key, 1)?;
self.inner.serialize_str(&text)
}
#[inline(always)]
fn is_human_readable(&self) -> bool {
self.inner.is_human_readable()
}
}