1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
//! Laying out JSON text that is already JSON.
//!
//! Everywhere else in this crate the layout of a document is decided while the
//! document is being produced, by the [write policy](crate::Options) the
//! writer was given. That only helps when the bytes came out of a `Write`
//! impl. A log line, a response body, a file on disk: those arrive as text, and
//! laying them out means reading the text back.
//!
//! [`prettify`] does that in one pass, and does it through the same writer the
//! value path uses. The walk below opens and closes containers with `open` and
//! `close`, breaks a member's line with `line`, spaces its colon with `colon`,
//! and separates elements with `item`, which is the whole whitespace
//! vocabulary [`to_string_with`](crate::to_string_with) has. Prettified text is
//! therefore byte-identical to what writing the same data under the same policy
//! would have produced, and stays that way when a setting is added, because
//! there is no second copy of the rules to keep in step.
//!
//! Values themselves are copied, not re-encoded. A number keeps the spelling
//! the input gave it and a string keeps its escapes, so `1.50` stays `1.50` and
//! `A` stays `A`. The output is the input's data laid out again, not
//! a round trip through this crate's number and string formatters.
//!
//! Structure is checked as the walk goes, because it has to be known to be laid
//! out at all: which container a value is in decides whether it gets a line or
//! a space, and how deep it is decides the indent. A document whose shape does
//! not hold up is an [`Error`] naming the byte that stopped it, rather than
//! output that is quietly wrong.
//!
//! Tokens are not checked past what stepping over them requires. A number is
//! taken by its alphabet, so `01` and `1.2.3` lay out unchanged rather than
//! being refused. Holding them to the grammar instead cost every well-formed
//! number in every document, to move a rejection one step earlier than the
//! reader that will make it anyway. This is not a validator, and
//! [`from_str`](crate::from_str) is the thing to reach for when the question is
//! whether a document is good.
use crate;
use crateParser;
use crateWriter;
use crate;
/// Lay out a JSON document across indented lines.
///
/// Two spaces per level, one member or element per line: [`Pretty`], the same
/// policy [`to_string_with`](crate::to_string_with) takes.
///
/// ```
/// let out = structio::prettify(r#"{"a":[1,2],"b":{}}"#).unwrap();
/// assert_eq!(out, "{\n \"a\": [\n 1,\n 2\n ],\n \"b\": {}\n}");
/// ```
///
/// The input must be a complete JSON document whose structure holds up.
/// Anything else is an error against the byte that stopped the walk:
///
/// ```
/// use structio::ErrorCode;
///
/// let e = structio::prettify(r#"{"a":}"#).unwrap_err();
/// assert_eq!(e.code, ErrorCode::UnexpectedCharacter);
/// assert_eq!(e.index, 5);
/// ```
/// [`prettify`] under an explicit [write policy](crate::Options).
///
/// The policy decides the layout exactly as it does when a value is written:
/// [`INDENT`](Options::INDENT) sets the width and
/// [`NEW_LINES_IN_ARRAYS`](Options::NEW_LINES_IN_ARRAYS) decides whether an
/// array gets a line per element.
///
/// ```
/// use structio::{PrettyInlineArrays, json::prettify_with};
///
/// let out = prettify_with::<PrettyInlineArrays>(r#"{"v":[1,2,3]}"#).unwrap();
/// assert_eq!(out, "{\n \"v\": [1, 2, 3]\n}");
/// ```
///
/// [`PRETTY`](Options::PRETTY) is honoured too, rather than assumed, so a
/// compact policy compacts. That makes [`Standard`](crate::Standard) a
/// minifier, which is the same walk with nothing to emit between tokens:
///
/// ```
/// use structio::{Standard, json::prettify_with};
///
/// let out = prettify_with::<Standard>("{\n \"a\": [1, 2]\n}").unwrap();
/// assert_eq!(out, r#"{"a":[1,2]}"#);
/// ```
///
/// [`minify`](crate::minify()) reaches the same bytes on any document that is
/// really JSON, and much faster, because compacting needs none of the structure
/// this walks. Reach for that unless you want the walk's checking too.
///
/// The reading settings do not apply, there being no schema here to have an
/// opinion about: an unknown key is every key. The exception is
/// [`ALLOW_COMMENTS`](Options::ALLOW_COMMENTS), which decides whether a
/// document may carry comments at all. It drops them, as everything in this
/// crate does, a comment being no part of what a writer can emit.
/// [`prettify`] into an existing `String`, replacing its contents and keeping
/// its allocation.
///
/// Prefer this in a loop, the way [`write_into`](crate::write_into) is
/// preferred over [`to_string`](crate::to_string).
///
/// On failure `out` holds however much was laid out before the error, which is
/// the same bargain [`read_into`](crate::read_into) makes: recovering the
/// original would mean copying it first, on every call, to serve the failing
/// case.
/// [`prettify_into`] under an explicit [write policy](crate::Options).
/// One whole document: the value, then nothing but whitespace.
/// Lay out one value, whatever it is.
///
/// The cursor must be on the value's first byte, whitespace already behind it.
/// That is the parser's own convention and every route here keeps it: the walk
/// above skips the leading run once, an opening bracket skips what follows it,
/// and `colon` and `comma_or_close` skip what follows them. Skipping again per
/// value would be a third of the whitespace work in a document that has none.
/// `{ "key": value, ... }`, one member per line.
/// `[value, ...]`, one element per line or all on one, as the policy says.
/// Copy one scalar token through, exactly as the input spelled it.
///
/// A string or a number is the input's own bytes, and its length is not known
/// until the parser has walked it, so it is copied. The three literals are
/// known text and go through the writer's fixed-size appenders instead, which
/// store a compile-time-constant run rather than calling out to a copy of four
/// bytes whose length the compiler cannot see.
///
/// Either way the parser is what finds the token's end, and it checks only what
/// finding the end requires: a string's escapes and its closing quote, a
/// literal's spelling, and a number's alphabet. Object keys come through here
/// too, a key being a string like any other.
///
/// The cursor must already be on the token, as it must be for [`value`].