use core::convert;
use crate::{
channel::Channel,
command::Command,
error::{ParseError, SerializationError},
util::{Parser, Serializer},
};
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Packet<T: AsRef<[u8]>> {
Initialization(InitializationPacket<T>),
Continuation(ContinuationPacket<T>),
}
impl<T: AsRef<[u8]>> Packet<T> {
pub fn channel(&self) -> Channel {
match self {
Self::Initialization(packet) => packet.channel,
Self::Continuation(packet) => packet.channel,
}
}
pub fn packet_type(&self) -> PacketType {
match self {
Self::Initialization(_) => PacketType::Initialization,
Self::Continuation(_) => PacketType::Continuation,
}
}
pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize, SerializationError> {
match self {
Self::Initialization(packet) => packet.serialize(buffer),
Self::Continuation(packet) => packet.serialize(buffer),
}
}
}
impl<T: AsRef<[u8]>> From<ContinuationPacket<T>> for Packet<T> {
fn from(packet: ContinuationPacket<T>) -> Self {
Self::Continuation(packet)
}
}
impl<T: AsRef<[u8]>> From<InitializationPacket<T>> for Packet<T> {
fn from(packet: InitializationPacket<T>) -> Self {
Self::Initialization(packet)
}
}
impl<'a, T: AsRef<[u8]> + convert::TryFrom<&'a [u8]>> convert::TryFrom<&'a [u8]> for Packet<T> {
type Error = ParseError;
fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
if data.len() < 5 {
return Err(ParseError::NotEnoughData);
}
let command_or_sequence = data[4];
if command_or_sequence.leading_ones() > 0 {
InitializationPacket::try_from(data).map(From::from)
} else {
ContinuationPacket::try_from(data).map(From::from)
}
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum PacketType {
Initialization,
Continuation,
}
pub const INITIALIZATION_HEADER_SIZE: usize = 7;
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct InitializationPacket<T: AsRef<[u8]>> {
pub channel: Channel,
pub command: Command,
pub length: u16,
pub data: T,
}
impl<T: AsRef<[u8]>> InitializationPacket<T> {
pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize, SerializationError> {
let mut serializer = Serializer::new(buffer);
serializer.push_slice(&self.channel.to_bytes())?;
serializer.push_slice(&[u8::from(self.command) | 0b1000_0000])?;
serializer.push_slice(&self.length.to_be_bytes())?;
serializer.push_slice(self.data.as_ref())?;
Ok(serializer.bytes_written())
}
}
impl<T: AsRef<[u8]>> convert::TryFrom<Packet<T>> for InitializationPacket<T> {
type Error = ParseError;
fn try_from(packet: Packet<T>) -> Result<Self, Self::Error> {
if let Packet::Initialization(packet) = packet {
Ok(packet)
} else {
Err(ParseError::InvalidPacketType {
expected: PacketType::Initialization,
actual: packet.packet_type(),
})
}
}
}
impl<'a, T: AsRef<[u8]> + convert::TryFrom<&'a [u8]>> convert::TryFrom<&'a [u8]>
for InitializationPacket<T>
{
type Error = ParseError;
fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
let mut parser = Parser::new(data);
let channel = parser.take_into()?;
let command = parser.take()?;
let length = parser.take_array()?;
let rest = parser.into_rest();
if command.leading_ones() == 0 {
return Err(ParseError::InvalidPacketType {
expected: PacketType::Initialization,
actual: PacketType::Continuation,
});
}
Ok(InitializationPacket {
channel,
command: Command::from(command & 0b0111_1111),
length: u16::from_be_bytes(length),
data: T::try_from(rest).map_err(|_| ParseError::BufferCreationFailed)?,
})
}
}
pub const CONTINUATION_HEADER_SIZE: usize = 5;
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct ContinuationPacket<T: AsRef<[u8]>> {
pub channel: Channel,
pub sequence: u8,
pub data: T,
}
impl<T: AsRef<[u8]>> ContinuationPacket<T> {
pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize, SerializationError> {
let mut serializer = Serializer::new(buffer);
serializer.push_slice(&self.channel.to_bytes())?;
serializer.push_slice(&[self.sequence])?;
serializer.push_slice(self.data.as_ref())?;
Ok(serializer.bytes_written())
}
}
impl<T: AsRef<[u8]>> convert::TryFrom<Packet<T>> for ContinuationPacket<T> {
type Error = ParseError;
fn try_from(packet: Packet<T>) -> Result<Self, Self::Error> {
if let Packet::Continuation(packet) = packet {
Ok(packet)
} else {
Err(ParseError::InvalidPacketType {
expected: PacketType::Continuation,
actual: packet.packet_type(),
})
}
}
}
impl<'a, T: AsRef<[u8]> + convert::TryFrom<&'a [u8]>> convert::TryFrom<&'a [u8]>
for ContinuationPacket<T>
{
type Error = ParseError;
fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
let mut parser = Parser::new(data);
let channel = parser.take_into()?;
let sequence = parser.take()?;
let rest = parser.into_rest();
if sequence.leading_ones() > 0 {
return Err(ParseError::InvalidPacketType {
expected: PacketType::Continuation,
actual: PacketType::Initialization,
});
}
Ok(ContinuationPacket {
channel,
sequence,
data: T::try_from(rest).map_err(|_| ParseError::BufferCreationFailed)?,
})
}
}
#[cfg(test)]
mod test {
use std::convert::TryFrom;
use quickcheck::{Arbitrary, TestResult};
use super::{ContinuationPacket, InitializationPacket, Packet, PacketType};
impl Arbitrary for Packet<Vec<u8>> {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
match PacketType::arbitrary(g) {
PacketType::Initialization => Packet::Initialization(Arbitrary::arbitrary(g)),
PacketType::Continuation => Packet::Continuation(Arbitrary::arbitrary(g)),
}
}
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
match self {
Packet::Initialization(packet) => Box::new(packet.shrink().map(From::from)),
Packet::Continuation(packet) => Box::new(packet.shrink().map(From::from)),
}
}
}
impl Arbitrary for PacketType {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
*g.choose(&[PacketType::Initialization, PacketType::Continuation])
.unwrap()
}
}
impl Arbitrary for InitializationPacket<Vec<u8>> {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
Self {
channel: Arbitrary::arbitrary(g),
command: Arbitrary::arbitrary(g),
length: Arbitrary::arbitrary(g),
data: Arbitrary::arbitrary(g),
}
}
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
let channel = self.channel;
let command = self.command;
let length = self.length;
Box::new(self.data.shrink().map(move |data| Self {
channel,
command,
length,
data,
}))
}
}
impl Arbitrary for ContinuationPacket<Vec<u8>> {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
Self {
channel: Arbitrary::arbitrary(g),
sequence: Arbitrary::arbitrary(g),
data: Arbitrary::arbitrary(g),
}
}
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
let channel = self.channel;
let sequence = self.sequence;
Box::new(self.data.shrink().map(move |data| Self {
channel,
sequence,
data,
}))
}
}
quickcheck::quickcheck! {
fn parse_init(data: Vec<u8>) -> bool {
let _ = InitializationPacket::<Vec<u8>>::try_from(data.as_slice());
true
}
}
quickcheck::quickcheck! {
fn serialize_init(packet: InitializationPacket<Vec<u8>>) -> bool {
let mut buffer = vec![0; packet.data.len() + 10];
let _ = packet.serialize(&mut buffer);
true
}
}
quickcheck::quickcheck! {
fn serialize_parse_init(packet: InitializationPacket<Vec<u8>>) -> TestResult {
if usize::from(packet.length) < packet.data.len() {
return TestResult::discard();
}
if u8::from(packet.command).leading_ones() > 0 {
return TestResult::discard();
}
let mut buffer = vec![0; packet.data.len() + 10];
let n = packet.serialize(&mut buffer).unwrap();
let parsed = InitializationPacket::try_from(&buffer[..n]).unwrap();
TestResult::from_bool(packet == parsed)
}
}
quickcheck::quickcheck! {
fn parse_cont(data: Vec<u8>) -> bool {
let _ = ContinuationPacket::<Vec<u8>>::try_from(data.as_slice());
true
}
}
quickcheck::quickcheck! {
fn serialize_cont(packet: ContinuationPacket<Vec<u8>>) -> bool {
let mut buffer = vec![0; packet.data.len() + 10];
let _ = packet.serialize(&mut buffer);
true
}
}
quickcheck::quickcheck! {
fn serialize_parse_cont(packet: ContinuationPacket<Vec<u8>>) -> TestResult {
if u8::from(packet.sequence).leading_ones() > 0 {
return TestResult::discard();
}
let mut buffer = vec![0; packet.data.len() + 10];
let n = packet.serialize(&mut buffer).unwrap();
let parsed = ContinuationPacket::try_from(&buffer[..n]).unwrap();
TestResult::from_bool(packet == parsed)
}
}
}