haggis-rs/src/special.rs

81 lines
2.2 KiB
Rust

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<T: Read>(reader: &mut T) -> Result<Self, Error> {
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<T: 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);
}
}