use std::cmp::Ordering;
use std::io::Read;
use std::marker::PhantomData;
use crate::slice_reader::BorrowedReader;
use crate::{DeserializeRevisioned, Error, Revisioned, SkipRevisioned};
pub trait WalkRevisioned: Revisioned {
type Walker<'r, R: Read + 'r>;
fn walk_revisioned<'r, R: Read>(reader: &'r mut R) -> Result<Self::Walker<'r, R>, Error>;
}
pub trait LengthPrefixedBytes: Revisioned {}
impl LengthPrefixedBytes for String {}
impl LengthPrefixedBytes for str {}
impl LengthPrefixedBytes for std::sync::Arc<str> {}
impl LengthPrefixedBytes for Box<str> {}
impl LengthPrefixedBytes for std::path::PathBuf {}
impl LengthPrefixedBytes for Vec<u8> {}
impl LengthPrefixedBytes for Vec<i8> {}
impl<T> LengthPrefixedBytes for std::borrow::Cow<'_, T>
where
T: ToOwned + Revisioned,
T::Owned: LengthPrefixedBytes,
{
}
#[cfg(feature = "bytes")]
impl LengthPrefixedBytes for bytes::Bytes {}
#[inline]
pub(crate) fn with_length_prefixed_bytes<R, F, T>(reader: &mut R, f: F) -> Result<T, Error>
where
R: BorrowedReader,
F: FnOnce(&[u8]) -> T,
{
let len = usize::deserialize_revisioned(reader)?;
let result = {
let bytes = reader.peek_bytes(len)?;
f(bytes)
};
reader.advance(len)?;
Ok(result)
}
pub struct LeafWalker<'r, T, R: Read + 'r> {
reader: &'r mut R,
_marker: PhantomData<fn() -> T>,
}
impl<'r, T, R: Read + 'r> LeafWalker<'r, T, R> {
#[inline]
pub fn new(reader: &'r mut R) -> Self {
Self {
reader,
_marker: PhantomData,
}
}
#[inline]
pub fn decode(self) -> Result<T, Error>
where
T: DeserializeRevisioned,
{
T::deserialize_revisioned(self.reader)
}
#[inline]
pub fn skip(self) -> Result<(), Error>
where
T: SkipRevisioned,
{
T::skip_revisioned(self.reader)
}
#[inline]
pub fn walk(self) -> Result<T::Walker<'r, R>, Error>
where
T: WalkRevisioned,
{
T::walk_revisioned(self.reader)
}
#[inline]
pub fn reader(&mut self) -> &mut R {
self.reader
}
#[inline]
pub fn into_reader(self) -> &'r mut R {
self.reader
}
}
impl<'r, T, R> LeafWalker<'r, T, R>
where
T: LengthPrefixedBytes,
R: BorrowedReader + 'r,
{
#[inline]
pub fn with_bytes<F, U>(self, f: F) -> Result<U, Error>
where
F: FnOnce(&[u8]) -> U,
{
with_length_prefixed_bytes(self.reader, f)
}
}
pub struct OptionWalker<'r, T, R: Read + 'r> {
reader: &'r mut R,
tag: u8,
_marker: PhantomData<fn() -> T>,
}
impl<'r, T, R: Read + 'r> OptionWalker<'r, T, R> {
#[inline]
pub fn new(reader: &'r mut R) -> Result<Self, Error> {
let tag = u8::deserialize_revisioned(reader)?;
match tag {
0 | 1 => Ok(Self {
reader,
tag,
_marker: PhantomData,
}),
v => Err(Error::Deserialize(format!("Invalid option value {v}"))),
}
}
#[inline]
pub fn is_some(&self) -> bool {
self.tag == 1
}
#[inline]
pub fn is_none(&self) -> bool {
self.tag == 0
}
#[inline]
pub fn decode(self) -> Result<Option<T>, Error>
where
T: DeserializeRevisioned,
{
match self.tag {
0 => Ok(None),
1 => Ok(Some(T::deserialize_revisioned(self.reader)?)),
v => Err(Error::Deserialize(format!("Invalid option value {v}"))),
}
}
#[inline]
pub fn skip(self) -> Result<(), Error>
where
T: SkipRevisioned,
{
if self.tag == 1 {
T::skip_revisioned(self.reader)?;
}
Ok(())
}
#[inline]
pub fn into_some(self) -> Result<T::Walker<'r, R>, Error>
where
T: WalkRevisioned,
{
match self.tag {
0 => Err(Error::Deserialize("Cannot walk into None payload".into())),
1 => T::walk_revisioned(self.reader),
v => Err(Error::Deserialize(format!("Invalid option value {v}"))),
}
}
}
pub struct ResultWalker<'r, T, E, R: Read + 'r> {
reader: &'r mut R,
tag: u32,
_marker: PhantomData<fn() -> Result<T, E>>,
}
impl<'r, T, E, R: Read + 'r> ResultWalker<'r, T, E, R> {
#[inline]
pub fn new(reader: &'r mut R) -> Result<Self, Error> {
let tag = u32::deserialize_revisioned(reader)?;
match tag {
0 | 1 => Ok(Self {
reader,
tag,
_marker: PhantomData,
}),
v => Err(Error::Deserialize(format!("Unknown Result variant index {v}"))),
}
}
#[inline]
pub fn is_ok(&self) -> bool {
self.tag == 0
}
#[inline]
pub fn is_err(&self) -> bool {
self.tag == 1
}
#[inline]
pub fn decode(self) -> Result<Result<T, E>, Error>
where
T: DeserializeRevisioned,
E: DeserializeRevisioned,
{
match self.tag {
0 => Ok(Ok(T::deserialize_revisioned(self.reader)?)),
1 => Ok(Err(E::deserialize_revisioned(self.reader)?)),
v => Err(Error::Deserialize(format!("Unknown Result variant index {v}"))),
}
}
#[inline]
pub fn skip(self) -> Result<(), Error>
where
T: SkipRevisioned,
E: SkipRevisioned,
{
match self.tag {
0 => T::skip_revisioned(self.reader),
1 => E::skip_revisioned(self.reader),
v => Err(Error::Deserialize(format!("Unknown Result variant index {v}"))),
}
}
#[inline]
pub fn into_ok(self) -> Result<T::Walker<'r, R>, Error>
where
T: WalkRevisioned,
{
match self.tag {
0 => T::walk_revisioned(self.reader),
1 => Err(Error::Deserialize("Cannot walk into Err as Ok".into())),
v => Err(Error::Deserialize(format!("Unknown Result variant index {v}"))),
}
}
#[inline]
pub fn into_err(self) -> Result<E::Walker<'r, R>, Error>
where
E: WalkRevisioned,
{
match self.tag {
0 => Err(Error::Deserialize("Cannot walk into Ok as Err".into())),
1 => E::walk_revisioned(self.reader),
v => Err(Error::Deserialize(format!("Unknown Result variant index {v}"))),
}
}
}
pub struct SeqWalker<'r, T, R: Read + 'r> {
reader: &'r mut R,
remaining: usize,
_marker: PhantomData<fn() -> T>,
}
impl<'r, T, R: Read + 'r> SeqWalker<'r, T, R> {
#[inline]
pub fn new(reader: &'r mut R) -> Result<Self, Error> {
let len = usize::deserialize_revisioned(reader)?;
Ok(Self {
reader,
remaining: len,
_marker: PhantomData,
})
}
#[inline]
pub fn remaining(&self) -> usize {
self.remaining
}
#[inline]
pub fn next_item(&mut self) -> Option<SeqItem<'_, 'r, T, R>> {
if self.remaining == 0 {
None
} else {
Some(SeqItem {
walker: self,
})
}
}
#[inline]
pub fn skip_remaining(mut self) -> Result<(), Error>
where
T: SkipRevisioned,
{
while self.remaining > 0 {
T::skip_revisioned(self.reader)?;
self.remaining -= 1;
}
Ok(())
}
}
pub struct SeqItem<'a, 'r, T, R: Read + 'r> {
walker: &'a mut SeqWalker<'r, T, R>,
}
impl<'a, 'r, T, R: Read + 'r> SeqItem<'a, 'r, T, R> {
#[inline]
pub fn decode(self) -> Result<T, Error>
where
T: DeserializeRevisioned,
{
let v = T::deserialize_revisioned(self.walker.reader)?;
self.walker.remaining -= 1;
Ok(v)
}
#[inline]
pub fn skip(self) -> Result<(), Error>
where
T: SkipRevisioned,
{
T::skip_revisioned(self.walker.reader)?;
self.walker.remaining -= 1;
Ok(())
}
#[inline]
pub fn walk(self) -> Result<T::Walker<'a, R>, Error>
where
T: WalkRevisioned,
{
let walker = T::walk_revisioned(self.walker.reader)?;
self.walker.remaining -= 1;
Ok(walker)
}
}
impl<'a, 'r, T, R> SeqItem<'a, 'r, T, R>
where
T: LengthPrefixedBytes,
R: BorrowedReader + 'r,
{
#[inline]
pub fn with_bytes<F, U>(self, f: F) -> Result<U, Error>
where
F: FnOnce(&[u8]) -> U,
{
let result = with_length_prefixed_bytes(self.walker.reader, f)?;
self.walker.remaining -= 1;
Ok(result)
}
}
pub struct MapWalker<'r, K, V, R: Read + 'r> {
reader: &'r mut R,
remaining: usize,
_marker: PhantomData<fn() -> (K, V)>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum MapCursor {
BeforeKey,
BeforeValue,
}
impl<'r, K, V, R: Read + 'r> MapWalker<'r, K, V, R> {
#[inline]
pub fn new(reader: &'r mut R) -> Result<Self, Error> {
let len = usize::deserialize_revisioned(reader)?;
Ok(Self {
reader,
remaining: len,
_marker: PhantomData,
})
}
#[inline]
pub fn remaining(&self) -> usize {
self.remaining
}
#[inline]
pub fn next_entry(&mut self) -> Option<MapEntry<'_, 'r, K, V, R>> {
if self.remaining == 0 {
None
} else {
Some(MapEntry {
walker: self,
cursor: MapCursor::BeforeKey,
})
}
}
#[inline]
pub fn skip_remaining(mut self) -> Result<(), Error>
where
K: SkipRevisioned,
V: SkipRevisioned,
{
while self.remaining > 0 {
K::skip_revisioned(self.reader)?;
V::skip_revisioned(self.reader)?;
self.remaining -= 1;
}
Ok(())
}
#[inline]
pub fn find<F>(mut self, mut predicate: F) -> Result<Option<LeafWalker<'r, V, R>>, Error>
where
K: DeserializeRevisioned + SkipRevisioned,
V: SkipRevisioned,
F: FnMut(&K) -> Ordering,
{
while self.remaining > 0 {
let key = K::deserialize_revisioned(self.reader)?;
match predicate(&key) {
Ordering::Less => {
V::skip_revisioned(self.reader)?;
self.remaining -= 1;
}
Ordering::Equal => {
return Ok(Some(LeafWalker::new(self.reader)));
}
Ordering::Greater => {
V::skip_revisioned(self.reader)?;
self.remaining -= 1;
while self.remaining > 0 {
K::skip_revisioned(self.reader)?;
V::skip_revisioned(self.reader)?;
self.remaining -= 1;
}
return Ok(None);
}
}
}
Ok(None)
}
}
impl<'r, K, V, R> MapWalker<'r, K, V, R>
where
K: LengthPrefixedBytes + SkipRevisioned,
V: SkipRevisioned,
R: BorrowedReader + 'r,
{
#[inline]
pub fn find_bytes<F>(mut self, mut predicate: F) -> Result<Option<LeafWalker<'r, V, R>>, Error>
where
F: FnMut(&[u8]) -> Ordering,
{
while self.remaining > 0 {
let key_len = usize::deserialize_revisioned(self.reader)?;
let cmp = {
let key_bytes = self.reader.peek_bytes(key_len)?;
predicate(key_bytes)
};
self.reader.advance(key_len)?;
match cmp {
Ordering::Less => {
V::skip_revisioned(self.reader)?;
self.remaining -= 1;
}
Ordering::Equal => {
return Ok(Some(LeafWalker::new(self.reader)));
}
Ordering::Greater => {
V::skip_revisioned(self.reader)?;
self.remaining -= 1;
while self.remaining > 0 {
K::skip_revisioned(self.reader)?;
V::skip_revisioned(self.reader)?;
self.remaining -= 1;
}
return Ok(None);
}
}
}
Ok(None)
}
}
pub struct MapEntry<'a, 'r, K, V, R: Read + 'r> {
walker: &'a mut MapWalker<'r, K, V, R>,
cursor: MapCursor,
}
impl<'a, 'r, K, V, R: Read + 'r> MapEntry<'a, 'r, K, V, R> {
fn expect_cursor(&self, expected: MapCursor, operation: &'static str) -> Result<(), Error> {
if self.cursor != expected {
return Err(Error::Deserialize(format!(
"MapEntry: invalid cursor for {operation} (expected {expected:?}, found {:?})",
self.cursor,
)));
}
Ok(())
}
#[inline]
pub fn decode_key(&mut self) -> Result<K, Error>
where
K: DeserializeRevisioned,
{
self.expect_cursor(MapCursor::BeforeKey, "decode_key")?;
let k = K::deserialize_revisioned(self.walker.reader)?;
self.cursor = MapCursor::BeforeValue;
Ok(k)
}
#[inline]
pub fn skip_key(&mut self) -> Result<(), Error>
where
K: SkipRevisioned,
{
self.expect_cursor(MapCursor::BeforeKey, "skip_key")?;
K::skip_revisioned(self.walker.reader)?;
self.cursor = MapCursor::BeforeValue;
Ok(())
}
#[inline]
pub fn decode_value(self) -> Result<V, Error>
where
V: DeserializeRevisioned,
{
self.expect_cursor(MapCursor::BeforeValue, "decode_value")?;
let v = V::deserialize_revisioned(self.walker.reader)?;
self.walker.remaining -= 1;
Ok(v)
}
#[inline]
pub fn skip_value(self) -> Result<(), Error>
where
V: SkipRevisioned,
{
self.expect_cursor(MapCursor::BeforeValue, "skip_value")?;
V::skip_revisioned(self.walker.reader)?;
self.walker.remaining -= 1;
Ok(())
}
#[inline]
pub fn walk_value(self) -> Result<V::Walker<'a, R>, Error>
where
V: WalkRevisioned,
{
self.expect_cursor(MapCursor::BeforeValue, "walk_value")?;
let w = V::walk_revisioned(self.walker.reader)?;
self.walker.remaining -= 1;
Ok(w)
}
#[inline]
pub fn decode_pair(mut self) -> Result<(K, V), Error>
where
K: DeserializeRevisioned,
V: DeserializeRevisioned,
{
let key = self.decode_key()?;
let value = self.decode_value()?;
Ok((key, value))
}
#[inline]
pub fn skip_pair(mut self) -> Result<(), Error>
where
K: SkipRevisioned,
V: SkipRevisioned,
{
self.skip_key()?;
self.skip_value()
}
}
impl<'a, 'r, K, V, R> MapEntry<'a, 'r, K, V, R>
where
R: BorrowedReader + 'r,
{
#[inline]
pub fn with_key_bytes<F, U>(&mut self, f: F) -> Result<U, Error>
where
K: LengthPrefixedBytes,
F: FnOnce(&[u8]) -> U,
{
self.expect_cursor(MapCursor::BeforeKey, "with_key_bytes")?;
let result = with_length_prefixed_bytes(self.walker.reader, f)?;
self.cursor = MapCursor::BeforeValue;
Ok(result)
}
#[inline]
pub fn with_value_bytes<F, U>(self, f: F) -> Result<U, Error>
where
V: LengthPrefixedBytes,
F: FnOnce(&[u8]) -> U,
{
self.expect_cursor(MapCursor::BeforeValue, "with_value_bytes")?;
let result = with_length_prefixed_bytes(self.walker.reader, f)?;
self.walker.remaining -= 1;
Ok(result)
}
}
pub struct StructWalker<'r, R: Read + 'r> {
reader: &'r mut R,
revision: u16,
position: u32,
}
impl<'r, R: Read + 'r> StructWalker<'r, R> {
#[inline]
pub fn new(reader: &'r mut R, revision: u16) -> Self {
Self {
reader,
revision,
position: 0,
}
}
#[inline]
pub fn revision(&self) -> u16 {
self.revision
}
#[inline]
pub fn position(&self) -> u32 {
self.position
}
#[inline]
pub fn decode<T: DeserializeRevisioned>(&mut self) -> Result<T, Error> {
let v = T::deserialize_revisioned(self.reader)?;
self.position += 1;
Ok(v)
}
#[inline]
pub fn skip<T: SkipRevisioned>(&mut self) -> Result<(), Error> {
T::skip_revisioned(self.reader)?;
self.position += 1;
Ok(())
}
#[inline]
pub fn walk<T: WalkRevisioned>(&mut self) -> Result<T::Walker<'_, R>, Error> {
let w = T::walk_revisioned(self.reader)?;
self.position += 1;
Ok(w)
}
#[inline]
pub fn into_walk<T: WalkRevisioned>(self) -> Result<T::Walker<'r, R>, Error> {
T::walk_revisioned(self.reader)
}
#[inline]
pub fn reader(&mut self) -> &mut R {
self.reader
}
#[inline]
pub fn into_reader(self) -> &'r mut R {
self.reader
}
}
pub struct EnumWalker<'r, R: Read + 'r> {
reader: &'r mut R,
revision: u16,
discriminant: u32,
}
impl<'r, R: Read + 'r> EnumWalker<'r, R> {
#[inline]
pub fn new(reader: &'r mut R, revision: u16) -> Result<Self, Error> {
let discriminant = u32::deserialize_revisioned(reader)?;
Ok(Self {
reader,
revision,
discriminant,
})
}
#[inline]
pub fn revision(&self) -> u16 {
self.revision
}
#[inline]
pub fn discriminant(&self) -> u32 {
self.discriminant
}
#[inline]
pub fn decode<T: DeserializeRevisioned>(self) -> Result<T, Error> {
T::deserialize_revisioned(self.reader)
}
#[inline]
pub fn skip<T: SkipRevisioned>(self) -> Result<(), Error> {
T::skip_revisioned(self.reader)
}
#[inline]
pub fn into_walk<T: WalkRevisioned>(self) -> Result<T::Walker<'r, R>, Error> {
T::walk_revisioned(self.reader)
}
#[inline]
pub fn reader(&mut self) -> &mut R {
self.reader
}
#[inline]
pub fn into_reader(self) -> &'r mut R {
self.reader
}
}
#[inline]
pub fn read_enum_discriminant<R: Read>(reader: &mut R) -> Result<u32, Error> {
u32::deserialize_revisioned(reader)
}