Browse Source

Re-use BytesMut for encoding and decoding.

Refactor LengthPrefixed{De, En}coder to Frame{De,En}coder.
wip
Titouan Rigoudy 5 years ago
parent
commit
da74ff8d4e
4 changed files with 281 additions and 236 deletions
  1. +1
    -0
      TODO.md
  2. +130
    -138
      src/proto/codec.rs
  3. +75
    -65
      src/proto/prefix.rs
  4. +75
    -33
      src/proto/value_codec.rs

+ 1
- 0
TODO.md View File

@ -1,6 +1,7 @@
Things to do:
-------------
- Switch from `encoding` to `encoding_rs` crate
- Define error type for ProtoDecoder errors.
- Remove BytesMut dependency from ProtoEncoder, use Vec<u8> instead.
- Remove dependency on bytes crate entirely.


+ 130
- 138
src/proto/codec.rs View File

@ -1,142 +1,134 @@
//! This module provides tokio Codec implementations for protocol messages.
//! This module provides a codec implementation for protocol frames.
//!
//! Specifically, the following types:
//!
//! * proto::peer::Message
//! * proto::server::ServerRequest
//! * proto::server::ServerResponse
//!
//! This enables wrapping AsyncRead and AsyncWrite objects into Stream and Sink
//! objects using tokio_codec's FramedRead and FramedWrite adapters.
// TODO: Refactor all this into futures and remove tokio dependency.
//! The goal of this codec is to transform byte streams into value streams.
use std::io;
use std::convert::TryInto;
use std::marker;
use bytes::BytesMut;
use tokio_codec;
use super::peer::Message;
use super::server::{ServerRequest, ServerResponse};
use super::u32::U32_BYTE_LEN;
use super::value_codec::{ValueDecode, ValueDecoder, ValueEncode, ValueEncoder};
use thiserror::Error;
use super::prefix::Prefixer;
use super::u32::{decode_u32, U32_BYTE_LEN};
use super::value_codec::{
ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, ValueEncoder,
};
#[derive(Debug, Error, PartialEq)]
pub enum FrameEncodeError {
#[error("encoded value length {length} is too large")]
ValueTooLarge {
/// The length of the encoded value.
length: usize,
},
#[error("failed to encode value: {0}")]
ValueEncodeError(#[from] ValueEncodeError),
}
/// Implements tokio's Encoder trait for types that implement ValueEncode.
pub struct LengthPrefixedEncoder<T> {
/// Encodes entire protocol frames containing values of type `T`.
pub struct FrameEncoder<T> {
phantom: marker::PhantomData<T>,
}
impl<T> LengthPrefixedEncoder<T> {
impl<T: ValueEncode> FrameEncoder<T> {
pub fn new() -> Self {
Self {
phantom: marker::PhantomData,
}
}
}
impl<T: ValueEncode> tokio_codec::Encoder for LengthPrefixedEncoder<T> {
type Item = T;
type Error = io::Error;
fn encode_to(&mut self, value: &T, buffer: &mut BytesMut) -> Result<(), FrameEncodeError> {
let mut prefixer = Prefixer::new(buffer);
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
// Encode the message.
// Note that this is ugly right now, but will get better once we switch
// off of Tokio and onto regular futures.
let mut buffer = vec![];
ValueEncoder::new(&mut buffer).encode(&item)?;
ValueEncoder::new(prefixer.suffix_mut()).encode(value)?;
// Encode the message length.
let mut prefix = vec![];
ValueEncoder::new(&mut prefix).encode_u32(buffer.len() as u32)?;
if let Err(prefixer) = prefixer.finalize() {
return Err(FrameEncodeError::ValueTooLarge {
length: prefixer.suffix().len(),
});
}
dst.reserve(prefix.len() + buffer.len());
dst.extend_from_slice(&prefix);
dst.extend_from_slice(&buffer);
Ok(())
}
}
/// Implements tokio's Decoder trait for types that implement ValueDecode.
pub struct LengthPrefixedDecoder<T> {
// The length, as a number of bytes, of the next item to decode.
// None if we have not read the length prefix yet.
// Some(n) if we read the length prefix, and are now waiting for `n` bytes
// to be available.
length: Option<usize>,
/// Decodes entire protocol frames containing values of type `T`.
pub struct FrameDecoder<T> {
// Only here to enable parameterizing `Decoder` by `T`.
phantom: marker::PhantomData<T>,
}
impl<T> LengthPrefixedDecoder<T> {
impl<T: ValueDecode> FrameDecoder<T> {
pub fn new() -> Self {
Self {
length: None,
phantom: marker::PhantomData,
}
}
// If necessary, atempts to decode a length prefix from `src`.
//
// Helper for decode() below.
//
// If self.length is not None, returns Ok(()).
// If there are not enough bytes in `src`, returns Ok(()).
// Otherwise, splits off the length prefix bytes from `src`, and:
// - returns an error if decoding the value failed.
// - sets self.length to Some(length) and returns Ok(()) otherwise.
fn maybe_decode_length(&mut self, src: &mut BytesMut) -> io::Result<()> {
if self.length.is_some() {
return Ok(()); // Aready read length.
}
if src.len() < U32_BYTE_LEN {
return Ok(()); // Not enough bytes yet.
/// Attempts to decode an entire frame from the given buffer.
///
/// Returns `Ok(Some(frame))` if successful, in which case the frame's bytes
/// have been split off from the left of `bytes`.
///
/// Returns `Ok(None)` if not enough bytes are available to decode an entire
/// frame yet, in which case `bytes` is untouched.
///
/// Returns an error if the length prefix or the framed value are malformed,
/// in which case `bytes` is untouched.
pub fn decode_from(&mut self, bytes: &mut BytesMut) -> Result<Option<T>, ValueDecodeError> {
if bytes.len() < U32_BYTE_LEN {
return Ok(None); // Not enough bytes yet.
}
let prefix = src.split_to(U32_BYTE_LEN);
let length = ValueDecoder::new(&prefix).decode::<u32>()?;
self.length = Some(length as usize);
Ok(())
}
}
impl<T: ValueDecode> tokio_codec::Decoder for LengthPrefixedDecoder<T> {
type Item = T;
type Error = io::Error;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
// If we have not read the length prefix yet, attempt to do so first.
self.maybe_decode_length(src)?;
let length = match self.length {
None => return Ok(None), // Not enough bytes yet.
Some(n) => n,
};
if src.len() < length {
// Split the prefix off. After this:
//
// | bytes (len 4) | suffix |
//
// NOTE: This method would be simpler if we could use split_to() instead
// here such that `bytes` contained the suffix. At the end, we would not
// have to replace `bytes` with `suffix`. However, that would require
// calling `prefix.unsplit(*bytes)`, and that does not work since
// `bytes` is only borrowed, and unsplit() takes its argument by value.
let mut suffix = bytes.split_off(U32_BYTE_LEN);
// unwrap() cannot panic because `bytes` is of the exact right length.
let array: [u8; U32_BYTE_LEN] = bytes.as_ref().try_into().unwrap();
let length = decode_u32(array) as usize;
if suffix.len() < length {
// Re-assemble `bytes` as it first was.
bytes.unsplit(suffix);
return Ok(None); // Not enough bytes yet.
}
// Split off the right amount of bytes from the buffer.
let buf = src.split_to(length);
self.length = None;
// Split off the right amount of bytes from the buffer. After this:
//
// | bytes (len 4) | contents | suffix |
//
let mut contents = suffix.split_to(length);
// Attempt to decode the value.
let item = ValueDecoder::new(&buf).decode()?;
let item = match ValueDecoder::new(&contents).decode() {
Ok(item) => item,
Err(error) => {
// Re-assemble `bytes` as it first was.
contents.unsplit(suffix);
bytes.unsplit(contents);
return Err(error);
}
};
// Remove the decoded bytes from the left of `bytes`.
*bytes = suffix;
Ok(Some(item))
}
}
mod tests {
use bytes::BytesMut;
use tokio_codec::{Decoder, Encoder};
use crate::proto::ValueEncode;
use super::{LengthPrefixedDecoder, LengthPrefixedEncoder};
use super::{FrameDecoder, FrameEncoder};
// Test value: [1, 3, 3, 7] in little-endian.
const U32_1337: u32 = 1 + (3 << 8) + (3 << 16) + (7 << 24);
@ -144,8 +136,9 @@ mod tests {
#[test]
fn encode_u32() {
let mut bytes = BytesMut::new();
LengthPrefixedEncoder::new()
.encode(U32_1337, &mut bytes)
FrameEncoder::new()
.encode_to(&U32_1337, &mut bytes)
.unwrap();
assert_eq!(
@ -157,12 +150,31 @@ mod tests {
);
}
#[test]
fn encode_appends() {
let mut bytes = BytesMut::new();
let mut encoder = FrameEncoder::new();
encoder.encode_to(&U32_1337, &mut bytes).unwrap();
encoder.encode_to(&U32_1337, &mut bytes).unwrap();
assert_eq!(
bytes,
vec![
4, 0, 0, 0, // 1 32-bit integer = 4 bytes.
1, 3, 3, 7, // Little-endian integer.
4, 0, 0, 0, // Repeated.
1, 3, 3, 7,
]
);
}
#[test]
fn encode_vec() {
let v: Vec<u32> = vec![1, 3, 3, 7];
let mut bytes = BytesMut::new();
LengthPrefixedEncoder::new().encode(v, &mut bytes).unwrap();
FrameEncoder::new().encode_to(&v, &mut bytes).unwrap();
assert_eq!(
bytes,
@ -178,17 +190,33 @@ mod tests {
}
#[test]
fn decode_not_enough_data() {
fn decode_not_enough_data_for_prefix() {
let mut bytes = BytesMut::from(vec![
4, 0, 0, // Incomplete 32-bit length prefix.
]);
let value: Option<u32> = LengthPrefixedDecoder::new().decode(&mut bytes).unwrap();
let value: Option<u32> = FrameDecoder::new().decode_from(&mut bytes).unwrap();
assert_eq!(value, None);
assert_eq!(bytes, vec![4, 0, 0]); // Untouched.
}
#[test]
fn decode_not_enough_data_for_contents() {
let initial_bytes = vec![
4, 0, 0, 0, // Length 4.
1, 2, 3, // But there are only 3 bytes!
];
let mut bytes = BytesMut::new();
bytes.extend_from_slice(&initial_bytes);
let value: Option<u32> = FrameDecoder::new().decode_from(&mut bytes).unwrap();
assert_eq!(value, None);
assert_eq!(bytes, initial_bytes); // Untouched.
}
#[test]
fn decode_u32() {
let mut bytes = BytesMut::from(vec![
@ -197,7 +225,7 @@ mod tests {
4, 2, // Trailing bytes.
]);
let value = LengthPrefixedDecoder::new().decode(&mut bytes).unwrap();
let value = FrameDecoder::new().decode_from(&mut bytes).unwrap();
assert_eq!(value, Some(U32_1337));
assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off.
@ -215,47 +243,13 @@ mod tests {
4, 2, // Trailing bytes.
]);
let value = LengthPrefixedDecoder::new().decode(&mut bytes).unwrap();
let value = FrameDecoder::new().decode_from(&mut bytes).unwrap();
let expected_value: Vec<u32> = vec![1, 3, 3, 7];
assert_eq!(value, Some(expected_value));
assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off.
}
#[test]
fn decode_stateful() {
let mut decoder = LengthPrefixedDecoder::new();
let mut bytes = BytesMut::from(vec![
4, 0, 0, 0, // 32-bit integer = 4 bytes.
1, 3, // Incomplete integer.
]);
let value = decoder.decode(&mut bytes).unwrap();
assert_eq!(value, None);
assert_eq!(bytes, vec![1, 3]); // Decoded bytes were split off.
bytes.extend_from_slice(&[
3, 7, // End of integer.
4, 0, 0, 0, // Second identical message waiting to be read.
1, 3, 3, 7, //
4, 2, // Trailing bytes.
]);
// Decoder has state, remembers that the length prefix was 4.
let value = decoder.decode(&mut bytes).unwrap();
assert_eq!(value, Some(U32_1337));
// Decoder state resets after entire item is decoded.
// Decode the second message now.
let value = decoder.decode(&mut bytes).unwrap();
assert_eq!(value, Some(U32_1337));
assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off.
}
#[test]
fn roundtrip() {
let value: Vec<String> = vec![
@ -267,10 +261,8 @@ mod tests {
let mut buffer = BytesMut::new();
LengthPrefixedEncoder::new()
.encode(value.clone(), &mut buffer)
.unwrap();
let decoded = LengthPrefixedDecoder::new().decode(&mut buffer).unwrap();
FrameEncoder::new().encode_to(&value, &mut buffer).unwrap();
let decoded = FrameDecoder::new().decode_from(&mut buffer).unwrap();
assert_eq!(decoded, Some(value));
assert_eq!(buffer, vec![]);


+ 75
- 65
src/proto/prefix.rs View File

@ -3,50 +3,79 @@
use std::convert::TryFrom;
use bytes::BytesMut;
use crate::proto::u32::{encode_u32, U32_BYTE_LEN};
/// Encodes a length prefix in a buffer.
pub struct Prefixer {
/// The position of the length prefix in the target buffer.
position: usize,
}
/// Helper for writing length-prefixed values into buffers, without having to
/// know the length ahead of encoding time.
#[derive(Debug)]
pub struct Prefixer<'a> {
/// The prefix buffer.
///
/// The length of the suffix buffer is written to the end of this buffer
/// when the prefixer is finalized.
///
/// Contains any bytes with which this prefixer was constructed.
prefix: &'a mut BytesMut,
impl Prefixer {
/// Reserves space for the length prefix at the end of the given buffer.
/// The suffix buffer.
///
/// Returns a prefixer for writing the length later.
pub fn new(buffer: &mut Vec<u8>) -> Prefixer {
// Remember where we were.
let result = Prefixer {
position: buffer.len(),
};
// Reserve enough bytes to write the prefix into later.
buffer.extend_from_slice(&[0; U32_BYTE_LEN]);
result
/// This is the buffer into which data is written before finalization.
suffix: BytesMut,
}
impl Prefixer<'_> {
/// Constructs a prefixer for easily appending a length prefixed value to
/// the given buffer.
pub fn new<'a>(buffer: &'a mut BytesMut) -> Prefixer<'a> {
// Reserve some space fot the prefix, but don't write it yet.
buffer.reserve(U32_BYTE_LEN);
// Split off the suffix, into which bytes will be written.
let suffix = buffer.split_off(buffer.len() + U32_BYTE_LEN);
Prefixer {
prefix: buffer,
suffix: suffix,
}
}
/// Writes the length prefix into the given buffer in the reserved space.
///
/// The given buffer must be the same one passed to new(), and should not
/// have been truncated since then.
/// Returns a reference to the buffer into which data is written.
pub fn suffix(&self) -> &BytesMut {
&self.suffix
}
/// Returns a mutable reference to a buffer into which data can be written.
pub fn suffix_mut(&mut self) -> &mut BytesMut {
&mut self.suffix
}
/// Returns a buffer containing the original data passed at construction
/// time, to which a length-prefixed value is appended. The value itself is
/// the data written into the buffer returned by `get_mut()`.
///
/// Panics if the buffer is not large enough to store the prefix.
/// Returns `Ok(length)` if successful, in which case the length of the
/// suffix is `length`.
///
/// Returns `Err(length)` if `length`, the length of the suffix, is too
/// large to store in the reserved space.
pub fn finalize(self, buffer: &mut Vec<u8>) -> Result<(), usize> {
// The position at which the value should have been encoded.
let value_position = self.position + U32_BYTE_LEN;
assert!(buffer.len() >= value_position);
// Calculate the value's length, check it is not too large.
let length = buffer.len() - value_position;
let length_u32 = u32::try_from(length).map_err(|_| length)?;
// Write the length prefix into the reserved space.
let length_bytes = encode_u32(length_u32);
buffer[self.position..value_position].copy_from_slice(&length_bytes);
Ok(())
/// Returns `Err(self)` if the length of the suffix is too large to store as
/// a prefix.
pub fn finalize(self) -> Result<u32, Self> {
// Check that the suffix's length is not too large.
let length = self.suffix.len();
let length_u32 = match u32::try_from(length) {
Ok(value) => value,
Err(_) => return Err(self),
};
// Write the prefix.
self.prefix.extend_from_slice(&encode_u32(length_u32));
// Join the prefix and suffix back again. Because `self.prefix` is
// private, we are sure that this is O(1).
self.prefix.unsplit(self.suffix);
Ok(length_u32)
}
}
@ -56,23 +85,16 @@ mod tests {
use std::convert::TryInto;
use crate::proto::u32::{decode_u32, U32_BYTE_LEN};
#[test]
fn new_reserves_space() {
let mut buffer = vec![13];
Prefixer::new(&mut buffer);
use bytes::{BufMut, BytesMut};
assert_eq!(buffer.len(), U32_BYTE_LEN + 1);
assert_eq!(buffer[0], 13);
}
use crate::proto::u32::{decode_u32, U32_BYTE_LEN};
#[test]
fn finalize_empty() {
let mut buffer = vec![13];
let mut buffer = BytesMut::new();
buffer.put_u8(13);
Prefixer::new(&mut buffer).finalize(&mut buffer).unwrap();
Prefixer::new(&mut buffer).finalize().unwrap();
assert_eq!(buffer.len(), U32_BYTE_LEN + 1);
let array: [u8; U32_BYTE_LEN] = buffer[1..].try_into().unwrap();
@ -81,13 +103,14 @@ mod tests {
#[test]
fn finalize_ok() {
let mut buffer = vec![13];
let mut buffer = BytesMut::new();
buffer.put_u8(13);
let prefixer = Prefixer::new(&mut buffer);
let mut prefixer = Prefixer::new(&mut buffer);
buffer.extend_from_slice(&[0; 42]);
prefixer.suffix_mut().extend_from_slice(&[0; 42]);
prefixer.finalize(&mut buffer).unwrap();
prefixer.finalize().unwrap();
// 1 junk prefix byte, length prefix, 42 bytes of value.
assert_eq!(buffer.len(), U32_BYTE_LEN + 43);
@ -95,17 +118,4 @@ mod tests {
let array: [u8; U32_BYTE_LEN] = prefix.try_into().unwrap();
assert_eq!(decode_u32(array), 42);
}
#[test]
#[should_panic]
fn finalize_truncated() {
let mut buffer = vec![13];
let prefixer = Prefixer::new(&mut buffer);
buffer = vec![];
// Explodes.
let _ = prefixer.finalize(&mut buffer);
}
}

+ 75
- 33
src/proto/value_codec.rs View File

@ -12,17 +12,21 @@
//! encoded characters.
//! * Pairs are serialized as two consecutive values.
//! * Vectors are serialized as length-prefixed arrays of serialized values.
//!
//! See the `frame_codec` module for the codec applied to byte streams.
use std::io;
use std::net;
use crate::proto::prefix::Prefixer;
use crate::proto::u32::{decode_u32, encode_u32, U32_BYTE_LEN};
use bytes::{BufMut, BytesMut};
use encoding::all::WINDOWS_1252;
use encoding::{DecoderTrap, EncoderTrap, Encoding};
use std::convert::{TryFrom, TryInto};
use thiserror::Error;
use super::prefix::Prefixer;
use super::u32::{decode_u32, encode_u32, U32_BYTE_LEN};
pub trait Decode<T> {
/// Attempts to decode an instance of `T` from `self`.
fn decode(&mut self) -> io::Result<T>;
@ -316,7 +320,7 @@ impl From<ValueEncodeError> for io::Error {
/// A type for encoding various types of values into protocol messages.
pub struct ValueEncoder<'a> {
/// The buffer to which the encoder appends encoded bytes.
buffer: &'a mut Vec<u8>,
buffer: &'a mut BytesMut,
}
/// This trait is implemented by types that can be encoded into messages using
@ -331,7 +335,7 @@ impl<'a> ValueEncoder<'a> {
/// Wraps the given buffer for encoding values into.
///
/// Encoded bytes are appended. The buffer is not pre-cleared.
pub fn new(buffer: &'a mut Vec<u8>) -> Self {
pub fn new(buffer: &'a mut BytesMut) -> Self {
ValueEncoder { buffer: buffer }
}
@ -348,29 +352,33 @@ impl<'a> ValueEncoder<'a> {
/// Encodes the given boolean value into the underlying buffer.
pub fn encode_bool(&mut self, val: bool) -> Result<(), ValueEncodeError> {
self.buffer.push(val as u8);
self.buffer.put_u8(val as u8);
Ok(())
}
/// Encodes the given string into the underlying buffer.
pub fn encode_string(&mut self, val: &str) -> Result<(), ValueEncodeError> {
// Reserve space for the length prefix.
let prefixer = Prefixer::new(self.buffer);
let mut prefixer = Prefixer::new(self.buffer);
// Encode the string. We are quite certain this cannot fail because we
// use EncoderTrap::Replace to replace any unencodable characters with
// '?' which is always encodable in Windows-1252.
WINDOWS_1252
.encode_to(val, EncoderTrap::Replace, self.buffer)
.unwrap();
//
// TODO: Switch to the encoding_rs crate.
let bytes = WINDOWS_1252.encode(val, EncoderTrap::Replace).unwrap();
prefixer.suffix_mut().extend_from_slice(&bytes);
// Write the length prefix in the space we initially reserved for it.
prefixer
.finalize(self.buffer)
.map_err(|length| ValueEncodeError::StringTooLong {
if let Err(prefixer) = prefixer.finalize() {
return Err(ValueEncodeError::StringTooLong {
string: val.to_string(),
length: length,
})
length: prefixer.suffix().len(),
});
}
Ok(())
}
/// Encodes the given value into the underlying buffer.
@ -469,6 +477,8 @@ pub mod tests {
use std::u16;
use std::u32;
use bytes::{BufMut, BytesMut};
use super::{ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncoder};
// Declared here because assert_eq!(bytes, &[]) fails to infer types.
@ -478,7 +488,7 @@ pub mod tests {
where
T: fmt::Debug + Eq + PartialEq + ValueEncode + ValueDecode,
{
let mut bytes = vec![];
let mut bytes = BytesMut::new();
ValueEncoder::new(&mut bytes).encode(&input).unwrap();
let output = ValueDecoder::new(&bytes).decode::<T>().unwrap();
@ -501,9 +511,12 @@ pub mod tests {
#[test]
fn encode_u32() {
for &(val, ref encoded_bytes) in &U32_ENCODINGS {
let mut bytes = vec![13];
let mut expected_bytes = vec![13];
expected_bytes.extend(encoded_bytes);
let mut bytes = BytesMut::new();
bytes.put_u8(13);
let mut expected_bytes = BytesMut::new();
expected_bytes.put_u8(13);
expected_bytes.extend_from_slice(encoded_bytes);
ValueEncoder::new(&mut bytes).encode_u32(val).unwrap();
assert_eq!(bytes, expected_bytes);
@ -532,7 +545,9 @@ pub mod tests {
#[test]
fn decode_u32_unexpected_eof() {
let buffer = vec![13];
let mut buffer = BytesMut::new();
buffer.put_u8(13);
let mut decoder = ValueDecoder::new(&buffer);
let result = decoder.decode::<u32>();
@ -550,15 +565,21 @@ pub mod tests {
#[test]
fn encode_bool_false() {
let mut bytes = vec![13];
let mut bytes = BytesMut::new();
bytes.put_u8(13);
ValueEncoder::new(&mut bytes).encode_bool(false).unwrap();
assert_eq!(bytes, vec![13, 0]);
}
#[test]
fn encode_bool_true() {
let mut bytes = vec![13];
let mut bytes = BytesMut::new();
bytes.put_u8(13);
ValueEncoder::new(&mut bytes).encode_bool(true).unwrap();
assert_eq!(bytes, vec![13, 1]);
}
@ -628,11 +649,15 @@ pub mod tests {
continue;
}
let mut bytes = vec![13];
let mut expected_bytes = vec![13];
let mut bytes = BytesMut::new();
bytes.put_u8(13);
let mut expected_bytes = BytesMut::new();
expected_bytes.put_u8(13);
expected_bytes.extend(encoded_bytes);
ValueEncoder::new(&mut bytes).encode(&(val as u16)).unwrap();
assert_eq!(bytes, expected_bytes);
}
}
@ -687,12 +712,17 @@ pub mod tests {
#[test]
fn encode_ipv4() {
for &(val, ref encoded_bytes) in &U32_ENCODINGS {
let mut bytes = vec![13];
let mut expected_bytes = vec![13];
let mut bytes = BytesMut::new();
bytes.put_u8(13);
let mut expected_bytes = BytesMut::new();
expected_bytes.put_u8(13);
expected_bytes.extend(encoded_bytes);
let addr = net::Ipv4Addr::from(val);
ValueEncoder::new(&mut bytes).encode(&addr).unwrap();
assert_eq!(bytes, expected_bytes);
}
}
@ -727,25 +757,29 @@ pub mod tests {
#[test]
fn encode_string() {
for &(string, encoded_bytes) in &STRING_ENCODINGS {
let mut bytes = vec![13];
let mut expected_bytes = vec![13];
let mut bytes = BytesMut::new();
bytes.put_u8(13);
let mut expected_bytes = BytesMut::new();
expected_bytes.put_u8(13);
expected_bytes.extend(encoded_bytes);
ValueEncoder::new(&mut bytes).encode_string(string).unwrap();
assert_eq!(bytes, expected_bytes);
}
}
#[test]
fn encode_string_with_unencodable_characters() {
let mut bytes = vec![];
let mut bytes = BytesMut::new();
ValueEncoder::new(&mut bytes)
.encode_string("忠犬ハチ公")
.unwrap();
// Characters not in the Windows 1252 codepage are rendered as '?'.
assert_eq!(bytes, &[5, 0, 0, 0, 63, 63, 63, 63, 63]);
assert_eq!(bytes, vec![5, 0, 0, 0, 63, 63, 63, 63, 63]);
assert_eq!(ValueDecoder::new(&bytes).decode_string().unwrap(), "?????");
}
@ -771,8 +805,11 @@ pub mod tests {
#[test]
fn encode_pair_u32_string() {
let mut bytes = vec![13];
let mut expected_bytes = vec![13];
let mut bytes = BytesMut::new();
bytes.put_u8(13);
let mut expected_bytes = BytesMut::new();
expected_bytes.put_u8(13);
let (integer, ref expected_integer_bytes) = U32_ENCODINGS[0];
let (string, expected_string_bytes) = STRING_ENCODINGS[0];
@ -813,13 +850,18 @@ pub mod tests {
#[test]
fn encode_u32_vector() {
let mut vec = vec![];
let mut expected_bytes = vec![13, U32_ENCODINGS.len() as u8, 0, 0, 0];
let mut expected_bytes = BytesMut::new();
expected_bytes.extend_from_slice(&[13, U32_ENCODINGS.len() as u8, 0, 0, 0]);
for &(val, ref encoded_bytes) in &U32_ENCODINGS {
vec.push(val);
expected_bytes.extend(encoded_bytes);
}
let mut bytes = vec![13];
let mut bytes = BytesMut::new();
bytes.put_u8(13);
ValueEncoder::new(&mut bytes).encode(&vec).unwrap();
assert_eq!(bytes, expected_bytes);


Loading…
Cancel
Save