use crate::error::{DeserializeError, DeserializeFailure};
use cbor_event::{de::Deserializer, se::Serializer, Sz};
use std::io::{BufRead, Seek, Write};
pub struct CBORReadLen {
deser_len: cbor_event::LenSz,
read: u64,
}
impl CBORReadLen {
pub fn new(len: cbor_event::LenSz) -> Self {
Self {
deser_len: len,
read: 0,
}
}
pub fn read(&self) -> u64 {
self.read
}
pub fn read_elems(&mut self, count: usize) -> Result<(), DeserializeFailure> {
match self.deser_len {
cbor_event::LenSz::Len(n, _) => {
self.read += count as u64;
if self.read > n {
Err(DeserializeFailure::DefiniteLenMismatch(n, None))
} else {
Ok(())
}
}
cbor_event::LenSz::Indefinite => Ok(()),
}
}
pub fn finish(&self) -> Result<(), DeserializeFailure> {
match self.deser_len {
cbor_event::LenSz::Len(n, _) => {
if self.read == n {
Ok(())
} else {
Err(DeserializeFailure::DefiniteLenMismatch(n, Some(self.read)))
}
}
cbor_event::LenSz::Indefinite => Ok(()),
}
}
}
impl From<cbor_event::Len> for CBORReadLen {
fn from(len: cbor_event::Len) -> Self {
Self::new(len_to_len_sz(len))
}
}
pub fn len_to_len_sz(len: cbor_event::Len) -> cbor_event::LenSz {
match len {
cbor_event::Len::Len(n) => cbor_event::LenSz::Len(n, fit_sz(n, None, true)),
cbor_event::Len::Indefinite => cbor_event::LenSz::Indefinite,
}
}
pub trait DeserializeEmbeddedGroup {
fn deserialize_as_embedded_group<R: BufRead + Seek>(
raw: &mut Deserializer<R>,
read_len: &mut CBORReadLen,
len: cbor_event::LenSz,
) -> Result<Self, DeserializeError>
where
Self: Sized;
}
#[inline]
pub fn sz_max(sz: cbor_event::Sz) -> u64 {
match sz {
Sz::Inline => 23u64,
Sz::One => u8::MAX as u64,
Sz::Two => u16::MAX as u64,
Sz::Four => u32::MAX as u64,
Sz::Eight => u64::MAX,
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum LenEncoding {
Canonical,
Definite(cbor_event::Sz),
Indefinite,
}
impl Default for LenEncoding {
fn default() -> Self {
Self::Canonical
}
}
impl From<cbor_event::LenSz> for LenEncoding {
fn from(len_sz: cbor_event::LenSz) -> Self {
match len_sz {
cbor_event::LenSz::Len(len, sz) => {
if cbor_event::Sz::canonical(len) == sz {
Self::Canonical
} else {
Self::Definite(sz)
}
}
cbor_event::LenSz::Indefinite => Self::Indefinite,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum StringEncoding {
Canonical,
Indefinite(Vec<(u64, Sz)>),
Definite(Sz),
}
impl Default for StringEncoding {
fn default() -> Self {
Self::Canonical
}
}
impl From<cbor_event::StringLenSz> for StringEncoding {
fn from(len_sz: cbor_event::StringLenSz) -> Self {
match len_sz {
cbor_event::StringLenSz::Len(sz) => Self::Definite(sz),
cbor_event::StringLenSz::Indefinite(lens) => Self::Indefinite(lens),
}
}
}
#[inline]
pub fn fit_sz(len: u64, sz: Option<cbor_event::Sz>, force_canonical: bool) -> Sz {
match sz {
Some(sz) => {
if !force_canonical && len <= sz_max(sz) {
sz
} else {
Sz::canonical(len)
}
}
None => Sz::canonical(len),
}
}
impl LenEncoding {
pub fn to_len_sz(&self, len: u64, force_canonical: bool) -> cbor_event::LenSz {
if force_canonical {
cbor_event::LenSz::Len(len, cbor_event::Sz::canonical(len))
} else {
match self {
Self::Canonical => cbor_event::LenSz::Len(len, cbor_event::Sz::canonical(len)),
Self::Definite(sz) => {
if sz_max(*sz) >= len {
cbor_event::LenSz::Len(len, *sz)
} else {
cbor_event::LenSz::Len(len, cbor_event::Sz::canonical(len))
}
}
Self::Indefinite => cbor_event::LenSz::Indefinite,
}
}
}
pub fn end<'a, W: Write + Sized>(
&self,
serializer: &'a mut Serializer<W>,
force_canonical: bool,
) -> cbor_event::Result<&'a mut Serializer<W>> {
if !force_canonical && *self == Self::Indefinite {
serializer.write_special(cbor_event::Special::Break)?;
}
Ok(serializer)
}
}
impl StringEncoding {
pub fn to_str_len_sz(&self, len: u64, force_canonical: bool) -> cbor_event::StringLenSz {
if force_canonical {
cbor_event::StringLenSz::Len(cbor_event::Sz::canonical(len))
} else {
match self {
Self::Canonical => cbor_event::StringLenSz::Len(cbor_event::Sz::canonical(len)),
Self::Definite(sz) => {
if sz_max(*sz) >= len {
cbor_event::StringLenSz::Len(*sz)
} else {
cbor_event::StringLenSz::Len(cbor_event::Sz::canonical(len))
}
}
Self::Indefinite(lens) => cbor_event::StringLenSz::Indefinite(lens.clone()),
}
}
}
}
pub trait Serialize {
fn serialize<'a, W: Write + Sized>(
&self,
serializer: &'a mut Serializer<W>,
force_canonical: bool,
) -> cbor_event::Result<&'a mut Serializer<W>>;
fn to_cbor_bytes(&self) -> Vec<u8> {
let mut buf = Serializer::new_vec();
self.serialize(&mut buf, false).unwrap();
buf.finalize()
}
fn to_canonical_cbor_bytes(&self) -> Vec<u8> {
let mut buf = Serializer::new_vec();
self.serialize(&mut buf, true).unwrap();
buf.finalize()
}
}
pub trait SerializeEmbeddedGroup {
fn serialize_as_embedded_group<'a, W: Write + Sized>(
&self,
serializer: &'a mut Serializer<W>,
force_canonical: bool,
) -> cbor_event::Result<&'a mut Serializer<W>>;
}
pub trait Deserialize {
fn deserialize<R: BufRead + Seek>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError>
where
Self: Sized;
fn from_cbor_bytes(data: &[u8]) -> Result<Self, DeserializeError>
where
Self: Sized,
{
let mut raw = Deserializer::from(std::io::Cursor::new(data));
Self::deserialize(&mut raw)
}
}
pub trait ToBytes {
fn to_bytes(&self) -> Vec<u8>;
}
impl<T: cbor_event::se::Serialize> ToBytes for T {
fn to_bytes(&self) -> Vec<u8> {
let mut buf = Serializer::new_vec();
self.serialize(&mut buf).unwrap();
buf.finalize()
}
}
pub trait FromBytes {
fn from_bytes(data: Vec<u8>) -> Result<Self, DeserializeError>
where
Self: Sized;
}
impl<T: Deserialize> FromBytes for T {
fn from_bytes(data: Vec<u8>) -> Result<Self, DeserializeError>
where
Self: Sized,
{
let mut raw = Deserializer::from(std::io::Cursor::new(data));
Self::deserialize(&mut raw).map_err(Into::into)
}
}
pub trait RawBytesEncoding {
fn to_raw_bytes(&self) -> &[u8];
fn from_raw_bytes(bytes: &[u8]) -> Result<Self, DeserializeError>
where
Self: Sized;
fn to_raw_hex(&self) -> String {
hex::encode(self.to_raw_bytes())
}
fn from_raw_hex(hex_str: &str) -> Result<Self, DeserializeError>
where
Self: Sized,
{
let bytes = hex::decode(hex_str).map_err(|e| {
DeserializeError::from(DeserializeFailure::InvalidStructure(Box::new(e)))
})?;
Self::from_raw_bytes(bytes.as_ref())
}
}