bitstr/
lib.rs

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!(&[82, 105, 111], bit_str);
306    assert_eq!("Rust", bit_str2);
307    assert_eq!("Rust", bit_str2);
308}