diameter 0.7.1

Rust Implementation of the Diameter Protocol.
Documentation
use crate::error::Result;
use std::fmt;
use std::io::Read;
use std::io::Write;
use std::net::Ipv6Addr;

#[derive(Debug, Clone)]
pub struct IPv6(Ipv6Addr);

impl IPv6 {
    pub fn new(value: Ipv6Addr) -> IPv6 {
        IPv6(value)
    }

    pub fn decode_from<R: Read>(reader: &mut R) -> Result<IPv6> {
        let mut b = [0; 16];
        reader.read_exact(&mut b)?;

        let ip = Ipv6Addr::new(
            (b[0] as u16) << 8 | b[1] as u16,
            (b[2] as u16) << 8 | b[3] as u16,
            (b[4] as u16) << 8 | b[5] as u16,
            (b[6] as u16) << 8 | b[7] as u16,
            (b[8] as u16) << 8 | b[9] as u16,
            (b[10] as u16) << 8 | b[11] as u16,
            (b[12] as u16) << 8 | b[13] as u16,
            (b[14] as u16) << 8 | b[15] as u16,
        );
        Ok(IPv6(ip))
    }

    pub fn encode_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        writer.write_all(&self.0.octets())?;
        Ok(())
    }

    pub fn length(&self) -> u32 {
        16
    }
}

impl fmt::Display for IPv6 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;

    #[test]
    fn test_encode_decode() {
        let ipv6_addr = Ipv6Addr::new(
            0x664f, 0x0c54, 0x5729, 0xf308, 0x569f, 0xb682, 0x80b6, 0x0140,
        );
        let avp = IPv6::new(ipv6_addr);
        let mut encoded = Vec::new();
        avp.encode_to(&mut encoded).unwrap();
        let mut cursor = Cursor::new(&encoded);
        let avp = IPv6::decode_from(&mut cursor).unwrap();
        assert_eq!(avp.0, ipv6_addr);
    }
}