Skip to content

Commit e3656bd

Browse files
committed
Implement RFC 640
1 parent 12b846a commit e3656bd

File tree

4 files changed

+801
-1
lines changed

4 files changed

+801
-1
lines changed

src/libcore/fmt/builders.rs

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
use prelude::*;
2+
use fmt::{self, Write, FlagV1};
3+
4+
struct PadAdapter<'a, 'b: 'a> {
5+
fmt: &'a mut fmt::Formatter<'b>,
6+
on_newline: bool,
7+
}
8+
9+
impl<'a, 'b: 'a> PadAdapter<'a, 'b> {
10+
fn new(fmt: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b> {
11+
PadAdapter {
12+
fmt: fmt,
13+
on_newline: false,
14+
}
15+
}
16+
}
17+
18+
impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
19+
fn write_str(&mut self, mut s: &str) -> fmt::Result {
20+
while !s.is_empty() {
21+
if self.on_newline {
22+
try!(self.fmt.write_str(" "));
23+
}
24+
25+
let split = match s.find('\n') {
26+
Some(pos) => {
27+
self.on_newline = true;
28+
pos + 1
29+
}
30+
None => {
31+
self.on_newline = false;
32+
s.len()
33+
}
34+
};
35+
try!(self.fmt.write_str(&s[..split]));
36+
s = &s[split..];
37+
}
38+
39+
Ok(())
40+
}
41+
}
42+
43+
/// A struct to help with `fmt::Debug` implementations.
44+
///
45+
/// Constructed by the `Formatter::debug_struct` method.
46+
#[must_use]
47+
pub struct DebugStruct<'a, 'b: 'a> {
48+
fmt: &'a mut fmt::Formatter<'b>,
49+
result: fmt::Result,
50+
has_fields: bool,
51+
}
52+
53+
pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str)
54+
-> DebugStruct<'a, 'b> {
55+
let result = fmt.write_str(name);
56+
DebugStruct {
57+
fmt: fmt,
58+
result: result,
59+
has_fields: false,
60+
}
61+
}
62+
63+
impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
64+
/// Adds a new field to the generated struct output.
65+
#[unstable(feature = "core", reason = "method was just created")]
66+
pub fn field<S>(mut self, name: &str, value: &S) -> DebugStruct<'a, 'b>
67+
where S: fmt::Debug {
68+
self.result = self.result.and_then(|_| {
69+
let prefix = if self.has_fields {
70+
","
71+
} else {
72+
" {"
73+
};
74+
75+
if self.is_pretty() {
76+
let mut writer = PadAdapter::new(self.fmt);
77+
fmt::write(&mut writer, format_args!("{}\n{}: {:#?}", prefix, name, value))
78+
} else {
79+
write!(self.fmt, "{} {}: {:?}", prefix, name, value)
80+
}
81+
});
82+
83+
self.has_fields = true;
84+
self
85+
}
86+
87+
/// Consumes the `DebugStruct`, finishing output and returning any error
88+
/// encountered.
89+
#[unstable(feature = "core", reason = "method was just created")]
90+
pub fn finish(mut self) -> fmt::Result {
91+
if self.has_fields {
92+
self.result = self.result.and_then(|_| {
93+
if self.is_pretty() {
94+
self.fmt.write_str("\n}")
95+
} else {
96+
self.fmt.write_str(" }")
97+
}
98+
});
99+
}
100+
self.result
101+
}
102+
103+
fn is_pretty(&self) -> bool {
104+
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
105+
}
106+
}
107+
108+
/// A struct to help with `fmt::Debug` implementations.
109+
///
110+
/// Constructed by the `Formatter::debug_tuple` method.
111+
#[must_use]
112+
pub struct DebugTuple<'a, 'b: 'a> {
113+
fmt: &'a mut fmt::Formatter<'b>,
114+
result: fmt::Result,
115+
has_fields: bool,
116+
}
117+
118+
pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> {
119+
let result = fmt.write_str(name);
120+
DebugTuple {
121+
fmt: fmt,
122+
result: result,
123+
has_fields: false,
124+
}
125+
}
126+
127+
impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
128+
/// Adds a new field to the generated tuple struct output.
129+
#[unstable(feature = "core", reason = "method was just created")]
130+
pub fn field<S>(mut self, value: &S) -> DebugTuple<'a, 'b> where S: fmt::Debug {
131+
self.result = self.result.and_then(|_| {
132+
let (prefix, space) = if self.has_fields {
133+
(",", " ")
134+
} else {
135+
("(", "")
136+
};
137+
138+
if self.is_pretty() {
139+
let mut writer = PadAdapter::new(self.fmt);
140+
fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, value))
141+
} else {
142+
write!(self.fmt, "{}{}{:?}", prefix, space, value)
143+
}
144+
});
145+
146+
self.has_fields = true;
147+
self
148+
}
149+
150+
/// Consumes the `DebugTuple`, finishing output and returning any error
151+
/// encountered.
152+
#[unstable(feature = "core", reason = "method was just created")]
153+
pub fn finish(mut self) -> fmt::Result {
154+
if self.has_fields {
155+
self.result = self.result.and_then(|_| {
156+
if self.is_pretty() {
157+
self.fmt.write_str("\n)")
158+
} else {
159+
self.fmt.write_str(")")
160+
}
161+
});
162+
}
163+
self.result
164+
}
165+
166+
fn is_pretty(&self) -> bool {
167+
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
168+
}
169+
}
170+
171+
/// A struct to help with `fmt::Debug` implementations.
172+
///
173+
/// Constructed by the `Formatter::debug_set` method.
174+
#[must_use]
175+
pub struct DebugSet<'a, 'b: 'a> {
176+
fmt: &'a mut fmt::Formatter<'b>,
177+
result: fmt::Result,
178+
has_fields: bool,
179+
}
180+
181+
pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugSet<'a, 'b> {
182+
let result = write!(fmt, "{} {{", name);
183+
DebugSet {
184+
fmt: fmt,
185+
result: result,
186+
has_fields: false,
187+
}
188+
}
189+
190+
impl<'a, 'b: 'a> DebugSet<'a, 'b> {
191+
/// Adds a new entry to the set output.
192+
#[unstable(feature = "core", reason = "method was just created")]
193+
pub fn entry<S>(mut self, entry: &S) -> DebugSet<'a, 'b> where S: fmt::Debug {
194+
self.result = self.result.and_then(|_| {
195+
let prefix = if self.has_fields {
196+
","
197+
} else {
198+
""
199+
};
200+
201+
if self.is_pretty() {
202+
let mut writer = PadAdapter::new(self.fmt);
203+
fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry))
204+
} else {
205+
write!(self.fmt, "{} {:?}", prefix, entry)
206+
}
207+
});
208+
209+
self.has_fields = true;
210+
self
211+
}
212+
213+
/// Consumes the `DebugSet`, finishing output and returning any error
214+
/// encountered.
215+
#[unstable(feature = "core", reason = "method was just created")]
216+
pub fn finish(self) -> fmt::Result {
217+
self.result.and_then(|_| {
218+
let end = match (self.has_fields, self.is_pretty()) {
219+
(false, _) => "}",
220+
(true, false) => " }",
221+
(true, true) => "\n}",
222+
};
223+
self.fmt.write_str(end)
224+
})
225+
}
226+
227+
fn is_pretty(&self) -> bool {
228+
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
229+
}
230+
}
231+
232+
/// A struct to help with `fmt::Debug` implementations.
233+
///
234+
/// Constructed by the `Formatter::debug_map` method.
235+
#[must_use]
236+
pub struct DebugMap<'a, 'b: 'a> {
237+
fmt: &'a mut fmt::Formatter<'b>,
238+
result: fmt::Result,
239+
has_fields: bool,
240+
}
241+
242+
pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugMap<'a, 'b> {
243+
let result = write!(fmt, "{} {{", name);
244+
DebugMap {
245+
fmt: fmt,
246+
result: result,
247+
has_fields: false,
248+
}
249+
}
250+
251+
impl<'a, 'b: 'a> DebugMap<'a, 'b> {
252+
/// Adds a new entry to the map output.
253+
#[unstable(feature = "core", reason = "method was just created")]
254+
pub fn entry<K, V>(mut self, key: &K, value: &V) -> DebugMap<'a, 'b>
255+
where K: fmt::Debug, V: fmt::Debug {
256+
self.result = self.result.and_then(|_| {
257+
let prefix = if self.has_fields {
258+
","
259+
} else {
260+
""
261+
};
262+
263+
if self.is_pretty() {
264+
let mut writer = PadAdapter::new(self.fmt);
265+
fmt::write(&mut writer, format_args!("{}\n{:#?}: {:#?}", prefix, key, value))
266+
} else {
267+
write!(self.fmt, "{} {:?}: {:?}", prefix, key, value)
268+
}
269+
});
270+
271+
self.has_fields = true;
272+
self
273+
}
274+
275+
/// Consumes the `DebugMap`, finishing output and returning any error
276+
/// encountered.
277+
#[unstable(feature = "core", reason = "method was just created")]
278+
pub fn finish(self) -> fmt::Result {
279+
self.result.and_then(|_| {
280+
let end = match (self.has_fields, self.is_pretty()) {
281+
(false, _) => "}",
282+
(true, false) => " }",
283+
(true, true) => "\n}",
284+
};
285+
self.fmt.write_str(end)
286+
})
287+
}
288+
289+
fn is_pretty(&self) -> bool {
290+
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
291+
}
292+
}

0 commit comments

Comments
 (0)