use crate::cbor::{CborDecoder, CborEncoder};
use crate::error::{Error, Result};
#[cfg(feature = "alloc")]
use crate::types::CborMajorType;
#[cfg(feature = "alloc")]
use alloc::{borrow::ToOwned, boxed::Box, collections::BTreeMap, string::String, vec, vec::Vec};
use core::str;
pub trait CborSerialize {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()>;
}
pub trait CborDeserialize<'de>: Sized {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self>;
}
pub struct CborSerializer<'a> {
encoder: CborEncoder<'a>,
}
impl<'a> CborSerializer<'a> {
pub fn new(out: &'a mut [u8]) -> Self {
Self {
encoder: CborEncoder::new(out),
}
}
pub fn as_written(&self) -> &[u8] {
self.encoder.as_written()
}
pub fn len(&self) -> usize {
self.encoder.len()
}
pub fn is_empty(&self) -> bool {
self.encoder.is_empty()
}
pub fn encoder_mut(&mut self) -> &mut CborEncoder<'a> {
&mut self.encoder
}
pub fn null(&mut self) -> Result<()> {
self.encoder.encode_null()
}
pub fn bool(&mut self, value: bool) -> Result<()> {
if value {
self.encoder.encode_true()
} else {
self.encoder.encode_false()
}
}
pub fn u64(&mut self, value: u64) -> Result<()> {
self.encoder.encode_u64(value)
}
pub fn i64(&mut self, value: i64) -> Result<()> {
self.encoder.encode_i64(value)
}
pub fn bytes(&mut self, value: &[u8]) -> Result<()> {
self.encoder.encode_bstr(value)
}
pub fn str(&mut self, value: &str) -> Result<()> {
self.encoder.encode_tstr(value)
}
pub fn array(&mut self, len: usize) -> Result<()> {
self.encoder.encode_array_start(len)
}
pub fn map(&mut self, len: usize) -> Result<()> {
self.encoder.encode_map_start(len)
}
pub fn tag(&mut self, tag: u64) -> Result<()> {
self.encoder.encode_tag(tag)
}
pub fn sequence<I, T>(&mut self, values: I) -> Result<()>
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
T: CborSerialize,
{
let values = values.into_iter();
self.array(values.len())?;
for value in values {
value.serialize(self)?;
}
Ok(())
}
pub fn map_entries<I, K, V>(&mut self, entries: I) -> Result<()>
where
I: IntoIterator<Item = (K, V)>,
I::IntoIter: ExactSizeIterator,
K: CborSerialize,
V: CborSerialize,
{
let entries = entries.into_iter();
self.map(entries.len())?;
for (key, value) in entries {
key.serialize(self)?;
value.serialize(self)?;
}
Ok(())
}
}
pub struct CborDeserializer<'de> {
decoder: CborDecoder<'de>,
}
impl<'de> CborDeserializer<'de> {
pub fn new(input: &'de [u8]) -> Self {
Self {
decoder: CborDecoder::new(input),
}
}
pub fn position(&self) -> usize {
self.decoder.position()
}
pub fn is_finished(&self) -> bool {
self.decoder.is_finished()
}
pub fn decoder_mut(&mut self) -> &mut CborDecoder<'de> {
&mut self.decoder
}
pub fn null(&mut self) -> Result<()> {
self.decoder.decode_null()
}
pub fn bool(&mut self) -> Result<bool> {
self.decoder.decode_bool()
}
pub fn u64(&mut self) -> Result<u64> {
self.decoder.decode_u64()
}
pub fn i64(&mut self) -> Result<i64> {
self.decoder.decode_i64()
}
pub fn bytes(&mut self) -> Result<&'de [u8]> {
self.decoder.decode_bstr()
}
pub fn str(&mut self) -> Result<&'de str> {
str::from_utf8(self.decoder.decode_tstr_bytes()?).map_err(|_| Error::CborMalformed)
}
pub fn array(&mut self) -> Result<usize> {
self.decoder.decode_array_start()
}
pub fn map(&mut self) -> Result<usize> {
self.decoder.decode_map_start()
}
pub fn tag(&mut self) -> Result<u64> {
self.decoder.decode_tag()
}
#[cfg(feature = "alloc")]
pub fn array_values<T>(&mut self) -> Result<Vec<T>>
where
T: CborDeserialize<'de>,
{
let len = self.array()?;
let mut values = Vec::with_capacity(len);
for _ in 0..len {
values.push(T::deserialize(self)?);
}
Ok(values)
}
#[cfg(feature = "alloc")]
pub fn map_values<K, V>(&mut self) -> Result<Vec<(K, V)>>
where
K: CborDeserialize<'de>,
V: CborDeserialize<'de>,
{
let len = self.map()?;
let mut values = Vec::with_capacity(len);
for _ in 0..len {
values.push((K::deserialize(self)?, V::deserialize(self)?));
}
Ok(values)
}
pub fn borrowed_bytes(&mut self) -> Result<&'de [u8]> {
self.bytes()
}
pub fn borrowed_str(&mut self) -> Result<&'de str> {
self.str()
}
}
pub fn to_slice<'out, T: CborSerialize + ?Sized>(
value: &T,
out: &'out mut [u8],
) -> Result<&'out [u8]> {
let mut serializer = CborSerializer::new(out);
value.serialize(&mut serializer)?;
let len = serializer.len();
Ok(&out[..len])
}
#[cfg(feature = "alloc")]
pub fn to_vec<T: CborSerialize + ?Sized>(value: &T) -> Result<Vec<u8>> {
let mut size = 256;
loop {
let mut out = vec![0; size];
match to_slice(value, &mut out) {
Ok(slice) => {
let len = slice.len();
out.truncate(len);
return Ok(out);
}
Err(Error::BufferTooSmall) if size < 16 * 1024 * 1024 => size *= 2,
Err(err) => return Err(err),
}
}
}
pub fn from_slice<'de, T: CborDeserialize<'de>>(input: &'de [u8]) -> Result<T> {
let mut deserializer = CborDeserializer::new(input);
let value = T::deserialize(&mut deserializer)?;
if deserializer.is_finished() {
Ok(value)
} else {
Err(Error::CborMalformed)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ByteStr<'a>(pub &'a [u8]);
impl<'a> ByteStr<'a> {
pub fn as_bytes(self) -> &'a [u8] {
self.0
}
}
#[cfg(feature = "alloc")]
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ByteBuf(pub Vec<u8>);
#[cfg(feature = "alloc")]
impl ByteBuf {
pub fn into_vec(self) -> Vec<u8> {
self.0
}
}
#[cfg(feature = "alloc")]
#[derive(Clone, Debug, PartialEq)]
pub enum CborValue {
Null,
Bool(bool),
Unsigned(u64),
Integer(i64),
Bytes(Vec<u8>),
Text(String),
Array(Vec<CborValue>),
Map(Vec<(CborValue, CborValue)>),
Tag(u64, Box<CborValue>),
}
#[cfg(feature = "alloc")]
impl CborSerialize for CborValue {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
match self {
Self::Null => serializer.null(),
Self::Bool(value) => serializer.bool(*value),
Self::Unsigned(value) => serializer.u64(*value),
Self::Integer(value) => serializer.i64(*value),
Self::Bytes(value) => serializer.bytes(value),
Self::Text(value) => serializer.str(value),
Self::Array(values) => {
serializer.array(values.len())?;
for value in values {
value.serialize(serializer)?;
}
Ok(())
}
Self::Map(entries) => {
serializer.map(entries.len())?;
for (key, value) in entries {
key.serialize(serializer)?;
value.serialize(serializer)?;
}
Ok(())
}
Self::Tag(tag, value) => {
serializer.tag(*tag)?;
value.serialize(serializer)
}
}
}
}
#[cfg(feature = "alloc")]
impl<'de> CborDeserialize<'de> for CborValue {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
let major = deserializer
.decoder
.peek_type()
.ok_or(Error::CborMalformed)?;
if major == CborMajorType::UINT {
return Ok(Self::Unsigned(deserializer.u64()?));
}
if major == CborMajorType::NEGATIVE_INT {
return Ok(Self::Integer(deserializer.i64()?));
}
if major == CborMajorType::BYTES {
return Ok(Self::Bytes(deserializer.bytes()?.to_vec()));
}
if major == CborMajorType::TEXT {
return Ok(Self::Text(deserializer.str()?.to_owned()));
}
if major == CborMajorType::ARRAY {
let len = deserializer.array()?;
let mut values = Vec::with_capacity(len);
for _ in 0..len {
values.push(Self::deserialize(deserializer)?);
}
return Ok(Self::Array(values));
}
if major == CborMajorType::MAP {
let len = deserializer.map()?;
let mut entries = Vec::with_capacity(len);
for _ in 0..len {
let key = Self::deserialize(deserializer)?;
let value = Self::deserialize(deserializer)?;
entries.push((key, value));
}
return Ok(Self::Map(entries));
}
if major == CborMajorType::TAG {
let tag = deserializer.tag()?;
let value = Self::deserialize(deserializer)?;
return Ok(Self::Tag(tag, Box::new(value)));
}
let item = deserializer.decoder.decode_head()?;
match item.value {
value if value == simple_value(crate::raw::WOLFCOSE_CBOR_NULL) => Ok(Self::Null),
value if value == simple_value(crate::raw::WOLFCOSE_CBOR_TRUE) => Ok(Self::Bool(true)),
value if value == simple_value(crate::raw::WOLFCOSE_CBOR_FALSE) => {
Ok(Self::Bool(false))
}
_ => Err(Error::CborType),
}
}
}
impl CborSerialize for () {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.null()
}
}
impl<'de> CborDeserialize<'de> for () {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
deserializer.null()
}
}
impl CborSerialize for bool {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.bool(*self)
}
}
impl<'de> CborDeserialize<'de> for bool {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
deserializer.bool()
}
}
macro_rules! impl_unsigned {
($($ty:ty),* $(,)?) => {
$(
impl CborSerialize for $ty {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.u64((*self).into())
}
}
impl<'de> CborDeserialize<'de> for $ty {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
deserializer.u64()?.try_into().map_err(|_| Error::CborOverflow)
}
}
)*
};
}
impl_unsigned!(u8, u16, u32, u64);
impl CborSerialize for usize {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.u64((*self).try_into().map_err(|_| Error::CborOverflow)?)
}
}
impl<'de> CborDeserialize<'de> for usize {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
deserializer
.u64()?
.try_into()
.map_err(|_| Error::CborOverflow)
}
}
macro_rules! impl_signed {
($($ty:ty),* $(,)?) => {
$(
impl CborSerialize for $ty {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.i64((*self).into())
}
}
impl<'de> CborDeserialize<'de> for $ty {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
deserializer.i64()?.try_into().map_err(|_| Error::CborOverflow)
}
}
)*
};
}
impl_signed!(i8, i16, i32, i64);
impl CborSerialize for isize {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.i64((*self).try_into().map_err(|_| Error::CborOverflow)?)
}
}
impl<'de> CborDeserialize<'de> for isize {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
deserializer
.i64()?
.try_into()
.map_err(|_| Error::CborOverflow)
}
}
impl CborSerialize for str {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.str(self)
}
}
#[cfg(feature = "alloc")]
impl CborSerialize for String {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.str(self)
}
}
impl<'de> CborDeserialize<'de> for &'de str {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
deserializer.str()
}
}
#[cfg(feature = "alloc")]
impl<'de> CborDeserialize<'de> for String {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
Ok(deserializer.str()?.to_owned())
}
}
impl<'a> CborSerialize for ByteStr<'a> {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.bytes(self.0)
}
}
#[cfg(feature = "alloc")]
impl CborSerialize for ByteBuf {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.bytes(&self.0)
}
}
impl<'de> CborDeserialize<'de> for &'de [u8] {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
deserializer.bytes()
}
}
#[cfg(feature = "alloc")]
impl<'de> CborDeserialize<'de> for ByteBuf {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
Ok(Self(deserializer.bytes()?.to_vec()))
}
}
impl<T: CborSerialize + ?Sized> CborSerialize for &T {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
(*self).serialize(serializer)
}
}
impl<T: CborSerialize> CborSerialize for Option<T> {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
match self {
Some(value) => value.serialize(serializer),
None => serializer.null(),
}
}
}
impl<'de, T: CborDeserialize<'de>> CborDeserialize<'de> for Option<T> {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
if deserializer.decoder.peek_initial_byte() == Some(crate::raw::WOLFCOSE_CBOR_NULL as u8) {
deserializer.null()?;
Ok(None)
} else {
T::deserialize(deserializer).map(Some)
}
}
}
impl<T: CborSerialize> CborSerialize for [T] {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.array(self.len())?;
for value in self {
value.serialize(serializer)?;
}
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<T: CborSerialize> CborSerialize for Vec<T> {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
self.as_slice().serialize(serializer)
}
}
#[cfg(feature = "alloc")]
impl<'de, T: CborDeserialize<'de>> CborDeserialize<'de> for Vec<T> {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
let len = deserializer.array()?;
let mut values = Vec::with_capacity(len);
for _ in 0..len {
values.push(T::deserialize(deserializer)?);
}
Ok(values)
}
}
impl<T: CborSerialize, const N: usize> CborSerialize for [T; N] {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
self.as_slice().serialize(serializer)
}
}
#[cfg(feature = "alloc")]
impl<'de, T: CborDeserialize<'de>, const N: usize> CborDeserialize<'de> for [T; N] {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
let values = Vec::<T>::deserialize(deserializer)?;
values.try_into().map_err(|_| Error::CborMalformed)
}
}
#[cfg(feature = "alloc")]
impl<K: CborSerialize, V: CborSerialize> CborSerialize for BTreeMap<K, V> {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.map(self.len())?;
for (key, value) in self {
key.serialize(serializer)?;
value.serialize(serializer)?;
}
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<'de, K, V> CborDeserialize<'de> for BTreeMap<K, V>
where
K: CborDeserialize<'de> + Ord,
V: CborDeserialize<'de>,
{
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
let len = deserializer.map()?;
let mut map = BTreeMap::new();
for _ in 0..len {
let key = K::deserialize(deserializer)?;
let value = V::deserialize(deserializer)?;
map.insert(key, value);
}
Ok(map)
}
}
macro_rules! tuple_impl {
($($name:ident : $idx:tt),+ $(,)?) => {
impl<$($name: CborSerialize),+> CborSerialize for ($($name,)+) {
fn serialize(&self, serializer: &mut CborSerializer<'_>) -> Result<()> {
serializer.array(tuple_impl!(@count $($name),+))?;
$(self.$idx.serialize(serializer)?;)+
Ok(())
}
}
impl<'de, $($name: CborDeserialize<'de>),+> CborDeserialize<'de> for ($($name,)+) {
fn deserialize(deserializer: &mut CborDeserializer<'de>) -> Result<Self> {
let len = deserializer.array()?;
if len != tuple_impl!(@count $($name),+) {
return Err(Error::CborMalformed);
}
Ok(($($name::deserialize(deserializer)?,)+))
}
}
};
(@count $head:ident $(,$tail:ident)*) => {
1usize $(+ { let _ = stringify!($tail); 1usize })*
};
}
tuple_impl!(A: 0);
tuple_impl!(A: 0, B: 1);
tuple_impl!(A: 0, B: 1, C: 2);
tuple_impl!(A: 0, B: 1, C: 2, D: 3);
tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4);
tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5);
#[cfg(feature = "alloc")]
fn simple_value(initial_byte: u32) -> u64 {
(initial_byte & 0x1f) as u64
}