Skip to content

Commit 88d570e

Browse files
authored
Merge pull request #172 from Joxit/feat/custom-generator
Custom Generator impl by publishing codegen mod
2 parents bbca97e + 3d8d27c commit 88d570e

File tree

3 files changed

+96
-2
lines changed

3 files changed

+96
-2
lines changed

src/codegen.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static ESCAPED: [u8; 256] = [
3838
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
3939
];
4040

41+
/// Default trait for serializing JSONValue into string.
4142
pub trait Generator {
4243
type T: Write;
4344

@@ -181,6 +182,7 @@ pub trait Generator {
181182
}
182183
}
183184

185+
/// In-Memory Generator, this uses a Vec to store the JSON result.
184186
pub struct DumpGenerator {
185187
code: Vec<u8>,
186188
}
@@ -225,6 +227,7 @@ impl Generator for DumpGenerator {
225227
}
226228
}
227229

230+
/// Pretty In-Memory Generator, this uses a Vec to store the JSON result and add indent.
228231
pub struct PrettyGenerator {
229232
code: Vec<u8>,
230233
dent: u16,
@@ -288,6 +291,7 @@ impl Generator for PrettyGenerator {
288291
}
289292
}
290293

294+
/// Writer Generator, this uses a custom writer to store the JSON result.
291295
pub struct WriterGenerator<'a, W: 'a + Write> {
292296
writer: &'a mut W
293297
}
@@ -314,7 +318,7 @@ impl<'a, W> Generator for WriterGenerator<'a, W> where W: Write {
314318
}
315319
}
316320

317-
321+
/// Pretty Writer Generator, this uses a custom writer to store the JSON result and add indent.
318322
pub struct PrettyWriterGenerator<'a, W: 'a + Write> {
319323
writer: &'a mut W,
320324
dent: u16,

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@
198198
199199
use std::result;
200200

201-
mod codegen;
201+
pub mod codegen;
202202
mod parser;
203203
mod value;
204204
mod error;

tests/customgen.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#[macro_use]
2+
extern crate json;
3+
4+
use json::codegen::Generator;
5+
use json::object::{self, Object};
6+
use json::{JsonValue, Null};
7+
use std::io;
8+
9+
/// Custom generator that sort keys by name; based on DumpGenerator.
10+
pub struct CustomGenerator {
11+
code: Vec<u8>,
12+
}
13+
14+
impl CustomGenerator {
15+
pub fn new() -> Self {
16+
CustomGenerator {
17+
code: Vec::with_capacity(1024),
18+
}
19+
}
20+
21+
pub fn consume(self) -> String {
22+
// Original strings were unicode, numbers are all ASCII,
23+
// therefore this is safe.
24+
unsafe { String::from_utf8_unchecked(self.code) }
25+
}
26+
}
27+
28+
impl Generator for CustomGenerator {
29+
type T = Vec<u8>;
30+
#[inline(always)]
31+
fn get_writer(&mut self) -> &mut Vec<u8> {
32+
&mut self.code
33+
}
34+
35+
#[inline(always)]
36+
fn write_min(&mut self, _: &[u8], min: u8) -> io::Result<()> {
37+
self.code.push(min);
38+
Ok(())
39+
}
40+
#[inline(always)]
41+
fn write_object(&mut self, object: &Object) -> io::Result<()> {
42+
self.write_char(b'{')?;
43+
let mut entries: Vec<(&str, &JsonValue)> = Vec::new();
44+
for (k, v) in object.iter() {
45+
entries.push((k, v));
46+
}
47+
48+
entries.sort_by(|(k1, _), (k2, _)| k1.partial_cmp(k2).unwrap());
49+
50+
let mut iter = entries.iter();
51+
if let Some((key, value)) = iter.next() {
52+
self.indent();
53+
self.new_line()?;
54+
self.write_string(key)?;
55+
self.write_min(b": ", b':')?;
56+
self.write_json(value)?;
57+
} else {
58+
self.write_char(b'}')?;
59+
return Ok(());
60+
}
61+
62+
for (key, value) in iter {
63+
self.write_char(b',')?;
64+
self.new_line()?;
65+
self.write_string(key)?;
66+
self.write_min(b": ", b':')?;
67+
self.write_json(value)?;
68+
}
69+
70+
self.dedent();
71+
self.new_line()?;
72+
self.write_char(b'}')
73+
}
74+
}
75+
76+
#[test]
77+
fn object_keys_sorted() {
78+
let o = object! {
79+
"c" => Null,
80+
"b" => Null,
81+
"a" => Null,
82+
};
83+
let mut gen = CustomGenerator::new();
84+
gen.write_json(&o).expect("Can't fail");
85+
let json = gen.consume();
86+
let dump = o.dump();
87+
assert_eq!(json, r#"{"a":null,"b":null,"c":null}"#);
88+
assert_eq!(dump, r#"{"c":null,"b":null,"a":null}"#);
89+
assert_ne!(json, dump);
90+
}

0 commit comments

Comments
 (0)