use anyhow::{Result, anyhow};
use zerocopy::{
FromBytes, Immutable, KnownLayout,
byteorder::{BigEndian, U32, U64},
};
#[inline]
pub fn build_read_capacity10(cdb: &mut [u8; 16], lba: u32, pmi: bool, control: u8) {
cdb.fill(0);
cdb[0] = 0x25; cdb[1] = 0x00; cdb[2..6].copy_from_slice(&lba.to_be_bytes()); cdb[8] = if pmi { 0x01 } else { 0x00 }; cdb[9] = control;
}
#[inline]
pub fn build_read_capacity16(
cdb: &mut [u8; 16],
lba: u64,
pmi: bool,
alloc_len: u32,
control: u8,
) {
cdb.fill(0);
cdb[0] = 0x9E; cdb[1] = 0x10; cdb[2..10].copy_from_slice(&lba.to_be_bytes()); cdb[10..14].copy_from_slice(&alloc_len.to_be_bytes()); cdb[14] = if pmi { 0x01 } else { 0x00 }; cdb[15] = control;
}
#[repr(C)]
#[derive(FromBytes, KnownLayout, Immutable, Debug)]
pub struct Rc10Raw {
pub max_lba: U32<BigEndian>,
pub block_len: U32<BigEndian>,
}
#[repr(C)]
#[derive(FromBytes, KnownLayout, Immutable, Debug)]
pub struct Rc16Raw {
pub max_lba: U64<BigEndian>,
pub block_len: U32<BigEndian>,
}
impl Rc10Raw {
#[inline]
pub fn total_bytes(&self) -> u64 {
(self.max_lba.get() as u64 + 1) * self.block_len.get() as u64
}
#[inline]
pub fn indicates_overflow(&self) -> bool {
self.max_lba == u32::MAX
}
}
impl Rc16Raw {
#[inline]
pub fn total_bytes(&self) -> u128 {
(self.max_lba.get() as u128 + 1) * self.block_len.get() as u128
}
}
#[inline]
pub fn parse_read_capacity10_zerocopy(buf: &[u8]) -> Result<&Rc10Raw> {
let (raw, _rest) = Rc10Raw::ref_from_prefix(buf)
.map_err(|_| anyhow!("READ CAPACITY(10): need ≥ 8 bytes, got {}", buf.len()))?;
Ok(raw)
}
#[inline]
pub fn parse_read_capacity16_zerocopy(buf: &[u8]) -> Result<&Rc16Raw> {
let (raw, _rest) = Rc16Raw::ref_from_prefix(buf)
.map_err(|_| anyhow!("READ CAPACITY(16): need ≥ 12 bytes, got {}", buf.len()))?;
Ok(raw)
}