diff --git a/src/database/de.rs b/src/database/de.rs index 9ee52267..e5fdf7cb 100644 --- a/src/database/de.rs +++ b/src/database/de.rs @@ -5,6 +5,7 @@ use serde::{ Deserialize, }; +/// Deserialize into T from buffer. pub(crate) fn from_slice<'a, T>(buf: &'a [u8]) -> Result where T: Deserialize<'a>, @@ -22,6 +23,7 @@ where }) } +/// Deserialization state. pub(crate) struct Deserializer<'de> { buf: &'de [u8], pos: usize, @@ -33,6 +35,11 @@ pub(crate) struct Deserializer<'de> { #[derive(Debug, Deserialize)] 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> { /// Record separator; an intentionally invalid-utf8 byte. 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 /// record is skipped but at the top-level all records are skipped such that /// deserialization completes with self.finished() == Ok. @@ -61,10 +75,16 @@ impl<'de> Deserializer<'de> { if self.seq { self.record_next(); } 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 /// of the next record. Slice of the current record is returned. #[inline] @@ -101,7 +121,6 @@ impl<'de> Deserializer<'de> { ); self.inc_pos(started.into()); - self.seq = true; } /// 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 V: Visitor<'de>, { + self.sequence_start(); visitor.visit_seq(self) } @@ -135,6 +155,7 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { where V: Visitor<'de>, { + self.sequence_start(); visitor.visit_seq(self) } @@ -142,6 +163,7 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { where V: Visitor<'de>, { + self.sequence_start(); visitor.visit_seq(self) } @@ -170,6 +192,7 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { { match name { "Ignore" => self.record_ignore(), + "IgnoreAll" => self.record_ignore_all(), _ => unimplemented!("Unrecognized deserialization Directive {name:?}"), }; diff --git a/src/database/mod.rs b/src/database/mod.rs index c39b2b2f..6d3b2079 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -24,7 +24,7 @@ extern crate rust_rocksdb as rocksdb; pub use self::{ database::Database, - de::Ignore, + de::{Ignore, IgnoreAll}, deserialized::Deserialized, handle::Handle, keyval::{KeyVal, Slice},