use std::fmt::{self, Display};
use std::str::FromStr;
use crate::{Result, Error, error};
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Device
{
id: u64,
major: u64,
minor: u64
}
impl Device
{
pub const fn new(id: u64) -> Self
{
Self
{
major: dev_to_major(id),
minor: dev_to_minor(id),
id
}
}
pub const fn id(&self) -> u64
{
self.id
}
pub const fn major(&self) -> u64
{
self.major
}
pub const fn minor(&self) -> u64
{
self.minor
}
pub const fn from_both(major: u64, minor: u64) -> Self
{
Self
{
major,
minor,
id: dev_from_major_minor(major, minor)
}
}
}
const fn dev_from_major_minor(major: u64, minor: u64) -> u64
{
(major & 0xFFFFF000) << 32 |
(major & 0xFFF) << 8 |
(minor & 0xFFFFFF00) << 12 |
(minor & 0xFF)
}
const fn dev_to_major(dev: u64) -> u64
{
(dev >> 8) & 0xFFFF
}
const fn dev_to_minor(dev: u64) -> u64
{
(dev & 0xFF) | ((dev >> 12) & 0xFFFFFF00)
}
impl Display for Device
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}:{}:{}", self.id, self.major, self.minor)
}
}
impl FromStr for Device
{
type Err = Error;
fn from_str(s: &str) -> Result<Self>
{
let parts: Vec<&str> = s.splitn(2, ':').collect();
if !parts.len() == 3
{
error!("expected two ':' separators, making 3 values total. Input has {} values", parts.len())
}
Ok(Self
{
id: parts[0].parse::<u64>()?,
major: parts[1].parse::<u64>()?,
minor: parts[2].parse::<u64>()?
})
}
}