Skip to content

Commit

Permalink
Serialize high precision numbers correctly.
Browse files Browse the repository at this point in the history
  • Loading branch information
timothee-haudebourg committed Feb 15, 2024
1 parent 54093a1 commit 810b51f
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "json-syntax"
version = "0.11.5"
version = "0.11.6"
edition = "2021"
authors = ["Timothée Haudebourg <author@haudebourg.net>"]
description = "Strict JSON parsing and mapping library"
Expand Down
2 changes: 2 additions & 0 deletions src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ mod ser;
pub use de::*;
pub use ser::*;

const NUMBER_TOKEN: &str = "$serde_json::private::Number";

/// Serializes the given `value` into a JSON [`Value`].
///
/// # Example
Expand Down
20 changes: 9 additions & 11 deletions src/serde/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use crate::{
Array, NumberBuf, Object, Value,
};

use super::NUMBER_TOKEN;

impl Value {
#[cold]
fn invalid_type<E>(&self, exp: &dyn Expected) -> E
Expand Down Expand Up @@ -124,41 +126,39 @@ impl<'de> Deserialize<'de> for Value {
where
V: MapAccess<'de>,
{
const NUMBER_TOKEN: &str = "$serde_json::private::Number";

enum MapTag {
Number,
None(Key)
None(Key),
}

impl<'de> Deserialize<'de> for MapTag {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>
D: serde::Deserializer<'de>,
{
struct Visitor;

impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = MapTag;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string key")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error
E: serde::de::Error,
{
if v == NUMBER_TOKEN {
Ok(MapTag::Number)
} else {
Ok(MapTag::None(v.into()))
}
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error
E: serde::de::Error,
{
if v == NUMBER_TOKEN {
Ok(MapTag::Number)
Expand Down Expand Up @@ -187,9 +187,7 @@ impl<'de> Deserialize<'de> for Value {

Ok(Value::Object(object))
}
None => {
Ok(Value::Object(Object::new()))
}
None => Ok(Value::Object(Object::new())),
}
}
}
Expand Down
232 changes: 215 additions & 17 deletions src/serde/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use serde::{ser::Impossible, Serialize};
use smallstr::SmallString;
use std::fmt;

use super::NUMBER_TOKEN;
use crate::{object::Key, Array, NumberBuf, Object, Value};

impl Serialize for Value {
Expand Down Expand Up @@ -49,13 +50,15 @@ impl Serialize for Object {
pub enum SerializeError {
Custom(String),
NonStringKey,
MalformedHighPrecisionNumber,
}

impl fmt::Display for SerializeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Custom(msg) => msg.fmt(f),
Self::NonStringKey => write!(f, "key must be a string"),
Self::MalformedHighPrecisionNumber => write!(f, "malformed high-precision number"),
}
}
}
Expand All @@ -82,8 +85,8 @@ impl serde::Serializer for Serializer {
type SerializeTuple = SerializeArray;
type SerializeTupleStruct = SerializeArray;
type SerializeTupleVariant = SerializeTupleVariant;
type SerializeMap = SerializeObject;
type SerializeStruct = SerializeObject;
type SerializeMap = SerializeMap;
type SerializeStruct = SerializeMap;
type SerializeStructVariant = SerializeStructVariant;

#[inline(always)]
Expand Down Expand Up @@ -259,7 +262,7 @@ impl serde::Serializer for Serializer {
}

fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Ok(SerializeObject {
Ok(SerializeMap::Object {
obj: Object::new(),
next_key: None,
})
Expand Down Expand Up @@ -294,6 +297,178 @@ impl serde::Serializer for Serializer {
}
}

pub struct StringNumberSerializer;

impl serde::Serializer for StringNumberSerializer {
type Ok = NumberBuf;
type Error = SerializeError;

type SerializeSeq = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeTuple = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeTupleStruct = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeTupleVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeMap = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeStruct = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;

fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
NumberBuf::new(v.as_bytes().into())
.map_err(|_| SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_newtype_struct<T: ?Sized>(
self,
_name: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}

fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(SerializeError::MalformedHighPrecisionNumber)
}
}

pub struct KeySerializer;

impl serde::Serializer for KeySerializer {
Expand Down Expand Up @@ -586,41 +761,64 @@ impl serde::ser::SerializeStructVariant for SerializeStructVariant {
}
}

pub struct SerializeObject {
obj: Object,
next_key: Option<Key>,
pub enum SerializeMap {
Object { obj: Object, next_key: Option<Key> },
Number(Option<NumberBuf>),
}

impl serde::ser::SerializeMap for SerializeObject {
impl serde::ser::SerializeMap for SerializeMap {
type Ok = Value;
type Error = SerializeError;

fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
self.next_key = Some(key.serialize(KeySerializer)?);
Ok(())
match self {
Self::Number(_) => Err(SerializeError::MalformedHighPrecisionNumber),
Self::Object { obj, next_key } => {
let key = key.serialize(KeySerializer)?;

if obj.is_empty() && key == NUMBER_TOKEN {
*self = Self::Number(None)
} else {
*next_key = Some(key);
}

Ok(())
}
}
}

fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
let key = self
.next_key
.take()
.expect("serialize_value called before serialize_key");
self.obj.insert(key, value.serialize(Serializer)?);
Ok(())
match self {
Self::Number(n) => {
*n = Some(value.serialize(StringNumberSerializer)?);
Ok(())
}
Self::Object { obj, next_key } => {
let key = next_key
.take()
.expect("serialize_value called before serialize_key");
obj.insert(key, value.serialize(Serializer)?);
Ok(())
}
}
}

fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Value::Object(self.obj))
match self {
Self::Number(Some(n)) => Ok(Value::Number(n)),
Self::Number(None) => Err(SerializeError::MalformedHighPrecisionNumber),
Self::Object { obj, .. } => Ok(Value::Object(obj)),
}
}
}

impl serde::ser::SerializeStruct for SerializeObject {
impl serde::ser::SerializeStruct for SerializeMap {
type Ok = Value;
type Error = SerializeError;

Expand Down

0 comments on commit 810b51f

Please sign in to comment.