4
4
use crate :: Bytes ;
5
5
#[ cfg( feature = "serde" ) ]
6
6
use serde:: ser:: { Serialize , Serializer } ;
7
- use std:: borrow:: Borrow ;
8
- use std:: str:: Utf8Error ;
7
+ use std:: { borrow:: Borrow , hash, str:: Utf8Error } ;
9
8
10
- #[ derive( Clone , Debug , Eq , Hash , PartialEq ) ]
9
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
11
10
pub struct BytesString {
12
11
bytes : Bytes ,
13
12
}
@@ -40,9 +39,9 @@ impl BytesString {
40
39
/// # Errors
41
40
///
42
41
/// Returns a `Utf8Error` if the bytes are not valid UTF-8.
43
- pub fn from_slice ( slice : & [ u8 ] ) -> Result < BytesString , Utf8Error > {
42
+ pub fn from_slice ( slice : & [ u8 ] ) -> Result < Self , Utf8Error > {
44
43
std:: str:: from_utf8 ( slice) ?;
45
- Ok ( BytesString {
44
+ Ok ( Self {
46
45
bytes : Bytes :: copy_from_slice ( slice) ,
47
46
} )
48
47
}
@@ -64,9 +63,9 @@ impl BytesString {
64
63
/// # Errors
65
64
///
66
65
/// Returns a `Utf8Error` if the bytes are not valid UTF-8.
67
- pub fn from_bytes ( bytes : Bytes ) -> Result < BytesString , Utf8Error > {
66
+ pub fn from_bytes ( bytes : Bytes ) -> Result < Self , Utf8Error > {
68
67
std:: str:: from_utf8 ( & bytes) ?;
69
- Ok ( BytesString { bytes } )
68
+ Ok ( Self { bytes } )
70
69
}
71
70
72
71
/// Creates a `BytesString` from a string slice within the given buffer.
@@ -75,12 +74,10 @@ impl BytesString {
75
74
///
76
75
/// * `bytes` - A `tinybytes::Bytes` instance that will be converted into a `BytesString`.
77
76
/// * `slice` - The string slice pointing into the given bytes that will form the `BytesString`.
78
- pub fn from_bytes_slice ( bytes : & Bytes , slice : & str ) -> BytesString {
77
+ pub fn from_bytes_slice ( bytes : & Bytes , slice : & str ) -> Self {
79
78
// SAFETY: This is safe as a str slice is definitely a valid UTF-8 slice.
80
79
unsafe {
81
- BytesString :: from_bytes_unchecked (
82
- bytes. slice_ref ( slice. as_bytes ( ) ) . expect ( "Invalid slice" ) ,
83
- )
80
+ Self :: from_bytes_unchecked ( bytes. slice_ref ( slice. as_bytes ( ) ) . expect ( "Invalid slice" ) )
84
81
}
85
82
}
86
83
@@ -97,8 +94,8 @@ impl BytesString {
97
94
///
98
95
/// This function is unsafe because it assumes the bytes are valid UTF-8. If the bytes are not
99
96
/// valid UTF-8, the behavior is undefined.
100
- pub unsafe fn from_bytes_unchecked ( bytes : Bytes ) -> BytesString {
101
- BytesString { bytes }
97
+ pub unsafe fn from_bytes_unchecked ( bytes : Bytes ) -> Self {
98
+ Self { bytes }
102
99
}
103
100
104
101
/// Returns the string slice representation of the `BytesString` (without validating the bytes).
@@ -113,7 +110,7 @@ impl BytesString {
113
110
114
111
impl Default for BytesString {
115
112
fn default ( ) -> Self {
116
- BytesString {
113
+ Self {
117
114
bytes : Bytes :: empty ( ) ,
118
115
}
119
116
}
@@ -125,9 +122,38 @@ impl Borrow<str> for BytesString {
125
122
}
126
123
}
127
124
125
+ impl AsRef < str > for BytesString {
126
+ fn as_ref ( & self ) -> & str {
127
+ self . as_str ( )
128
+ }
129
+ }
130
+
131
+ impl From < String > for BytesString {
132
+ fn from ( value : String ) -> Self {
133
+ // SAFETY: This is safe as a String is always a valid UTF-8 slice.
134
+ unsafe { Self :: from_bytes_unchecked ( Bytes :: from_underlying ( value) ) }
135
+ }
136
+ }
137
+
138
+ impl From < & ' static str > for BytesString {
139
+ fn from ( value : & ' static str ) -> Self {
140
+ // SAFETY: This is safe as a str is always a valid UTF-8 slice.
141
+ unsafe { Self :: from_bytes_unchecked ( Bytes :: from_static ( value. as_bytes ( ) ) ) }
142
+ }
143
+ }
144
+
145
+ // We can't derive Hash from Bytes as [u8] and str do not provide the same hash
146
+ impl hash:: Hash for BytesString {
147
+ #[ inline]
148
+ fn hash < H : hash:: Hasher > ( & self , state : & mut H ) {
149
+ self . as_str ( ) . hash ( state) ;
150
+ }
151
+ }
152
+
128
153
#[ cfg( test) ]
129
154
mod tests {
130
155
use super :: * ;
156
+ use std:: hash:: { DefaultHasher , Hash , Hasher } ;
131
157
132
158
#[ test]
133
159
fn test_from_slice ( ) {
@@ -190,4 +216,30 @@ mod tests {
190
216
let borrowed: & str = bytes_string. borrow ( ) ;
191
217
assert_eq ! ( borrowed, "borrow" ) ;
192
218
}
219
+
220
+ #[ test]
221
+ fn from_string ( ) {
222
+ let string = String :: from ( "hello" ) ;
223
+ let bytes_string = BytesString :: from ( string) ;
224
+ assert_eq ! ( bytes_string. as_str( ) , "hello" )
225
+ }
226
+
227
+ #[ test]
228
+ fn from_static_str ( ) {
229
+ let static_str = "hello" ;
230
+ let bytes_string = BytesString :: from ( static_str) ;
231
+ assert_eq ! ( bytes_string. as_str( ) , "hello" )
232
+ }
233
+
234
+ fn calculate_hash < T : Hash > ( t : & T ) -> u64 {
235
+ let mut s = DefaultHasher :: new ( ) ;
236
+ t. hash ( & mut s) ;
237
+ s. finish ( )
238
+ }
239
+
240
+ #[ test]
241
+ fn hash ( ) {
242
+ let bytes_string = BytesString :: from_slice ( b"test hash" ) . unwrap ( ) ;
243
+ assert_eq ! ( calculate_hash( & bytes_string) , calculate_hash( & "test hash" ) ) ;
244
+ }
193
245
}
0 commit comments