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// TODO: replace with `struct Arg([u8])` and use `&Arg`
16#[derive(Eq, PartialEq, Hash)]
17#[repr(transparent)]
18pub struct Arg([u8]);
19
20impl Arg {
21    pub const fn new(bytes: &[u8]) -> &Self {
22        // SAFETY: Arg is repr transparent to a byte slice, so it's safe to
23        // transmute into it.
24        unsafe { mem::transmute(bytes) }
25    }
26
27    pub const fn bytes(&self) -> &[u8] {
28        &self.0
29    }
30}
31
32impl PartialEq<[u8]> for Arg {
33    fn eq(&self, other: &[u8]) -> bool {
34        self.0 == *other
35    }
36}
37
38impl PartialEq<&[u8]> for Arg {
39    fn eq(&self, other: &&[u8]) -> bool {
40        self.0 == **other
41    }
42}
43
44impl PartialEq<str> for Arg {
45    fn eq(&self, other: &str) -> bool {
46        self.0 == *other.as_bytes()
47    }
48}
49
50impl fmt::Debug for Arg {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        match str::from_utf8(self.bytes()) {
53            Ok(s) => write!(f, "{:?}", s),
54            Err(_) => write!(f, "{:?}", &self.0),
55        }
56    }
57}