mod serde_ser;
use serde::Deserialize;
pub use serde_ser::Serializer;
mod serde_de;
pub use serde_de::Deserializer;
use crate::{
io::{Read, Write},
types::CborIntegerValue,
};
pub struct Tagged<'a, const TAG: u64, V: 'a> {
inner: V,
_marker: std::marker::PhantomData<&'a ()>,
}
#[derive(Debug)]
pub(crate) struct DynamicTaggedValue<'a> {
pub(crate) tag: CborIntegerValue,
pub(crate) value: std::borrow::Cow<'a, crate::Value<'a>>,
}
pub(crate) const DYN_TAGGED_TYP_NAME: &'static str = "seabored::serde::DynamicTaggedValue";
impl<'de> ::serde::Deserialize<'de> for DynamicTaggedValue<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct DynamicTaggedValueVisitor;
impl<'de> ::serde::de::Visitor<'de> for DynamicTaggedValueVisitor {
type Value = DynamicTaggedValue<'de>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "A Dynamically tagged CBOR Value")
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
let tag = serde_de::TAG.get().expect("This should never happen");
let value = crate::Value::deserialize(deserializer)?;
Ok(DynamicTaggedValue {
tag: tag.into(),
value: std::borrow::Cow::Owned(value),
})
}
}
deserializer.deserialize_newtype_struct(DYN_TAGGED_TYP_NAME, DynamicTaggedValueVisitor)
}
}
impl<'a> ::serde::Serialize for DynamicTaggedValue<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_newtype_struct(DYN_TAGGED_TYP_NAME, self)
}
}
#[inline(always)]
pub(crate) fn parse_tag_from_typ(typ: &str) -> Option<u64> {
const TAGGED_VALUE_TYP_ROOT_NAME: &'static str = "seabored::serde::Tagged";
let (tname, targs) = typ.split_once('<')?;
if tname != TAGGED_VALUE_TYP_ROOT_NAME {
return None;
}
let (_, targs) = targs.split_once(',').unwrap(); let (tag_str, _) = targs.split_once(',').unwrap(); let tag_str = tag_str.trim();
Some(if tag_str == "u64::MAX" {
u64::MAX
} else {
tag_str.parse().unwrap() })
}
impl<'a, const TAG: u64, V: serde::Serialize + 'a> serde::Serialize for Tagged<'a, TAG, V> {
#[inline(always)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_newtype_struct(std::any::type_name::<Self>(), &self.inner)
}
}
impl<'a, 'de: 'a, const TAG: u64, V: serde::Deserialize<'de> + 'a> serde::Deserialize<'de>
for Tagged<'a, TAG, V>
{
#[inline(always)]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct TaggedValueVisitor<'a, 'de: 'a, const TAG: u64, V: serde::Deserialize<'de>>(
std::marker::PhantomData<(&'a V, &'de ())>,
);
impl<'a, 'de: 'a, const TAG: u64, V: serde::Deserialize<'de>> serde::de::Visitor<'de>
for TaggedValueVisitor<'a, 'de, TAG, V>
{
type Value = Tagged<'a, TAG, V>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "A CBOR Tagged Value")
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
let inner = V::deserialize(deserializer)?;
Ok(inner.into())
}
}
deserializer.deserialize_newtype_struct(
std::any::type_name::<Self>(),
TaggedValueVisitor::<'a, 'de, TAG, V>(Default::default()),
)
}
}
impl<'a, const TAG: u64, V: 'a> From<V> for Tagged<'a, TAG, V> {
#[inline(always)]
fn from(inner: V) -> Self {
Self {
inner,
_marker: Default::default(),
}
}
}
impl<'a, const TAG: u64, V: 'a> std::fmt::Debug for Tagged<'a, TAG, V>
where
V: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Tagged")
.field("TAG", &TAG)
.field("inner", &self.inner)
.finish()
}
}
impl<'a, const TAG: u64, V: 'a> PartialEq for Tagged<'a, TAG, V>
where
V: PartialEq,
{
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.inner.eq(&other.inner)
}
}
impl<'a, const TAG: u64, V: 'a> Tagged<'a, TAG, V> {
#[inline(always)]
pub fn into_inner(self) -> V {
self.inner
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct SimpleValue(pub u8);
impl SimpleValue {
pub(crate) const TYP_NAME: &'static str = "seabored::serde::SimpleValue";
}
impl serde::Serialize for SimpleValue {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_newtype_struct(Self::TYP_NAME, self)
}
}
impl<'de> serde::Deserialize<'de> for SimpleValue {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct SimpleValueVisitor;
impl<'de> serde::de::Visitor<'de> for SimpleValueVisitor {
type Value = SimpleValue;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "A CBOR SimpleValue")
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(SimpleValue(u8::deserialize(deserializer)?))
}
}
deserializer.deserialize_newtype_struct(Self::TYP_NAME, SimpleValueVisitor)
}
}
#[inline(always)]
pub fn from_slice<'de, T: serde::Deserialize<'de>>(
buf: &'de [u8],
) -> Result<T, crate::error::SeaboredDeError<'de>> {
from_reader(buf)
}
#[inline(always)]
pub fn from_reader<'de, T: serde::Deserialize<'de>, R: Read<'de>>(
reader: R,
) -> Result<T, crate::error::SeaboredDeError<'de>> {
let mut deserializer = serde_de::Deserializer::new(reader);
serde::Deserialize::deserialize(&mut deserializer)
}
#[inline(always)]
pub fn to_writer<W: Write, T: serde::Serialize>(
writer: &mut W,
value: &T,
) -> Result<usize, crate::error::SeaboredSerError> {
let mut serializer = serde_ser::Serializer { writer };
value.serialize(&mut serializer)
}
#[inline(always)]
pub fn to_vec<T: serde::Serialize>(value: &T) -> Result<Vec<u8>, crate::error::SeaboredSerError> {
let mut buf = vec![];
let written = to_writer(&mut buf, value)?;
debug_assert_eq!(written, buf.len());
Ok(buf)
}
#[cfg(test)]
mod tests {
use crate::{
Value,
serde::{SimpleValue, Tagged},
};
struct Repo;
impl Repo {
pub const TV: u64 = 99999;
}
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
struct SubTest<'a> {
sub: (),
#[serde(with = "serde_bytes")]
data: &'a [u8],
}
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
enum Mune {
Nothing,
Whatever { id: u32 },
}
const TEST_CONST: u64 = 9999999;
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
struct Test<'a> {
v1: bool,
v2: String,
v3: (),
v4: Option<u64>,
#[serde(with = "serde_bytes")]
v5: Vec<u8>,
v6: f32,
i32_pos: i32,
i32_zero: i32,
i32_neg: i32,
i16_neg: i16,
v7: Option<i64>,
v7_pos: Option<i64>,
#[serde(borrow)]
v8: Tagged<'a, { Repo::TV }, bool>,
#[serde(borrow)]
v9: Tagged<'a, 12u64, std::borrow::Cow<'a, serde_bytes::Bytes>>,
v10: SimpleValue,
#[serde(borrow)]
v11: Tagged<'a, { TEST_CONST }, bool>,
#[serde(borrow)]
v12: Tagged<'a, { u64::MAX }, ()>,
#[serde(borrow)]
v13: Tagged<'a, 69, Option<u64>>, v14: Option<()>,
v15: Tagged<'a, 420, Value<'a>>, v16: Value<'a>,
data: SubTest<'a>,
mune1: Mune,
mune2: Mune,
}
impl Default for Test<'_> {
fn default() -> Self {
Test {
v1: false,
v2: "Here is a test!".into(),
v3: (),
v4: None,
v5: vec![1, 2, 3, 4, 5, 6],
v6: std::f32::consts::PI,
i32_neg: -1,
i32_zero: 0,
i32_pos: 1,
i16_neg: i16::MIN,
v7: Some(-100),
v7_pos: Some(100),
v8: false.into(),
v9: Tagged::from(std::borrow::Cow::Owned(vec![7, 8, 9].into())),
v10: SimpleValue(59),
v11: true.into(),
v12: ().into(),
v13: Some(64).into(),
v14: Some(()),
v15: Tagged::from(Value::Bool(false)),
v16: Value::Tagged(((u32::MAX as u64).into(), Box::new(Value::Bool(true)))),
data: SubTest {
sub: (),
data: &[1, 43, 35, 64],
},
mune1: Mune::Nothing,
mune2: Mune::Whatever { id: 100 },
}
}
}
#[wasm_bindgen_test::wasm_bindgen_test(unsupported = test)]
fn can_roundtrip() {
use pretty_assertions::assert_eq;
let value = Test::default();
let mut buf = vec![];
super::to_writer(&mut buf, &value).unwrap();
let value2 = super::from_slice::<Test>(&buf).unwrap();
assert_eq!(value, value2);
}
}