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}