1 use std::fmt;
2 use std::ops::Deref;
3 use std::str;
4 
5 use bytes::Bytes;
6 
7 use clear::Clear;
8 
9 /// Thin wrapper around `Bytes` which guarantees that bytes are valid UTF-8 string.
10 #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
11 pub struct Chars(Bytes);
12 
13 impl Chars {
14     /// New empty object.
new() -> Chars15     pub fn new() -> Chars {
16         Chars(Bytes::new())
17     }
18 
19     /// Try convert from `Bytes`
from_bytes(bytes: Bytes) -> Result<Chars, str::Utf8Error>20     pub fn from_bytes(bytes: Bytes) -> Result<Chars, str::Utf8Error> {
21         str::from_utf8(&bytes)?;
22 
23         Ok(Chars(bytes))
24     }
25 
26     /// Len in bytes.
len(&self) -> usize27     pub fn len(&self) -> usize {
28         self.0.len()
29     }
30 
31     /// Self-explanatory
is_empty(&self) -> bool32     pub fn is_empty(&self) -> bool {
33         self.0.is_empty()
34     }
35 }
36 
37 impl<'a> From<&'a str> for Chars {
from(src: &'a str) -> Chars38     fn from(src: &'a str) -> Chars {
39         Chars(Bytes::copy_from_slice(src.as_bytes()))
40     }
41 }
42 
43 impl From<String> for Chars {
from(src: String) -> Chars44     fn from(src: String) -> Chars {
45         Chars(Bytes::from(src))
46     }
47 }
48 
49 impl Default for Chars {
default() -> Self50     fn default() -> Self {
51         Chars::new()
52     }
53 }
54 
55 impl Deref for Chars {
56     type Target = str;
57 
deref(&self) -> &str58     fn deref(&self) -> &str {
59         unsafe { str::from_utf8_unchecked(&self.0) }
60     }
61 }
62 
63 impl Clear for Chars {
clear(&mut self)64     fn clear(&mut self) {
65         self.0.clear();
66     }
67 }
68 
69 impl fmt::Display for Chars {
70     #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result71     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72         fmt::Display::fmt(&**self, f)
73     }
74 }
75 
76 impl fmt::Debug for Chars {
77     #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result78     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79         fmt::Debug::fmt(&**self, f)
80     }
81 }
82 
83 #[cfg(test)]
84 mod test {
85     use super::Chars;
86 
87     #[test]
test_display_and_debug()88     fn test_display_and_debug() {
89         let s = "test";
90         let string: String = s.into();
91         let chars: Chars = s.into();
92 
93         assert_eq!(format!("{}", string), format!("{}", chars));
94         assert_eq!(format!("{:?}", string), format!("{:?}", chars));
95     }
96 }
97