use alloc::{borrow::Cow, string::String};
use core::{convert::Infallible, marker::PhantomData, slice};
#[cfg(feature = "std")]
use std::io;
use serde_core::de::{self, Deserialize, DeserializeSeed};
use crate::{ArrayBufferViewTag, Error, SerializationTag, util::is_int};
trait Read<'de>
where
Error: From<Self::Error>
{
type Error;
fn next(&mut self) -> Result<Option<u8>, Self::Error>;
fn peek(&mut self) -> Result<Option<u8>, Self::Error>;
fn bytes(&mut self, len: u64) -> Result<Cow<'de, [u8]>, Error>;
fn bytes_into(&mut self, buf: &mut [u8]) -> Result<(), Error>;
fn discard(&mut self);
}
#[cfg(feature = "std")]
struct IoRead<R: io::Read> {
iter: io::Bytes<R>,
peeked_ch: Option<u8>
}
#[cfg(feature = "std")]
impl<'a, R: io::Read> Read<'a> for IoRead<R> {
type Error = io::Error;
#[inline]
fn next(&mut self) -> io::Result<Option<u8>> {
match self.peeked_ch.take() {
Some(ch) => Ok(Some(ch)),
None => match self.iter.next() {
Some(Err(err)) => Err(err),
Some(Ok(ch)) => Ok(Some(ch)),
None => Ok(None)
}
}
}
#[inline]
fn peek(&mut self) -> io::Result<Option<u8>> {
match self.peeked_ch {
Some(ch) => Ok(Some(ch)),
None => match self.iter.next() {
Some(Err(err)) => Err(err),
Some(Ok(ch)) => {
self.peeked_ch = Some(ch);
Ok(self.peeked_ch)
}
None => Ok(None)
}
}
}
#[inline]
fn discard(&mut self) {
self.peeked_ch = None;
}
#[inline]
fn bytes(&mut self, len: u64) -> Result<Cow<'a, [u8]>, Error> {
debug_assert!(self.peeked_ch.is_none(), "bytes shouldnt follow peek");
self.iter.by_ref().take(len as _).collect::<io::Result<_>>().map_err(Error::from)
}
fn bytes_into(&mut self, buf: &mut [u8]) -> Result<(), Error> {
debug_assert!(self.peeked_ch.is_none(), "bytes shouldnt follow peek");
for i in 0..buf.len() {
if let Some(byte) = self.iter.next() {
buf[i] = byte?;
} else {
return Err(Error::UnexpectedEof);
}
}
Ok(())
}
}
struct SliceRead<'a> {
slice: &'a [u8],
idx: usize
}
impl<'a> Read<'a> for SliceRead<'a> {
type Error = Infallible;
#[inline]
fn next(&mut self) -> Result<Option<u8>, Infallible> {
Ok(if self.idx < self.slice.len() {
let ch = self.slice[self.idx];
self.idx += 1;
Some(ch)
} else {
None
})
}
#[inline]
fn peek(&mut self) -> Result<Option<u8>, Infallible> {
Ok(if self.idx < self.slice.len() { Some(self.slice[self.idx]) } else { None })
}
#[inline]
fn discard(&mut self) {
self.idx += 1;
}
#[inline]
fn bytes(&mut self, len: u64) -> Result<Cow<'a, [u8]>, Error> {
let end = self.idx + len as usize;
if end > self.slice.len() {
return Err(Error::UnexpectedEof);
}
let slice = unsafe { slice::from_raw_parts(self.slice.as_ptr().add(self.idx), len as _) };
self.idx = end;
Ok(Cow::Borrowed(slice))
}
#[inline]
fn bytes_into(&mut self, bytes: &mut [u8]) -> Result<(), Error> {
let end = self.idx + bytes.len() as usize;
if end > self.slice.len() {
return Err(Error::UnexpectedEof);
}
bytes.copy_from_slice(&self.slice[self.idx..end]);
self.idx = end;
Ok(())
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct DeserializeOptions {}
impl Default for DeserializeOptions {
fn default() -> Self {
Self {}
}
}
struct Deserializer<R> {
read: R,
#[expect(unused)]
options: DeserializeOptions,
version: Option<u8>
}
impl<'a, R: Read<'a>> Deserializer<R>
where
Error: From<R::Error>
{
fn check_version(&mut self) -> Result<(), Error> {
let Some(0xFF) = self.read.next()? else {
return Err(Error::UnexpectedEof);
};
let version = self.read_var_int()? as u8;
if !(13..=16).contains(&version) {
Err(Error::BadVersion(version))
} else {
self.version = Some(version as u8);
Ok(())
}
}
fn next_tag(&mut self) -> Result<SerializationTag, Error> {
Ok(loop {
let next = self.read.next()?;
let Some(tag) = next else {
return Err(Error::UnexpectedEof);
};
match SerializationTag::try_from(tag) {
Ok(tag) => {
if tag != SerializationTag::Padding {
break tag;
} else {
continue;
}
}
Err(tag) => return Err(Error::UnknownTag(tag))
}
})
}
fn peek_tag(&mut self) -> Result<SerializationTag, Error> {
Ok(loop {
let next = self.read.peek()?;
let Some(tag) = next else {
return Err(Error::UnexpectedEof);
};
match SerializationTag::try_from(tag) {
Ok(tag) => {
if tag != SerializationTag::Padding {
break tag;
} else {
self.read.discard(); continue;
}
}
Err(tag) => return Err(Error::UnknownTag(tag))
}
})
}
fn read_var_int(&mut self) -> Result<u64, Error> {
let mut v = 0;
let mut shift = 0;
loop {
let Some(byte) = self.read.next()? else {
break Ok(v);
};
v |= ((byte & 0x7F) as u64) << shift;
shift += 7;
if byte & 0x80 == 0 {
break Ok(v);
}
}
}
fn read_zigzag(&mut self) -> Result<i64, Error> {
let v = self.read_var_int()?;
Ok((v >> 1) as i64 ^ -((v & 1) as i64))
}
fn read_string(&mut self, tag: SerializationTag) -> Result<Cow<'a, str>, Error> {
match tag {
SerializationTag::OneByteString => {
let len = self.read_var_int()?;
let bytes = self.read.bytes(len)?;
if bytes.len() < 128 && bytes.is_ascii() {
Ok(match bytes {
Cow::Borrowed(c) => Cow::Borrowed(unsafe { str::from_utf8_unchecked(c) }),
Cow::Owned(c) => Cow::Owned(unsafe { String::from_utf8_unchecked(c) })
})
} else {
let mut string = String::with_capacity(bytes.len() * 2);
let written = crate::utf::latin1_to_utf8(&bytes, unsafe { slice::from_raw_parts_mut(string.as_mut_ptr(), string.capacity()) }).len();
unsafe { string.as_mut_vec().set_len(written) };
Ok(Cow::Owned(string))
}
}
SerializationTag::TwoByteString => {
let len = self.read_var_int()?;
let bytes = self.read.bytes(len)?;
let mut out = String::with_capacity(bytes.len() / 2 * 3);
match unsafe { bytes.align_to::<u16>() } {
(&[], arr, &[]) => {
let written = crate::utf::utf16_to_utf8(arr, unsafe { slice::from_raw_parts_mut(out.as_mut_ptr(), out.capacity()) })
.map_err(|_| Error::BadUtf16)?
.len();
unsafe { out.as_mut_vec().set_len(written) };
}
_ => {
for c in char::decode_utf16(
bytes
.chunks_exact(2)
.map(|x| unsafe { <[_; 2]>::try_from(x).unwrap_unchecked() })
.map(|x| u16::from_le_bytes(x))
) {
out.push(c.map_err(|_| Error::BadUtf16)?);
}
}
}
Ok(Cow::Owned(out))
}
SerializationTag::Utf8String => {
let len = self.read_var_int()?;
let bytes = self.read.bytes(len)?;
Ok(match bytes {
Cow::Borrowed(c) => Cow::Borrowed(str::from_utf8(c).map_err(|_| Error::BadUtf8)?),
Cow::Owned(c) => Cow::Owned(String::from_utf8(c).map_err(|_| Error::BadUtf8)?)
})
}
_ => unreachable!()
}
}
fn check_length(&mut self, expected: u64) -> Result<(), Error> {
let len = self.read_var_int()?;
if len != expected {
return Err(Error::LengthMismatch { head: expected, tail: len });
}
Ok(())
}
}
impl<'a, 'de, R: Read<'de>> serde_core::Deserializer<'de> for &'a mut Deserializer<R>
where
Error: From<R::Error>
{
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde_core::de::Visitor<'de>
{
match self.next_tag()? {
SerializationTag::BeginDenseJSArray => {
let len = self.read_var_int()?;
let mut ended_seq = false;
let value = visitor.visit_seq(ArrayAccess {
de: self,
len,
ended_seq: &mut ended_seq,
_p: PhantomData
})?;
if ended_seq {
Ok(value)
} else if self.peek_tag()? == SerializationTag::EndDenseJSArray {
self.read.discard();
if self.read_var_int()? != 0 {
return Err(Error::ArrayWithProperties);
}
self.check_length(len)?;
Ok(value)
} else {
Err(Error::UnexpectedEof)
}
}
tag @ (SerializationTag::BeginJSObject | SerializationTag::BeginJSMap) => {
let mut ended_seq = false;
let value = visitor.visit_map(MapAccess {
de: self,
read_entries: 0,
is_object: tag == SerializationTag::BeginJSObject,
ended_seq: &mut ended_seq,
_p: PhantomData
})?;
if ended_seq {
Ok(value)
} else {
let end_tag = match tag {
SerializationTag::BeginJSObject => SerializationTag::EndJSObject,
SerializationTag::BeginJSMap => SerializationTag::EndJSMap,
_ => unreachable!()
};
if self.peek_tag()? == end_tag {
self.read.discard();
let _ = self.read_var_int()?;
Ok(value)
} else {
Err(Error::UnexpectedEof)
}
}
}
SerializationTag::Int32 => visitor.visit_i32(self.read_zigzag()? as _),
SerializationTag::Uint32 => visitor.visit_u32(self.read_var_int()? as _),
SerializationTag::Double => {
let mut bytes = [0; 8];
self.read.bytes_into(&mut bytes)?;
let value = f64::from_le_bytes(bytes);
if is_int(value) && value != -0. {
visitor.visit_i64(value as i64)
} else {
visitor.visit_f64(value)
}
}
SerializationTag::Null | SerializationTag::Undefined => visitor.visit_unit(),
SerializationTag::True => visitor.visit_bool(true),
SerializationTag::False => visitor.visit_bool(false),
tag @ (SerializationTag::OneByteString | SerializationTag::TwoByteString | SerializationTag::Utf8String) => match self.read_string(tag)? {
Cow::Borrowed(c) => visitor.visit_borrowed_str(c),
Cow::Owned(c) => visitor.visit_string(c)
},
SerializationTag::ArrayBuffer => {
let len = self.read_var_int()?;
let bytes = self.read.bytes(len)?;
if let Ok(SerializationTag::ArrayBufferView) = self.peek_tag() {
self.read.discard();
let Some(view_type) = self.read.next()? else {
return Err(Error::UnexpectedEof);
};
let view_type = match ArrayBufferViewTag::try_from(view_type) {
Ok(view_type) => view_type,
Err(c) => return Err(Error::UnknownTypedArrayType(c))
};
let byte_offset = self.read_var_int()? as usize;
let len2 = self.read_var_int()? as usize;
if let Some(version) = self.version
&& version >= 14
{
let _flags = self.read_var_int()?;
}
match view_type {
ArrayBufferViewTag::Uint8Array | ArrayBufferViewTag::Uint8ClampedArray | ArrayBufferViewTag::DataView => match bytes {
Cow::Borrowed(c) => visitor.visit_borrowed_bytes(&c[byte_offset..byte_offset + len2]),
Cow::Owned(c) => {
if byte_offset != 0 || len2 != len as usize {
visitor.visit_byte_buf(c)
} else {
visitor.visit_bytes(&c[byte_offset..byte_offset + len2])
}
}
},
c => return Err(Error::UnknownTypedArrayType(c as _))
}
} else {
match bytes {
Cow::Borrowed(c) => visitor.visit_borrowed_bytes(c),
Cow::Owned(c) => visitor.visit_byte_buf(c)
}
}
}
SerializationTag::BigInt => {
let bitfield = self.read_var_int()?;
let sign_bit = bitfield & 1;
let byte_len = bitfield >> 1;
if byte_len > 16 {
return Err(Error::BigIntTooBig);
}
let mut padded = [0; 16];
self.read.bytes_into(&mut padded[..byte_len as usize])?;
let v = i128::from_le_bytes(padded);
visitor.visit_i128(if sign_bit == 0 { v } else { -v })
}
SerializationTag::Date => {
let mut bytes = [0; 8];
self.read.bytes_into(&mut bytes)?;
visitor.visit_f64(f64::from_le_bytes(bytes))
}
SerializationTag::BeginJSSet => {
let mut ended_seq = false;
let value = visitor.visit_seq(SetAccess {
de: self,
read: 0,
ended_seq: &mut ended_seq,
_p: PhantomData
})?;
if ended_seq {
Ok(value)
} else if self.peek_tag()? == SerializationTag::EndJSSet {
self.read.discard();
let _ = self.read_var_int()?;
Ok(value)
} else {
Err(Error::UnexpectedEof)
}
}
tag => Err(Error::UnhandledTag(tag))
}
}
fn deserialize_enum<V>(self, _name: &'static str, _variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>
{
match self.peek_tag()? {
SerializationTag::BeginJSObject => {
self.read.discard();
let value = visitor.visit_enum(EnumAccess { de: self, _p: PhantomData })?;
if self.next_tag()? != SerializationTag::EndJSObject {
return Err(Error::UnexpectedEof);
}
let _ = self.read_var_int()?;
Ok(value)
}
SerializationTag::OneByteString | SerializationTag::TwoByteString | SerializationTag::Utf8String => {
Ok(visitor.visit_enum(UnitVariantAccess { de: self, _p: PhantomData })?)
}
tag => Err(Error::UnhandledTag(tag))
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>
{
match self.peek_tag()? {
SerializationTag::Null | SerializationTag::Undefined => {
self.read.discard();
visitor.visit_none()
}
_ => visitor.visit_some(self)
}
}
serde_core::forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char i128 u128
str string bytes byte_buf unit unit_struct
seq tuple tuple_struct map struct identifier ignored_any
newtype_struct
}
}
struct ArrayAccess<'a, 'de: 'a, R: Read<'de> + 'a>
where
Error: From<R::Error>
{
de: &'a mut Deserializer<R>,
len: u64,
ended_seq: &'a mut bool,
_p: PhantomData<&'de ()>
}
impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for ArrayAccess<'a, 'de, R>
where
Error: From<R::Error>
{
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where
T: DeserializeSeed<'de>
{
if self.de.peek_tag()? == SerializationTag::EndDenseJSArray {
self.de.read.discard();
if self.de.read_var_int()? != 0 {
return Err(Error::ArrayWithProperties);
}
self.de.check_length(self.len)?;
*self.ended_seq = true;
return Ok(None);
}
seed.deserialize(&mut *self.de).map(Some)
}
fn size_hint(&self) -> Option<usize> {
Some(self.len as _)
}
}
struct SetAccess<'a, 'de: 'a, R: Read<'de> + 'a>
where
Error: From<R::Error>
{
de: &'a mut Deserializer<R>,
read: u64,
ended_seq: &'a mut bool,
_p: PhantomData<&'de ()>
}
impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SetAccess<'a, 'de, R>
where
Error: From<R::Error>
{
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where
T: DeserializeSeed<'de>
{
if self.de.peek_tag()? == SerializationTag::EndJSSet {
self.de.read.discard();
self.de.check_length(self.read)?;
*self.ended_seq = true;
return Ok(None);
}
seed.deserialize(&mut *self.de).inspect(|_| self.read += 1).map(Some)
}
}
struct MapAccess<'a, 'de: 'a, R: Read<'de> + 'a>
where
Error: From<R::Error>
{
de: &'a mut Deserializer<R>,
read_entries: usize,
is_object: bool,
ended_seq: &'a mut bool,
_p: PhantomData<&'de ()>
}
impl<'de, 'a, R: Read<'de> + 'a> MapAccess<'a, 'de, R>
where
Error: From<R::Error>
{
fn end_tag(&self) -> SerializationTag {
if self.is_object { SerializationTag::EndJSObject } else { SerializationTag::EndJSMap }
}
}
impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, 'de, R>
where
Error: From<R::Error>
{
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: DeserializeSeed<'de>
{
if self.de.peek_tag()? == self.end_tag() {
self.de.read.discard();
self.de
.check_length(if self.is_object { self.read_entries } else { self.read_entries * 2 } as u64)?;
*self.ended_seq = true;
return Ok(None);
}
seed.deserialize(&mut *self.de).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: DeserializeSeed<'de>
{
seed.deserialize(&mut *self.de).inspect(|_| self.read_entries += 1)
}
}
struct EnumAccess<'a, 'de: 'a, R: Read<'de> + 'a>
where
Error: From<R::Error>
{
de: &'a mut Deserializer<R>,
_p: PhantomData<&'de ()>
}
impl<'de, 'a, R: Read<'de> + 'a> de::EnumAccess<'de> for EnumAccess<'a, 'de, R>
where
Error: From<R::Error>
{
type Variant = Self;
type Error = Error;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: DeserializeSeed<'de>
{
let val = seed.deserialize(&mut *self.de)?;
Ok((val, self))
}
}
impl<'de, 'a, R: Read<'de> + 'a> de::VariantAccess<'de> for EnumAccess<'a, 'de, R>
where
Error: From<R::Error>
{
type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> {
Err(Error::Custom(String::from("expected unit variant")))
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>
{
seed.deserialize(self.de)
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>
{
de::Deserializer::deserialize_seq(self.de, visitor)
}
fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>
{
de::Deserializer::deserialize_map(self.de, visitor)
}
}
struct UnitVariantAccess<'a, 'de: 'a, R: Read<'de> + 'a>
where
Error: From<R::Error>
{
de: &'a mut Deserializer<R>,
_p: PhantomData<&'de ()>
}
impl<'de, 'a, R: Read<'de> + 'a> de::EnumAccess<'de> for UnitVariantAccess<'a, 'de, R>
where
Error: From<R::Error>
{
type Variant = Self;
type Error = Error;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: DeserializeSeed<'de>
{
let val = seed.deserialize(&mut *self.de)?;
Ok((val, self))
}
}
impl<'de, 'a, R: Read<'de> + 'a> de::VariantAccess<'de> for UnitVariantAccess<'a, 'de, R>
where
Error: From<R::Error>
{
type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> {
Ok(())
}
fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>
{
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"))
}
fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>
{
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"))
}
fn struct_variant<V>(self, _: &'static [&'static str], _: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>
{
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"))
}
}
pub fn from_slice<'a, T: Deserialize<'a>>(slice: &'a [u8], options: DeserializeOptions) -> Result<T, Error> {
let mut deserializer = Deserializer {
read: SliceRead { slice, idx: 0 },
options,
version: None
};
deserializer.check_version()?;
T::deserialize(&mut deserializer)
}
#[cfg(feature = "std")]
pub fn from_reader<T: serde_core::de::DeserializeOwned>(read: impl io::Read, options: DeserializeOptions) -> Result<T, Error> {
let mut deserializer = Deserializer {
read: IoRead { iter: read.bytes(), peeked_ch: None },
options,
version: None
};
deserializer.check_version()?;
T::deserialize(&mut deserializer)
}