use { crate::Error, std::io::{Read, Write}, }; /// Represents the major and minor numbers of a Unix special Device node #[derive(Debug, PartialEq, Eq)] pub struct Special { pub major: u32, pub minor: u32, } impl Special { pub(crate) fn read(reader: &mut T) -> Result { let mut buf = [0; 8]; reader.read_exact(&mut buf)?; let major: [u8; 4] = buf[..4].try_into()?; let major = u32::from_le_bytes(major); let minor: [u8; 4] = buf[4..].try_into()?; let minor = u32::from_le_bytes(minor); Ok(Self { major, minor }) } pub(crate) fn write(&self, writer: &mut T) -> Result<(), Error> { writer.write_all(&self.major.to_le_bytes())?; writer.write_all(&self.minor.to_le_bytes())?; Ok(()) } #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] #[allow(clippy::cast_possible_truncation)] pub(super) fn from_rdev(rdev: u64) -> Self { Self { major: ((rdev >> 8) & 0xff) as u32, minor: (rdev & 0xffff_00ff) as u32, } } #[cfg(target_os = "linux")] #[allow(clippy::cast_possible_truncation)] pub(super) fn from_rdev(rdev: u64) -> Self { let mut major = 0; major |= (rdev & 0x0000_0000_000f_ff00) >> 8; major |= (rdev & 0xffff_f000_0000_0000) >> 32; let mut minor = 0; minor |= rdev & 0x0000_0000_0000_00ff; minor |= (rdev & 0x0000_0fff_fff0_0000) >> 12; Self { major: major as u32, minor: minor as u32, } } } #[cfg(test)] mod tests { use super::*; use std::fs::File; #[test] fn load_store() { { let mut fd = File::options() .write(true) .create(true) .truncate(true) .open("test/device") .unwrap(); let dev = Special { major: 42, minor: 69, }; dev.write(&mut fd).unwrap(); } let mut fd = File::open("test/device").unwrap(); let dev = Special::read(&mut fd).unwrap(); assert_eq!(dev.major, 42); assert_eq!(dev.minor, 69); } }