1use crate::error::OutOfRangeError;
2use std::convert::TryFrom;
3use std::fmt::{self, Write};
4
5#[derive(Clone, Copy)]
6pub struct Name {
7 pub bytes: [u8; 26],
8}
9
10#[derive(Clone, Copy)]
11pub struct DosFilename {
12 pub bytes: [u8; 13],
13}
14
15#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
16pub struct RangedU8<const LOW: u8, const HIGH: u8>(u8);
17
18
19impl<const LOW: u8, const HIGH: u8> RangedU8<LOW, HIGH> {
20 pub fn as_u8(self) -> u8 {
21 self.0
22 }
23}
24
25impl<const LOW: u8, const HIGH: u8> TryFrom<u8> for RangedU8<LOW, HIGH> {
26 type Error = OutOfRangeError<LOW, HIGH>;
27
28 fn try_from(raw: u8) -> Result<Self, Self::Error> {
29 if (LOW..=HIGH).contains(&raw) {
30 Ok(RangedU8(raw))
31 } else {
32 Err(OutOfRangeError(raw))
33 }
34 }
35}
36
37impl<const LOW: u8, const HIGH: u8> From<RangedU8<LOW, HIGH>> for u8 {
38 fn from(ranged: RangedU8<LOW, HIGH>) -> u8 {
39 ranged.as_u8()
40 }
41}
42
43fn null_terminated(bytes: &[u8]) -> &[u8] {
44 let null_pos = bytes.iter()
45 .position(|&b| b == 0)
46 .unwrap_or(bytes.len());
47 &bytes[..null_pos]
48}
49
50fn debug_bytestring(bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
51 f.write_char('"')?;
52 for &byte in null_terminated(bytes) {
53 if byte.is_ascii_graphic() || byte == b' ' {
54 f.write_char(byte.into())?;
55 } else {
56 write!(f, "<0x{:02X}>", byte)?;
57 }
58 }
59 f.write_char('"')
60}
61
62impl fmt::Debug for Name {
63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 debug_bytestring(&self.bytes, f)
65 }
66}
67
68impl fmt::Debug for DosFilename {
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 debug_bytestring(&self.bytes, f)
71 }
72}
73
74impl fmt::Display for Name {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 String::from_utf8_lossy(null_terminated(&self.bytes)).fmt(f)
77 }
78}
79
80impl fmt::Display for DosFilename {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 String::from_utf8_lossy(null_terminated(&self.bytes)).fmt(f)
83 }
84}
85
86impl<const LOW: u8, const HIGH: u8> fmt::Debug for RangedU8<LOW, HIGH> {
87 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88 self.as_u8().fmt(f)
89 }
90}