1 #![cfg(feature = "bytes")] 2 3 use std::fmt; 4 use std::ops::Deref; 5 use std::str; 6 7 use bytes::Bytes; 8 9 use crate::clear::Clear; 10 11 /// Thin wrapper around `Bytes` which guarantees that bytes are valid UTF-8 string. 12 /// Should be API-compatible to `String`. 13 #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] 14 pub struct Chars(Bytes); 15 16 impl Chars { 17 /// New empty object. new() -> Chars18 pub fn new() -> Chars { 19 Chars(Bytes::new()) 20 } 21 22 /// Try convert from `Bytes` from_bytes(bytes: Bytes) -> Result<Chars, str::Utf8Error>23 pub fn from_bytes(bytes: Bytes) -> Result<Chars, str::Utf8Error> { 24 str::from_utf8(&bytes)?; 25 26 Ok(Chars(bytes)) 27 } 28 29 /// Len in bytes. len(&self) -> usize30 pub fn len(&self) -> usize { 31 self.0.len() 32 } 33 34 /// Self-explanatory is_empty(&self) -> bool35 pub fn is_empty(&self) -> bool { 36 self.0.is_empty() 37 } 38 } 39 40 impl<'a> From<&'a str> for Chars { from(src: &'a str) -> Chars41 fn from(src: &'a str) -> Chars { 42 Chars(Bytes::copy_from_slice(src.as_bytes())) 43 } 44 } 45 46 impl From<String> for Chars { from(src: String) -> Chars47 fn from(src: String) -> Chars { 48 Chars(Bytes::from(src)) 49 } 50 } 51 52 impl Into<String> for Chars { into(self) -> String53 fn into(self) -> String { 54 // This is safe because `Chars` is guaranteed to store a valid UTF-8 string 55 unsafe { String::from_utf8_unchecked(self.0.as_ref().to_owned()) } 56 } 57 } 58 59 impl Default for Chars { default() -> Self60 fn default() -> Self { 61 Chars::new() 62 } 63 } 64 65 impl Deref for Chars { 66 type Target = str; 67 deref(&self) -> &str68 fn deref(&self) -> &str { 69 // This is safe because `Chars` is guaranteed to store a valid UTF-8 string 70 unsafe { str::from_utf8_unchecked(&self.0) } 71 } 72 } 73 74 impl Clear for Chars { clear(&mut self)75 fn clear(&mut self) { 76 self.0.clear(); 77 } 78 } 79 80 impl fmt::Display for Chars { 81 #[inline] fmt(&self, f: &mut fmt::Formatter) -> fmt::Result82 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 83 fmt::Display::fmt(&**self, f) 84 } 85 } 86 87 impl fmt::Debug for Chars { 88 #[inline] fmt(&self, f: &mut fmt::Formatter) -> fmt::Result89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 90 fmt::Debug::fmt(&**self, f) 91 } 92 } 93 94 #[cfg(test)] 95 mod test { 96 use super::Chars; 97 98 #[test] test_display_and_debug()99 fn test_display_and_debug() { 100 let s = "test"; 101 let string: String = s.into(); 102 let chars: Chars = s.into(); 103 104 assert_eq!(format!("{}", string), format!("{}", chars)); 105 assert_eq!(format!("{:?}", string), format!("{:?}", chars)); 106 } 107 } 108