proxy_wasm_experimental/
bytestring.rs

1// Copyright 2020 Tetrate
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use core::hash;
16use core::ops;
17use std::fmt;
18use std::string::FromUtf8Error;
19
20/// Represents a borrowed string value that is not necessarily UTF-8 encoded,
21/// e.g. an HTTP header value.
22pub struct ByteStr {
23    bytes: [u8],
24}
25
26impl ByteStr {
27    #[inline]
28    fn from_bytes(slice: &[u8]) -> &ByteStr {
29        unsafe { &*(slice as *const [u8] as *const ByteStr) }
30    }
31
32    #[inline]
33    fn from_bytes_mut(slice: &mut [u8]) -> &mut ByteStr {
34        unsafe { &mut *(slice as *mut [u8] as *mut ByteStr) }
35    }
36
37    #[inline]
38    pub fn as_bytes(&self) -> &[u8] {
39        &self.bytes
40    }
41}
42
43impl ops::Deref for ByteStr {
44    type Target = [u8];
45
46    #[inline]
47    fn deref(&self) -> &[u8] {
48        &self.bytes
49    }
50}
51
52impl ops::DerefMut for ByteStr {
53    #[inline]
54    fn deref_mut(&mut self) -> &mut [u8] {
55        &mut self.bytes
56    }
57}
58
59impl AsRef<[u8]> for ByteStr {
60    #[inline]
61    fn as_ref(&self) -> &[u8] {
62        &self.bytes
63    }
64}
65
66impl AsMut<[u8]> for ByteStr {
67    #[inline]
68    fn as_mut(&mut self) -> &mut [u8] {
69        &mut self.bytes
70    }
71}
72
73// Implementation borrowed from https://github.com/tokio-rs/bytes/blob/master/src/fmt/debug.rs
74impl fmt::Debug for ByteStr {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        write!(f, "b\"")?;
77        for &b in &self.bytes {
78            // https://doc.rust-lang.org/reference/tokens.html#byte-escapes
79            if b == b'\n' {
80                write!(f, "\\n")?;
81            } else if b == b'\r' {
82                write!(f, "\\r")?;
83            } else if b == b'\t' {
84                write!(f, "\\t")?;
85            } else if b == b'\\' || b == b'"' {
86                write!(f, "\\{}", b as char)?;
87            } else if b == b'\0' {
88                write!(f, "\\0")?;
89            // ASCII printable
90            } else if (0x20..0x7f).contains(&b) {
91                write!(f, "{}", b as char)?;
92            } else {
93                write!(f, "\\x{:02x}", b)?;
94            }
95        }
96        write!(f, "\"")?;
97        Ok(())
98    }
99}
100
101impl fmt::Display for ByteStr {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        fmt::Display::fmt(&String::from_utf8_lossy(&self.bytes), f)
104    }
105}
106
107impl ops::Index<usize> for ByteStr {
108    type Output = u8;
109
110    #[inline]
111    fn index(&self, idx: usize) -> &u8 {
112        &self.as_bytes()[idx]
113    }
114}
115
116impl ops::Index<ops::RangeFull> for ByteStr {
117    type Output = ByteStr;
118
119    #[inline]
120    fn index(&self, _: ops::RangeFull) -> &ByteStr {
121        self
122    }
123}
124
125impl ops::Index<ops::Range<usize>> for ByteStr {
126    type Output = ByteStr;
127
128    #[inline]
129    fn index(&self, r: ops::Range<usize>) -> &ByteStr {
130        ByteStr::from_bytes(&self.as_bytes()[r.start..r.end])
131    }
132}
133
134impl ops::Index<ops::RangeInclusive<usize>> for ByteStr {
135    type Output = ByteStr;
136
137    #[inline]
138    fn index(&self, r: ops::RangeInclusive<usize>) -> &ByteStr {
139        ByteStr::from_bytes(&self.as_bytes()[*r.start()..=*r.end()])
140    }
141}
142
143impl ops::Index<ops::RangeFrom<usize>> for ByteStr {
144    type Output = ByteStr;
145
146    #[inline]
147    fn index(&self, r: ops::RangeFrom<usize>) -> &ByteStr {
148        ByteStr::from_bytes(&self.as_bytes()[r.start..])
149    }
150}
151
152impl ops::Index<ops::RangeTo<usize>> for ByteStr {
153    type Output = ByteStr;
154
155    #[inline]
156    fn index(&self, r: ops::RangeTo<usize>) -> &ByteStr {
157        ByteStr::from_bytes(&self.as_bytes()[..r.end])
158    }
159}
160
161impl ops::Index<ops::RangeToInclusive<usize>> for ByteStr {
162    type Output = ByteStr;
163
164    #[inline]
165    fn index(&self, r: ops::RangeToInclusive<usize>) -> &ByteStr {
166        ByteStr::from_bytes(&self.as_bytes()[..=r.end])
167    }
168}
169
170impl ops::IndexMut<usize> for ByteStr {
171    #[inline]
172    fn index_mut(&mut self, idx: usize) -> &mut u8 {
173        &mut self.bytes[idx]
174    }
175}
176
177impl ops::IndexMut<ops::RangeFull> for ByteStr {
178    #[inline]
179    fn index_mut(&mut self, _: ops::RangeFull) -> &mut ByteStr {
180        self
181    }
182}
183
184impl ops::IndexMut<ops::Range<usize>> for ByteStr {
185    #[inline]
186    fn index_mut(&mut self, r: ops::Range<usize>) -> &mut ByteStr {
187        ByteStr::from_bytes_mut(&mut self.bytes[r.start..r.end])
188    }
189}
190
191impl ops::IndexMut<ops::RangeInclusive<usize>> for ByteStr {
192    #[inline]
193    fn index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut ByteStr {
194        ByteStr::from_bytes_mut(&mut self.bytes[*r.start()..=*r.end()])
195    }
196}
197
198impl ops::IndexMut<ops::RangeFrom<usize>> for ByteStr {
199    #[inline]
200    fn index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut ByteStr {
201        ByteStr::from_bytes_mut(&mut self.bytes[r.start..])
202    }
203}
204
205impl ops::IndexMut<ops::RangeTo<usize>> for ByteStr {
206    #[inline]
207    fn index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut ByteStr {
208        ByteStr::from_bytes_mut(&mut self.bytes[..r.end])
209    }
210}
211
212impl ops::IndexMut<ops::RangeToInclusive<usize>> for ByteStr {
213    #[inline]
214    fn index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut ByteStr {
215        ByteStr::from_bytes_mut(&mut self.bytes[..=r.end])
216    }
217}
218
219impl Eq for ByteStr {}
220
221impl PartialEq<ByteStr> for ByteStr {
222    #[inline]
223    fn eq(&self, other: &ByteStr) -> bool {
224        self.as_bytes() == other.as_bytes()
225    }
226}
227
228impl PartialEq<String> for ByteStr {
229    #[inline]
230    fn eq(&self, other: &String) -> bool {
231        self.as_bytes() == other.as_bytes()
232    }
233}
234
235impl PartialEq<Vec<u8>> for ByteStr {
236    #[inline]
237    fn eq(&self, other: &Vec<u8>) -> bool {
238        self.as_bytes() == other.as_slice()
239    }
240}
241
242impl PartialEq<str> for ByteStr {
243    #[inline]
244    fn eq(&self, other: &str) -> bool {
245        self.as_bytes() == other.as_bytes()
246    }
247}
248
249impl PartialEq<&str> for ByteStr {
250    #[inline]
251    fn eq(&self, other: &&str) -> bool {
252        self.as_bytes() == other.as_bytes()
253    }
254}
255
256impl PartialEq<[u8]> for ByteStr {
257    #[inline]
258    fn eq(&self, other: &[u8]) -> bool {
259        self.as_bytes() == other
260    }
261}
262
263impl PartialEq<&[u8]> for ByteStr {
264    #[inline]
265    fn eq(&self, other: &&[u8]) -> bool {
266        self.as_bytes() == *other
267    }
268}
269
270impl PartialEq<ByteStr> for String {
271    #[inline]
272    fn eq(&self, other: &ByteStr) -> bool {
273        *other == *self
274    }
275}
276
277impl PartialEq<ByteStr> for Vec<u8> {
278    #[inline]
279    fn eq(&self, other: &ByteStr) -> bool {
280        *other == *self
281    }
282}
283
284impl PartialEq<ByteStr> for str {
285    #[inline]
286    fn eq(&self, other: &ByteStr) -> bool {
287        *other == *self
288    }
289}
290
291impl PartialEq<ByteStr> for &str {
292    #[inline]
293    fn eq(&self, other: &ByteStr) -> bool {
294        *other == *self
295    }
296}
297
298impl PartialEq<ByteStr> for &[u8] {
299    #[inline]
300    fn eq(&self, other: &ByteStr) -> bool {
301        *other == *self
302    }
303}
304
305impl PartialEq<ByteStr> for [u8] {
306    #[inline]
307    fn eq(&self, other: &ByteStr) -> bool {
308        *other == *self
309    }
310}
311
312impl hash::Hash for ByteStr {
313    fn hash<H>(&self, state: &mut H)
314    where
315        H: hash::Hasher,
316    {
317        self.as_bytes().hash(state);
318    }
319}
320
321/// Represents a string value that is not necessarily UTF-8 encoded,
322/// e.g. an HTTP header value.
323#[derive(Default, Eq, Clone)]
324pub struct ByteString {
325    bytes: Vec<u8>,
326}
327
328impl ByteString {
329    pub fn new() -> Self {
330        Self::default()
331    }
332
333    pub fn is_empty(&self) -> bool {
334        self.as_ref().is_empty()
335    }
336
337    pub fn len(&self) -> usize {
338        self.as_ref().len()
339    }
340
341    pub fn as_bytes(&self) -> &[u8] {
342        self.as_ref()
343    }
344
345    pub fn into_bytes(self) -> Vec<u8> {
346        self.bytes
347    }
348
349    pub fn into_string(self) -> Result<String, FromUtf8Error> {
350        String::from_utf8(self.bytes)
351    }
352}
353
354impl ops::Deref for ByteString {
355    type Target = ByteStr;
356
357    #[inline]
358    fn deref(&self) -> &ByteStr {
359        ByteStr::from_bytes(&self.bytes)
360    }
361}
362
363impl ops::DerefMut for ByteString {
364    #[inline]
365    fn deref_mut(&mut self) -> &mut ByteStr {
366        ByteStr::from_bytes_mut(&mut self.bytes)
367    }
368}
369
370impl AsRef<[u8]> for ByteString {
371    #[inline]
372    fn as_ref(&self) -> &[u8] {
373        &self.bytes
374    }
375}
376
377impl AsMut<[u8]> for ByteString {
378    #[inline]
379    fn as_mut(&mut self) -> &mut [u8] {
380        &mut self.bytes
381    }
382}
383
384impl fmt::Display for ByteString {
385    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
386        fmt::Display::fmt(&**self, f)
387    }
388}
389
390impl fmt::Debug for ByteString {
391    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392        fmt::Debug::fmt(&**self, f)
393    }
394}
395
396impl From<Vec<u8>> for ByteString {
397    #[inline]
398    fn from(bytes: Vec<u8>) -> Self {
399        ByteString { bytes }
400    }
401}
402
403impl From<&[u8]> for ByteString {
404    #[inline]
405    fn from(bytes: &[u8]) -> Self {
406        bytes.to_owned().into()
407    }
408}
409
410impl From<String> for ByteString {
411    #[inline]
412    fn from(text: String) -> Self {
413        text.into_bytes().into()
414    }
415}
416
417impl From<&str> for ByteString {
418    #[inline]
419    fn from(text: &str) -> Self {
420        text.to_owned().into()
421    }
422}
423
424impl From<&ByteString> for ByteString {
425    #[inline]
426    fn from(data: &ByteString) -> Self {
427        data.clone()
428    }
429}
430
431impl PartialEq for ByteString {
432    #[inline]
433    fn eq(&self, other: &ByteString) -> bool {
434        self.bytes == other.bytes
435    }
436}
437
438impl PartialEq<String> for ByteString {
439    #[inline]
440    fn eq(&self, other: &String) -> bool {
441        self.as_ref() == other.as_bytes()
442    }
443}
444
445impl PartialEq<Vec<u8>> for ByteString {
446    #[inline]
447    fn eq(&self, other: &Vec<u8>) -> bool {
448        self.as_ref() == other.as_slice()
449    }
450}
451
452impl PartialEq<str> for ByteString {
453    #[inline]
454    fn eq(&self, other: &str) -> bool {
455        self.as_ref() == other.as_bytes()
456    }
457}
458
459impl PartialEq<&str> for ByteString {
460    #[inline]
461    fn eq(&self, other: &&str) -> bool {
462        self.as_ref() == other.as_bytes()
463    }
464}
465
466impl PartialEq<[u8]> for ByteString {
467    #[inline]
468    fn eq(&self, other: &[u8]) -> bool {
469        self.as_ref() == other
470    }
471}
472
473impl PartialEq<&[u8]> for ByteString {
474    #[inline]
475    fn eq(&self, other: &&[u8]) -> bool {
476        self.as_ref() == *other
477    }
478}
479
480impl PartialEq<ByteString> for String {
481    #[inline]
482    fn eq(&self, other: &ByteString) -> bool {
483        *other == *self
484    }
485}
486
487impl PartialEq<ByteString> for Vec<u8> {
488    #[inline]
489    fn eq(&self, other: &ByteString) -> bool {
490        *other == *self
491    }
492}
493
494impl PartialEq<ByteString> for str {
495    #[inline]
496    fn eq(&self, other: &ByteString) -> bool {
497        *other == *self
498    }
499}
500
501impl PartialEq<ByteString> for &str {
502    #[inline]
503    fn eq(&self, other: &ByteString) -> bool {
504        *other == *self
505    }
506}
507
508impl PartialEq<ByteString> for [u8] {
509    #[inline]
510    fn eq(&self, other: &ByteString) -> bool {
511        *other == *self
512    }
513}
514
515impl PartialEq<ByteString> for &[u8] {
516    #[inline]
517    fn eq(&self, other: &ByteString) -> bool {
518        *other == *self
519    }
520}
521
522impl hash::Hash for ByteString {
523    fn hash<H>(&self, state: &mut H)
524    where
525        H: hash::Hasher,
526    {
527        (&**self).hash(state);
528    }
529}
530
531#[cfg(test)]
532mod tests {
533    use super::*;
534    use std::collections::hash_map::DefaultHasher;
535    use std::hash::{Hash, Hasher};
536
537    #[test]
538    fn test_bytestring_bstr_utf8() {
539        use bstr::ByteSlice;
540
541        let string: ByteString = "hello".into();
542        assert_eq!(string.is_utf8(), true);
543        assert_eq!(string.starts_with_str("hel"), true);
544        assert_eq!(string.ends_with_str("lo"), true);
545    }
546
547    #[test]
548    fn test_bytestring_bstr_bytes() {
549        use bstr::ByteSlice;
550
551        let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
552        assert_eq!(bytes.is_utf8(), false);
553        assert_eq!(bytes.starts_with_str(b"\x90"), true);
554        assert_eq!(bytes.ends_with_str(b"\x92"), true);
555    }
556
557    #[test]
558    fn test_bytestring_display_utf8() {
559        let string: ByteString = "utf-8 encoded string".into();
560
561        assert_eq!(format!("{}", string), "utf-8 encoded string");
562    }
563
564    #[test]
565    fn test_bytestring_debug_utf8() {
566        let string: ByteString = "utf-8 encoded string".into();
567
568        assert_eq!(format!("{:?}", string), "b\"utf-8 encoded string\"");
569    }
570
571    #[test]
572    fn test_bytestring_display_bytes() {
573        let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
574
575        assert_eq!(format!("{}", bytes), "���");
576    }
577
578    #[test]
579    fn test_bytestring_debug_bytes() {
580        let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
581
582        assert_eq!(format!("{:?}", bytes), "b\"\\x90\\x91\\x92\"");
583    }
584
585    #[test]
586    fn test_bytestring_as_ref() {
587        fn receive<T>(value: T)
588        where
589            T: AsRef<[u8]>,
590        {
591            value.as_ref();
592        }
593
594        let string: ByteString = "utf-8 encoded string".into();
595        receive(string);
596
597        let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
598        receive(bytes);
599    }
600
601    #[test]
602    fn test_bytestring_substr_eq_utf8() {
603        let string: ByteString = "hello".into();
604
605        assert_eq!(string[1..=3], "ell");
606        assert_eq!(string[1..=3], "ell".to_owned());
607
608        assert_eq!("ell", string[1..=3]);
609        assert_eq!("ell".to_owned(), string[1..=3]);
610    }
611
612    #[test]
613    fn test_bytestring_substr_eq_bytes() {
614        let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
615
616        assert_eq!(bytes[1..2], b"\x91" as &[u8]);
617        assert_eq!(bytes[1..2], b"\x91".to_vec());
618
619        assert_eq!(b"\x91" as &[u8], bytes[1..2]);
620        assert_eq!(b"\x91".to_vec(), bytes[1..2]);
621    }
622
623    #[test]
624    #[allow(clippy::eq_op)]
625    fn test_bytestring_eq_string() {
626        let string: ByteString = "utf-8 encoded string".into();
627
628        assert_eq!(string, "utf-8 encoded string");
629        assert_eq!(string, b"utf-8 encoded string" as &[u8]);
630
631        assert_eq!("utf-8 encoded string", string);
632        assert_eq!(b"utf-8 encoded string" as &[u8], string);
633
634        assert_eq!(string, string);
635    }
636
637    #[test]
638    #[allow(clippy::eq_op)]
639    fn test_bytestring_eq_bytes() {
640        let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
641
642        assert_eq!(bytes, vec![144u8, 145u8, 146u8]);
643        assert_eq!(bytes, b"\x90\x91\x92" as &[u8]);
644
645        assert_eq!(vec![144u8, 145u8, 146u8], bytes);
646        assert_eq!(b"\x90\x91\x92" as &[u8], bytes);
647
648        assert_eq!(bytes, bytes);
649    }
650
651    fn hash<T: Hash>(t: &T) -> u64 {
652        let mut h = DefaultHasher::new();
653        t.hash(&mut h);
654        h.finish()
655    }
656
657    #[test]
658    fn test_bytestring_hash_string() {
659        let string: ByteString = "utf-8 encoded string".into();
660
661        assert_ne!(hash(&string), hash(&"utf-8 encoded string"));
662        assert_eq!(hash(&string), hash(&b"utf-8 encoded string"));
663
664        assert_ne!(hash(&"utf-8 encoded string"), hash(&string));
665        assert_eq!(hash(&b"utf-8 encoded string"), hash(&string));
666    }
667
668    #[test]
669    fn test_bytestring_hash_bytes() {
670        let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
671
672        assert_eq!(hash(&bytes), hash(&vec![144u8, 145u8, 146u8]));
673        assert_eq!(hash(&bytes), hash(&[144u8, 145u8, 146u8]));
674
675        assert_eq!(hash(&vec![144u8, 145u8, 146u8]), hash(&bytes));
676        assert_eq!(hash(&[144u8, 145u8, 146u8]), hash(&bytes));
677    }
678}