2017-12-11 18:19:25 +01:00
|
|
|
// Copyright 2017 Parity Technologies (UK) Ltd.
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
|
|
// to deal in the Software without restriction, including without limitation
|
|
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
#![warn(missing_docs)]
|
|
|
|
|
|
|
|
//! Encoding and decoding state machines for protobuf varints
|
|
|
|
|
|
|
|
// TODO: Non-allocating `BigUint`?
|
2017-11-01 11:59:52 +01:00
|
|
|
extern crate bytes;
|
2017-11-22 18:01:28 +01:00
|
|
|
#[macro_use]
|
|
|
|
extern crate error_chain;
|
2018-03-07 16:20:55 +01:00
|
|
|
extern crate futures;
|
|
|
|
extern crate num_bigint;
|
|
|
|
extern crate num_traits;
|
|
|
|
extern crate tokio_io;
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2018-06-22 16:12:23 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
extern crate tokio_codec;
|
|
|
|
|
2018-01-24 11:14:17 +01:00
|
|
|
use bytes::{BufMut, Bytes, BytesMut, IntoBuf};
|
2018-03-07 16:20:55 +01:00
|
|
|
use futures::{Async, Poll};
|
2017-11-01 11:59:52 +01:00
|
|
|
use num_bigint::BigUint;
|
2017-11-22 18:01:28 +01:00
|
|
|
use num_traits::ToPrimitive;
|
2017-11-01 11:59:52 +01:00
|
|
|
use std::io;
|
|
|
|
use std::io::prelude::*;
|
2018-01-09 15:44:05 +01:00
|
|
|
use std::marker::PhantomData;
|
|
|
|
use std::mem;
|
2018-05-14 15:55:16 +02:00
|
|
|
use tokio_io::codec::{Decoder, Encoder};
|
|
|
|
use tokio_io::{AsyncRead, AsyncWrite};
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
mod errors {
|
|
|
|
error_chain! {
|
|
|
|
errors {
|
|
|
|
ParseError {
|
|
|
|
description("error parsing varint")
|
|
|
|
display("error parsing varint")
|
|
|
|
}
|
|
|
|
WriteError {
|
|
|
|
description("error writing varint")
|
|
|
|
display("error writing varint")
|
|
|
|
}
|
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
foreign_links {
|
|
|
|
Io(::std::io::Error);
|
|
|
|
}
|
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
pub use errors::{Error, ErrorKind};
|
|
|
|
|
|
|
|
const USABLE_BITS_PER_BYTE: usize = 7;
|
|
|
|
|
|
|
|
/// The state struct for the varint-to-bytes FSM
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct EncoderState<T> {
|
|
|
|
source: T,
|
2017-12-12 12:50:33 +01:00
|
|
|
// A "chunk" is a section of the `source` `USABLE_BITS_PER_BYTE` bits long
|
2017-11-22 18:01:28 +01:00
|
|
|
num_chunks: usize,
|
|
|
|
cur_chunk: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Whether or not the varint writing was completed
|
|
|
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
|
|
|
pub enum WriteState {
|
|
|
|
/// The encoder has finished writing
|
|
|
|
Done(usize),
|
|
|
|
/// The encoder still must write more bytes
|
|
|
|
Pending(usize),
|
|
|
|
}
|
|
|
|
|
|
|
|
fn ceil_div(a: usize, b: usize) -> usize {
|
|
|
|
(a + b - 1) / b
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A trait to get the minimum number of bits required to represent a number
|
|
|
|
pub trait Bits {
|
|
|
|
/// The minimum number of bits required to represent `self`
|
|
|
|
fn bits(&self) -> usize;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Bits for BigUint {
|
|
|
|
fn bits(&self) -> usize {
|
|
|
|
BigUint::bits(self)
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
2017-11-22 18:01:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_bits {
|
|
|
|
($t:ty) => {
|
|
|
|
impl Bits for $t {
|
|
|
|
fn bits(&self) -> usize {
|
|
|
|
(std::mem::size_of::<$t>() * 8) - self.leading_zeros() as usize
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 15:55:16 +02:00
|
|
|
};
|
2017-11-22 18:01:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl_bits!(usize);
|
|
|
|
impl_bits!(u64);
|
|
|
|
impl_bits!(u32);
|
|
|
|
impl_bits!(u16);
|
|
|
|
impl_bits!(u8);
|
|
|
|
|
|
|
|
/// Helper trait to allow multiple integer types to be encoded
|
|
|
|
pub trait EncoderHelper: Sized {
|
|
|
|
/// Write as much as possible of the inner integer to the output `AsyncWrite`
|
|
|
|
fn write<W: AsyncWrite>(encoder: &mut EncoderState<Self>, output: W)
|
|
|
|
-> Poll<WriteState, Error>;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Helper trait to allow multiple integer types to be encoded
|
|
|
|
pub trait DecoderHelper: Sized {
|
|
|
|
/// Decode a single byte
|
2017-12-15 17:38:10 +01:00
|
|
|
fn decode_one(decoder: &mut DecoderState<Self>, byte: u8) -> errors::Result<Option<Self>>;
|
2017-11-22 18:01:28 +01:00
|
|
|
|
|
|
|
/// Read as much of the varint as possible
|
|
|
|
fn read<R: AsyncRead>(decoder: &mut DecoderState<Self>, input: R) -> Poll<Option<Self>, Error>;
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_decoderstate {
|
2017-12-15 17:38:10 +01:00
|
|
|
($t:ty) => {
|
|
|
|
impl_decoderstate!(
|
|
|
|
$t,
|
|
|
|
|a| a as $t,
|
|
|
|
|a: $t, b| -> Option<$t> { a.checked_shl(b as u32) }
|
|
|
|
);
|
|
|
|
};
|
2018-05-14 15:55:16 +02:00
|
|
|
($t:ty, $make_fn:expr) => {
|
|
|
|
impl_decoderstate!($t, $make_fn, $make_fn);
|
|
|
|
};
|
2017-12-15 17:38:10 +01:00
|
|
|
($t:ty, $make_fn:expr, $shift_fn:expr) => {
|
2017-11-22 18:01:28 +01:00
|
|
|
impl DecoderHelper for $t {
|
|
|
|
#[inline]
|
2018-03-07 16:20:55 +01:00
|
|
|
fn decode_one(
|
|
|
|
decoder: &mut DecoderState<Self>,
|
|
|
|
byte: u8,
|
|
|
|
) -> ::errors::Result<Option<$t>> {
|
2017-12-15 17:38:10 +01:00
|
|
|
let res = decoder.accumulator.take().and_then(|accumulator| {
|
2018-05-14 15:55:16 +02:00
|
|
|
let out = accumulator
|
|
|
|
| match $shift_fn(
|
|
|
|
$make_fn(byte & 0x7F),
|
|
|
|
decoder.shift * USABLE_BITS_PER_BYTE,
|
|
|
|
) {
|
|
|
|
Some(a) => a,
|
|
|
|
None => return Some(Err(ErrorKind::ParseError.into())),
|
|
|
|
};
|
2017-11-22 18:01:28 +01:00
|
|
|
decoder.shift += 1;
|
|
|
|
|
|
|
|
if byte & 0x80 == 0 {
|
2017-12-15 17:38:10 +01:00
|
|
|
Some(Ok(out))
|
2017-11-22 18:01:28 +01:00
|
|
|
} else {
|
|
|
|
decoder.accumulator = AccumulatorState::InProgress(out);
|
|
|
|
None
|
|
|
|
}
|
2017-12-15 17:38:10 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
match res {
|
|
|
|
Some(Ok(number)) => Ok(Some(number)),
|
|
|
|
Some(Err(err)) => Err(err),
|
|
|
|
None => Ok(None),
|
|
|
|
}
|
2017-11-22 18:01:28 +01:00
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
fn read<R: AsyncRead>(
|
|
|
|
decoder: &mut DecoderState<Self>,
|
2018-05-14 15:55:16 +02:00
|
|
|
mut input: R,
|
2017-11-22 18:01:28 +01:00
|
|
|
) -> Poll<Option<Self>, Error> {
|
|
|
|
if decoder.accumulator == AccumulatorState::Finished {
|
|
|
|
return Err(Error::with_chain(
|
|
|
|
io::Error::new(
|
|
|
|
io::ErrorKind::Other,
|
|
|
|
"Attempted to parse a second varint (create a new instance!)",
|
|
|
|
),
|
|
|
|
ErrorKind::ParseError,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
loop {
|
|
|
|
// We read one at a time to prevent consuming too much of the buffer.
|
|
|
|
let mut buffer: [u8; 1] = [0];
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
match input.read_exact(&mut buffer) {
|
|
|
|
Ok(()) => {
|
2017-12-15 17:38:10 +01:00
|
|
|
if let Some(out) = Self::decode_one(decoder, buffer[0])? {
|
2017-11-22 18:01:28 +01:00
|
|
|
break Ok(Async::Ready(Some(out)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
|
|
|
|
break Ok(Async::NotReady);
|
|
|
|
}
|
|
|
|
Err(inner) => if decoder.accumulator == AccumulatorState::NotStarted {
|
|
|
|
break Ok(Async::Ready(None));
|
|
|
|
} else {
|
2018-05-14 15:55:16 +02:00
|
|
|
break Err(Error::with_chain(inner, ErrorKind::ParseError));
|
2017-11-22 18:01:28 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
2018-05-14 15:55:16 +02:00
|
|
|
};
|
2017-11-22 18:01:28 +01:00
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
macro_rules! impl_encoderstate {
|
2018-05-14 15:55:16 +02:00
|
|
|
($t:ty) => {
|
|
|
|
impl_encoderstate!($t, <$t>::from);
|
|
|
|
};
|
2017-11-22 18:01:28 +01:00
|
|
|
($t:ty, $make_fn:expr) => {
|
|
|
|
impl EncoderHelper for $t {
|
|
|
|
/// Write as much as possible of the inner integer to the output `AsyncWrite`
|
|
|
|
fn write<W: AsyncWrite>(
|
|
|
|
encoder: &mut EncoderState<Self>,
|
|
|
|
mut output: W,
|
|
|
|
) -> Poll<WriteState, Error> {
|
|
|
|
fn encode_one(encoder: &EncoderState<$t>) -> Option<u8> {
|
|
|
|
let last_chunk = encoder.num_chunks - 1;
|
|
|
|
|
|
|
|
if encoder.cur_chunk > last_chunk {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2018-05-14 15:55:16 +02:00
|
|
|
let masked = (&encoder.source >> (encoder.cur_chunk * USABLE_BITS_PER_BYTE))
|
|
|
|
& $make_fn((1 << USABLE_BITS_PER_BYTE) - 1usize);
|
|
|
|
let masked = masked
|
|
|
|
.to_u8()
|
|
|
|
.expect("Masked with 0b0111_1111, is less than u8::MAX, QED");
|
2017-11-22 18:01:28 +01:00
|
|
|
|
|
|
|
if encoder.cur_chunk == last_chunk {
|
|
|
|
Some(masked)
|
|
|
|
} else {
|
|
|
|
Some(masked | (1 << USABLE_BITS_PER_BYTE))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut written = 0usize;
|
|
|
|
|
|
|
|
loop {
|
|
|
|
if let Some(byte) = encode_one(&encoder) {
|
|
|
|
let buffer: [u8; 1] = [byte];
|
|
|
|
|
|
|
|
match output.write_all(&buffer) {
|
|
|
|
Ok(()) => {
|
|
|
|
written += 1;
|
|
|
|
encoder.cur_chunk += 1;
|
|
|
|
}
|
|
|
|
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
|
|
|
|
break if written == 0 {
|
|
|
|
Ok(Async::NotReady)
|
|
|
|
} else {
|
|
|
|
Ok(Async::Ready(WriteState::Pending(written)))
|
|
|
|
};
|
|
|
|
}
|
2018-05-14 15:55:16 +02:00
|
|
|
Err(inner) => {
|
|
|
|
break Err(Error::with_chain(inner, ErrorKind::WriteError))
|
|
|
|
}
|
2017-11-22 18:01:28 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break Ok(Async::Ready(WriteState::Done(written)));
|
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-14 15:55:16 +02:00
|
|
|
};
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
impl_encoderstate!(usize);
|
|
|
|
impl_encoderstate!(BigUint);
|
|
|
|
impl_encoderstate!(u64, (|val| val as u64));
|
|
|
|
impl_encoderstate!(u32, (|val| val as u32));
|
|
|
|
|
|
|
|
impl_decoderstate!(usize);
|
2017-12-15 17:38:10 +01:00
|
|
|
impl_decoderstate!(BigUint, BigUint::from, |a, b| Some(a << b));
|
|
|
|
impl_decoderstate!(u64);
|
|
|
|
impl_decoderstate!(u32);
|
2017-11-22 18:01:28 +01:00
|
|
|
|
|
|
|
impl<T> EncoderState<T> {
|
|
|
|
pub fn source(&self) -> &T {
|
|
|
|
&self.source
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Bits> EncoderState<T> {
|
|
|
|
/// Create a new encoder
|
|
|
|
pub fn new(inner: T) -> Self {
|
|
|
|
let bits = inner.bits();
|
|
|
|
EncoderState {
|
|
|
|
source: inner,
|
|
|
|
num_chunks: ceil_div(bits, USABLE_BITS_PER_BYTE).max(1),
|
|
|
|
cur_chunk: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: EncoderHelper> EncoderState<T> {
|
|
|
|
/// Write as much as possible of the inner integer to the output `AsyncWrite`
|
|
|
|
pub fn write<W: AsyncWrite>(&mut self, output: W) -> Poll<WriteState, Error> {
|
|
|
|
T::write(self, output)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
|
|
enum AccumulatorState<T> {
|
|
|
|
InProgress(T),
|
|
|
|
NotStarted,
|
|
|
|
Finished,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Default> AccumulatorState<T> {
|
|
|
|
fn take(&mut self) -> Option<T> {
|
|
|
|
use AccumulatorState::*;
|
2018-05-14 15:55:16 +02:00
|
|
|
use std::mem;
|
2017-11-22 18:01:28 +01:00
|
|
|
|
|
|
|
match mem::replace(self, AccumulatorState::Finished) {
|
|
|
|
InProgress(inner) => Some(inner),
|
|
|
|
NotStarted => Some(Default::default()),
|
|
|
|
Finished => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The state struct for the varint bytes-to-bigint FSM
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct DecoderState<T> {
|
|
|
|
accumulator: AccumulatorState<T>,
|
|
|
|
shift: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Default> Default for DecoderState<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
DecoderState {
|
|
|
|
accumulator: AccumulatorState::NotStarted,
|
|
|
|
shift: 0,
|
|
|
|
}
|
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
impl<T: Default> DecoderState<T> {
|
|
|
|
/// Make a new decoder
|
2017-11-01 11:59:52 +01:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Default::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
impl<T: DecoderHelper> DecoderState<T> {
|
|
|
|
/// Make a new decoder
|
|
|
|
pub fn read<R: AsyncRead>(&mut self, input: R) -> Poll<Option<T>, Error> {
|
|
|
|
T::read(self, input)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Wrapper around `DecoderState` to make a `tokio` `Decoder`
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct VarintDecoder<T> {
|
|
|
|
state: Option<DecoderState<T>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Default for VarintDecoder<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
VarintDecoder { state: None }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> VarintDecoder<T> {
|
|
|
|
/// Make a new decoder
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Default::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Default + DecoderHelper> Decoder for VarintDecoder<T> {
|
|
|
|
type Item = T;
|
2017-11-01 11:59:52 +01:00
|
|
|
type Error = io::Error;
|
|
|
|
|
|
|
|
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
|
|
|
loop {
|
2018-01-23 19:23:37 +01:00
|
|
|
if src.is_empty() {
|
|
|
|
if self.state.is_some() {
|
|
|
|
break Err(io::Error::from(io::ErrorKind::UnexpectedEof));
|
|
|
|
} else {
|
|
|
|
break Ok(None);
|
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
} else {
|
|
|
|
// We know that the length is not 0, so this cannot fail.
|
|
|
|
let first_byte = src.split_to(1)[0];
|
2017-11-22 18:01:28 +01:00
|
|
|
let mut state = self.state.take().unwrap_or_default();
|
2017-12-15 17:38:10 +01:00
|
|
|
let out = T::decode_one(&mut state, first_byte)
|
|
|
|
.map_err(|_| io::Error::from(io::ErrorKind::Other))?;
|
2017-11-22 18:01:28 +01:00
|
|
|
|
|
|
|
if let Some(out) = out {
|
|
|
|
break Ok(Some(out));
|
|
|
|
} else {
|
|
|
|
self.state = Some(state);
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-09 15:44:05 +01:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct VarintCodec<W> {
|
|
|
|
inner: VarintCodecInner,
|
|
|
|
marker: PhantomData<W>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Default for VarintCodec<T> {
|
|
|
|
#[inline]
|
|
|
|
fn default() -> VarintCodec<T> {
|
|
|
|
VarintCodec {
|
|
|
|
inner: VarintCodecInner::WaitingForLen(VarintDecoder::default()),
|
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum VarintCodecInner {
|
|
|
|
WaitingForLen(VarintDecoder<usize>),
|
|
|
|
WaitingForData(usize),
|
2018-01-24 11:14:17 +01:00
|
|
|
Poisoned,
|
2018-01-09 15:44:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Decoder for VarintCodec<T> {
|
|
|
|
type Item = BytesMut;
|
|
|
|
type Error = io::Error;
|
|
|
|
|
|
|
|
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
|
|
|
loop {
|
2018-01-24 11:14:17 +01:00
|
|
|
match mem::replace(&mut self.inner, VarintCodecInner::Poisoned) {
|
2018-01-09 15:44:05 +01:00
|
|
|
VarintCodecInner::WaitingForData(len) => {
|
|
|
|
if src.len() >= len {
|
|
|
|
self.inner = VarintCodecInner::WaitingForLen(VarintDecoder::default());
|
|
|
|
return Ok(Some(src.split_to(len)));
|
|
|
|
} else {
|
|
|
|
self.inner = VarintCodecInner::WaitingForData(len);
|
|
|
|
return Ok(None);
|
|
|
|
}
|
2018-03-07 16:20:55 +01:00
|
|
|
}
|
|
|
|
VarintCodecInner::WaitingForLen(mut decoder) => match decoder.decode(src)? {
|
|
|
|
None => {
|
|
|
|
self.inner = VarintCodecInner::WaitingForLen(decoder);
|
|
|
|
return Ok(None);
|
|
|
|
}
|
|
|
|
Some(len) => {
|
|
|
|
self.inner = VarintCodecInner::WaitingForData(len);
|
2018-01-09 15:44:05 +01:00
|
|
|
}
|
|
|
|
},
|
2018-01-24 11:14:17 +01:00
|
|
|
VarintCodecInner::Poisoned => panic!("varint codec was poisoned"),
|
2018-01-09 15:44:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<D> Encoder for VarintCodec<D>
|
2018-03-07 16:20:55 +01:00
|
|
|
where
|
|
|
|
D: IntoBuf + AsRef<[u8]>,
|
2018-01-09 15:44:05 +01:00
|
|
|
{
|
|
|
|
type Item = D;
|
|
|
|
type Error = io::Error;
|
|
|
|
|
|
|
|
fn encode(&mut self, item: D, dst: &mut BytesMut) -> Result<(), io::Error> {
|
2018-01-24 11:14:17 +01:00
|
|
|
let encoded_len = encode(item.as_ref().len());
|
2018-03-15 15:18:21 +01:00
|
|
|
dst.reserve(encoded_len.len() + item.as_ref().len());
|
2018-01-09 15:44:05 +01:00
|
|
|
dst.put(encoded_len);
|
|
|
|
dst.put(item);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
/// Syncronously decode a number from a `Read`
|
|
|
|
pub fn decode<R: Read, T: Default + DecoderHelper>(mut input: R) -> errors::Result<T> {
|
|
|
|
let mut decoder = DecoderState::default();
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
loop {
|
|
|
|
// We read one at a time to prevent consuming too much of the buffer.
|
|
|
|
let mut buffer: [u8; 1] = [0];
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
match input.read_exact(&mut buffer) {
|
|
|
|
Ok(()) => {
|
2017-12-15 17:38:10 +01:00
|
|
|
if let Some(out) = T::decode_one(&mut decoder, buffer[0])
|
|
|
|
.map_err(|_| io::Error::from(io::ErrorKind::Other))?
|
|
|
|
{
|
|
|
|
break Ok(out);
|
|
|
|
}
|
|
|
|
}
|
2017-11-22 18:01:28 +01:00
|
|
|
Err(inner) => break Err(Error::with_chain(inner, ErrorKind::ParseError)),
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
|
|
|
}
|
2017-11-22 18:01:28 +01:00
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
/// Syncronously decode a number from a `Read`
|
2018-01-24 11:14:17 +01:00
|
|
|
pub fn encode<T: EncoderHelper + Bits>(input: T) -> Bytes {
|
|
|
|
use tokio_io::io::AllowStdIo;
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
let mut encoder = EncoderState::new(input);
|
2018-01-24 11:14:17 +01:00
|
|
|
let mut out = AllowStdIo::new(BytesMut::new().writer());
|
2017-11-22 18:01:28 +01:00
|
|
|
|
|
|
|
match T::write(&mut encoder, &mut out).expect("Writing to a vec should never fail, Q.E.D") {
|
2018-01-24 11:14:17 +01:00
|
|
|
Async::Ready(_) => out.into_inner().into_inner().freeze(),
|
2017-11-22 18:01:28 +01:00
|
|
|
Async::NotReady => unreachable!(),
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2018-03-07 16:20:55 +01:00
|
|
|
use super::{decode, EncoderState, VarintDecoder};
|
2017-11-01 11:59:52 +01:00
|
|
|
use futures::{Future, Stream};
|
2018-05-14 15:55:16 +02:00
|
|
|
use num_bigint::BigUint;
|
2018-06-22 16:12:23 +02:00
|
|
|
use tokio_codec::FramedRead;
|
2017-11-01 11:59:52 +01:00
|
|
|
|
2017-12-15 17:38:10 +01:00
|
|
|
#[test]
|
|
|
|
fn large_number_fails() {
|
|
|
|
use super::WriteState;
|
2018-05-14 15:55:16 +02:00
|
|
|
use futures::Async;
|
|
|
|
use std::io::Cursor;
|
2017-12-15 17:38:10 +01:00
|
|
|
|
|
|
|
let mut out = vec![0u8; 10];
|
|
|
|
|
|
|
|
{
|
|
|
|
let writable: Cursor<&mut [_]> = Cursor::new(&mut out);
|
|
|
|
|
|
|
|
let mut state = EncoderState::new(::std::u64::MAX);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
state.write(writable).unwrap(),
|
|
|
|
Async::Ready(WriteState::Done(10))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let result: Result<Option<u32>, _> = FramedRead::new(&out[..], VarintDecoder::new())
|
|
|
|
.into_future()
|
|
|
|
.map(|(out, _)| out)
|
|
|
|
.map_err(|(out, _)| out)
|
|
|
|
.wait();
|
|
|
|
|
|
|
|
assert!(result.is_err());
|
|
|
|
}
|
|
|
|
|
2017-11-01 11:59:52 +01:00
|
|
|
#[test]
|
2017-11-22 18:01:28 +01:00
|
|
|
fn can_decode_basic_biguint() {
|
2017-11-01 11:59:52 +01:00
|
|
|
assert_eq!(
|
|
|
|
BigUint::from(300u16),
|
|
|
|
decode(&[0b10101100, 0b00000010][..]).unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2017-11-22 18:01:28 +01:00
|
|
|
fn can_decode_basic_biguint_async() {
|
2017-11-01 11:59:52 +01:00
|
|
|
let result = FramedRead::new(&[0b10101100, 0b00000010][..], VarintDecoder::new())
|
|
|
|
.into_future()
|
|
|
|
.map(|(out, _)| out)
|
|
|
|
.map_err(|(out, _)| out)
|
|
|
|
.wait();
|
|
|
|
|
|
|
|
assert_eq!(result.unwrap(), Some(BigUint::from(300u16)));
|
|
|
|
}
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
#[test]
|
|
|
|
fn can_decode_trivial_usize_async() {
|
|
|
|
let result = FramedRead::new(&[1][..], VarintDecoder::new())
|
|
|
|
.into_future()
|
|
|
|
.map(|(out, _)| out)
|
|
|
|
.map_err(|(out, _)| out)
|
|
|
|
.wait();
|
|
|
|
|
|
|
|
assert_eq!(result.unwrap(), Some(1usize));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_decode_basic_usize_async() {
|
|
|
|
let result = FramedRead::new(&[0b10101100, 0b00000010][..], VarintDecoder::new())
|
|
|
|
.into_future()
|
|
|
|
.map(|(out, _)| out)
|
|
|
|
.map_err(|(out, _)| out)
|
|
|
|
.wait();
|
|
|
|
|
|
|
|
assert_eq!(result.unwrap(), Some(300usize));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_encode_basic_biguint_async() {
|
|
|
|
use super::WriteState;
|
2018-05-14 15:55:16 +02:00
|
|
|
use futures::Async;
|
|
|
|
use std::io::Cursor;
|
2017-11-22 18:01:28 +01:00
|
|
|
|
|
|
|
let mut out = vec![0u8; 2];
|
|
|
|
|
|
|
|
{
|
|
|
|
let writable: Cursor<&mut [_]> = Cursor::new(&mut out);
|
|
|
|
|
|
|
|
let mut state = EncoderState::new(BigUint::from(300usize));
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
state.write(writable).unwrap(),
|
|
|
|
Async::Ready(WriteState::Done(2))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(out, vec![0b10101100, 0b00000010]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_encode_basic_usize_async() {
|
|
|
|
use super::WriteState;
|
2018-05-14 15:55:16 +02:00
|
|
|
use futures::Async;
|
|
|
|
use std::io::Cursor;
|
2017-11-22 18:01:28 +01:00
|
|
|
|
|
|
|
let mut out = vec![0u8; 2];
|
|
|
|
|
|
|
|
{
|
|
|
|
let writable: Cursor<&mut [_]> = Cursor::new(&mut out);
|
|
|
|
|
|
|
|
let mut state = EncoderState::new(300usize);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
state.write(writable).unwrap(),
|
|
|
|
Async::Ready(WriteState::Done(2))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(out, vec![0b10101100, 0b00000010]);
|
|
|
|
}
|
|
|
|
|
2017-11-01 11:59:52 +01:00
|
|
|
#[test]
|
|
|
|
fn unexpected_eof_async() {
|
|
|
|
use std::io;
|
|
|
|
|
2017-11-22 18:01:28 +01:00
|
|
|
let result = FramedRead::new(&[0b10101100, 0b10000010][..], VarintDecoder::<usize>::new())
|
2017-11-01 11:59:52 +01:00
|
|
|
.into_future()
|
|
|
|
.map(|(out, _)| out)
|
|
|
|
.map_err(|(out, _)| out)
|
|
|
|
.wait();
|
|
|
|
|
|
|
|
assert_eq!(result.unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
|
|
|
|
}
|
2018-01-23 19:23:37 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_panic_after_eof() {
|
|
|
|
FramedRead::new(&[1, 1][..], VarintDecoder::<usize>::new())
|
|
|
|
.collect()
|
|
|
|
.wait()
|
|
|
|
.unwrap();
|
|
|
|
}
|
2017-11-01 11:59:52 +01:00
|
|
|
}
|