winstructs 0.3.2

Common structures used in parsing various windows protocols
Documentation
use crate::err::Result;
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
use serde::Serialize;

use std::fmt;
use std::io::{Cursor, Read};

#[derive(Serialize, Debug, Clone, PartialOrd, PartialEq)]
pub struct Authority(u64);

impl Authority {
    pub fn from_buffer(buffer: &[u8]) -> Result<Self> {
        Self::from_reader(&mut Cursor::new(buffer))
    }

    #[inline]
    pub fn from_reader<R: Read>(reader: &mut R) -> Result<Authority> {
        let id_high = reader.read_u32::<BigEndian>()?;
        let id_low = reader.read_u16::<BigEndian>()?;

        Ok(Authority(u64::from((id_high as u16) ^ (id_low))))
    }
}

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

#[derive(Serialize, Debug, Clone, PartialOrd, PartialEq)]
pub struct SubAuthorityList(Vec<SubAuthority>);

impl SubAuthorityList {
    pub fn from_buffer(buffer: &[u8], count: u8) -> Result<Self> {
        Self::from_reader(&mut Cursor::new(buffer), count)
    }

    #[inline]
    pub fn from_reader<R: Read>(buffer: &mut R, count: u8) -> Result<SubAuthorityList> {
        let mut list: Vec<SubAuthority> = Vec::with_capacity(count as usize);

        for _ in 0..count {
            list.push(SubAuthority::from_reader(buffer)?)
        }

        Ok(SubAuthorityList(list))
    }
}

impl fmt::Display for SubAuthorityList {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for element in self.0.iter() {
            write!(f, "-{}", element).expect("Writing to a String cannot fail");
        }

        Ok(())
    }
}

#[derive(Serialize, Debug, Clone, PartialOrd, PartialEq)]
pub struct SubAuthority(u32);

impl SubAuthority {
    pub fn from_buffer(buffer: &[u8]) -> Result<Self> {
        Self::from_reader(&mut Cursor::new(buffer))
    }

    #[inline]
    pub fn from_reader<R: Read>(buffer: &mut R) -> Result<SubAuthority> {
        Ok(SubAuthority(buffer.read_u32::<LittleEndian>()?))
    }
}

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

#[cfg(test)]
mod tests {
    use crate::security::authority::{Authority, SubAuthority, SubAuthorityList};

    #[test]
    fn test_parse_authority() {
        let buffer: &[u8] = &[0x00, 0x00, 0x00, 0x00, 0x00, 0x05];

        let authority = Authority::from_buffer(&buffer).unwrap();
        assert_eq!(authority.0, 5);
    }

    #[test]
    fn test_parse_sub_authority() {
        let buffer: &[u8] = &[0x12, 0x00, 0x00, 0x00];

        let sub_authority = SubAuthority::from_buffer(&buffer).unwrap();
        assert_eq!(sub_authority.0, 18);
    }

    #[test]
    fn test_parses_sub_authority_list() {
        let buffer: &[u8] = &[
            0x12, 0x00, 0x00, 0x00, 0x00, 0x13, 0x18, 0x00, 0x3F, 0x00, 0x0F, 0x00,
        ];

        let sub_authority = SubAuthorityList::from_buffer(&buffer, 3).unwrap();

        assert_eq!(sub_authority.0[0].0, 18);
        assert_eq!(sub_authority.0[1].0, 1_577_728);
        assert_eq!(sub_authority.0[2].0, 983_103);
    }
}