winnow/stream/
impls.rs

1macro_rules! impl_partial_eq {
2    ($lhs:ty, $rhs:ty) => {
3        #[allow(unused_lifetimes)]
4        impl<'a> PartialEq<$rhs> for $lhs {
5            #[inline]
6            fn eq(&self, other: &$rhs) -> bool {
7                let l = self.as_ref();
8                let r: &Self = other.as_ref();
9                PartialEq::eq(l, r)
10            }
11        }
12
13        #[allow(unused_lifetimes)]
14        impl<'a> PartialEq<$lhs> for $rhs {
15            #[inline]
16            fn eq(&self, other: &$lhs) -> bool {
17                PartialEq::eq(other, self)
18            }
19        }
20    };
21}
22
23macro_rules! impl_partial_ord {
24    ($lhs:ty, $rhs:ty) => {
25        #[allow(unused_lifetimes)]
26        impl<'a> PartialOrd<$rhs> for $lhs {
27            #[inline]
28            fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
29                let l = self.as_ref();
30                let r: &Self = other.as_ref();
31                PartialOrd::partial_cmp(l, r)
32            }
33        }
34
35        #[allow(unused_lifetimes)]
36        impl<'a> PartialOrd<$lhs> for $rhs {
37            #[inline]
38            fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
39                PartialOrd::partial_cmp(other, self)
40            }
41        }
42    };
43}
44
45mod bytes {
46    use crate::lib::std::{cmp::Ordering, fmt, ops};
47
48    use crate::stream::Bytes;
49
50    impl fmt::Display for Bytes {
51        #[inline]
52        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53            <Self as fmt::UpperHex>::fmt(self, f)
54        }
55    }
56
57    impl fmt::Debug for Bytes {
58        #[inline]
59        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60            <Self as fmt::UpperHex>::fmt(self, f)
61        }
62    }
63
64    impl fmt::LowerHex for Bytes {
65        #[inline]
66        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67            for byte in self.as_bytes() {
68                write!(f, "{byte:0>2x}")?;
69            }
70            Ok(())
71        }
72    }
73
74    impl fmt::UpperHex for Bytes {
75        #[inline]
76        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77            for (i, byte) in self.as_bytes().iter().enumerate() {
78                if 0 < i {
79                    let absolute = (self.as_bytes().as_ptr() as usize) + i;
80                    if f.alternate() && absolute != 0 && absolute % 4 == 0 {
81                        write!(f, "_")?;
82                    }
83                }
84                write!(f, "{byte:0>2X}")?;
85            }
86            Ok(())
87        }
88    }
89
90    impl ops::Deref for Bytes {
91        type Target = [u8];
92
93        #[inline]
94        fn deref(&self) -> &[u8] {
95            self.as_bytes()
96        }
97    }
98
99    impl ops::Index<usize> for Bytes {
100        type Output = u8;
101
102        #[inline]
103        fn index(&self, idx: usize) -> &u8 {
104            &self.as_bytes()[idx]
105        }
106    }
107
108    impl ops::Index<ops::RangeFull> for Bytes {
109        type Output = Bytes;
110
111        #[inline]
112        fn index(&self, _: ops::RangeFull) -> &Bytes {
113            self
114        }
115    }
116
117    impl ops::Index<ops::Range<usize>> for Bytes {
118        type Output = Bytes;
119
120        #[inline]
121        fn index(&self, r: ops::Range<usize>) -> &Bytes {
122            Bytes::new(&self.as_bytes()[r.start..r.end])
123        }
124    }
125
126    impl ops::Index<ops::RangeInclusive<usize>> for Bytes {
127        type Output = Bytes;
128
129        #[inline]
130        fn index(&self, r: ops::RangeInclusive<usize>) -> &Bytes {
131            Bytes::new(&self.as_bytes()[*r.start()..=*r.end()])
132        }
133    }
134
135    impl ops::Index<ops::RangeFrom<usize>> for Bytes {
136        type Output = Bytes;
137
138        #[inline]
139        fn index(&self, r: ops::RangeFrom<usize>) -> &Bytes {
140            Bytes::new(&self.as_bytes()[r.start..])
141        }
142    }
143
144    impl ops::Index<ops::RangeTo<usize>> for Bytes {
145        type Output = Bytes;
146
147        #[inline]
148        fn index(&self, r: ops::RangeTo<usize>) -> &Bytes {
149            Bytes::new(&self.as_bytes()[..r.end])
150        }
151    }
152
153    impl ops::Index<ops::RangeToInclusive<usize>> for Bytes {
154        type Output = Bytes;
155
156        #[inline]
157        fn index(&self, r: ops::RangeToInclusive<usize>) -> &Bytes {
158            Bytes::new(&self.as_bytes()[..=r.end])
159        }
160    }
161
162    impl AsRef<[u8]> for Bytes {
163        #[inline]
164        fn as_ref(&self) -> &[u8] {
165            self.as_bytes()
166        }
167    }
168
169    impl AsRef<Bytes> for [u8] {
170        #[inline]
171        fn as_ref(&self) -> &Bytes {
172            Bytes::new(self)
173        }
174    }
175
176    impl AsRef<Bytes> for str {
177        #[inline]
178        fn as_ref(&self) -> &Bytes {
179            Bytes::new(self)
180        }
181    }
182
183    #[cfg(feature = "alloc")]
184    impl crate::lib::std::borrow::ToOwned for Bytes {
185        type Owned = crate::lib::std::vec::Vec<u8>;
186
187        #[inline]
188        fn to_owned(&self) -> Self::Owned {
189            crate::lib::std::vec::Vec::from(self.as_bytes())
190        }
191    }
192
193    #[cfg(feature = "alloc")]
194    impl crate::lib::std::borrow::Borrow<Bytes> for crate::lib::std::vec::Vec<u8> {
195        #[inline]
196        fn borrow(&self) -> &Bytes {
197            Bytes::from_bytes(self.as_slice())
198        }
199    }
200
201    impl<'a> Default for &'a Bytes {
202        fn default() -> &'a Bytes {
203            Bytes::new(b"")
204        }
205    }
206
207    impl<'a> From<&'a [u8]> for &'a Bytes {
208        #[inline]
209        fn from(s: &'a [u8]) -> &'a Bytes {
210            Bytes::new(s)
211        }
212    }
213
214    impl<'a> From<&'a Bytes> for &'a [u8] {
215        #[inline]
216        fn from(s: &'a Bytes) -> &'a [u8] {
217            Bytes::as_bytes(s)
218        }
219    }
220
221    impl<'a> From<&'a str> for &'a Bytes {
222        #[inline]
223        fn from(s: &'a str) -> &'a Bytes {
224            Bytes::new(s.as_bytes())
225        }
226    }
227
228    impl Eq for Bytes {}
229
230    impl PartialEq<Bytes> for Bytes {
231        #[inline]
232        fn eq(&self, other: &Bytes) -> bool {
233            self.as_bytes() == other.as_bytes()
234        }
235    }
236
237    impl_partial_eq!(Bytes, [u8]);
238    impl_partial_eq!(Bytes, &'a [u8]);
239    impl_partial_eq!(Bytes, str);
240    impl_partial_eq!(Bytes, &'a str);
241
242    impl PartialOrd for Bytes {
243        #[inline]
244        fn partial_cmp(&self, other: &Bytes) -> Option<Ordering> {
245            Some(self.cmp(other))
246        }
247    }
248
249    impl Ord for Bytes {
250        #[inline]
251        fn cmp(&self, other: &Bytes) -> Ordering {
252            Ord::cmp(self.as_bytes(), other.as_bytes())
253        }
254    }
255
256    impl_partial_ord!(Bytes, [u8]);
257    impl_partial_ord!(Bytes, &'a [u8]);
258    impl_partial_ord!(Bytes, str);
259    impl_partial_ord!(Bytes, &'a str);
260
261    #[cfg(all(test, feature = "std"))]
262    mod display {
263        use crate::stream::Bytes;
264
265        #[test]
266        fn clean() {
267            assert_eq!(&format!("{}", Bytes::new(b"abc")), "616263");
268            assert_eq!(&format!("{}", Bytes::new(b"\xf0\x28\x8c\xbc")), "F0288CBC");
269        }
270    }
271
272    #[cfg(all(test, feature = "std"))]
273    mod debug {
274        use crate::stream::Bytes;
275
276        #[test]
277        fn test_debug() {
278            assert_eq!(
279                "000000206674797069736F6D0000020069736F6D69736F32617663316D70",
280                format!(
281                    "{:?}",
282                    Bytes::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp")
283                ),
284            );
285        }
286
287        #[test]
288        fn test_pretty_debug() {
289            // Output can change from run-to-run
290            format!(
291                "{:#?}",
292                Bytes::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp")
293            );
294        }
295
296        #[test]
297        fn test_sliced() {
298            // Output can change from run-to-run
299            let total = Bytes::new(b"12345678901234567890");
300            format!("{total:#?}");
301            format!("{:#?}", &total[1..]);
302            format!("{:#?}", &total[10..]);
303        }
304    }
305}
306
307mod bstr {
308    use crate::lib::std::{cmp::Ordering, fmt, ops};
309
310    use crate::stream::BStr;
311
312    #[cfg(feature = "alloc")]
313    impl fmt::Display for BStr {
314        #[inline]
315        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316            crate::lib::std::string::String::from_utf8_lossy(self.as_bytes()).fmt(f)
317        }
318    }
319
320    impl fmt::Debug for BStr {
321        #[inline]
322        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
323            if !f.alternate() {
324                write!(f, "\"")?;
325            }
326            for byte in self.as_bytes() {
327                let c = *byte as char;
328                write!(f, "{}", c.escape_debug())?;
329            }
330            if !f.alternate() {
331                write!(f, "\"")?;
332            }
333            Ok(())
334        }
335    }
336
337    impl ops::Deref for BStr {
338        type Target = [u8];
339
340        #[inline]
341        fn deref(&self) -> &[u8] {
342            self.as_bytes()
343        }
344    }
345
346    impl ops::Index<usize> for BStr {
347        type Output = u8;
348
349        #[inline]
350        fn index(&self, idx: usize) -> &u8 {
351            &self.as_bytes()[idx]
352        }
353    }
354
355    impl ops::Index<ops::RangeFull> for BStr {
356        type Output = BStr;
357
358        #[inline]
359        fn index(&self, _: ops::RangeFull) -> &BStr {
360            self
361        }
362    }
363
364    impl ops::Index<ops::Range<usize>> for BStr {
365        type Output = BStr;
366
367        #[inline]
368        fn index(&self, r: ops::Range<usize>) -> &BStr {
369            BStr::new(&self.as_bytes()[r.start..r.end])
370        }
371    }
372
373    impl ops::Index<ops::RangeInclusive<usize>> for BStr {
374        type Output = BStr;
375
376        #[inline]
377        fn index(&self, r: ops::RangeInclusive<usize>) -> &BStr {
378            BStr::new(&self.as_bytes()[*r.start()..=*r.end()])
379        }
380    }
381
382    impl ops::Index<ops::RangeFrom<usize>> for BStr {
383        type Output = BStr;
384
385        #[inline]
386        fn index(&self, r: ops::RangeFrom<usize>) -> &BStr {
387            BStr::new(&self.as_bytes()[r.start..])
388        }
389    }
390
391    impl ops::Index<ops::RangeTo<usize>> for BStr {
392        type Output = BStr;
393
394        #[inline]
395        fn index(&self, r: ops::RangeTo<usize>) -> &BStr {
396            BStr::new(&self.as_bytes()[..r.end])
397        }
398    }
399
400    impl ops::Index<ops::RangeToInclusive<usize>> for BStr {
401        type Output = BStr;
402
403        #[inline]
404        fn index(&self, r: ops::RangeToInclusive<usize>) -> &BStr {
405            BStr::new(&self.as_bytes()[..=r.end])
406        }
407    }
408
409    impl AsRef<[u8]> for BStr {
410        #[inline]
411        fn as_ref(&self) -> &[u8] {
412            self.as_bytes()
413        }
414    }
415
416    impl AsRef<BStr> for [u8] {
417        #[inline]
418        fn as_ref(&self) -> &BStr {
419            BStr::new(self)
420        }
421    }
422
423    impl AsRef<BStr> for str {
424        #[inline]
425        fn as_ref(&self) -> &BStr {
426            BStr::new(self)
427        }
428    }
429
430    #[cfg(feature = "alloc")]
431    impl crate::lib::std::borrow::ToOwned for BStr {
432        type Owned = crate::lib::std::vec::Vec<u8>;
433
434        #[inline]
435        fn to_owned(&self) -> Self::Owned {
436            crate::lib::std::vec::Vec::from(self.as_bytes())
437        }
438    }
439
440    #[cfg(feature = "alloc")]
441    impl crate::lib::std::borrow::Borrow<BStr> for crate::lib::std::vec::Vec<u8> {
442        #[inline]
443        fn borrow(&self) -> &BStr {
444            BStr::from_bytes(self.as_slice())
445        }
446    }
447
448    impl<'a> Default for &'a BStr {
449        fn default() -> &'a BStr {
450            BStr::new(b"")
451        }
452    }
453
454    impl<'a> From<&'a [u8]> for &'a BStr {
455        #[inline]
456        fn from(s: &'a [u8]) -> &'a BStr {
457            BStr::new(s)
458        }
459    }
460
461    impl<'a> From<&'a BStr> for &'a [u8] {
462        #[inline]
463        fn from(s: &'a BStr) -> &'a [u8] {
464            BStr::as_bytes(s)
465        }
466    }
467
468    impl<'a> From<&'a str> for &'a BStr {
469        #[inline]
470        fn from(s: &'a str) -> &'a BStr {
471            BStr::new(s.as_bytes())
472        }
473    }
474
475    impl Eq for BStr {}
476
477    impl PartialEq<BStr> for BStr {
478        #[inline]
479        fn eq(&self, other: &BStr) -> bool {
480            self.as_bytes() == other.as_bytes()
481        }
482    }
483
484    impl_partial_eq!(BStr, [u8]);
485    impl_partial_eq!(BStr, &'a [u8]);
486    impl_partial_eq!(BStr, str);
487    impl_partial_eq!(BStr, &'a str);
488
489    impl PartialOrd for BStr {
490        #[inline]
491        fn partial_cmp(&self, other: &BStr) -> Option<Ordering> {
492            Some(self.cmp(other))
493        }
494    }
495
496    impl Ord for BStr {
497        #[inline]
498        fn cmp(&self, other: &BStr) -> Ordering {
499            Ord::cmp(self.as_bytes(), other.as_bytes())
500        }
501    }
502
503    impl_partial_ord!(BStr, [u8]);
504    impl_partial_ord!(BStr, &'a [u8]);
505    impl_partial_ord!(BStr, str);
506    impl_partial_ord!(BStr, &'a str);
507
508    #[cfg(all(test, feature = "std"))]
509    mod display {
510        use crate::stream::BStr;
511
512        #[test]
513        fn clean() {
514            assert_eq!(&format!("{}", BStr::new(b"abc")), "abc");
515            assert_eq!(&format!("{}", BStr::new(b"\xf0\x28\x8c\xbc")), "�(��");
516        }
517    }
518
519    #[cfg(all(test, feature = "std"))]
520    mod debug {
521        use crate::stream::BStr;
522
523        #[test]
524        fn test_debug() {
525            assert_eq!(&format!("{:?}", BStr::new(b"abc")), "\"abc\"");
526
527            assert_eq!(
528                "\"\\0\\0\\0 ftypisom\\0\\0\\u{2}\\0isomiso2avc1mp\"",
529                format!(
530                    "{:?}",
531                    BStr::new(b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp")
532                ),
533            );
534        }
535
536        #[test]
537        fn test_pretty_debug() {
538            assert_eq!(&format!("{:#?}", BStr::new(b"abc")), "abc");
539        }
540    }
541}