• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of ICU4X. For terms of use, please see the file
2 // called LICENSE at the top level of the ICU4X source tree
3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4 
5 use core::borrow::Borrow;
6 
7 #[cfg(feature = "serde")]
8 use alloc::boxed::Box;
9 
10 /// A struct transparent over `[u8]` with convenient helper functions.
11 #[repr(transparent)]
12 #[derive(PartialEq, Eq, PartialOrd, Ord)]
13 pub(crate) struct ByteStr([u8]);
14 
15 impl ByteStr {
from_byte_slice_with_value<'a, 'l>( input: &'l [(&'a [u8], usize)], ) -> &'l [(&'a ByteStr, usize)]16     pub const fn from_byte_slice_with_value<'a, 'l>(
17         input: &'l [(&'a [u8], usize)],
18     ) -> &'l [(&'a ByteStr, usize)] {
19         // Safety: [u8] and ByteStr have the same layout and invariants
20         unsafe { core::mem::transmute(input) }
21     }
22 
from_str_slice_with_value<'a, 'l>( input: &'l [(&'a str, usize)], ) -> &'l [(&'a ByteStr, usize)]23     pub const fn from_str_slice_with_value<'a, 'l>(
24         input: &'l [(&'a str, usize)],
25     ) -> &'l [(&'a ByteStr, usize)] {
26         // Safety: str and ByteStr have the same layout, and ByteStr is less restrictive
27         unsafe { core::mem::transmute(input) }
28     }
29 
from_bytes(input: &[u8]) -> &Self30     pub fn from_bytes(input: &[u8]) -> &Self {
31         // Safety: [u8] and ByteStr have the same layout and invariants
32         unsafe { core::mem::transmute(input) }
33     }
34 
35     #[cfg(feature = "serde")]
from_boxed_bytes(input: Box<[u8]>) -> Box<Self>36     pub fn from_boxed_bytes(input: Box<[u8]>) -> Box<Self> {
37         // Safety: [u8] and ByteStr have the same layout and invariants
38         unsafe { core::mem::transmute(input) }
39     }
40 
41     #[allow(dead_code)] // may want this in the future
from_str(input: &str) -> &Self42     pub fn from_str(input: &str) -> &Self {
43         Self::from_bytes(input.as_bytes())
44     }
45 
46     #[allow(dead_code)] // may want this in the future
empty() -> &'static Self47     pub fn empty() -> &'static Self {
48         Self::from_bytes(&[])
49     }
50 
51     #[allow(dead_code)] // not used in all features
as_bytes(&self) -> &[u8]52     pub const fn as_bytes(&self) -> &[u8] {
53         &self.0
54     }
55 
len(&self) -> usize56     pub const fn len(&self) -> usize {
57         self.0.len()
58     }
59 
60     #[allow(dead_code)] // not used in all features
is_all_ascii(&self) -> bool61     pub fn is_all_ascii(&self) -> bool {
62         for byte in self.0.iter() {
63             if !byte.is_ascii() {
64                 return false;
65             }
66         }
67         true
68     }
69 
70     #[allow(dead_code)] // may want this in the future
byte_at(&self, index: usize) -> Option<u8>71     pub(crate) fn byte_at(&self, index: usize) -> Option<u8> {
72         self.0.get(index).copied()
73     }
74 
75     /// Returns the byte at the given index, panicking if out of bounds.
byte_at_or_panic(&self, index: usize) -> u876     pub(crate) const fn byte_at_or_panic(&self, index: usize) -> u8 {
77         self.0[index]
78     }
79 
80     /// Const function to evaluate `self < other`.
is_less_then(&self, other: &Self) -> bool81     pub(crate) const fn is_less_then(&self, other: &Self) -> bool {
82         let mut i = 0;
83         while i < self.len() && i < other.len() {
84             if self.0[i] < other.0[i] {
85                 return true;
86             }
87             if self.0[i] > other.0[i] {
88                 return false;
89             }
90             i += 1;
91         }
92         self.len() < other.len()
93     }
94 
95     /// Const function to evaluate `self[..prefix_len] == other[..prefix_len]`
prefix_eq(&self, other: &ByteStr, prefix_len: usize) -> bool96     pub(crate) const fn prefix_eq(&self, other: &ByteStr, prefix_len: usize) -> bool {
97         assert!(prefix_len <= self.len());
98         assert!(prefix_len <= other.len());
99         let mut i = 0;
100         while i < prefix_len {
101             if self.0[i] != other.0[i] {
102                 return false;
103             }
104             i += 1;
105         }
106         true
107     }
108 }
109 
110 impl Borrow<[u8]> for ByteStr {
borrow(&self) -> &[u8]111     fn borrow(&self) -> &[u8] {
112         self.as_bytes()
113     }
114 }
115 
116 #[cfg(feature = "alloc")]
117 impl Borrow<[u8]> for alloc::boxed::Box<ByteStr> {
borrow(&self) -> &[u8]118     fn borrow(&self) -> &[u8] {
119         self.as_bytes()
120     }
121 }
122