use arrayvec for integer deserialization buffer

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-11-25 01:01:39 +00:00
parent 6f1d50dda3
commit 343ec59a8b
2 changed files with 26 additions and 5 deletions

View file

@ -35,6 +35,8 @@ pub enum Error {
// third-party // third-party
#[error(transparent)] #[error(transparent)]
CapacityError(#[from] arrayvec::CapacityError),
#[error(transparent)]
CargoToml(#[from] cargo_toml::Error), CargoToml(#[from] cargo_toml::Error),
#[error(transparent)] #[error(transparent)]
Clap(#[from] clap::error::Error), Clap(#[from] clap::error::Error),

View file

@ -1,3 +1,4 @@
use arrayvec::ArrayVec;
use conduit::{checked, debug::DebugInspect, err, utils::string, Error, Result}; use conduit::{checked, debug::DebugInspect, err, utils::string, Error, Result};
use serde::{ use serde::{
de, de,
@ -52,7 +53,7 @@ impl<'de> Deserializer<'de> {
let len = self.buf.len(); let len = self.buf.len();
let parsed = &self.buf[0..pos]; let parsed = &self.buf[0..pos];
let unparsed = &self.buf[pos..]; let unparsed = &self.buf[pos..];
let remain = checked!(len - pos)?; let remain = self.remaining()?;
let trailing_sep = remain == 1 && unparsed[0] == Self::SEP; let trailing_sep = remain == 1 && unparsed[0] == Self::SEP;
(remain == 0 || trailing_sep) (remain == 0 || trailing_sep)
.then_some(()) .then_some(())
@ -139,6 +140,14 @@ impl<'de> Deserializer<'de> {
self.pos = self.pos.saturating_add(n); self.pos = self.pos.saturating_add(n);
debug_assert!(self.pos <= self.buf.len(), "pos out of range"); debug_assert!(self.pos <= self.buf.len(), "pos out of range");
} }
/// Unconsumed input bytes.
#[inline]
fn remaining(&self) -> Result<usize> {
let pos = self.pos;
let len = self.buf.len();
checked!(len - pos)
}
} }
impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
@ -240,8 +249,13 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
} }
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> { fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let bytes: [u8; size_of::<i64>()] = self.buf[self.pos..].try_into()?; const BYTES: usize = size_of::<i64>();
self.inc_pos(size_of::<i64>());
let end = self.pos.saturating_add(BYTES);
let bytes: ArrayVec<u8, BYTES> = self.buf[self.pos..end].try_into()?;
let bytes = bytes.into_inner().expect("array size matches i64");
self.inc_pos(BYTES);
visitor.visit_i64(i64::from_be_bytes(bytes)) visitor.visit_i64(i64::from_be_bytes(bytes))
} }
@ -258,8 +272,13 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
} }
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> { fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
let bytes: [u8; size_of::<u64>()] = self.buf[self.pos..].try_into()?; const BYTES: usize = size_of::<u64>();
self.inc_pos(size_of::<u64>());
let end = self.pos.saturating_add(BYTES);
let bytes: ArrayVec<u8, BYTES> = self.buf[self.pos..end].try_into()?;
let bytes = bytes.into_inner().expect("array size matches u64");
self.inc_pos(BYTES);
visitor.visit_u64(u64::from_be_bytes(bytes)) visitor.visit_u64(u64::from_be_bytes(bytes))
} }