debug_builders/
lib.rs

1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use std::fmt::{self, Write};
12
13#[cfg(test)]
14mod test;
15
16const ALTERNATE_MASK: u32 = 1 << 2;
17
18struct PadAdapter<'a, 'b: 'a> {
19    fmt: &'a mut fmt::Formatter<'b>,
20    on_newline: bool,
21}
22
23impl<'a, 'b: 'a> PadAdapter<'a, 'b> {
24    fn new(fmt: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b> {
25        PadAdapter {
26            fmt: fmt,
27            on_newline: false,
28        }
29    }
30}
31
32impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
33    fn write_str(&mut self, mut s: &str) -> fmt::Result {
34        while !s.is_empty() {
35            if self.on_newline {
36                try!(self.fmt.write_str("    "));
37            }
38
39            let split = match s.find('\n') {
40                Some(pos) => {
41                    self.on_newline = true;
42                    pos + 1
43                }
44                None => {
45                    self.on_newline = false;
46                    s.len()
47                }
48            };
49            try!(self.fmt.write_str(&s[..split]));
50            s = &s[split..];
51        }
52
53        Ok(())
54    }
55}
56
57/// A struct to help with `fmt::Debug` implementations.
58///
59/// Constructed by the `Formatter::debug_struct` method.
60#[must_use]
61pub struct DebugStruct<'a, 'b: 'a> {
62    fmt: &'a mut fmt::Formatter<'b>,
63    result: fmt::Result,
64    has_fields: bool,
65}
66
67impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
68    /// Creates a new `DebugStruct`.
69    pub fn new(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugStruct<'a, 'b> {
70        let result = fmt.write_str(name);
71        DebugStruct {
72            fmt: fmt,
73            result: result,
74            has_fields: false,
75        }
76    }
77
78    /// Adds a new field to the generated struct output.
79    pub fn field(mut self, name: &str, value: &fmt::Debug) -> DebugStruct<'a, 'b> {
80        self.result = self.result.and_then(|_| {
81            let prefix = if self.has_fields {
82                ","
83            } else {
84                " {"
85            };
86
87            if self.is_pretty() {
88                let mut writer = PadAdapter::new(self.fmt);
89                fmt::write(&mut writer, format_args!("{}\n{}: {:#?}", prefix, name, value))
90            } else {
91                write!(self.fmt, "{} {}: {:?}", prefix, name, value)
92            }
93        });
94
95        self.has_fields = true;
96        self
97    }
98
99    /// Consumes the `DebugStruct`, finishing output and returning any error
100    /// encountered.
101    pub fn finish(mut self) -> fmt::Result {
102        if self.has_fields {
103            self.result = self.result.and_then(|_| {
104                if self.is_pretty() {
105                    self.fmt.write_str("\n}")
106                } else {
107                    self.fmt.write_str(" }")
108                }
109            });
110        }
111        self.result
112    }
113
114    fn is_pretty(&self) -> bool {
115        self.fmt.flags() & ALTERNATE_MASK != 0
116    }
117}
118
119/// A struct to help with `fmt::Debug` implementations.
120#[must_use]
121pub struct DebugTuple<'a, 'b: 'a> {
122    fmt: &'a mut fmt::Formatter<'b>,
123    result: fmt::Result,
124    has_fields: bool,
125}
126
127impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
128    /// Creates a new `DebugTuple`.
129    pub fn new(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> {
130        let result = fmt.write_str(name);
131        DebugTuple {
132            fmt: fmt,
133            result: result,
134            has_fields: false,
135        }
136    }
137
138    /// Adds a new field to the generated tuple struct output.
139    pub fn field(mut self, value: &fmt::Debug) -> DebugTuple<'a, 'b> {
140        self.result = self.result.and_then(|_| {
141            let (prefix, space) = if self.has_fields {
142                (",", " ")
143            } else {
144                ("(", "")
145            };
146
147            if self.is_pretty() {
148                let mut writer = PadAdapter::new(self.fmt);
149                fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, value))
150            } else {
151                write!(self.fmt, "{}{}{:?}", prefix, space, value)
152            }
153        });
154
155        self.has_fields = true;
156        self
157    }
158
159    /// Consumes the `DebugTuple`, finishing output and returning any error
160    /// encountered.
161    pub fn finish(mut self) -> fmt::Result {
162        if self.has_fields {
163            self.result = self.result.and_then(|_| {
164                if self.is_pretty() {
165                    self.fmt.write_str("\n)")
166                } else {
167                    self.fmt.write_str(")")
168                }
169            });
170        }
171        self.result
172    }
173
174    fn is_pretty(&self) -> bool {
175        self.fmt.flags() & ALTERNATE_MASK != 0
176    }
177}
178
179struct DebugInner<'a, 'b: 'a> {
180    fmt: &'a mut fmt::Formatter<'b>,
181    result: fmt::Result,
182    has_fields: bool,
183}
184
185impl<'a, 'b: 'a> DebugInner<'a, 'b> {
186    fn entry(&mut self, entry: &fmt::Debug) {
187        self.result = self.result.and_then(|_| {
188            if self.is_pretty() {
189                let mut writer = PadAdapter::new(self.fmt);
190                let prefix = if self.has_fields { "," } else { "" };
191                fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry))
192            } else {
193                let prefix = if self.has_fields { ", " } else { "" };
194                write!(self.fmt, "{}{:?}", prefix, entry)
195            }
196        });
197
198        self.has_fields = true;
199    }
200
201    pub fn finish(&mut self) {
202        let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" };
203        self.result = self.result.and_then(|_| self.fmt.write_str(prefix));
204    }
205
206    fn is_pretty(&self) -> bool {
207        self.fmt.flags() & ALTERNATE_MASK != 0
208    }
209}
210
211/// A struct to help with `fmt::Debug` implementations.
212#[must_use]
213pub struct DebugSet<'a, 'b: 'a> {
214    inner: DebugInner<'a, 'b>,
215}
216
217impl<'a, 'b: 'a> DebugSet<'a, 'b> {
218    /// Creates a new `DebugSet`.
219    pub fn new(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
220        let result = write!(fmt, "{{");
221        DebugSet {
222            inner: DebugInner {
223                fmt: fmt,
224                result: result,
225                has_fields: false,
226            }
227        }
228    }
229
230    /// Adds a new entry to the set output.
231    pub fn entry(mut self, entry: &fmt::Debug) -> DebugSet<'a, 'b> {
232        self.inner.entry(entry);
233        self
234    }
235
236    /// Consumes the `DebugSet`, finishing output and returning any error
237    /// encountered.
238    pub fn finish(mut self) -> fmt::Result {
239        self.inner.finish();
240        self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
241    }
242}
243
244/// A struct to help with `fmt::Debug` implementations.
245#[must_use]
246pub struct DebugList<'a, 'b: 'a> {
247    inner: DebugInner<'a, 'b>,
248}
249
250impl<'a, 'b: 'a> DebugList<'a, 'b> {
251    /// Creates a new `DebugList`.
252    pub fn new(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
253        let result = write!(fmt, "[");
254        DebugList {
255            inner: DebugInner {
256                fmt: fmt,
257                result: result,
258                has_fields: false,
259            }
260        }
261    }
262
263    /// Adds a new entry to the set output.
264    pub fn entry(mut self, entry: &fmt::Debug) -> DebugList<'a, 'b> {
265        self.inner.entry(entry);
266        self
267    }
268
269    /// Consumes the `DebugSet`, finishing output and returning any error
270    /// encountered.
271    pub fn finish(mut self) -> fmt::Result {
272        self.inner.finish();
273        self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
274    }
275}
276
277/// A struct to help with `fmt::Debug` implementations.
278#[must_use]
279pub struct DebugMap<'a, 'b: 'a> {
280    fmt: &'a mut fmt::Formatter<'b>,
281    result: fmt::Result,
282    has_fields: bool,
283}
284
285impl<'a, 'b: 'a> DebugMap<'a, 'b> {
286    /// Creates a new `DebugMap`.
287    pub fn new(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
288        let result = write!(fmt, "{{");
289        DebugMap {
290            fmt: fmt,
291            result: result,
292            has_fields: false,
293        }
294    }
295
296    /// Adds a new entry to the map output.
297    pub fn entry(mut self, key: &fmt::Debug, value: &fmt::Debug) -> DebugMap<'a, 'b> {
298        self.result = self.result.and_then(|_| {
299            if self.is_pretty() {
300                let mut writer = PadAdapter::new(self.fmt);
301                let prefix = if self.has_fields { "," } else { "" };
302                fmt::write(&mut writer, format_args!("{}\n{:#?}: {:#?}", prefix, key, value))
303            } else {
304                let prefix = if self.has_fields { ", " } else { "" };
305                write!(self.fmt, "{}{:?}: {:?}", prefix, key, value)
306            }
307        });
308
309        self.has_fields = true;
310        self
311    }
312
313    /// Consumes the `DebugMap`, finishing output and returning any error
314    /// encountered.
315    pub fn finish(self) -> fmt::Result {
316        let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" };
317        self.result.and_then(|_| write!(self.fmt, "{}}}", prefix))
318    }
319
320    fn is_pretty(&self) -> bool {
321        self.fmt.flags() & ALTERNATE_MASK != 0
322    }
323}