1use std::cmp::Ordering;
2use std::convert::AsRef;
3use std::fmt::{Debug, Display, Formatter};
4use std::mem::transmute;
5use std::str::{from_utf8, Utf8Error};
6
7#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct BitStr {
9 inner: [u8],
10}
11
12impl BitStr {
13 #[inline]
14 pub fn from(bytes: &[u8]) -> &Self {
15 unsafe { transmute::<&[u8], &Self>(bytes) }
16 }
17
18 #[allow(clippy::should_implement_trait)]
19 #[inline]
20 pub fn from_str(bytes: &str) -> &Self {
21 Self::from(bytes.as_bytes())
22 }
23
24 #[inline]
25 pub fn as_bytes(&self) -> &[u8] {
26 &self.inner
27 }
28
29 #[inline]
30 pub fn from_mut(bytes: &mut [u8]) -> &mut Self {
31 unsafe { transmute::<&mut [u8], &mut Self>(bytes) }
32 }
33
34 #[inline]
35 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
36 &mut self.inner
37 }
38
39 #[inline]
40 pub fn len(&self) -> usize {
41 self.inner.len()
42 }
43
44 #[inline]
45 pub fn is_empty(&self) -> bool {
46 self.inner.is_empty()
47 }
48
49 #[inline]
50 pub fn as_ptr(&self) -> *const u8 {
51 self.inner.as_ptr()
52 }
53
54 #[inline]
55 pub fn first(&self) -> Option<u8> {
56 self.inner.first().copied()
57 }
58
59 #[inline]
60 pub fn first_mut(&mut self) -> Option<&mut u8> {
61 self.inner.first_mut()
62 }
63
64 #[inline]
65 pub fn last(&self) -> Option<u8> {
66 self.inner.last().copied()
67 }
68
69 #[inline]
70 pub fn last_mut(&mut self) -> Option<&mut u8> {
71 self.inner.last_mut()
72 }
73
74 #[inline]
75 pub fn split_first(&self) -> Option<(u8, &BitStr)> {
76 self.inner.split_first().map(|(&a, b)| (a, BitStr::from(b)))
77 }
78
79 #[inline]
80 pub fn split_last_mut(&mut self) -> Option<(&mut u8, &mut BitStr)> {
81 self.inner
82 .split_last_mut()
83 .map(|(a, b)| (a, BitStr::from_mut(b)))
84 }
85
86 #[inline]
87 pub fn split_at(&self, mid: usize) -> (&BitStr, &BitStr) {
88 let (a, b) = self.inner.split_at(mid);
89 (BitStr::from(a), BitStr::from(b))
90 }
91
92 #[inline]
93 pub fn split_at_mut(&mut self, mid: usize) -> (&mut BitStr, &mut BitStr) {
94 let (a, b) = self.inner.split_at_mut(mid);
95 (BitStr::from_mut(a), BitStr::from_mut(b))
96 }
97
98 #[inline]
99 pub fn contains_u8(&self, x: u8) -> bool {
100 self.inner.contains(&x)
101 }
102
103 #[inline]
104 pub fn contains(&self, x: u8) -> bool {
105 self.inner.contains(&x)
106 }
107
108 #[inline]
109 pub fn starts_with<T: AsRef<BitStr>>(&self, x: T) -> bool {
110 self.inner.starts_with(x.as_ref().as_bytes())
111 }
112
113 #[inline]
114 pub fn ends_with<T: AsRef<BitStr>>(&self, x: T) -> bool {
115 self.inner.ends_with(x.as_ref().as_bytes())
116 }
117
118 #[inline]
119 pub fn bytes(&self) -> std::iter::Cloned<std::slice::Iter<u8>> {
120 self.inner.iter().cloned()
121 }
122
123 #[inline]
124 pub fn bytes_mut(&mut self) -> std::slice::IterMut<u8> {
125 self.inner.iter_mut()
126 }
127
128 #[inline]
129 pub fn to_str(&self) -> Result<&str, Utf8Error> {
130 from_utf8(self.as_bytes())
131 }
132
133 #[inline]
134 pub fn is_ascii(&self) -> bool {
135 self.inner.is_ascii()
136 }
137
138 #[inline]
139 pub fn eq_ignore_ascii_case(&self, other: &BitStr) -> bool {
140 self.inner.eq_ignore_ascii_case(&other.inner)
141 }
142
143 #[inline]
144 pub fn make_ascii_uppercase(&mut self) {
145 self.inner.make_ascii_uppercase()
146 }
147
148 #[inline]
149 pub fn make_ascii_lowercase(&mut self) {
150 self.inner.make_ascii_lowercase()
151 }
152}
153
154impl AsRef<BitStr> for BitStr {
155 #[inline]
156 fn as_ref(&self) -> &BitStr {
157 self
158 }
159}
160
161impl AsRef<BitStr> for [u8] {
162 #[inline]
163 fn as_ref(&self) -> &BitStr {
164 BitStr::from(self)
165 }
166}
167
168impl AsRef<BitStr> for str {
169 #[inline]
170 fn as_ref(&self) -> &BitStr {
171 BitStr::from(self.as_bytes())
172 }
173}
174
175impl AsRef<[u8]> for BitStr {
176 #[inline]
177 fn as_ref(&self) -> &[u8] {
178 &self.inner
179 }
180}
181
182impl<'a> Default for &'a BitStr {
183 #[inline]
184 fn default() -> Self {
185 BitStr::from(&[])
186 }
187}
188
189impl<'a> Default for &'a mut BitStr {
190 #[inline]
191 fn default() -> Self {
192 BitStr::from_mut(&mut [])
193 }
194}
195
196impl<'a> IntoIterator for &'a BitStr {
197 type Item = u8;
198 type IntoIter = std::iter::Cloned<std::slice::Iter<'a, u8>>;
199 #[inline]
200 fn into_iter(self) -> Self::IntoIter {
201 self.bytes()
202 }
203}
204
205impl<'a> IntoIterator for &'a mut BitStr {
206 type Item = &'a mut u8;
207 type IntoIter = std::slice::IterMut<'a, u8>;
208 #[inline]
209 fn into_iter(self) -> Self::IntoIter {
210 self.bytes_mut()
211 }
212}
213
214impl<'a> From<&'a [u8]> for &'a BitStr {
215 #[inline]
216 fn from(src: &'a [u8]) -> &'a BitStr {
217 BitStr::from(src)
218 }
219}
220
221impl Display for BitStr {
222 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
223 let s = String::from_utf8_lossy(&self.inner.as_ref()).into_owned();
224 f.write_str(&s);
225 Ok(())
226 }
227}
228
229impl Debug for BitStr {
230 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
231 let s = String::from_utf8_lossy(&self.inner.as_ref()).into_owned();
232 f.write_str(&s)
233 }
234}
235
236macro_rules! impl_ord {
237 ($t:ty) => {
238 impl PartialEq<$t> for BitStr {
239 #[inline]
240 fn eq(&self, other: &$t) -> bool {
241 <BitStr as PartialEq>::eq(self, other.as_ref())
242 }
243 }
244 impl PartialEq<BitStr> for $t {
245 #[inline]
246 fn eq(&self, other: &BitStr) -> bool {
247 <BitStr as PartialEq>::eq(self.as_ref(), other)
248 }
249 }
250 impl PartialOrd<$t> for BitStr {
251 #[inline]
252 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
253 <BitStr as PartialOrd>::partial_cmp(self, other.as_ref())
254 }
255 }
256 impl PartialOrd<BitStr> for $t {
257 #[inline]
258 fn partial_cmp(&self, other: &BitStr) -> Option<Ordering> {
259 <BitStr as PartialOrd>::partial_cmp(self.as_ref(), other)
260 }
261 }
262 };
263}
264
265impl_ord!(str);
266impl_ord!(&str);
267impl_ord!([u8]);
268impl_ord!(&[u8]);
269
270#[test]
271fn test_display() {
272 let rio = BitStr::from(&[82, 105, 111]);
273 assert_eq!(&format!("{}", rio), "Rio");
274}
275
276#[test]
277fn test_debug() {
278 let rio = BitStr::from(&[82, 105, 111]);
279 assert_eq!(&format!("{:?}", rio), "Rio");
280}
281
282#[test]
283fn test_contains_u8() {
284 let str_bitstr: &BitStr = BitStr::from(&[82, 105, 111]);
285 assert!(str_bitstr.contains_u8(82), "{}", true);
286}
287
288#[test]
289fn test_first_and_last() {
290 let bytes = [82, 105, 111];
291 let bit_str: &BitStr = BitStr::from(&bytes);
292 assert_eq!(111, bit_str.last().unwrap());
293 assert_eq!(82, bit_str.first().unwrap());
294}
295
296#[test]
297fn test_from() {
298 let bytes = [82, 105, 111];
299 let bit_str: &BitStr = BitStr::from(&bytes);
300
301 let bt = b"Rust";
302 let bit_str2: &BitStr = BitStr::from(bt);
303
304 assert_eq!("Rio", bit_str);
305 assert_eq!("Rust", bit_str2);
307 assert_eq!("Rust", bit_str2);
308}