forked from syndicate-lang/preserves
Avoid a few small allocations when decoding
This commit is contained in:
parent
316a772fec
commit
d29ec9ffc4
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "preserves"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
|
||||
edition = "2018"
|
||||
description = "Implementation of the Preserves serialization format via serde."
|
||||
|
|
|
@ -65,6 +65,35 @@ pub struct Decoder<'a, 'b, R: Read, N: NestedValue<D>, D: Domain> {
|
|||
read_annotations: bool,
|
||||
}
|
||||
|
||||
struct CountedStream<'de, 'a, 'b, R: Read, N: NestedValue<D>, D: Domain> {
|
||||
count: usize,
|
||||
decoder: &'de mut Decoder<'a, 'b, R, N, D>,
|
||||
}
|
||||
|
||||
impl<'de, 'a, 'b, R: Read, N: NestedValue<D>, D: Domain> Iterator for CountedStream<'de, 'a, 'b, R, N, D> {
|
||||
type Item = Result<N>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.count == 0 { return None }
|
||||
self.count -= 1;
|
||||
Some(self.decoder.next())
|
||||
}
|
||||
}
|
||||
|
||||
struct DelimitedStream<'de, 'a, 'b, R: Read, N: NestedValue<D>, D: Domain> {
|
||||
decoder: &'de mut Decoder<'a, 'b, R, N, D>,
|
||||
}
|
||||
|
||||
impl<'de, 'a, 'b, R: Read, N: NestedValue<D>, D: Domain> Iterator for DelimitedStream<'de, 'a, 'b, R, N, D> {
|
||||
type Item = Result<N>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.decoder.peekend() {
|
||||
Err(e) => Some(Err(e)),
|
||||
Ok(true) => None,
|
||||
Ok(false) => Some(self.decoder.next()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn decodeint(bs: &[u8]) -> BigInt {
|
||||
BigInt::from_signed_bytes_be(bs)
|
||||
}
|
||||
|
@ -124,15 +153,14 @@ impl<'a, 'b, R: Read, N: NestedValue<D>, D: Domain> Decoder<'a, 'b, R, N, D> {
|
|||
Ok(v)
|
||||
}
|
||||
|
||||
pub fn readbytes(&mut self, n: usize) -> Result<Vec<u8>> {
|
||||
pub fn readbytes(&mut self, bs: &mut [u8]) -> Result<()> {
|
||||
if *self.buf != PeekState::Empty {
|
||||
unreachable!();
|
||||
}
|
||||
let mut bs = vec![0; n];
|
||||
match self.read.read_exact(&mut bs) {
|
||||
match self.read.read_exact(bs) {
|
||||
Ok(()) => {
|
||||
self.index += n;
|
||||
Ok(bs)
|
||||
self.index += bs.len();
|
||||
Ok(())
|
||||
}
|
||||
Err(e) =>
|
||||
if e.kind() == std::io::ErrorKind::UnexpectedEof {
|
||||
|
@ -143,15 +171,6 @@ impl<'a, 'b, R: Read, N: NestedValue<D>, D: Domain> Decoder<'a, 'b, R, N, D> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn readvalues(&mut self, mut count: usize) -> Result<Vec<N>> {
|
||||
let mut pieces: Vec<N> = Vec::with_capacity(count);
|
||||
while count > 0 {
|
||||
pieces.push(self.next()?);
|
||||
count -= 1;
|
||||
}
|
||||
Ok(pieces)
|
||||
}
|
||||
|
||||
pub fn decodeop(b: u8) -> Result<(Op, u8)> {
|
||||
Ok((Op::try_from(b >> 4)?, b & 15))
|
||||
}
|
||||
|
@ -195,34 +214,37 @@ impl<'a, 'b, R: Read, N: NestedValue<D>, D: Domain> Decoder<'a, 'b, R, N, D> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn decodecompound(minor: CompoundMinor, mut pieces: Vec<N>) -> Result<N> {
|
||||
pub fn decodecompound<I: Iterator<Item = Result<N>>>(minor: CompoundMinor, mut pieces: I) ->
|
||||
Result<N>
|
||||
{
|
||||
match minor {
|
||||
CompoundMinor::Record =>
|
||||
if pieces.is_empty() {
|
||||
Err(Error::Syntax("Too few elements in encoded record"))
|
||||
} else {
|
||||
let label = pieces.remove(0);
|
||||
Ok(Value::record(label, pieces).wrap())
|
||||
match pieces.next() {
|
||||
None => Err(Error::Syntax("Too few elements in encoded record")),
|
||||
Some(labelres) => {
|
||||
let label = labelres?;
|
||||
Ok(Value::record(label, pieces.collect::<Result<Vec<N>>>()?).wrap())
|
||||
}
|
||||
},
|
||||
CompoundMinor::Sequence => Ok(Value::Sequence(pieces).wrap()),
|
||||
CompoundMinor::Sequence => {
|
||||
Ok(Value::Sequence(pieces.collect::<Result<Vec<N>>>()?).wrap())
|
||||
}
|
||||
CompoundMinor::Set => {
|
||||
let mut s = Set::new();
|
||||
while let Some(v) = pieces.pop() {
|
||||
s.insert(v);
|
||||
}
|
||||
for res in pieces { s.insert(res?); }
|
||||
Ok(Value::Set(s).wrap())
|
||||
}
|
||||
CompoundMinor::Dictionary =>
|
||||
if pieces.len() % 2 != 0 {
|
||||
Err(Error::Syntax("Missing dictionary value"))
|
||||
} else {
|
||||
let mut d = Map::new();
|
||||
while let Some(v) = pieces.pop() {
|
||||
let k = pieces.pop().unwrap();
|
||||
d.insert(k, v);
|
||||
CompoundMinor::Dictionary => {
|
||||
let mut d = Map::new();
|
||||
while let Some(kres) = pieces.next() {
|
||||
let k = kres?;
|
||||
match pieces.next() {
|
||||
Some(vres) => { d.insert(k, vres?); }
|
||||
None => return Err(Error::Syntax("Missing dictionary value")),
|
||||
}
|
||||
Ok(Value::Dictionary(d).wrap())
|
||||
},
|
||||
}
|
||||
Ok(Value::Dictionary(d).wrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,11 +260,7 @@ impl<'a, 'b, R: Read, N: NestedValue<D>, D: Domain> Decoder<'a, 'b, R, N, D> {
|
|||
}
|
||||
|
||||
pub fn valuestream(&mut self, minor: CompoundMinor) -> Result<N> {
|
||||
let mut pieces: Vec<N> = Vec::new();
|
||||
while !self.peekend()? {
|
||||
pieces.push(self.next()?);
|
||||
}
|
||||
Self::decodecompound(minor, pieces)
|
||||
Self::decodecompound(minor, DelimitedStream { decoder: self })
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> Result<N> {
|
||||
|
@ -251,11 +269,13 @@ impl<'a, 'b, R: Read, N: NestedValue<D>, D: Domain> Decoder<'a, 'b, R, N, D> {
|
|||
(Op::Misc(0), 0) => Ok(Value::from(false).wrap()),
|
||||
(Op::Misc(0), 1) => Ok(Value::from(true).wrap()),
|
||||
(Op::Misc(0), 2) => {
|
||||
let bs: &[u8] = &self.readbytes(4)?;
|
||||
let mut bs: [u8; 4] = Default::default();
|
||||
self.readbytes(&mut bs)?;
|
||||
Ok(Value::from(f32::from_bits(u32::from_be_bytes(bs.try_into().unwrap()))).wrap())
|
||||
}
|
||||
(Op::Misc(0), 3) => {
|
||||
let bs: &[u8] = &self.readbytes(8)?;
|
||||
let mut bs: [u8; 8] = Default::default();
|
||||
self.readbytes(&mut bs)?;
|
||||
Ok(Value::from(f64::from_bits(u64::from_be_bytes(bs.try_into().unwrap()))).wrap())
|
||||
}
|
||||
(Op::Misc(0), 5) => {
|
||||
|
@ -295,11 +315,13 @@ impl<'a, 'b, R: Read, N: NestedValue<D>, D: Domain> Decoder<'a, 'b, R, N, D> {
|
|||
(Op::Misc(_), _) => unreachable!(),
|
||||
(Op::Atom(minor), arg) => {
|
||||
let count = self.wirelength(arg)?;
|
||||
Self::decodebinary(minor, self.readbytes(count)?)
|
||||
let mut bs = vec![0; count];
|
||||
self.readbytes(&mut bs)?;
|
||||
Self::decodebinary(minor, bs)
|
||||
}
|
||||
(Op::Compound(minor), arg) => {
|
||||
let count = self.wirelength(arg)?;
|
||||
Self::decodecompound(minor, self.readvalues(count)?)
|
||||
Self::decodecompound(minor, CountedStream { count, decoder: self })
|
||||
}
|
||||
(Op::Reserved(3), 15) => continue,
|
||||
(Op::Reserved(_), _) => Err(InvalidOp.into()),
|
||||
|
|
Loading…
Reference in New Issue