add IgnoreAll directive to deserializer

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-10-09 19:41:52 +00:00 committed by strawberry
parent d3d11356ee
commit 19880ce12b
2 changed files with 26 additions and 3 deletions

View file

@ -5,6 +5,7 @@ use serde::{
Deserialize, Deserialize,
}; };
/// Deserialize into T from buffer.
pub(crate) fn from_slice<'a, T>(buf: &'a [u8]) -> Result<T> pub(crate) fn from_slice<'a, T>(buf: &'a [u8]) -> Result<T>
where where
T: Deserialize<'a>, T: Deserialize<'a>,
@ -22,6 +23,7 @@ where
}) })
} }
/// Deserialization state.
pub(crate) struct Deserializer<'de> { pub(crate) struct Deserializer<'de> {
buf: &'de [u8], buf: &'de [u8],
pos: usize, pos: usize,
@ -33,6 +35,11 @@ pub(crate) struct Deserializer<'de> {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Ignore; pub struct Ignore;
/// Directive to ignore all remaining records. This can be used in a sequence to
/// ignore the rest of the sequence.
#[derive(Debug, Deserialize)]
pub struct IgnoreAll;
impl<'de> Deserializer<'de> { impl<'de> Deserializer<'de> {
/// Record separator; an intentionally invalid-utf8 byte. /// Record separator; an intentionally invalid-utf8 byte.
const SEP: u8 = b'\xFF'; const SEP: u8 = b'\xFF';
@ -53,6 +60,13 @@ impl<'de> Deserializer<'de> {
))) )))
} }
/// Called at the start of arrays and tuples
#[inline]
fn sequence_start(&mut self) {
debug_assert!(!self.seq, "Nested sequences are not handled at this time");
self.seq = true;
}
/// Consume the current record to ignore it. Inside a sequence the next /// Consume the current record to ignore it. Inside a sequence the next
/// record is skipped but at the top-level all records are skipped such that /// record is skipped but at the top-level all records are skipped such that
/// deserialization completes with self.finished() == Ok. /// deserialization completes with self.finished() == Ok.
@ -61,10 +75,16 @@ impl<'de> Deserializer<'de> {
if self.seq { if self.seq {
self.record_next(); self.record_next();
} else { } else {
self.record_trail(); self.record_ignore_all();
} }
} }
/// Consume the current and all remaining records to ignore them. Similar to
/// Ignore at the top-level, but it can be provided in a sequence to Ignore
/// all remaining elements.
#[inline]
fn record_ignore_all(&mut self) { self.record_trail(); }
/// Consume the current record. The position pointer is moved to the start /// Consume the current record. The position pointer is moved to the start
/// of the next record. Slice of the current record is returned. /// of the next record. Slice of the current record is returned.
#[inline] #[inline]
@ -101,7 +121,6 @@ impl<'de> Deserializer<'de> {
); );
self.inc_pos(started.into()); self.inc_pos(started.into());
self.seq = true;
} }
/// Consume all remaining bytes, which may include record separators, /// Consume all remaining bytes, which may include record separators,
@ -128,6 +147,7 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
self.sequence_start();
visitor.visit_seq(self) visitor.visit_seq(self)
} }
@ -135,6 +155,7 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
self.sequence_start();
visitor.visit_seq(self) visitor.visit_seq(self)
} }
@ -142,6 +163,7 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
self.sequence_start();
visitor.visit_seq(self) visitor.visit_seq(self)
} }
@ -170,6 +192,7 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
{ {
match name { match name {
"Ignore" => self.record_ignore(), "Ignore" => self.record_ignore(),
"IgnoreAll" => self.record_ignore_all(),
_ => unimplemented!("Unrecognized deserialization Directive {name:?}"), _ => unimplemented!("Unrecognized deserialization Directive {name:?}"),
}; };

View file

@ -24,7 +24,7 @@ extern crate rust_rocksdb as rocksdb;
pub use self::{ pub use self::{
database::Database, database::Database,
de::Ignore, de::{Ignore, IgnoreAll},
deserialized::Deserialized, deserialized::Deserialized,
handle::Handle, handle::Handle,
keyval::{KeyVal, Slice}, keyval::{KeyVal, Slice},