use std::borrow::Cow;
use std::collections::BTreeMap;
use std::fmt::{Display, Write as _};
use std::io::{self, Write};
use std::ops::Range;
use cadmpeg_core::decode::{DecodeContext, DepthGuard};
use cadmpeg_core::CodecError;
use serde::ser::{self, Serialize};
use super::{nests_too_deep_message, NativeConvertError, MAX_NATIVE_NESTING_DEPTH};
const RAW_VALUE_STRUCT: &str = "$serde_json::private::RawValue";
pub(super) const WORK: &str = "construct canonical native value";
pub(super) enum Written {
Text,
Object(Members),
}
impl Written {
pub(super) fn place(self, out: &mut Vec<u8>) {
if let Self::Object(members) = self {
members.close(out);
}
}
}
struct Member {
text: Range<usize>,
value: usize,
}
pub(super) struct Members {
start: usize,
entries: BTreeMap<Cow<'static, str>, Member>,
in_order: bool,
}
impl Members {
fn close(self, out: &mut Vec<u8>) {
if !self.in_order {
let body = self.start + 1..out.len();
reorder(out, body, self.entries.values().map(|member| &member.text));
}
out.push(b'}');
}
pub(super) fn into_record(
mut self,
out: Vec<u8>,
) -> Result<(crate::ids::Identity, Box<str>), NativeConvertError> {
let id_first = self.start == 0
&& self.in_order
&& self
.entries
.first_key_value()
.is_some_and(|(key, _)| key == "id");
let member = self
.entries
.remove("id")
.ok_or(NativeConvertError::MissingId)?;
let id = serde_json::from_slice::<String>(&out[member.value..member.text.end])
.map_err(|_| NativeConvertError::MissingId)?;
let id = crate::ids::Identity::new(id)?;
let mut json = out;
if !id_first {
let body = self.start + 1..json.len();
let order = std::iter::once(&member.text)
.chain(self.entries.values().map(|member| &member.text));
reorder(&mut json, body, order);
json.drain(..self.start);
}
json.push(b'}');
let json = String::from_utf8(json).map_err(|_| {
NativeConvertError::ConversionMessage("canonical native text is not UTF-8".to_owned())
})?;
Ok((id, json.into_boxed_str()))
}
}
fn reorder<'m>(
out: &mut [u8],
body: Range<usize>,
order: impl Iterator<Item = &'m Range<usize>> + Clone,
) {
let Some((longest, longest_text)) =
order.clone().enumerate().max_by_key(|(_, text)| text.len())
else {
return;
};
let mut aside = Vec::with_capacity(body.len() - longest_text.len());
let mut target = body.start;
for (index, text) in order.clone().enumerate() {
if index != longest {
aside.extend_from_slice(&out[text.clone()]);
}
if index < longest {
target += text.len() + 1;
}
}
out.copy_within(longest_text.clone(), target);
let mut at = body.start;
let mut read = 0;
for (index, text) in order.enumerate() {
if index > 0 {
out[at] = b',';
at += 1;
}
if index != longest {
out[at..at + text.len()].copy_from_slice(&aside[read..read + text.len()]);
read += text.len();
}
at += text.len();
}
}
fn open_variant(out: &mut Vec<u8>, variant: &str) -> serde_json::Result<()> {
out.push(b'{');
serde_json::to_writer(&mut *out, variant)?;
out.push(b':');
Ok(())
}
pub(super) fn to_text<'a, T: Serialize + ?Sized>(
ctx: &'a DecodeContext<'a>,
depth: usize,
value: &T,
) -> Result<String, CanonError> {
let mut out = Vec::new();
value
.serialize(CanonText::within(ctx, depth, &mut out))?
.place(&mut out);
String::from_utf8(out)
.map_err(|_| <CanonError as ser::Error>::custom("canonical native text is not UTF-8"))
}
pub(super) fn collect_display_text<T: Display + ?Sized>(value: &T) -> Result<String, CanonError> {
let mut text = String::new();
write!(text, "{value}")
.map_err(|_| <CanonError as ser::Error>::custom("a formatting error occurred"))?;
Ok(text)
}
#[derive(Debug)]
pub(super) enum Step {
Key(String),
Index(usize),
}
#[derive(Debug)]
pub(super) enum CanonError {
NonFinite(Vec<Step>),
Json(serde_json::Error),
Resource(CodecError),
Message(String),
}
impl CanonError {
pub(super) fn into_native(self, ctx: &DecodeContext<'_>) -> super::NativeConvertError {
if let Some(limit) = ctx.resource_refusal() {
return super::NativeConvertError::Resource(cadmpeg_core::CodecError::ResourceLimit(
limit,
));
}
match self {
Self::NonFinite(steps) => super::NativeConvertError::NonFiniteNumber {
field: Self::field_path(&steps),
},
Self::Json(error) => super::NativeConvertError::Serde(error),
Self::Resource(error) => super::NativeConvertError::Resource(error),
Self::Message(message) => super::NativeConvertError::ConversionMessage(message),
}
}
pub(super) fn within(self, step: impl FnOnce() -> Step) -> Self {
let Self::NonFinite(mut steps) = self else {
return self;
};
steps.push(step());
Self::NonFinite(steps)
}
pub(super) fn field_path(steps: &[Step]) -> String {
let mut path = String::new();
for step in steps.iter().rev() {
match step {
Step::Key(key) => {
if !path.is_empty() {
path.push('.');
}
path.push_str(key);
}
Step::Index(index) => {
path.push('[');
path.push_str(&index.to_string());
path.push(']');
}
}
}
path
}
}
impl std::fmt::Display for CanonError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NonFinite(steps) => {
f.write_str("field ")?;
let mut started = false;
for step in steps.iter().rev() {
match step {
Step::Key(key) => {
if started {
f.write_str(".")?;
}
f.write_str(key)?;
started |= !key.is_empty();
}
Step::Index(index) => {
write!(f, "[{index}]")?;
started = true;
}
}
}
f.write_str(" holds a non-finite number")
}
Self::Json(error) => error.fmt(f),
Self::Resource(error) => error.fmt(f),
Self::Message(message) => f.write_str(message),
}
}
}
impl std::error::Error for CanonError {}
impl ser::Error for CanonError {
fn custom<T: Display>(message: T) -> Self {
Self::Json(<serde_json::Error as ser::Error>::custom(message))
}
}
impl From<CodecError> for CanonError {
fn from(error: CodecError) -> Self {
Self::Resource(error)
}
}
impl From<serde_json::Error> for CanonError {
fn from(error: serde_json::Error) -> Self {
Self::Json(error)
}
}
fn enter<'a>(ctx: &'a DecodeContext<'a>, depth: usize) -> Result<(usize, DepthGuard<'a>), Error> {
match depth.checked_sub(1) {
Some(depth) => {
let nested = ctx.enter_nested(WORK)?;
Ok((depth, nested))
}
None => Err(ser::Error::custom(nests_too_deep_message())),
}
}
fn open_map<'a, 'o>(
ctx: &'a DecodeContext<'a>,
depth: usize,
out: &'o mut Vec<u8>,
) -> Result<CanonMap<'a, 'o>, Error> {
let (depth, nested) = enter(ctx, depth)?;
let start = out.len();
out.push(b'{');
Ok(CanonMap {
ctx,
_nested: nested,
out,
members: Members {
start,
entries: BTreeMap::new(),
in_order: true,
},
key: None,
depth,
})
}
pub(super) struct CanonText<'a, 'o> {
ctx: &'a DecodeContext<'a>,
depth: usize,
out: &'o mut Vec<u8>,
}
type Error = CanonError;
impl<'a, 'o> CanonText<'a, 'o> {
pub(super) fn for_record(ctx: &'a DecodeContext<'a>, out: &'o mut Vec<u8>) -> Self {
Self::within(ctx, MAX_NATIVE_NESTING_DEPTH + 1, out)
}
pub(super) fn within(ctx: &'a DecodeContext<'a>, depth: usize, out: &'o mut Vec<u8>) -> Self {
Self { ctx, depth, out }
}
fn scalar<T: Serialize + ?Sized>(self, value: &T) -> Result<Written, Error> {
serde_json::to_writer(self.out, value)?;
Ok(Written::Text)
}
fn number(self, value: f64) -> Result<Written, Error> {
if !value.is_finite() {
return Err(CanonError::NonFinite(Vec::new()));
}
self.scalar(&value)
}
fn null(self) -> Written {
self.out.extend_from_slice(b"null");
Written::Text
}
}
impl<'a, 'o> ser::Serializer for CanonText<'a, 'o> {
type Ok = Written;
type Error = Error;
type SerializeSeq = CanonSeq<'a, 'o>;
type SerializeTuple = CanonSeq<'a, 'o>;
type SerializeTupleStruct = CanonSeq<'a, 'o>;
type SerializeTupleVariant = CanonVariantSeq<'a, 'o>;
type SerializeMap = CanonMap<'a, 'o>;
type SerializeStruct = CanonStruct<'a, 'o>;
type SerializeStructVariant = CanonVariantMap<'a, 'o>;
fn serialize_bool(self, value: bool) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_i8(self, value: i8) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_i16(self, value: i16) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_i32(self, value: i32) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_i64(self, value: i64) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_i128(self, value: i128) -> Result<Written, Error> {
if let Ok(value) = i64::try_from(value) {
return self.scalar(&value);
}
if let Ok(value) = u64::try_from(value) {
return self.scalar(&value);
}
Err(ser::Error::custom("number out of range"))
}
fn serialize_u8(self, value: u8) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_u16(self, value: u16) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_u32(self, value: u32) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_u64(self, value: u64) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_u128(self, value: u128) -> Result<Written, Error> {
if let Ok(value) = u64::try_from(value) {
return self.scalar(&value);
}
Err(ser::Error::custom("number out of range"))
}
fn serialize_f32(self, value: f32) -> Result<Written, Error> {
self.number(f64::from(value))
}
fn serialize_f64(self, value: f64) -> Result<Written, Error> {
self.number(value)
}
fn serialize_char(self, value: char) -> Result<Written, Error> {
self.scalar(&value)
}
fn serialize_str(self, value: &str) -> Result<Written, Error> {
self.scalar(value)
}
fn serialize_bytes(self, value: &[u8]) -> Result<Written, Error> {
let mut bytes = self.serialize_seq(Some(value.len()))?;
for byte in value {
ser::SerializeSeq::serialize_element(&mut bytes, byte)?;
}
ser::SerializeSeq::end(bytes)
}
fn serialize_none(self) -> Result<Written, Error> {
Ok(self.null())
}
fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<Written, Error> {
let _depth = self.ctx.enter_nested(WORK)?;
value.serialize(self)
}
fn serialize_unit(self) -> Result<Written, Error> {
Ok(self.null())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Written, Error> {
Ok(self.null())
}
fn serialize_unit_variant(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
) -> Result<Written, Error> {
self.serialize_str(variant)
}
fn serialize_newtype_struct<T: Serialize + ?Sized>(
self,
_name: &'static str,
value: &T,
) -> Result<Written, Error> {
let _depth = self.ctx.enter_nested(WORK)?;
value.serialize(self)
}
fn serialize_newtype_variant<T: Serialize + ?Sized>(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
value: &T,
) -> Result<Written, Error> {
let (depth, _nested) = enter(self.ctx, self.depth)?;
open_variant(self.out, variant)?;
value
.serialize(CanonText::within(self.ctx, depth, &mut *self.out))
.map_err(|error| error.within(|| Step::Key(variant.to_owned())))?
.place(self.out);
self.out.push(b'}');
Ok(Written::Text)
}
fn serialize_seq(self, _len: Option<usize>) -> Result<CanonSeq<'a, 'o>, Error> {
let (depth, nested) = enter(self.ctx, self.depth)?;
self.out.push(b'[');
Ok(CanonSeq {
ctx: self.ctx,
_nested: nested,
out: self.out,
len: 0,
depth,
})
}
fn serialize_tuple(self, len: usize) -> Result<CanonSeq<'a, 'o>, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<CanonSeq<'a, 'o>, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
len: usize,
) -> Result<CanonVariantSeq<'a, 'o>, Error> {
let (depth, nested) = enter(self.ctx, self.depth)?;
open_variant(self.out, variant)?;
Ok(CanonVariantSeq {
_nested: nested,
variant,
seq: CanonText::within(self.ctx, depth, self.out).serialize_seq(Some(len))?,
})
}
fn serialize_map(self, _len: Option<usize>) -> Result<CanonMap<'a, 'o>, Error> {
open_map(self.ctx, self.depth, self.out)
}
fn serialize_struct(
self,
name: &'static str,
len: usize,
) -> Result<CanonStruct<'a, 'o>, Error> {
if name == RAW_VALUE_STRUCT {
Ok(CanonStruct::Raw {
ctx: self.ctx,
depth: self.depth,
out: self.out,
parsed: None,
})
} else {
self.serialize_map(Some(len)).map(CanonStruct::Object)
}
}
fn serialize_struct_variant(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
_len: usize,
) -> Result<CanonVariantMap<'a, 'o>, Error> {
let (depth, nested) = enter(self.ctx, self.depth)?;
open_variant(self.out, variant)?;
Ok(CanonVariantMap {
_nested: nested,
variant,
map: open_map(self.ctx, depth, self.out)?,
})
}
fn collect_str<T: Display + ?Sized>(self, value: &T) -> Result<Written, Error> {
let start = self.out.len();
self.out.push(b'"');
let mut content = StringContent {
out: &mut *self.out,
};
if write!(content, "{value}").is_err() {
self.out.truncate(start);
return Err(ser::Error::custom("a formatting error occurred"));
}
self.out.push(b'"');
Ok(Written::Text)
}
}
struct StringContent<'o> {
out: &'o mut Vec<u8>,
}
impl std::fmt::Write for StringContent<'_> {
fn write_str(&mut self, text: &str) -> std::fmt::Result {
if text
.bytes()
.all(|byte| byte >= 0x20 && byte != b'"' && byte != b'\\')
{
self.out.extend_from_slice(text.as_bytes());
return Ok(());
}
let start = self.out.len();
serde_json::to_writer(&mut *self.out, text).map_err(|_| std::fmt::Error)?;
self.out.pop();
self.out.remove(start);
Ok(())
}
}
pub(super) struct CanonSeq<'a, 'o> {
ctx: &'a DecodeContext<'a>,
_nested: DepthGuard<'a>,
out: &'o mut Vec<u8>,
len: usize,
depth: usize,
}
impl<'o> CanonSeq<'_, 'o> {
fn close(self) -> &'o mut Vec<u8> {
self.out.push(b']');
self.out
}
}
impl ser::SerializeSeq for CanonSeq<'_, '_> {
type Ok = Written;
type Error = Error;
fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
let start = self.out.len();
if self.len > 0 {
self.out.push(b',');
}
let written = value
.serialize(CanonText::within(self.ctx, self.depth, &mut *self.out))
.map(|element| element.place(self.out));
match written {
Ok(()) => {
self.len += 1;
Ok(())
}
Err(error) => {
self.out.truncate(start);
let index = self.len;
Err(error.within(|| Step::Index(index)))
}
}
}
fn end(self) -> Result<Written, Error> {
self.close();
Ok(Written::Text)
}
}
impl ser::SerializeTuple for CanonSeq<'_, '_> {
type Ok = Written;
type Error = Error;
fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Written, Error> {
ser::SerializeSeq::end(self)
}
}
impl ser::SerializeTupleStruct for CanonSeq<'_, '_> {
type Ok = Written;
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Written, Error> {
ser::SerializeSeq::end(self)
}
}
pub(super) struct CanonVariantSeq<'a, 'o> {
_nested: DepthGuard<'a>,
variant: &'static str,
seq: CanonSeq<'a, 'o>,
}
impl ser::SerializeTupleVariant for CanonVariantSeq<'_, '_> {
type Ok = Written;
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
let variant = self.variant;
ser::SerializeSeq::serialize_element(&mut self.seq, value)
.map_err(|error| error.within(|| Step::Key(variant.to_owned())))
}
fn end(self) -> Result<Written, Error> {
self.seq.close().push(b'}');
Ok(Written::Text)
}
}
pub(super) struct CanonMap<'a, 'o> {
ctx: &'a DecodeContext<'a>,
_nested: DepthGuard<'a>,
out: &'o mut Vec<u8>,
members: Members,
key: Option<String>,
depth: usize,
}
impl<'o> CanonMap<'_, 'o> {
fn insert<T: Serialize + ?Sized>(
&mut self,
key: Cow<'static, str>,
value: &T,
) -> Result<(), Error> {
let entries = &mut self.members.entries;
let after_last = entries.last_key_value().is_none_or(|(last, _)| key > *last);
if !after_last && entries.contains_key(&key) {
return Err(CanonError::Message(format!("duplicate key {key}")));
}
let out = &mut *self.out;
let separator = out.len();
if !entries.is_empty() {
out.push(b',');
}
let text = out.len();
match write_member(self.ctx, self.depth, out, &key, value) {
Ok(value_start) => {
let member = Member {
text: text..out.len(),
value: value_start,
};
entries.insert(key, member);
self.members.in_order &= after_last;
Ok(())
}
Err(error) => {
out.truncate(separator);
Err(error.within(|| Step::Key(key.into_owned())))
}
}
}
fn finish(self) -> Result<(Members, &'o mut Vec<u8>), Error> {
if self.key.is_some() {
return Err(ser::Error::custom("map ended before the pending value"));
}
Ok((self.members, self.out))
}
}
impl ser::SerializeMap for CanonMap<'_, '_> {
type Ok = Written;
type Error = Error;
fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<(), Error> {
if self.key.is_some() {
return Err(ser::Error::custom(
"key serialized before the preceding value",
));
}
self.key = Some(key.serialize(CanonKey { ctx: self.ctx })?);
Ok(())
}
fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
let key = self
.key
.take()
.ok_or_else(|| <Error as ser::Error>::custom("value serialized before key"))?;
self.insert(Cow::Owned(key), value)
}
fn end(self) -> Result<Written, Error> {
let (members, _) = self.finish()?;
Ok(Written::Object(members))
}
}
fn write_member<'a, T: Serialize + ?Sized>(
ctx: &'a DecodeContext<'a>,
depth: usize,
out: &mut Vec<u8>,
key: &str,
value: &T,
) -> Result<usize, Error> {
serde_json::to_writer(&mut *out, key)?;
out.push(b':');
let value_start = out.len();
value
.serialize(CanonText::within(ctx, depth, &mut *out))?
.place(out);
Ok(value_start)
}
pub(super) enum CanonStruct<'a, 'o> {
Object(CanonMap<'a, 'o>),
Raw {
ctx: &'a DecodeContext<'a>,
depth: usize,
out: &'o mut Vec<u8>,
parsed: Option<Written>,
},
}
impl ser::SerializeStruct for CanonStruct<'_, '_> {
type Ok = Written;
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Error> {
match self {
Self::Object(map) => map.insert(Cow::Borrowed(key), value),
Self::Raw {
ctx,
depth,
out,
parsed,
} => {
if key != RAW_VALUE_STRUCT || parsed.is_some() {
return Err(ser::Error::custom(
"raw JSON requires exactly one payload field",
));
}
let text = to_text(ctx, *depth, value)?;
let Ok(json) = serde_json::from_str::<String>(&text) else {
return Err(ser::Error::custom("raw JSON payload must be a string"));
};
let start = out.len();
match super::replay::emit(&json, CanonText::within(ctx, *depth, out), *depth) {
Ok(replayed) => {
*parsed = Some(replayed);
Ok(())
}
Err(error) => {
out.truncate(start);
Err(error)
}
}
}
}
}
fn end(self) -> Result<Written, Error> {
match self {
Self::Object(map) => ser::SerializeMap::end(map),
Self::Raw {
parsed: Some(parsed),
..
} => Ok(parsed),
Self::Raw { parsed: None, .. } => {
Err(ser::Error::custom("raw JSON has no payload field"))
}
}
}
}
pub(super) struct CanonVariantMap<'a, 'o> {
_nested: DepthGuard<'a>,
variant: &'static str,
map: CanonMap<'a, 'o>,
}
impl ser::SerializeStructVariant for CanonVariantMap<'_, '_> {
type Ok = Written;
type Error = Error;
fn serialize_field<T: Serialize + ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Error> {
let variant = self.variant;
self.map
.insert(Cow::Borrowed(key), value)
.map_err(|error| error.within(|| Step::Key(variant.to_owned())))
}
fn end(self) -> Result<Written, Error> {
let (members, out) = self.map.finish()?;
members.close(out);
out.push(b'}');
Ok(Written::Text)
}
}
pub(super) struct CanonKey<'a> {
pub(super) ctx: &'a DecodeContext<'a>,
}
struct NumberText {
bytes: [u8; 128],
len: usize,
}
impl Write for NumberText {
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
let end = self
.len
.checked_add(bytes.len())
.filter(|end| *end <= self.bytes.len())
.ok_or_else(|| io::Error::other("native number text exceeds its fixed buffer"))?;
self.bytes[self.len..end].copy_from_slice(bytes);
self.len = end;
Ok(bytes.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
fn number_key_text<T: Serialize>(value: &T) -> Result<String, Error> {
let mut text = NumberText {
bytes: [0; 128],
len: 0,
};
serde_json::to_writer(&mut text, value)?;
let text = std::str::from_utf8(&text.bytes[..text.len])
.map_err(|_| <Error as ser::Error>::custom("native number text is not UTF-8"))?;
Ok(text.to_owned())
}
fn key_must_be_a_string() -> Error {
ser::Error::custom("key must be a string")
}
impl ser::Serializer for CanonKey<'_> {
type Ok = String;
type Error = Error;
type SerializeSeq = ser::Impossible<String, Error>;
type SerializeTuple = ser::Impossible<String, Error>;
type SerializeTupleStruct = ser::Impossible<String, Error>;
type SerializeTupleVariant = ser::Impossible<String, Error>;
type SerializeMap = ser::Impossible<String, Error>;
type SerializeStruct = ser::Impossible<String, Error>;
type SerializeStructVariant = ser::Impossible<String, Error>;
fn serialize_bool(self, value: bool) -> Result<String, Error> {
let text = if value { "true" } else { "false" };
Ok(text.to_owned())
}
fn serialize_i8(self, value: i8) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_i16(self, value: i16) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_i32(self, value: i32) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_i64(self, value: i64) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_i128(self, value: i128) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_u8(self, value: u8) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_u16(self, value: u16) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_u32(self, value: u32) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_u64(self, value: u64) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_u128(self, value: u128) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_f32(self, value: f32) -> Result<String, Error> {
if value.is_finite() {
number_key_text(&value)
} else {
Err(ser::Error::custom("float key must be finite"))
}
}
fn serialize_f64(self, value: f64) -> Result<String, Error> {
if value.is_finite() {
number_key_text(&value)
} else {
Err(ser::Error::custom("float key must be finite"))
}
}
fn serialize_char(self, value: char) -> Result<String, Error> {
Ok(value.to_string())
}
fn serialize_str(self, value: &str) -> Result<String, Error> {
Ok(value.to_owned())
}
fn serialize_bytes(self, _value: &[u8]) -> Result<String, Error> {
Err(key_must_be_a_string())
}
fn serialize_none(self) -> Result<String, Error> {
Err(key_must_be_a_string())
}
fn serialize_some<T: Serialize + ?Sized>(self, _value: &T) -> Result<String, Error> {
Err(key_must_be_a_string())
}
fn serialize_unit(self) -> Result<String, Error> {
Err(key_must_be_a_string())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<String, Error> {
Err(key_must_be_a_string())
}
fn serialize_unit_variant(
self,
_name: &'static str,
_index: u32,
variant: &'static str,
) -> Result<String, Error> {
Ok(variant.to_owned())
}
fn serialize_newtype_struct<T: Serialize + ?Sized>(
self,
_name: &'static str,
value: &T,
) -> Result<String, Error> {
let _depth = self.ctx.enter_nested(WORK)?;
value.serialize(self)
}
fn serialize_newtype_variant<T: Serialize + ?Sized>(
self,
_name: &'static str,
_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<String, Error> {
Err(key_must_be_a_string())
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
Err(key_must_be_a_string())
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Error> {
Err(key_must_be_a_string())
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, Error> {
Err(key_must_be_a_string())
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Error> {
Err(key_must_be_a_string())
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
Err(key_must_be_a_string())
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Error> {
Err(key_must_be_a_string())
}
fn serialize_struct_variant(
self,
_name: &'static str,
_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Error> {
Err(key_must_be_a_string())
}
fn collect_str<T: Display + ?Sized>(self, value: &T) -> Result<String, Error> {
collect_display_text(value)
}
}
#[cfg(test)]
mod tests;