#[cfg(feature = "timestamp")]
pub mod timestamp;
use crate::encode::{Binary, Error, SerializeIntoSlice};
#[allow(unused_imports)]
use crate::marker::Marker;
#[allow(unused_imports)]
use byteorder::{BigEndian, ByteOrder};
use core::{convert::TryInto, fmt::Display, marker::PhantomData};
use serde::{ser::SerializeStruct, Deserialize, Serialize};
#[repr(transparent)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
struct ExtType(i8);
impl core::fmt::Debug for ExtType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("ExtType").field(&self.0).finish()
}
}
impl Display for ExtType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.0 == -1 {
f.write_str("-1 (Timestamp)")
} else {
write!(f, "{}", self.0)
}
}
}
#[derive(PartialEq, Eq)]
pub struct Ext<'a> {
typ: ExtType,
data: Binary<'a>,
}
impl<'a> core::fmt::Debug for Ext<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Ext").field("typ", &self.typ).field("data", &self.data).finish()
}
}
impl<'a> Ext<'a> {
pub const fn new_from_binary(typ: i8, data: Binary<'a>) -> Self {
Ext { typ: ExtType(typ), data }
}
pub const fn new(typ: i8, data: &'a [u8]) -> Self {
Ext {
typ: ExtType(typ),
data: Binary::new(data),
}
}
#[inline(always)]
pub const fn get_type(&self) -> i8 {
self.typ.0
}
#[inline(always)]
pub const fn get_data(&self) -> &Binary<'a> {
&self.data
}
}
#[inline]
pub(crate) fn get_ext_start(data_len: usize) -> Result<(Marker, usize), Error> {
let (marker, header_len) = match data_len {
#[cfg(feature = "fixext")]
1 | 2 | 4 | 8 | 16 => {
let header_len = 2;
let marker = match data_len {
1 => Marker::FixExt1,
2 => Marker::FixExt2,
4 => Marker::FixExt4,
8 => Marker::FixExt8,
16 => Marker::FixExt16,
_ => unreachable!(),
};
(marker, header_len)
}
#[cfg(feature = "ext8")]
0..=0xff => (Marker::Ext8, 3),
#[cfg(feature = "ext16")]
0x100..=0xffff => (Marker::Ext16, 4),
#[cfg(feature = "ext32")]
0x1_0000..=0xffff_ffff => (Marker::Ext32, 6),
_ => return Err(Error::OutOfBounds),
};
Ok((marker, header_len))
}
pub(crate) fn read_ext_len<B: zerocopy::ByteSlice>(buf: B) -> Result<(usize, usize), crate::decode::Error> {
if buf.len() < 2 {
return Err(crate::decode::Error::EndOfBuffer(Marker::Ext8));
}
let marker: Marker = buf[0].try_into().unwrap();
let (header_len, data_len) = match marker {
#[cfg(feature = "fixext")]
Marker::FixExt1 => (2, 1),
#[cfg(feature = "fixext")]
Marker::FixExt2 => (2, 2),
#[cfg(feature = "fixext")]
Marker::FixExt4 => (2, 4),
#[cfg(feature = "fixext")]
Marker::FixExt8 => (2, 8),
#[cfg(feature = "fixext")]
Marker::FixExt16 => (2, 16),
#[cfg(feature = "ext8")]
Marker::Ext8 => (3, buf[1] as usize),
#[cfg(feature = "ext16")]
Marker::Ext16 => {
if buf.len() < 4 {
return Err(crate::decode::Error::EndOfBuffer(Marker::Ext16));
}
(4, BigEndian::read_u16(&buf[1..3]) as usize)
}
#[cfg(feature = "ext32")]
Marker::Ext32 => {
if buf.len() < 6 {
return Err(crate::decode::Error::EndOfBuffer(Marker::Ext32));
}
(6, BigEndian::read_u32(&buf[1..5]) as usize)
}
_ => return Err(crate::decode::Error::InvalidType),
};
if buf.len() >= header_len + data_len {
Ok((header_len, data_len))
} else {
Err(crate::decode::Error::EndOfBuffer(Marker::Ext8))
}
}
pub fn serialize_ext(value: &Ext<'_>, buf: &mut [u8]) -> Result<usize, Error> {
let typ = value.get_type();
let data = value.get_data();
let (marker, header_len) = get_ext_start(data.len())?;
if buf.len() < data.len() + header_len {
return Err(Error::EndOfBuffer);
}
buf[0] = marker.to_u8();
if header_len > 2 {
#[cfg(all(feature = "ext8", not(any(feature = "ext16", feature = "ext32"))))]
{
buf[1] = data.len() as u8;
}
#[cfg(any(feature = "ext16", feature = "ext32"))]
{
BigEndian::write_uint(&mut buf[1..], data.len() as u64, header_len - 2);
}
}
buf[header_len - 1] = typ as u8;
buf[header_len..data.len() + header_len].clone_from_slice(data);
Ok(data.len() + header_len)
}
pub fn try_deserialize_ext(buf: &[u8]) -> Result<Ext<'_>, crate::decode::Error> {
if buf.len() < 3 {
return Err(crate::decode::Error::EndOfBuffer(Marker::Ext8));
}
let (header_len, data_len) = read_ext_len(buf)?;
if buf.len() < header_len + data_len {
return Err(crate::decode::Error::EndOfBuffer(Marker::Ext8));
}
let typ = buf[header_len - 1] as i8;
return Ok(Ext::new(typ, &buf[header_len..header_len + data_len]));
}
impl<'a> SerializeIntoSlice for &Ext<'a> {
fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> {
serialize_ext(self, buf)
}
}
pub(crate) const TYPE_NAME: &str = "$Ext";
pub(crate) const FIELD_TYPE_NAME: &str = "type";
pub(crate) const FIELD_DATA_NAME: &str = "data";
#[cfg(feature = "serde")]
impl<'a> ::serde::ser::Serialize for Ext<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut s = serializer.serialize_struct(TYPE_NAME, 2)?;
s.serialize_field(FIELD_TYPE_NAME, &self.typ)?;
s.serialize_field(FIELD_DATA_NAME, &self.data)?;
s.end()
}
}
#[cfg(feature = "serde")]
impl<'de: 'a, 'a> ::serde::de::Deserialize<'de> for Ext<'a> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: ::serde::de::Deserializer<'de>,
{
struct ExtVisitor<'a>(PhantomData<&'a ()>);
impl<'de: 'a, 'a> ::serde::de::Visitor<'de> for ExtVisitor<'a> {
type Value = Ext<'a>;
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str("a MsgPack ext data")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let typ: Option<ExtType> = seq.next_element()?;
let data: Option<Binary> = seq.next_element()?;
match (typ, data) {
(Some(typ), Some(data)) => Ok(Ext::new_from_binary(typ.0, data)),
(Some(_), None) => Err(::serde::de::Error::custom("ext data not found")),
_ => Err(::serde::de::Error::custom("ext type field not found")),
}
}
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where
V: ::serde::de::MapAccess<'de>,
{
enum Field {
Type,
Data,
}
impl<'de> ::serde::de::Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> ::serde::de::Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("`type` or `data`")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
match v {
"type" => Ok(Field::Type),
"data" => Ok(Field::Data),
_ => Err(::serde::de::Error::unknown_field(
v,
&["type", "data"],
)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
let mut typ = None;
let mut data = None;
loop {
match map.next_key::<Field>() {
Ok(Some(Field::Type)) => typ = Some(map.next_value::<ExtType>()?),
Ok(Some(Field::Data)) => data = Some(map.next_value::<Binary>()?),
Ok(None) => break, Err(_e) => {
map.next_value()?;
}
}
}
match (typ, data) {
(Some(typ), Some(data)) => Ok(Ext::new_from_binary(typ.0, data)),
(Some(_), None) => Err(::serde::de::Error::custom("ext data not found")),
_ => Err(::serde::de::Error::custom("ext type field not found")),
}
}
}
static FIELDS: [&str; 2] = [FIELD_TYPE_NAME, FIELD_DATA_NAME];
deserializer.deserialize_struct(TYPE_NAME, &FIELDS, ExtVisitor(PhantomData))
}
}