1use alloc::borrow::ToOwned;
2use alloc::string::String;
3use core::borrow::Borrow;
4use core::fmt;
5use core::hash::{Hash, Hasher};
6use core::ops::Deref;
7
8use trie::Break;
9
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
14pub struct BString(String);
15
16impl fmt::Debug for BString {
17 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18 self.0.fmt(f)
19 }
20}
21
22impl From<BString> for String {
23 #[inline]
24 fn from(bs: BString) -> String {
25 bs.0
26 }
27}
28
29impl From<String> for BString {
30 #[inline]
31 fn from(s: String) -> BString {
32 BString(s)
33 }
34}
35
36impl<'a> From<&'a str> for BString {
37 #[inline]
38 fn from(s: &'a str) -> BString {
39 BString(s.into())
40 }
41}
42
43impl Deref for BString {
44 type Target = BStr;
45
46 #[inline]
47 fn deref(&self) -> &Self::Target {
48 From::from(self.0.as_str())
49 }
50}
51
52impl Borrow<BStr> for BString {
53 #[inline]
54 fn borrow(&self) -> &BStr {
55 self
56 }
57}
58
59impl Borrow<[u8]> for BString {
60 #[inline]
61 fn borrow(&self) -> &[u8] {
62 self.0.as_bytes()
63 }
64}
65
66#[allow(clippy::derived_hash_with_manual_eq)]
67impl Hash for BString {
68 #[inline]
69 fn hash<H: Hasher>(&self, state: &mut H) {
70 self.0.as_bytes().hash(state);
71 }
72}
73
74impl Break for BString {
75 type Split = BStr;
76
77 #[inline]
78 fn empty<'a>() -> &'a BStr {
79 BStr::empty()
80 }
81
82 #[inline]
83 fn find_break(&self, loc: usize) -> &BStr {
84 (**self).find_break(loc)
85 }
86}
87
88#[derive(PartialEq, Eq, PartialOrd, Ord)]
91pub struct BStr(str);
92
93impl fmt::Debug for BStr {
94 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95 self.0.fmt(f)
96 }
97}
98
99impl<'a> From<&'a str> for &'a BStr {
100 fn from(s: &'a str) -> &'a BStr {
101 unsafe { &*(s as *const str as *const BStr) }
102 }
103}
104
105impl ToOwned for BStr {
106 type Owned = BString;
107
108 #[inline]
109 fn to_owned(&self) -> BString {
110 self.0.to_owned().into()
111 }
112}
113
114impl Borrow<[u8]> for BStr {
115 #[inline]
116 fn borrow(&self) -> &[u8] {
117 self.0.as_bytes()
118 }
119}
120
121#[allow(clippy::derived_hash_with_manual_eq)]
122impl Hash for BStr {
123 #[inline]
124 fn hash<H: Hasher>(&self, state: &mut H) {
125 self.0.as_bytes().hash(state);
126 }
127}
128
129impl Break for BStr {
130 type Split = BStr;
131
132 #[inline]
133 fn empty<'a>() -> &'a BStr {
134 <&'a BStr>::from(<&'a str>::default())
135 }
136
137 #[inline]
138 fn find_break(&self, mut loc: usize) -> &BStr {
139 while !self.0.is_char_boundary(loc) {
140 loc -= 1;
141 }
142
143 From::from(&self.as_str()[..loc])
144 }
145}
146
147impl BStr {
148 #[inline]
149 pub fn as_str(&self) -> &str {
150 &self.0
151 }
152}
153
154impl AsRef<BStr> for str {
155 fn as_ref(&self) -> &BStr {
156 <&BStr>::from(self)
157 }
158}