Skip to main content

debate_parser/
arg.rs

1use core::{fmt, mem};
2
3/**
4A single, raw argument passed in from the command line.
5
6This type is used in two ways: to indicate long command line options, and to
7indicate arguments themselves. For instance, given
8`--target foo --path=bar input.txt`, `target`, `foo`, `path`, `bar`, and
9`input.txt` would all be passed as [`Arg`] values to the relevant functions.
10
11An [`Arg`] internally is just a byte slice, since that's what the OS gives us.
12Callers can manually turn it into a [`str`] with [`from_utf8`][core::str::from_utf8],
13and from there parse it however they need.
14*/
15#[derive(Eq, PartialEq, Hash)]
16#[repr(transparent)]
17pub struct Arg([u8]);
18
19impl Arg {
20    pub const fn new(bytes: &[u8]) -> &Self {
21        // SAFETY: Arg is repr transparent to a byte slice, so it's safe to
22        // transmute into it.
23        unsafe { mem::transmute(bytes) }
24    }
25
26    pub const fn bytes(&self) -> &[u8] {
27        &self.0
28    }
29
30    /// Attempt to turn this `Arg` into a string. Returns question marks if
31    /// it's not valid utf-8.
32    pub fn as_str(&self) -> &str {
33        let questions: &str = "????????????????";
34        let bytes = self.bytes();
35
36        match str::from_utf8(bytes) {
37            Ok(s) => s,
38            Err(_) => match questions.get(..bytes.len()) {
39                Some(questions) => questions,
40                None => questions,
41            },
42        }
43    }
44}
45
46impl PartialEq<[u8]> for Arg {
47    fn eq(&self, other: &[u8]) -> bool {
48        self.0 == *other
49    }
50}
51
52impl PartialEq<&[u8]> for Arg {
53    fn eq(&self, other: &&[u8]) -> bool {
54        self.0 == **other
55    }
56}
57
58impl PartialEq<str> for Arg {
59    fn eq(&self, other: &str) -> bool {
60        self.0 == *other.as_bytes()
61    }
62}
63
64impl fmt::Debug for Arg {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        match str::from_utf8(self.bytes()) {
67            Ok(s) => write!(f, "{:?}", s),
68            Err(_) => write!(f, "{:x?}", &self.0),
69        }
70    }
71}