// Status: minimal — header read/write helpers + RxPacket builder.

#![allow(dead_code)]

pub const VSOCK_PKT_HDR_SIZE: usize = 44;

pub const VSOCK_OP_REQUEST: u16 = 1;
pub const VSOCK_OP_RESPONSE: u16 = 2;
pub const VSOCK_OP_RST: u16 = 3;
pub const VSOCK_OP_SHUTDOWN: u16 = 4;
pub const VSOCK_OP_RW: u16 = 5;
pub const VSOCK_OP_CREDIT_UPDATE: u16 = 6;
pub const VSOCK_OP_CREDIT_REQUEST: u16 = 7;

pub const VSOCK_TYPE_STREAM: u16 = 1;
pub const VSOCK_TYPE_DGRAM: u16 = 3;

pub const VSOCK_HOST_CID: u64 = 2;

fn le_u16(b: &[u8; VSOCK_PKT_HDR_SIZE], off: usize) -> u16 {
    u16::from_le_bytes([b[off], b[off + 1]])
}

fn le_u32(b: &[u8; VSOCK_PKT_HDR_SIZE], off: usize) -> u32 {
    u32::from_le_bytes([b[off], b[off + 1], b[off + 2], b[off + 3]])
}

fn le_u64(b: &[u8; VSOCK_PKT_HDR_SIZE], off: usize) -> u64 {
    u64::from_le_bytes([
        b[off],
        b[off + 1],
        b[off + 2],
        b[off + 3],
        b[off + 4],
        b[off + 5],
        b[off + 6],
        b[off + 7],
    ])
}

#[derive(Debug, Clone, Copy)]
pub struct Header {
    pub src_cid: u64,
    pub dst_cid: u64,
    pub src_port: u32,
    pub dst_port: u32,
    pub len: u32,
    pub type_: u16,
    pub op: u16,
    pub flags: u32,
    pub buf_alloc: u32,
    pub fwd_cnt: u32,
}

impl Header {
    pub fn parse(b: &[u8; VSOCK_PKT_HDR_SIZE]) -> Self {
        Self {
            src_cid: le_u64(b, 0),
            dst_cid: le_u64(b, 8),
            src_port: le_u32(b, 16),
            dst_port: le_u32(b, 20),
            len: le_u32(b, 24),
            type_: le_u16(b, 28),
            op: le_u16(b, 30),
            flags: le_u32(b, 32),
            buf_alloc: le_u32(b, 36),
            fwd_cnt: le_u32(b, 40),
        }
    }
    pub fn encode(&self) -> [u8; VSOCK_PKT_HDR_SIZE] {
        let mut b = [0u8; VSOCK_PKT_HDR_SIZE];
        b[0..8].copy_from_slice(&self.src_cid.to_le_bytes());
        b[8..16].copy_from_slice(&self.dst_cid.to_le_bytes());
        b[16..20].copy_from_slice(&self.src_port.to_le_bytes());
        b[20..24].copy_from_slice(&self.dst_port.to_le_bytes());
        b[24..28].copy_from_slice(&self.len.to_le_bytes());
        b[28..30].copy_from_slice(&self.type_.to_le_bytes());
        b[30..32].copy_from_slice(&self.op.to_le_bytes());
        b[32..36].copy_from_slice(&self.flags.to_le_bytes());
        b[36..40].copy_from_slice(&self.buf_alloc.to_le_bytes());
        b[40..44].copy_from_slice(&self.fwd_cnt.to_le_bytes());
        b
    }
}

#[derive(Debug, Clone)]
pub struct RxPacket {
    pub hdr: Header,
    pub data: Vec<u8>,
}

impl RxPacket {
    pub fn control(
        src_cid: u64,
        dst_cid: u64,
        src_port: u32,
        dst_port: u32,
        op: u16,
        type_: u16,
    ) -> Self {
        Self {
            hdr: Header {
                src_cid,
                dst_cid,
                src_port,
                dst_port,
                len: 0,
                type_,
                op,
                flags: 0,
                buf_alloc: 256 * 1024,
                fwd_cnt: 0,
            },
            data: Vec::new(),
        }
    }
    pub fn rst_for(req: &Header) -> Self {
        Self::control(
            req.dst_cid,
            req.src_cid,
            req.dst_port,
            req.src_port,
            VSOCK_OP_RST,
            req.type_,
        )
    }
    pub fn response_to(req: &Header) -> Self {
        Self::control(
            req.dst_cid,
            req.src_cid,
            req.dst_port,
            req.src_port,
            VSOCK_OP_RESPONSE,
            req.type_,
        )
    }
}
