diff --git a/TODO.md b/TODO.md index 071af29..efbf4c0 100644 --- a/TODO.md +++ b/TODO.md @@ -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 instead. - Remove dependency on bytes crate entirely. diff --git a/src/proto/codec.rs b/src/proto/codec.rs index d249627..7e47f7a 100644 --- a/src/proto/codec.rs +++ b/src/proto/codec.rs @@ -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 { +/// Encodes entire protocol frames containing values of type `T`. +pub struct FrameEncoder { phantom: marker::PhantomData, } -impl LengthPrefixedEncoder { +impl FrameEncoder { pub fn new() -> Self { Self { phantom: marker::PhantomData, } } -} -impl tokio_codec::Encoder for LengthPrefixedEncoder { - 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 { - // 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, - +/// Decodes entire protocol frames containing values of type `T`. +pub struct FrameDecoder { // Only here to enable parameterizing `Decoder` by `T`. phantom: marker::PhantomData, } -impl LengthPrefixedDecoder { +impl FrameDecoder { 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, 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::()?; - - self.length = Some(length as usize); - Ok(()) - } -} - -impl tokio_codec::Decoder for LengthPrefixedDecoder { - type Item = T; - type Error = io::Error; - - fn decode(&mut self, src: &mut BytesMut) -> Result, 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 = 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 = LengthPrefixedDecoder::new().decode(&mut bytes).unwrap(); + let value: Option = 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 = 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 = 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 = 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![]); diff --git a/src/proto/prefix.rs b/src/proto/prefix.rs index 7113000..c2a756b 100644 --- a/src/proto/prefix.rs +++ b/src/proto/prefix.rs @@ -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) -> 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) -> 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 { + // 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); - } } diff --git a/src/proto/value_codec.rs b/src/proto/value_codec.rs index fc23ae7..bbd6795 100644 --- a/src/proto/value_codec.rs +++ b/src/proto/value_codec.rs @@ -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 { /// Attempts to decode an instance of `T` from `self`. fn decode(&mut self) -> io::Result; @@ -316,7 +320,7 @@ impl From 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, + 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) -> 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::().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::(); @@ -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);