use crate::structures::util::read_uintptr;
#[derive(Debug, Clone, Copy, Default)]
pub struct ChanTypeExtra {
pub elem: u64,
pub dir: u64,
}
impl ChanTypeExtra {
pub fn size(ps: u8) -> usize {
(ps as usize).saturating_mul(2)
}
pub fn parse(data: &[u8], ps: u8) -> Option<Self> {
let p = ps as usize;
if data.len() < Self::size(ps) {
return None;
}
Some(Self {
elem: read_uintptr(data, 0, ps)?,
dir: read_uintptr(data, p, ps)?,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_recv_only() {
let mut buf = vec![0u8; 16];
buf[0..8].copy_from_slice(&0x5000u64.to_le_bytes());
buf[8..16].copy_from_slice(&1u64.to_le_bytes());
let c = ChanTypeExtra::parse(&buf, 8).unwrap();
assert_eq!(c.elem, 0x5000);
assert_eq!(c.dir, 1); }
#[test]
fn parse_send_only() {
let mut buf = vec![0u8; 16];
buf[0..8].copy_from_slice(&0x6000u64.to_le_bytes());
buf[8..16].copy_from_slice(&2u64.to_le_bytes());
let c = ChanTypeExtra::parse(&buf, 8).unwrap();
assert_eq!(c.dir, 2); }
#[test]
fn parse_bidirectional() {
let mut buf = vec![0u8; 16];
buf[0..8].copy_from_slice(&0x7000u64.to_le_bytes());
buf[8..16].copy_from_slice(&3u64.to_le_bytes());
let c = ChanTypeExtra::parse(&buf, 8).unwrap();
assert_eq!(c.dir, 3); }
#[test]
fn parse_32bit() {
let mut buf = vec![0u8; 8];
buf[0..4].copy_from_slice(&0x8000u32.to_le_bytes());
buf[4..8].copy_from_slice(&1u32.to_le_bytes());
let c = ChanTypeExtra::parse(&buf, 4).unwrap();
assert_eq!(c.elem, 0x8000);
assert_eq!(c.dir, 1);
}
#[test]
fn too_short_returns_none() {
let buf = vec![0u8; 12];
assert!(ChanTypeExtra::parse(&buf, 8).is_none());
}
#[test]
fn size_calculations() {
assert_eq!(ChanTypeExtra::size(4), 8);
assert_eq!(ChanTypeExtra::size(8), 16);
}
}