Skip to content

Commit 837e2b5

Browse files
committed
feat: simple type support
Signed-off-by: beltram <[email protected]>
1 parent 7c6ba83 commit 837e2b5

File tree

8 files changed

+416
-14
lines changed

8 files changed

+416
-14
lines changed

ciborium/src/de/mod.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ pub use error::Error;
88

99
use alloc::{string::String, vec::Vec};
1010

11+
use crate::{simple_type::SimpleTypeAccess, tag::TagAccess};
1112
use ciborium_io::Read;
1213
use ciborium_ll::*;
1314
use serde::de::{self, value::BytesDeserializer, Deserializer as _};
1415

15-
use crate::tag::TagAccess;
16-
1716
trait Expected<E: de::Error> {
1817
fn expected(self, kind: &'static str) -> E;
1918
}
@@ -213,8 +212,22 @@ where
213212
Header::Simple(simple::FALSE) => self.deserialize_bool(visitor),
214213
Header::Simple(simple::TRUE) => self.deserialize_bool(visitor),
215214
Header::Simple(simple::NULL) => self.deserialize_option(visitor),
216-
Header::Simple(simple::UNDEFINED) => self.deserialize_option(visitor),
217-
h @ Header::Simple(..) => Err(h.expected("known simple value")),
215+
Header::Simple(v @ simple::UNDEFINED) => {
216+
let _: Header = self.decoder.pull()?;
217+
visitor.visit_enum(SimpleTypeAccess::new(self, v))
218+
}
219+
// Those have to be registered via Standard Actions or are reserved so we should error whenever we
220+
// encounter one. This crate should be updated once new entries in this range are added
221+
// in the IANA registry
222+
h @ Header::Simple(0..=31) => Err(h.expected("known simple value")),
223+
// However we should support arbitrary simple types
224+
Header::Simple(v) => {
225+
let _: Header = self.decoder.pull()?;
226+
self.recurse(|me| {
227+
let access = SimpleTypeAccess::new(me, v);
228+
visitor.visit_enum(access)
229+
})
230+
}
218231

219232
h @ Header::Break => Err(h.expected("non-break")),
220233
}
@@ -604,6 +617,19 @@ where
604617
let access = TagAccess::new(me, tag);
605618
visitor.visit_enum(access)
606619
});
620+
} else if name == "@@ST@@" {
621+
return match self.decoder.pull()? {
622+
Header::Simple(v @ simple::UNDEFINED) => {
623+
self.decoder.push(Header::Positive(v as u64));
624+
visitor.visit_enum(SimpleTypeAccess::new(self, v))
625+
}
626+
h @ Header::Simple(0..=31) => Err(h.expected("known simple value")),
627+
Header::Simple(v) => {
628+
self.decoder.push(Header::Positive(v as u64));
629+
visitor.visit_enum(SimpleTypeAccess::new(self, v))
630+
}
631+
h => Err(h.expected("known simple value")),
632+
};
607633
}
608634

609635
loop {

ciborium/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ extern crate alloc;
9494

9595
pub mod de;
9696
pub mod ser;
97+
pub mod simple_type;
9798
pub mod tag;
9899
pub mod value;
99100

ciborium/src/ser/mod.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,21 @@ where
200200
#[inline]
201201
fn serialize_newtype_struct<U: ?Sized + ser::Serialize>(
202202
self,
203-
_name: &'static str,
203+
name: &'static str,
204204
value: &U,
205205
) -> Result<(), Self::Error> {
206-
value.serialize(self)
206+
if name == "@@SIMPLETYPE@@" {
207+
use serde::ser::Error as _;
208+
209+
let v = crate::Value::serialized(value).map_err(Error::custom)?;
210+
let v = v
211+
.as_integer()
212+
.ok_or_else(|| Error::custom("Internal error handling simple types"))?;
213+
let v = u8::try_from(v).map_err(Error::custom)?;
214+
Ok(self.0.push(Header::Simple(v))?)
215+
} else {
216+
value.serialize(self)
217+
}
207218
}
208219

209220
#[inline]
@@ -214,7 +225,16 @@ where
214225
variant: &'static str,
215226
value: &U,
216227
) -> Result<(), Self::Error> {
217-
if name != "@@TAG@@" || variant != "@@UNTAGGED@@" {
228+
if name == "@@ST@@" && variant == "@@SIMPLETYPE@@" {
229+
use serde::ser::Error as _;
230+
231+
let v = crate::Value::serialized(value).map_err(Error::custom)?;
232+
let v = v
233+
.as_integer()
234+
.ok_or_else(|| Error::custom("Internal error handling simple types"))?;
235+
let v = u8::try_from(v).map_err(Error::custom)?;
236+
return Ok(self.0.push(Header::Simple(v))?);
237+
} else if name != "@@TAG@@" || variant != "@@UNTAGGED@@" {
218238
self.0.push(Header::Map(Some(1)))?;
219239
self.serialize_str(variant)?;
220240
}

ciborium/src/simple_type.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//! Contains helper types for dealing with CBOR simple types
2+
3+
use serde::{de, de::Error as _, forward_to_deserialize_any, ser, Deserialize, Serialize};
4+
5+
#[derive(Debug, Deserialize, Serialize)]
6+
#[serde(rename = "@@ST@@")]
7+
enum Internal {
8+
/// The integer can either be 23, or (32..=255)
9+
#[serde(rename = "@@SIMPLETYPE@@")]
10+
SimpleType(u8),
11+
}
12+
13+
/// A CBOR simple value
14+
/// See https://datatracker.ietf.org/doc/html/rfc8949#section-3.3
15+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
16+
pub struct SimpleType(pub u8);
17+
18+
impl<'de> Deserialize<'de> for SimpleType {
19+
#[inline]
20+
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
21+
match Internal::deserialize(deserializer)? {
22+
Internal::SimpleType(t) => Ok(SimpleType(t)),
23+
}
24+
}
25+
}
26+
27+
impl Serialize for SimpleType {
28+
#[inline]
29+
fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
30+
Internal::SimpleType(self.0).serialize(serializer)
31+
}
32+
}
33+
34+
pub(crate) struct SimpleTypeAccess<D> {
35+
parent: Option<D>,
36+
state: usize,
37+
typ: u8,
38+
}
39+
40+
impl<D> SimpleTypeAccess<D> {
41+
pub fn new(parent: D, typ: u8) -> Self {
42+
Self {
43+
parent: Some(parent),
44+
state: 0,
45+
typ,
46+
}
47+
}
48+
}
49+
50+
impl<'de, D: de::Deserializer<'de>> de::Deserializer<'de> for &mut SimpleTypeAccess<D> {
51+
type Error = D::Error;
52+
53+
#[inline]
54+
fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
55+
self.state += 1;
56+
match self.state {
57+
1 => visitor.visit_str("@@SIMPLETYPE@@"),
58+
_ => visitor.visit_u8(self.typ),
59+
}
60+
}
61+
62+
forward_to_deserialize_any! {
63+
i8 i16 i32 i64 i128
64+
u8 u16 u32 u64 u128
65+
bool f32 f64
66+
char str string
67+
bytes byte_buf
68+
seq map
69+
struct tuple tuple_struct
70+
identifier ignored_any
71+
option unit unit_struct newtype_struct enum
72+
}
73+
}
74+
75+
impl<'de, D: de::Deserializer<'de>> de::EnumAccess<'de> for SimpleTypeAccess<D> {
76+
type Error = D::Error;
77+
type Variant = Self;
78+
79+
#[inline]
80+
fn variant_seed<V: de::DeserializeSeed<'de>>(
81+
mut self,
82+
seed: V,
83+
) -> Result<(V::Value, Self::Variant), Self::Error> {
84+
let variant = seed.deserialize(&mut self)?;
85+
Ok((variant, self))
86+
}
87+
}
88+
89+
impl<'de, D: de::Deserializer<'de>> de::VariantAccess<'de> for SimpleTypeAccess<D> {
90+
type Error = D::Error;
91+
92+
#[inline]
93+
fn unit_variant(self) -> Result<(), Self::Error> {
94+
Err(Self::Error::custom("expected simple type"))
95+
}
96+
97+
#[inline]
98+
fn newtype_variant_seed<U: de::DeserializeSeed<'de>>(
99+
mut self,
100+
seed: U,
101+
) -> Result<U::Value, Self::Error> {
102+
seed.deserialize(self.parent.take().unwrap())
103+
}
104+
105+
#[inline]
106+
fn tuple_variant<V: de::Visitor<'de>>(
107+
self,
108+
_len: usize,
109+
visitor: V,
110+
) -> Result<V::Value, Self::Error> {
111+
visitor.visit_seq(self)
112+
}
113+
114+
#[inline]
115+
fn struct_variant<V: de::Visitor<'de>>(
116+
self,
117+
_fields: &'static [&'static str],
118+
_visitor: V,
119+
) -> Result<V::Value, Self::Error> {
120+
Err(Self::Error::custom("expected simple_type"))
121+
}
122+
}
123+
124+
impl<'de, D: de::Deserializer<'de>> de::SeqAccess<'de> for SimpleTypeAccess<D> {
125+
type Error = D::Error;
126+
127+
#[inline]
128+
fn next_element_seed<T: de::DeserializeSeed<'de>>(
129+
&mut self,
130+
seed: T,
131+
) -> Result<Option<T::Value>, Self::Error> {
132+
if self.state < 2 {
133+
return Ok(Some(seed.deserialize(self)?));
134+
}
135+
136+
Ok(match self.parent.take() {
137+
Some(x) => Some(seed.deserialize(x)?),
138+
None => None,
139+
})
140+
}
141+
}

ciborium/src/value/de.rs

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// SPDX-License-Identifier: Apache-2.0
22

3-
use crate::tag::TagAccess;
3+
use crate::{simple_type::SimpleTypeAccess, tag::TagAccess};
44

55
use super::{Error, Integer, Value};
66

77
use alloc::{boxed::Box, string::String, vec::Vec};
88
use core::iter::Peekable;
99

10-
use ciborium_ll::tag;
10+
use ciborium_ll::{simple, tag};
1111
use serde::de::{self, Deserializer as _};
1212

1313
impl<'a> From<Integer> for de::Unexpected<'a> {
@@ -36,6 +36,7 @@ impl<'a> From<&'a Value> for de::Unexpected<'a> {
3636
Value::Map(..) => Self::Map,
3737
Value::Null => Self::Other("null"),
3838
Value::Tag(..) => Self::Other("tag"),
39+
Value::Simple(..) => Self::Other("simple"),
3940
}
4041
}
4142
}
@@ -141,9 +142,9 @@ impl<'de> serde::de::Visitor<'de> for Visitor {
141142
fn visit_enum<A: de::EnumAccess<'de>>(self, acc: A) -> Result<Self::Value, A::Error> {
142143
use serde::de::VariantAccess;
143144

144-
struct Inner;
145+
struct TagInner;
145146

146-
impl<'de> serde::de::Visitor<'de> for Inner {
147+
impl<'de> serde::de::Visitor<'de> for TagInner {
147148
type Value = Value;
148149

149150
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
@@ -162,9 +163,30 @@ impl<'de> serde::de::Visitor<'de> for Visitor {
162163
}
163164
}
164165

166+
struct SimpleTypeInner;
167+
168+
impl<'de> serde::de::Visitor<'de> for SimpleTypeInner {
169+
type Value = Value;
170+
171+
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
172+
write!(formatter, "a valid CBOR item")
173+
}
174+
175+
#[inline]
176+
fn visit_seq<A: de::SeqAccess<'de>>(self, mut acc: A) -> Result<Self::Value, A::Error> {
177+
let st = acc
178+
.next_element::<u8>()?
179+
.ok_or_else(|| de::Error::custom("expected simple type"))?;
180+
Ok(Value::Simple(st))
181+
}
182+
}
183+
165184
let (name, data): (String, _) = acc.variant()?;
166-
assert_eq!("@@TAGGED@@", name);
167-
data.tuple_variant(2, Inner)
185+
match name.as_str() {
186+
"@@TAGGED@@" => data.tuple_variant(2, TagInner),
187+
"@@SIMPLETYPE@@" => data.tuple_variant(1, SimpleTypeInner),
188+
_ => panic!("Implementation error"),
189+
}
168190
}
169191
}
170192

@@ -218,6 +240,7 @@ impl<'a> Deserializer<&'a Value> {
218240
.map(|x| x ^ !0)
219241
.map_err(|_| err())
220242
.and_then(|x| x.try_into().map_err(|_| err()))?,
243+
Value::Simple(x) => i128::from(*x).try_into().map_err(|_| err())?,
221244
_ => return Err(de::Error::invalid_type(self.0.into(), &"(big)int")),
222245
})
223246
}
@@ -228,13 +251,22 @@ impl<'a, 'de> de::Deserializer<'de> for Deserializer<&'a Value> {
228251

229252
#[inline]
230253
fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
254+
use serde::ser::Error as _;
231255
match self.0 {
232256
Value::Bytes(x) => visitor.visit_bytes(x),
233257
Value::Text(x) => visitor.visit_str(x),
234258
Value::Array(x) => visitor.visit_seq(Deserializer(x.iter())),
235259
Value::Map(x) => visitor.visit_map(Deserializer(x.iter().peekable())),
236260
Value::Bool(x) => visitor.visit_bool(*x),
237261
Value::Null => visitor.visit_none(),
262+
Value::Simple(v @ simple::UNDEFINED) => {
263+
visitor.visit_enum(SimpleTypeAccess::new(self, *v))
264+
}
265+
Value::Simple(0..=31) => Err(Self::Error::custom("Unsupported simple type")),
266+
Value::Simple(v) => {
267+
let access = SimpleTypeAccess::new(self, *v);
268+
visitor.visit_enum(access)
269+
}
238270

239271
Value::Tag(t, v) => {
240272
let parent: Deserializer<&Value> = Deserializer(v);
@@ -493,6 +525,18 @@ impl<'a, 'de> de::Deserializer<'de> for Deserializer<&'a Value> {
493525
let parent: Deserializer<&Value> = Deserializer(val);
494526
let access = TagAccess::new(parent, tag);
495527
return visitor.visit_enum(access);
528+
} else if name == "@@ST@@" {
529+
use serde::ser::Error as _;
530+
return match self.0 {
531+
Value::Simple(v @ simple::UNDEFINED) => {
532+
visitor.visit_enum(SimpleTypeAccess::new(Deserializer(self.0), *v))
533+
}
534+
Value::Simple(0..=31) => return Err(Error::custom("Unsupported simple type")),
535+
Value::Simple(v) => {
536+
visitor.visit_enum(SimpleTypeAccess::new(Deserializer(self.0), *v))
537+
}
538+
_ => Err(Error::custom("Implementation error for simple type")),
539+
};
496540
}
497541

498542
match self.0 {

0 commit comments

Comments
 (0)