#![allow(dead_code)]
use std::fmt;
use serde::de::{
self, DeserializeOwned, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum LegacyBincodeError {
Eof,
TrailingBytes,
InvalidValue(String),
LengthOverflow,
InvalidUtf8,
Message(String),
}
impl fmt::Display for LegacyBincodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Eof => write!(f, "unexpected end of input while decoding legacy bincode"),
Self::TrailingBytes => write!(f, "trailing bytes after decoding legacy bincode value"),
Self::InvalidValue(m) => write!(f, "invalid legacy bincode value: {m}"),
Self::LengthOverflow => write!(f, "legacy bincode length prefix exceeds input"),
Self::InvalidUtf8 => write!(f, "invalid UTF-8 in legacy bincode value"),
Self::Message(m) => write!(f, "legacy bincode decode error: {m}"),
}
}
}
impl std::error::Error for LegacyBincodeError {}
impl de::Error for LegacyBincodeError {
fn custom<T: fmt::Display>(msg: T) -> Self {
Self::Message(msg.to_string())
}
}
type Result<T> = std::result::Result<T, LegacyBincodeError>;
pub(crate) fn decode<T: DeserializeOwned>(bytes: &[u8]) -> Result<T> {
let mut de = LegacyDeserializer::new(bytes);
let value = T::deserialize(&mut de)?;
if de.input.is_empty() {
Ok(value)
} else {
Err(LegacyBincodeError::TrailingBytes)
}
}
struct LegacyDeserializer<'de> {
input: &'de [u8],
}
impl<'de> LegacyDeserializer<'de> {
fn new(input: &'de [u8]) -> Self {
Self { input }
}
fn take(&mut self, n: usize) -> Result<&'de [u8]> {
if self.input.len() < n {
return Err(LegacyBincodeError::Eof);
}
let (head, tail) = self.input.split_at(n);
self.input = tail;
Ok(head)
}
fn read_u8(&mut self) -> Result<u8> {
Ok(self.take(1)?[0])
}
fn read_u16(&mut self) -> Result<u16> {
let b = self.take(2)?;
Ok(u16::from_le_bytes([b[0], b[1]]))
}
fn read_u32(&mut self) -> Result<u32> {
let b = self.take(4)?;
Ok(u32::from_le_bytes([b[0], b[1], b[2], b[3]]))
}
fn read_u64(&mut self) -> Result<u64> {
let b = self.take(8)?;
Ok(u64::from_le_bytes([
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
]))
}
fn read_len(&mut self) -> Result<usize> {
let len = self.read_u64()?;
let len = usize::try_from(len).map_err(|_| LegacyBincodeError::LengthOverflow)?;
if len > self.input.len() {
return Err(LegacyBincodeError::LengthOverflow);
}
Ok(len)
}
}
impl<'de> de::Deserializer<'de> for &mut LegacyDeserializer<'de> {
type Error = LegacyBincodeError;
fn deserialize_any<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
Err(LegacyBincodeError::Message(
"legacy bincode is not self-describing; deserialize_any is unsupported".into(),
))
}
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.read_u8()? {
0 => visitor.visit_bool(false),
1 => visitor.visit_bool(true),
n => Err(LegacyBincodeError::InvalidValue(format!("bool byte {n}"))),
}
}
fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_i8(self.read_u8()? as i8)
}
fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_i16(self.read_u16()? as i16)
}
fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_i32(self.read_u32()? as i32)
}
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_i64(self.read_u64()? as i64)
}
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_u8(self.read_u8()?)
}
fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_u16(self.read_u16()?)
}
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_u32(self.read_u32()?)
}
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_u64(self.read_u64()?)
}
fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_f32(f32::from_bits(self.read_u32()?))
}
fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_f64(f64::from_bits(self.read_u64()?))
}
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let code = self.read_u32()?;
let c = char::from_u32(code)
.ok_or_else(|| LegacyBincodeError::InvalidValue(format!("char code {code}")))?;
visitor.visit_char(c)
}
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let len = self.read_len()?;
let bytes = self.take(len)?;
let s = std::str::from_utf8(bytes).map_err(|_| LegacyBincodeError::InvalidUtf8)?;
visitor.visit_borrowed_str(s)
}
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_str(visitor)
}
fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let len = self.read_len()?;
let bytes = self.take(len)?;
visitor.visit_borrowed_bytes(bytes)
}
fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
self.deserialize_bytes(visitor)
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
match self.read_u8()? {
0 => visitor.visit_none(),
1 => visitor.visit_some(self),
n => Err(LegacyBincodeError::InvalidValue(format!("option tag {n}"))),
}
}
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_unit()
}
fn deserialize_unit_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value> {
visitor.visit_unit()
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value> {
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let len = self.read_len()?;
visitor.visit_seq(CountedAccess::new(self, len))
}
fn deserialize_tuple<V: Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
visitor.visit_seq(CountedAccess::new(self, len))
}
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value> {
visitor.visit_seq(CountedAccess::new(self, len))
}
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let len = self.read_len()?;
visitor.visit_map(CountedAccess::new(self, len))
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
visitor.visit_seq(CountedAccess::new(self, fields.len()))
}
fn deserialize_enum<V: Visitor<'de>>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
let variant_index = self.read_u32()?;
visitor.visit_enum(EnumDeserializer {
de: self,
variant_index,
})
}
fn deserialize_identifier<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
Err(LegacyBincodeError::Message(
"legacy bincode does not encode identifiers".into(),
))
}
fn deserialize_ignored_any<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
Err(LegacyBincodeError::Message(
"cannot skip unknown field in non-self-describing legacy bincode".into(),
))
}
fn is_human_readable(&self) -> bool {
false
}
}
struct CountedAccess<'a, 'de: 'a> {
de: &'a mut LegacyDeserializer<'de>,
remaining: usize,
}
impl<'a, 'de> CountedAccess<'a, 'de> {
fn new(de: &'a mut LegacyDeserializer<'de>, len: usize) -> Self {
Self { de, remaining: len }
}
}
impl<'de, 'a> SeqAccess<'de> for CountedAccess<'a, 'de> {
type Error = LegacyBincodeError;
fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>> {
if self.remaining == 0 {
return Ok(None);
}
self.remaining -= 1;
seed.deserialize(&mut *self.de).map(Some)
}
fn size_hint(&self) -> Option<usize> {
Some(self.remaining)
}
}
impl<'de, 'a> MapAccess<'de> for CountedAccess<'a, 'de> {
type Error = LegacyBincodeError;
fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
if self.remaining == 0 {
return Ok(None);
}
self.remaining -= 1;
seed.deserialize(&mut *self.de).map(Some)
}
fn next_value_seed<Vv: DeserializeSeed<'de>>(&mut self, seed: Vv) -> Result<Vv::Value> {
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> Option<usize> {
Some(self.remaining)
}
}
struct EnumDeserializer<'a, 'de: 'a> {
de: &'a mut LegacyDeserializer<'de>,
variant_index: u32,
}
impl<'de, 'a> EnumAccess<'de> for EnumDeserializer<'a, 'de> {
type Error = LegacyBincodeError;
type Variant = VariantDeserializer<'a, 'de>;
fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant)> {
let variant = seed.deserialize(self.variant_index.into_deserializer())?;
Ok((variant, VariantDeserializer { de: self.de }))
}
}
struct VariantDeserializer<'a, 'de: 'a> {
de: &'a mut LegacyDeserializer<'de>,
}
impl<'de, 'a> VariantAccess<'de> for VariantDeserializer<'a, 'de> {
type Error = LegacyBincodeError;
fn unit_variant(self) -> Result<()> {
Ok(())
}
fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
seed.deserialize(&mut *self.de)
}
fn tuple_variant<V: Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
visitor.visit_seq(CountedAccess::new(self.de, len))
}
fn struct_variant<V: Visitor<'de>>(
self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value> {
visitor.visit_seq(CountedAccess::new(self.de, fields.len()))
}
}
#[cfg(test)]
pub(crate) mod tests;