mqtt-protocol 0.3.0

MQTT Protocol Library
Documentation
use std::io::{self, Read, Write};
use std::error::Error;
use std::string::FromUtf8Error;
use std::fmt;
use std::convert::From;
use std::marker::Sized;

use byteorder::{self, BigEndian, WriteBytesExt, ReadBytesExt};

pub trait Encodable<'a> {
    type Err: Error + 'a;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), Self::Err>;
    fn encoded_length(&self) -> u32;
}

pub trait Decodable<'a>: Sized {
    type Err: Error + 'a;
    type Cond;

    fn decode<R: Read>(reader: &mut R) -> Result<Self, Self::Err> {
        Self::decode_with(reader, None)
    }

    fn decode_with<R: Read>(reader: &mut R, Cond: Option<Self::Cond>) -> Result<Self, Self::Err>;
}

impl<'a> Encodable<'a> for &'a str {
    type Err = StringEncodeError;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), StringEncodeError> {
        writer.write_u16::<BigEndian>(self.as_bytes().len() as u16)
            .map_err(From::from)
            .and_then(|_| writer.write_all(self.as_bytes()))
            .map_err(StringEncodeError::IoError)
    }

    fn encoded_length(&self) -> u32 {
        2 + self.as_bytes().len() as u32
    }
}

impl<'a> Encodable<'a> for &'a [u8] {
    type Err = io::Error;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
        writer.write_all(self)
    }

    fn encoded_length(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> Encodable<'a> for String {
    type Err = StringEncodeError;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), StringEncodeError> {
        (&self[..]).encode(writer)
    }

    fn encoded_length(&self) -> u32 {
        (&self[..]).encoded_length()
    }
}

impl<'a> Decodable<'a> for String {
    type Err = StringEncodeError;
    type Cond = ();

    fn decode_with<R: Read>(reader: &mut R, _rest: Option<()>) -> Result<String, StringEncodeError> {
        let len = try!(reader.read_u16::<BigEndian>()) as usize;
        let mut buf = Vec::with_capacity(len);
        try!(reader.take(len as u64).read_to_end(&mut buf));

        if buf.len() < len {
            return Err(StringEncodeError::MalformedData);
        }

        String::from_utf8(buf).map_err(StringEncodeError::FromUtf8Error)
    }
}

impl<'a> Encodable<'a> for Vec<u8> {
    type Err = io::Error;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
        (&self[..]).encode(writer)
    }

    fn encoded_length(&self) -> u32 {
        (&self[..]).encoded_length()
    }
}

impl<'a> Decodable<'a> for Vec<u8> {
    type Err = io::Error;
    type Cond = u32;

    fn decode_with<R: Read>(reader: &mut R, length: Option<u32>) -> Result<Vec<u8>, io::Error> {
        match length {
            Some(length) => {
                let mut buf = Vec::with_capacity(length as usize);
                try!(reader.take(length as u64).read_to_end(&mut buf));
                Ok(buf)
            },
            None => {
                let mut buf = Vec::new();
                try!(reader.read_to_end(&mut buf));
                Ok(buf)
            }
        }
    }
}

impl<'a> Encodable<'a> for () {
    type Err = NoError;

    fn encode<W: Write>(&self, _: &mut W) -> Result<(), NoError> {
        Ok(())
    }

    fn encoded_length(&self) -> u32 {
        0
    }
}

impl<'a> Decodable<'a> for () {
    type Err = NoError;
    type Cond = ();

    fn decode_with<R: Read>(_: &mut R, _: Option<()>) -> Result<(), NoError> {
        Ok(())
    }
}

#[derive(Debug)]
pub struct NoError;

impl fmt::Display for NoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "No error")
    }
}

impl Error for NoError {
    fn description(&self) -> &str {
        "No error"
    }
}

#[derive(Debug)]
pub enum StringEncodeError {
    IoError(io::Error),
    FromUtf8Error(FromUtf8Error),
    MalformedData,
}

impl fmt::Display for StringEncodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &StringEncodeError::IoError(ref err) => err.fmt(f),
            &StringEncodeError::FromUtf8Error(ref err) => err.fmt(f),
            &StringEncodeError::MalformedData => write!(f, "Malformed data"),
        }
    }
}

impl Error for StringEncodeError {
    fn description(&self) -> &str {
        match self {
            &StringEncodeError::IoError(ref err) => err.description(),
            &StringEncodeError::FromUtf8Error(ref err) => err.description(),
            &StringEncodeError::MalformedData => "Malformed data",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &StringEncodeError::IoError(ref err) => Some(err),
            &StringEncodeError::FromUtf8Error(ref err) => Some(err),
            &StringEncodeError::MalformedData => None
        }
    }
}

impl From<io::Error> for StringEncodeError {
    fn from(err: io::Error) -> StringEncodeError {
        StringEncodeError::IoError(err)
    }
}

impl From<byteorder::Error> for StringEncodeError {
    fn from(err: byteorder::Error) -> StringEncodeError {
        StringEncodeError::IoError(From::from(err))
    }
}

impl From<FromUtf8Error> for StringEncodeError {
    fn from(err: FromUtf8Error) -> StringEncodeError {
        StringEncodeError::FromUtf8Error(err)
    }
}