1use {
2 snafu::prelude::*,
3 std::str::FromStr,
4};
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
8pub struct DeviceId {
9 pub major: u32,
10 pub minor: u32,
11}
12
13#[derive(Debug, Snafu)]
14#[snafu(display("Could not parse {string} as a device id"))]
15pub struct ParseDeviceIdError {
16 string: String,
17}
18
19impl FromStr for DeviceId {
20 type Err = ParseDeviceIdError;
21 fn from_str(string: &str) -> Result<Self, Self::Err> {
23 (|| {
24 let mut parts = string.split(':').fuse();
25 match (parts.next(), parts.next(), parts.next()) {
26 (Some(major), Some(minor), None) => {
27 let major = major.parse().ok()?;
28 let minor = minor.parse().ok()?;
29 Some(Self { major, minor })
30 }
31 (Some(int), None, None) => {
32 let int: u64 = int.parse().ok()?;
33 Some( int.into() )
34 }
35 _ => None,
36 }
37 })().with_context(|| ParseDeviceIdSnafu { string })
38 }
39}
40
41impl From<u64> for DeviceId {
42 fn from(num: u64) -> Self {
43 Self {
44 major: (num >> 8) as u32,
45 minor: (num & 0xFF) as u32,
46 }
47 }
48}
49
50impl DeviceId {
51 pub fn new(major: u32, minor: u32) -> Self {
52 Self { major, minor }
53 }
54}
55
56#[test]
57fn test_from_str() {
58 assert_eq!(DeviceId::new(8, 16), DeviceId::from_str("8:16").unwrap());
59}
60
61#[test]
62fn test_from_u64() {
63 assert_eq!(DeviceId::new(8, 16), DeviceId::from(2064u64));
64}