use alloc::vec::Vec;
use nex_macro::Packet;
use nex_macro_helper::packet::PrimitiveValues;
use nex_macro_helper::types::{u1, u16le, u3, u32le, u4, u64le, u7};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UsbPcapFunction(pub u16);
impl UsbPcapFunction {
    pub fn new(val: u16) -> Self {
        Self(val)
    }
}
impl PrimitiveValues for UsbPcapFunction {
    type T = (u16,);
    fn to_primitive_values(&self) -> Self::T {
        (self.0,)
    }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UsbPcapStatus(pub u32);
impl UsbPcapStatus {
    pub fn new(val: u32) -> Self {
        Self(val)
    }
}
impl PrimitiveValues for UsbPcapStatus {
    type T = (u32,);
    fn to_primitive_values(&self) -> Self::T {
        (self.0,)
    }
}
#[derive(Packet)]
pub struct UsbPcap {
    pub header_length: u16le,
    pub irp_id: u64le,
    #[construct_with(u32le)]
    pub status: UsbPcapStatus,
    #[construct_with(u16le)]
    pub function: UsbPcapFunction,
    pub reserved_info: u7,
    pub pdo_to_fdo: u1,
    pub bus: u16le,
    pub device: u16le,
    pub direction: u1,
    pub reserved_endpoint: u3,
    pub endpoint: u4,
    pub transfer: u8,
    pub data_length: u32le,
    #[length = "header_length - 27"]
    pub header_payload: Vec<u8>,
    #[length = "data_length"]
    #[payload]
    pub payload: Vec<u8>,
}
#[cfg(test)]
mod tests {
    use super::*;
    use nex_macro_helper::packet::Packet;
    #[test]
    fn usbpcap_packet_test() {
        let mut packet = [0u8; 35];
        {
            let mut usbpcap = MutableUsbPcapPacket::new(&mut packet[..]).unwrap();
            usbpcap.set_header_length(27);
            assert_eq!(usbpcap.get_header_length(), 27);
            usbpcap.set_irp_id(0x12_34);
            assert_eq!(usbpcap.get_irp_id(), 0x12_34);
            usbpcap.set_status(UsbPcapStatus(30));
            assert_eq!(usbpcap.get_status(), UsbPcapStatus(30));
            usbpcap.set_function(UsbPcapFunction(40));
            assert_eq!(usbpcap.get_function(), UsbPcapFunction(40));
            assert_eq!(usbpcap.get_reserved_info(), 0);
            usbpcap.set_pdo_to_fdo(1);
            assert_eq!(usbpcap.get_pdo_to_fdo(), 1);
            usbpcap.set_bus(60);
            assert_eq!(usbpcap.get_bus(), 60);
            usbpcap.set_device(70);
            assert_eq!(usbpcap.get_device(), 70);
            usbpcap.set_direction(1);
            assert_eq!(usbpcap.get_direction(), 1);
            assert_eq!(usbpcap.get_reserved_endpoint(), 0);
            usbpcap.set_endpoint(14);
            assert_eq!(usbpcap.get_endpoint(), 14);
            usbpcap.set_transfer(80);
            assert_eq!(usbpcap.get_transfer(), 80);
            usbpcap.set_data_length(2);
            assert_eq!(usbpcap.get_data_length(), 2);
            assert_eq!(usbpcap.get_header_payload(), Vec::<u8>::new());
            usbpcap.set_payload(&[90, 100]);
            assert_eq!(usbpcap.payload(), &[90, 100]);
        }
        let ref_packet = [
            27, 0, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 40, 0, 1, 60, 0, 70, 0,   142, 80,  2, 0, 0, 0, 90, 100, ];
        assert_eq!(&ref_packet[..], &packet[0..29]);
    }
    #[test]
    fn usbpcap_packet_test_variable_header() {
        let mut packet = [0u8; 35];
        {
            let mut usbpcap = MutableUsbPcapPacket::new(&mut packet[..]).unwrap();
            usbpcap.set_header_length(28);
            assert_eq!(usbpcap.get_header_length(), 28);
            usbpcap.set_header_payload(&[110]);
            assert_eq!(usbpcap.get_header_payload(), &[110]);
            assert_eq!(usbpcap.payload(), Vec::<u8>::new());
        }
        let ref_packet = [
            28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, ];
        assert_eq!(&ref_packet[..], &packet[0..28]);
    }
}