mco_redis/bytes/
string.rs1use std::{borrow, convert::TryFrom, fmt, hash, ops, slice, str};
3
4use crate::bytes::{Bytes, BytesMut, BytesVec};
5
6#[derive(Clone, Default, Eq, PartialOrd, Ord)]
8pub struct ByteString(Bytes);
9
10impl ByteString {
11 #[inline]
13 pub const fn new() -> Self {
14 ByteString(Bytes::new())
15 }
16
17 #[inline]
19 pub fn as_slice(&self) -> &[u8] {
20 self.0.as_ref()
21 }
22
23 #[inline]
25 pub fn as_bytes(&self) -> &Bytes {
26 &self.0
27 }
28
29 #[inline]
31 pub fn into_bytes(self) -> Bytes {
32 self.0
33 }
34
35 #[inline]
37 pub const fn from_static(src: &'static str) -> ByteString {
38 Self(Bytes::from_static(src.as_bytes()))
39 }
40
41 pub fn slice(
64 &self,
65 range: impl ops::RangeBounds<usize> + slice::SliceIndex<str> + Clone,
66 ) -> ByteString {
67 ops::Index::index(self.as_ref(), range.clone());
68 ByteString(self.0.slice(range))
69 }
70
71 pub fn split_off(&mut self, at: usize) -> ByteString {
95 let _ = self.split_at(at);
97
98 ByteString(self.0.split_off(at))
99 }
100
101 pub fn split_to(&mut self, at: usize) -> ByteString {
125 let _ = self.split_at(at);
127
128 ByteString(self.0.split_to(at))
129 }
130
131 #[inline]
133 pub fn trimdown(&mut self) {
134 self.0.trimdown()
135 }
136
137 #[inline]
145 pub const unsafe fn from_bytes_unchecked(src: Bytes) -> ByteString {
146 Self(src)
147 }
148}
149
150impl PartialEq<str> for ByteString {
151 fn eq(&self, other: &str) -> bool {
152 &self[..] == other
153 }
154}
155
156impl<T: AsRef<str>> PartialEq<T> for ByteString {
157 fn eq(&self, other: &T) -> bool {
158 &self[..] == other.as_ref()
159 }
160}
161
162impl AsRef<str> for ByteString {
163 #[inline]
164 fn as_ref(&self) -> &str {
165 &*self
166 }
167}
168
169impl hash::Hash for ByteString {
170 fn hash<H: hash::Hasher>(&self, state: &mut H) {
171 (**self).hash(state);
172 }
173}
174
175impl ops::Deref for ByteString {
176 type Target = str;
177
178 #[inline]
179 fn deref(&self) -> &str {
180 let bytes = self.0.as_ref();
181 unsafe { str::from_utf8_unchecked(bytes) }
184 }
185}
186
187impl borrow::Borrow<str> for ByteString {
188 #[inline]
189 fn borrow(&self) -> &str {
190 &*self
191 }
192}
193
194impl From<String> for ByteString {
195 #[inline]
196 fn from(value: String) -> Self {
197 Self(Bytes::from(value))
198 }
199}
200
201impl From<&str> for ByteString {
202 #[inline]
203 fn from(value: &str) -> Self {
204 Self(Bytes::copy_from_slice(value.as_ref()))
205 }
206}
207
208impl<'a> From<borrow::Cow<'a, str>> for ByteString {
209 #[inline]
210 fn from(value: borrow::Cow<'a, str>) -> Self {
211 match value {
212 borrow::Cow::Owned(s) => Self::from(s),
213 borrow::Cow::Borrowed(s) => Self::from(s),
214 }
215 }
216}
217
218impl TryFrom<&[u8]> for ByteString {
219 type Error = ();
220
221 #[inline]
222 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
223 if utf8::is_valid(value) {
224 Ok(ByteString(Bytes::copy_from_slice(value)))
225 } else {
226 Err(())
227 }
228 }
229}
230
231impl TryFrom<Vec<u8>> for ByteString {
232 type Error = ();
233
234 #[inline]
235 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
236 if utf8::is_valid(&value) {
237 Ok(ByteString(Bytes::from(value)))
238 } else {
239 Err(())
240 }
241 }
242}
243
244impl TryFrom<Bytes> for ByteString {
245 type Error = ();
246
247 #[inline]
248 fn try_from(value: Bytes) -> Result<Self, Self::Error> {
249 if utf8::is_valid(&value) {
250 Ok(ByteString(value))
251 } else {
252 Err(())
253 }
254 }
255}
256
257impl TryFrom<BytesMut> for ByteString {
258 type Error = ();
259
260 #[inline]
261 fn try_from(value: BytesMut) -> Result<Self, Self::Error> {
262 if utf8::is_valid(&value) {
263 Ok(ByteString(value.freeze()))
264 } else {
265 Err(())
266 }
267 }
268}
269
270impl TryFrom<BytesVec> for ByteString {
271 type Error = ();
272
273 #[inline]
274 fn try_from(value: BytesVec) -> Result<Self, Self::Error> {
275 if utf8::is_valid(&value) {
276 Ok(ByteString(value.freeze()))
277 } else {
278 Err(())
279 }
280 }
281}
282
283impl fmt::Debug for ByteString {
284 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
285 (**self).fmt(fmt)
286 }
287}
288
289impl fmt::Display for ByteString {
290 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
291 (**self).fmt(fmt)
292 }
293}
294
295mod serde {
296 use serde::de::{Deserialize, Deserializer};
297 use serde::ser::{Serialize, Serializer};
298
299 use super::ByteString;
300
301 impl Serialize for ByteString {
302 #[inline]
303 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
304 where
305 S: Serializer,
306 {
307 serializer.serialize_str(self.as_ref())
308 }
309 }
310
311 impl<'de> Deserialize<'de> for ByteString {
312 #[inline]
313 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
314 where
315 D: Deserializer<'de>,
316 {
317 String::deserialize(deserializer).map(ByteString::from)
318 }
319 }
320}
321
322#[cfg(feature = "simd")]
323mod utf8 {
324 pub(super) fn is_valid(input: &[u8]) -> bool {
325 simdutf8::basic::from_utf8(input).is_ok()
326 }
327}
328
329#[cfg(not(feature = "simd"))]
330mod utf8 {
331 pub(super) fn is_valid(input: &[u8]) -> bool {
332 std::str::from_utf8(input).is_ok()
333 }
334}
335
336#[cfg(test)]
337mod test {
338 use std::borrow::ToOwned;
339 use std::collections::hash_map::DefaultHasher;
340 use std::hash::{Hash, Hasher};
341
342 use super::*;
343
344 #[test]
345 fn test_basics() {
346 let mut s = ByteString::from_static("test");
347 s.trimdown();
348 assert_eq!(s, "test");
349 assert_eq!(s, *"test");
350 assert_eq!(s, "test".to_owned());
351 assert_eq!(s.as_slice(), b"test");
352 assert_eq!(s.as_bytes(), &Bytes::copy_from_slice(b"test"));
353
354 assert_eq!(format!("{}", s), "test");
355 assert_eq!(format!("{:?}", s), "\"test\"");
356 assert_eq!(s.into_bytes(), Bytes::copy_from_slice(b"test"));
357 }
358
359 #[test]
360 fn test_split() {
361 let mut s = ByteString::from_static("helloworld");
362 let s1 = s.split_off(5);
363 assert_eq!(s, "hello");
364 assert_eq!(s1, "world");
365
366 let mut s = ByteString::from_static("helloworld");
367 let s1 = s.split_to(5);
368 assert_eq!(s, "world");
369 assert_eq!(s1, "hello");
370 }
371
372 #[test]
373 fn test_new() {
374 let _: ByteString = ByteString::new();
375 }
376
377 #[test]
378 fn test_hash() {
379 let mut hasher1 = DefaultHasher::default();
380 "str".hash(&mut hasher1);
381
382 let mut hasher2 = DefaultHasher::default();
383 let s = ByteString::from_static("str");
384 s.hash(&mut hasher2);
385 assert_eq!(hasher1.finish(), hasher2.finish());
386 }
387
388 #[test]
389 fn test_from_string() {
390 let s: ByteString = "hello".to_owned().into();
391 assert_eq!(&s, "hello");
392 let t: &str = s.as_ref();
393 assert_eq!(t, "hello");
394 }
395
396 #[test]
397 fn test_from_str() {
398 let _: ByteString = "str".into();
399 }
400
401 #[test]
402 fn test_from_static_str() {
403 static _S: ByteString = ByteString::from_static("hello");
404 let _ = ByteString::from_static("str");
405 }
406
407 #[test]
408 fn test_try_from() {
409 let _ = ByteString::try_from(&b"nice bytes"[..]).unwrap();
410 let _ = ByteString::try_from(b"nice bytes".to_vec()).unwrap();
411 let _ = ByteString::try_from(Bytes::from_static(b"nice bytes")).unwrap();
412 let _ = ByteString::try_from(BytesMut::from(&b"nice bytes"[..])).unwrap();
413 let _ =
414 ByteString::try_from(BytesVec::copy_from_slice(&b"nice bytes"[..])).unwrap();
415 }
416
417 #[test]
418 fn test_serialize() {
419 let s: ByteString = serde_json::from_str(r#""nice bytes""#).unwrap();
420 assert_eq!(s, "nice bytes");
421 }
422
423 #[test]
424 fn test_deserialize() {
425 let s = serde_json::to_string(&ByteString::from_static("nice bytes")).unwrap();
426 assert_eq!(s, r#""nice bytes""#);
427 }
428}