1use std::ops::Deref;
2
3use binrw::binrw;
4
5use super::Bytes;
6
7#[doc(hidden)]
9#[macro_export]
10macro_rules! __ascii__ {
11 ($string:literal) => {
12 if $string.is_ascii() {
13 #[allow(deprecated)]
14 $crate::arch::Ascii::borrowed_unchecked($string)
15 } else {
16 panic!("the literal wasn't ASCII-formatted")
17 }
18 };
19}
20
21pub use __ascii__ as ascii;
22
23#[derive(Debug)]
25pub struct AsciiError {}
26
27impl std::fmt::Display for AsciiError {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 f.write_str("the input data wasn't ASCII-formatted")
30 }
31}
32
33impl std::error::Error for AsciiError {}
34
35#[binrw]
39#[derive(Default, Clone, PartialEq, Eq)]
40#[br(assert(self_0.as_borrow().is_ascii()))]
41pub struct Ascii<'b>(Bytes<'b>);
42
43impl<'b> Ascii<'b> {
44 pub fn owned(value: String) -> Result<Self, AsciiError> {
46 if value.is_ascii() {
47 Ok(Self(Bytes::owned(value.into_bytes())))
48 } else {
49 Err(AsciiError {})
50 }
51 }
52
53 pub const fn borrowed(value: &'b str) -> Result<Self, AsciiError> {
55 if value.is_ascii() {
56 Ok(Self(Bytes::borrowed(value.as_bytes())))
57 } else {
58 Err(AsciiError {})
59 }
60 }
61
62 #[doc(hidden)]
63 #[deprecated(
64 since = "0.0.0",
65 note = "This is an internal function, and is not safe to work with"
66 )]
67 pub const fn borrowed_unchecked(value: &'b str) -> Self {
68 Self(Bytes::borrowed(value.as_bytes()))
69 }
70
71 pub fn as_borrow<'a: 'b>(&'a self) -> Ascii<'a> {
73 Self(self.0.as_borrow())
74 }
75
76 pub fn into_string(self) -> String {
78 String::from_utf8(self.0.into_vec()).expect("The inner buffer contained non UTF-8 data")
79 }
80}
81
82impl std::fmt::Debug for Ascii<'_> {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 f.debug_tuple("Ascii").field(&&**self).finish()
85 }
86}
87
88impl std::fmt::Display for Ascii<'_> {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 f.write_str(self)
91 }
92}
93
94impl Deref for Ascii<'_> {
95 type Target = str;
96
97 fn deref(&self) -> &Self::Target {
98 std::str::from_utf8(&self.0).expect("The inner buffer contained non UTF-8 data")
99 }
100}
101
102impl AsRef<str> for Ascii<'_> {
103 fn as_ref(&self) -> &str {
104 self
105 }
106}
107
108impl TryFrom<String> for Ascii<'_> {
109 type Error = AsciiError;
110
111 fn try_from(value: String) -> Result<Self, AsciiError> {
112 Self::owned(value)
113 }
114}
115
116impl<'b> TryFrom<&'b str> for Ascii<'b> {
117 type Error = AsciiError;
118
119 fn try_from(value: &'b str) -> Result<Self, Self::Error> {
120 Self::borrowed(value)
121 }
122}