1use arrayvec::ArrayVec;
2use std::ascii;
3use std::fmt;
4use std::mem;
5use std::ops;
6use std::str;
7
8pub struct AlmostString([u8]);
9
10impl AlmostString {
11 pub fn new(bytes: &[u8]) -> &AlmostString {
12 unsafe { mem::transmute(bytes) }
13 }
14}
15
16pub struct AlmostStringSlice<'a>([&'a [u8]]);
17
18impl<'a> AlmostStringSlice<'a> {
19 pub fn new<'b>(bytes_slice: &'b [&'a [u8]]) -> &'b AlmostStringSlice<'a> {
20 unsafe { mem::transmute(bytes_slice) }
21 }
22}
23
24pub struct Bytes([u8]);
25
26impl Bytes {
27 pub fn new(bytes: &[u8]) -> &Bytes {
28 unsafe { mem::transmute(bytes) }
29 }
30}
31
32pub struct BytesSlice<'a>([&'a [u8]]);
33
34impl<'a> BytesSlice<'a> {
35 pub fn new<'b>(bytes_slice: &'b [&'a [u8]]) -> &'b BytesSlice<'a> {
36 unsafe { mem::transmute(bytes_slice) }
37 }
38}
39
40struct Byte {
41 string: ArrayVec<[u8; 4]>,
42}
43
44impl Byte {
45 fn new(byte: u8) -> Byte {
46 let mut string = ArrayVec::new();
47 if byte == b'\\' || byte == b'\"' {
48 string.push(b'\\');
49 string.push(byte);
50 } else {
51 string.extend(ascii::escape_default(byte));
52 }
53 Byte { string: string }
54 }
55}
56
57impl ops::Deref for Byte {
58 type Target = str;
59 fn deref(&self) -> &str {
60 unsafe { str::from_utf8_unchecked(&self.string) }
61 }
62}
63
64impl fmt::Debug for Bytes {
65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66 f.write_str("b\"")?;
67 for &byte in &self.0 {
68 f.write_str(&Byte::new(byte))?;
69 }
70 f.write_str("\"")?;
71 Ok(())
72 }
73}
74
75impl<'a> fmt::Debug for BytesSlice<'a> {
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 f.debug_list()
78 .entries(self.0.iter().cloned().map(Bytes::new))
79 .finish()
80 }
81}
82
83impl fmt::Debug for AlmostString {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 let string = String::from_utf8_lossy(&self.0);
87 fmt::Debug::fmt(&string, f)
88 }
89}
90
91impl fmt::Display for AlmostString {
92 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93 let string = String::from_utf8_lossy(&self.0);
95 if string.chars().any(|c| c < ' ' || c == '"') {
96 fmt::Debug::fmt(&string, f)
97 } else {
98 fmt::Display::fmt(&string, f)
99 }
100 }
101}
102
103impl<'a> fmt::Debug for AlmostStringSlice<'a> {
104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105 f.debug_list()
106 .entries(self.0.iter().cloned().map(AlmostString::new))
107 .finish()
108 }
109}