fmt_extra/
lib.rs

1use std::fmt;
2use std::ops::{Deref,DerefMut};
3use std::convert::From;
4use std::iter::IntoIterator;
5
6/// Given a str, display it as a posix-shell style single quoted string with no ambiguity.
7pub struct SingleQuotedStr<'a> {
8    s: &'a str
9}
10
11impl<'b> From<&'b str> for SingleQuotedStr<'b> {
12    fn from(i: &str) -> SingleQuotedStr {
13        SingleQuotedStr { s: i }
14    }
15}
16
17impl<'a> fmt::Display for SingleQuotedStr<'a> {
18    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19        let mut elems = self.s.split('\'');
20        let fst = elems.next().unwrap_or("");
21        try!(write!(f, "'{}", fst));
22        for elem in elems {
23            try!(write!(f, "'\\''{}", elem));
24        }
25        write!(f, "'")
26    }
27}
28
29impl<'a> Deref for SingleQuotedStr<'a> {
30    type Target = str;
31    #[inline]
32    fn deref(&self) -> &Self::Target {
33        self.s
34    }
35}
36
37/// Given a [u8] (bytes) display it as c-style source string with escapes
38#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
39pub struct CSrcStr<'a> {
40    d: &'a [u8]
41}
42
43impl<'b> From<&'b [u8]> for CSrcStr<'b> {
44    fn from(d: &[u8]) -> CSrcStr {
45        CSrcStr { d: d }
46    }
47}
48
49impl<'a> fmt::Display for CSrcStr<'a> {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        for i in self.d {
52            match *i as char {
53                'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'|'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z'|
54                'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z'|
55                '~'|'!'|'@'|'#'|'$'|'%'|'^'|'&'|'*'|'('|')'|'_'|'+'|
56                '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|
57                '`'|
58                '-'| '=' | '{' | '}' | '|' | '\\' |
59                '['| ']' | ':' | ';' | '\''|
60                '<'| '>' | ',' | '.' | '?' | '/' |
61                ' '
62                => {
63                    write!(f, "{}", *i as char)?;
64                },
65                '"' => {
66                    write!(f, "\\\"")?;  
67                },
68                '\n' => {
69                    write!(f, "\\n")?;
70                }
71                _ => {
72                    write!(f, "\\x{:02x}", *i)?;
73                }
74            }
75        }
76
77        Ok(())
78    }
79}
80
81impl<'a> Deref for CSrcStr<'a> {
82    type Target = [u8];
83    #[inline]
84    fn deref(&self) -> &Self::Target {
85        self.d
86    }
87}
88
89/// Display a given iterator over display-ables using by printing each display-able 1 display-able
90/// seperator.
91///
92/// NOTE: for now, the seperator is also emitted after the last display-able. This should be
93/// expected to change.
94pub struct Seperated<'a, D: fmt::Display, X: fmt::Display, I: IntoIterator<Item=X> + 'a> {
95    sep: D,
96    inner: &'a Fn() -> I,
97}
98
99impl<'a, D: fmt::Display, X: fmt::Display, I: IntoIterator<Item=X>> fmt::Display for Seperated<'a, D, X, I> {
100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101        for ref i in (self.inner)() {
102            try!(write!(f, "{}{}", i, self.sep));
103        }
104
105        Ok(())
106    }
107}
108
109impl<'a, D: fmt::Display, X: fmt::Display, I: IntoIterator<Item=X> + 'a> Seperated<'a, D, X, I> {
110    pub fn new(sep: D, inner: &'a Fn() -> I) -> Self {
111        Seperated { sep: sep, inner: inner }
112    }
113}
114
115/// A wrapper around anything that dereferences to a byte slice (`[u8]`) that displays it's
116/// contents as a hexidicimal string.
117#[derive(Clone, PartialEq, Eq)]
118pub struct Hs<T>(pub T);
119
120impl<T: AsRef<[u8]>> fmt::Display for Hs<T> {
121    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
122        let v = self.0.as_ref();
123        for e in v {
124            try!(write!(fmt, "{:02x}", e));
125        }
126        Ok(())
127    }
128}
129
130impl<T: AsRef<[u8]>> fmt::Debug for Hs<T> {
131    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
132        write!(fmt, "{}", self)
133    }
134}
135
136impl<T> Deref for Hs<T> {
137    type Target = T;
138    #[inline]
139    fn deref(&self) -> &Self::Target
140    {
141        &self.0
142    }
143}
144
145impl<T> DerefMut for Hs<T> {
146    #[inline]
147    fn deref_mut(&mut self) -> &mut Self::Target {
148        &mut self.0
149    }
150}
151
152/// A wrapper around anything that dereferences to a byte slice (`[u8]`) that displays it's
153/// contents as a string using rust-like (& c-like) escapes for non ascii characters
154///
155/// The entire thing is wrapped in double quotes (") and any interior double quotes are escaped as
156/// '\"'
157#[derive(Clone, PartialEq, Eq)]
158pub struct AsciiStr<T>(pub T);
159
160impl<T: AsRef<[u8]>> fmt::Display for AsciiStr<T> {
161    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
162        let v = self.0.as_ref();
163        try!(write!(fmt, "\""));
164        for e in v {
165            match *e {
166                b'"' => try!(write!(fmt, "\\\"")),
167                0x20...0x7E => try!(write!(fmt, "{}", *e as char)),
168                _ => try!(write!(fmt, "\\x{:02x}", e))
169            }
170        }
171        try!(write!(fmt, "\""));
172        Ok(())
173    }
174}
175
176impl<T: AsRef<[u8]>> fmt::Debug for AsciiStr<T> {
177    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
178        write!(fmt, "{}", self)
179    }
180}
181
182impl<T> Deref for AsciiStr<T> {
183    type Target = T;
184    #[inline]
185    fn deref(&self) -> &Self::Target
186    {
187        &self.0
188    }
189}
190
191impl<T> DerefMut for AsciiStr<T> {
192    #[inline]
193    fn deref_mut(&mut self) -> &mut Self::Target {
194        &mut self.0
195    }
196}
197
198#[test]
199fn test_asciistr() {
200    assert_eq!(format!("{}", AsciiStr(&b"hello\x88"[..])), "\"hello\\x88\"");
201    assert_eq!(format!("{}", AsciiStr(&b"hello\"\x88"[..])), "\"hello\\\"\\x88\"");
202}
203
204#[test]
205fn test_hs() {
206    assert_eq!(format!("{}", Hs(&b"hello"[..])), "68656c6c6f");
207    let b: &[u8;3] = b"ab\xEB";
208    assert_eq!(format!("{}", Hs(b)), "6162eb");
209}
210
211#[test]
212fn test_sqs() {
213    assert_eq!(format!("{}", SingleQuotedStr::from("'")), "''\\'''");
214    assert_eq!(format!("{}", SingleQuotedStr::from("a")), "'a'");
215}
216
217#[test]
218fn test_sep() {
219    let x = [1, 2, 3];
220    // FIXME: figure out how to use a literal
221    assert_eq!(format!("{}", Seperated::new(' ', &|| x.iter())), "1 2 3 ");
222}
223
224