pub fn stringify_sized_as<'buf>(
buf: &'buf mut [u8],
f: impl FnOnce(&mut Serializer<&mut SliceWriter<'_>>) -> Result<(), SerializeError<WriteError>>,
) -> Result<&'buf str, SerializeError<WriteError>>Expand description
Serialize via closure into a stack-allocated [u8; N].
Returns (buffer, bytes_written).
§Example
let mut buf = [0u8; 32];
let json = nanojson::stringify_sized_as(&mut buf, |s| {
s.object_begin()?;
s.member("n")?; s.integer(7)?;
s.object_end()
}).unwrap();
assert_eq!(json, "{\"n\":7}");Examples found in repository?
examples/sensor_log.rs (lines 196-222)
132fn main() {
133 // ==================================================================
134 // std tier — stringify / parse_as
135 // No buffer sizes to choose; heap grows as needed.
136 // ==================================================================
137
138 let json = nanojson::stringify_as(|json| {
139 json.array_begin()?;
140
141 json.object_begin()?;
142 json.member("type").unwrap(); json.string("reading")?;
143 json.member("sensor").unwrap(); json.string("temp")?;
144 json.member("value").unwrap(); json.integer(2350)?;
145 json.object_end()?;
146
147 json.object_begin()?;
148 json.member("type")?; json.string("reading")?;
149 json.member("sensor")?; json.string("humidity")?;
150 json.member("value")?; json.integer(6200)?;
151 json.object_end()?;
152
153 json.object_begin()?;
154 json.member("type")?; json.string("heartbeat")?;
155 json.object_end()?;
156
157 json.object_begin()?;
158 json.member("type")?; json.string("alert")?;
159 json.member("sensor")?; json.string("temp")?;
160 json.member("code")?; json.integer(1)?;
161 json.object_end()?;
162
163 json.array_end()
164 })
165 .unwrap();
166
167 std::println!("=== std tier ===");
168 std::println!("Log JSON:\n{}\n", json);
169
170 let mut records: [Option<Record>; 8] = [const { None }; 8];
171 let mut count = 0usize;
172
173 nanojson::parse_as(json.as_bytes(), |json| {
174 json.array_begin()?;
175 while json.array_item()? {
176 json.object_begin()?;
177 records[count] = Some(parse_record(json));
178 count += 1;
179 }
180 json.array_end()?;
181 Ok(())
182 })
183 .unwrap();
184
185 print_records(&records, count);
186
187 // ==================================================================
188 // no_std tier — serialize::<N> + Parser::new
189 // All memory on the stack; sizes chosen at compile time.
190 // ==================================================================
191
192 std::println!("\n=== no_std tier ===");
193
194 // Build the log into a 512-byte stack buffer.
195 let mut buf = [0; 512];
196 let log = nanojson::stringify_sized_as(&mut buf, |json| {
197 json.array_begin()?;
198
199 json.object_begin()?;
200 json.member("type")?; json.string("reading")?;
201 json.member("sensor")?; json.string("temp")?;
202 json.member("value")?; json.integer(2350)?;
203 json.object_end()?;
204
205 json.object_begin()?;
206 json.member("type")?; json.string("reading")?;
207 json.member("sensor")?; json.string("humidity")?;
208 json.member("value")?; json.integer(6200)?;
209 json.object_end()?;
210
211 json.object_begin()?;
212 json.member("type")?; json.string("heartbeat")?;
213 json.object_end()?;
214
215 json.object_begin()?;
216 json.member("type")?; json.string("alert")?;
217 json.member("sensor")?; json.string("temp")?;
218 json.member("code")?; json.integer(1)?;
219 json.object_end()?;
220
221 json.array_end()
222 })
223 .unwrap();
224
225 std::println!("Log JSON ({} bytes):\n{}\n", log.len(), log);
226
227 // Parse the log. str_buf = 32 bytes is enough for any single field value.
228 let mut records: [Option<Record>; 8] = [const { None }; 8];
229 let mut count = 0usize;
230
231 let mut str_buf = [0u8; 32];
232 let mut json = Parser::new(log.as_bytes(), &mut str_buf);
233
234 json.array_begin().unwrap();
235 while json.array_item().unwrap() {
236 json.object_begin().unwrap();
237 records[count] = Some(parse_record(&mut json));
238 count += 1;
239 }
240 json.array_end().unwrap();
241
242 print_records(&records, count);
243
244 // ==================================================================
245 // Size estimation — useful for choosing N on constrained targets
246 // ==================================================================
247
248 let n = nanojson::measure(|json| {
249 json.object_begin()?;
250 json.member("type")?; json.string("reading")?;
251 json.member("sensor")?; json.string("temp")?;
252 json.member("value")?; json.integer(2350)?;
253 json.object_end()
254 });
255 std::println!("\nA 'reading' record is {n} bytes when serialized.");
256}More examples
examples/manual.rs (lines 103-118)
19fn main() {
20 // ----------------------------------------------------------------
21 // 1. std tier — serialize into a String, no size choice needed
22 // ----------------------------------------------------------------
23
24 let json = nanojson::stringify_as(|s| {
25 s.object_begin()?;
26 s.member("name")?; s.string("Alice")?;
27 s.member("scores")?;
28 s.array_begin()?;
29 s.integer(95)?;
30 s.integer(87)?;
31 s.integer(100)?;
32 s.array_end()?;
33 s.member("meta")?;
34 s.object_begin()?;
35 s.member("active")?; s.boolean(true)?;
36 s.member("level")?; s.integer(3)?;
37 s.object_end()?;
38 s.object_end()
39 })
40 .unwrap();
41
42 std::println!("Serialized (std): {json}");
43
44 // ----------------------------------------------------------------
45 // 2. std tier — parse via closure, scratch buffer auto-allocated
46 // ----------------------------------------------------------------
47
48 let mut name_bytes = [0u8; 32];
49 let mut name_len = 0usize;
50 let mut scores = [0i64; 8];
51 let mut score_count = 0usize;
52 let mut active = false;
53 let mut level = 0i64;
54
55 nanojson::parse_as(json.as_bytes(), |p| {
56 p.object_begin()?;
57 while let Some(key) = p.member()? {
58 // key is &'src str — borrows the source, no copy needed.
59 match key {
60 "name" => {
61 let s = p.string()?;
62 name_len = s.len();
63 name_bytes[..name_len].copy_from_slice(s.as_bytes());
64 }
65 "scores" => {
66 p.array_begin()?;
67 while p.array_item()? {
68 scores[score_count] = p.integer()?;
69 score_count += 1;
70 }
71 p.array_end()?;
72 }
73 "meta" => {
74 p.object_begin()?;
75 while let Some(mk) = p.member()? {
76 match mk {
77 "active" => { active = p.boolean()?; }
78 "level" => { level = p.integer()?; }
79 other => panic!("unknown meta field: {other}"),
80 }
81 }
82 p.object_end()?;
83 }
84 other => panic!("unknown field: {other}"),
85 }
86 }
87 p.object_end()?;
88 Ok(())
89 })
90 .unwrap();
91
92 let name = core::str::from_utf8(&name_bytes[..name_len]).unwrap();
93 std::println!("name: {name}");
94 std::println!("scores: {:?}", &scores[..score_count]);
95 std::println!("active: {active}");
96 std::println!("level: {level}");
97
98 // ----------------------------------------------------------------
99 // 3. no_std tier — serialize into a fixed [u8; 512] stack buffer
100 // ----------------------------------------------------------------
101
102 let mut buf = [0; 512];
103 let json = nanojson::stringify_sized_as(&mut buf, |s| {
104 s.object_begin()?;
105 s.member("name")?; s.string("Alice")?;
106 s.member("scores")?;
107 s.array_begin()?;
108 s.integer(95)?;
109 s.integer(87)?;
110 s.integer(100)?;
111 s.array_end()?;
112 s.member("meta")?;
113 s.object_begin()?;
114 s.member("active")?; s.boolean(true)?;
115 s.member("level")?; s.integer(3)?;
116 s.object_end()?;
117 s.object_end()
118 })
119 .unwrap();
120
121 std::println!("\nSerialized (no_std, {} bytes): {}", json.len(), json);
122
123 // ----------------------------------------------------------------
124 // 4. no_std tier — parse with a 64-byte stack scratch buffer
125 //
126 // The scratch buffer only needs to fit the longest single string
127 // value after escape-decoding; 64 bytes is ample here.
128 // Object keys borrow from the source directly — no buffer needed.
129 // ----------------------------------------------------------------
130
131 let mut name_bytes = [0u8; 32];
132 let mut name_len = 0usize;
133 let mut scores = [0i64; 8];
134 let mut score_count = 0usize;
135 let mut active = false;
136 let mut level = 0i64;
137
138 let mut str_buf = [0u8; 64];
139 let mut p = Parser::new(json.as_bytes(), &mut str_buf);
140
141 p.object_begin().unwrap();
142 while let Some(key) = p.member().unwrap() {
143 match key {
144 "name" => {
145 let s = p.string().unwrap();
146 name_len = s.len();
147 name_bytes[..name_len].copy_from_slice(s.as_bytes());
148 }
149 "scores" => {
150 p.array_begin().unwrap();
151 while p.array_item().unwrap() {
152 scores[score_count] = p.integer().unwrap();
153 score_count += 1;
154 }
155 p.array_end().unwrap();
156 }
157 "meta" => {
158 p.object_begin().unwrap();
159 while let Some(mk) = p.member().unwrap() {
160 match mk {
161 "active" => { active = p.boolean().unwrap(); }
162 "level" => { level = p.integer().unwrap(); }
163 other => panic!("unknown meta field: {other}"),
164 }
165 }
166 p.object_end().unwrap();
167 }
168 other => panic!("unknown field: {other}"),
169 }
170 }
171 p.object_end().unwrap();
172
173 let name = core::str::from_utf8(&name_bytes[..name_len]).unwrap();
174 std::println!("\nParsed (no_std):");
175 std::println!("name: {name}");
176 std::println!("scores: {:?}", &scores[..score_count]);
177 std::println!("active: {active}");
178 std::println!("level: {level}");
179
180 // ----------------------------------------------------------------
181 // 5. Pretty-printing — uses Serializer directly (no convenience
182 // wrapper for this yet; SliceWriter is fine for a fixed output)
183 // ----------------------------------------------------------------
184
185 let mut pretty_buf = [0u8; 512];
186 let pretty_len;
187 {
188 let mut w = SliceWriter::new(&mut pretty_buf);
189 let mut ser: Serializer<_, 16> = Serializer::with_pretty(&mut w, 2);
190
191 ser.object_begin().unwrap();
192 ser.member("name").unwrap(); ser.string(name).unwrap();
193 ser.member("active").unwrap(); ser.boolean(active).unwrap();
194 ser.member("level").unwrap(); ser.integer(level).unwrap();
195 ser.object_end().unwrap();
196
197 pretty_len = w.pos();
198 }
199
200 std::println!("\nPretty-printed:\n{}", core::str::from_utf8(&pretty_buf[..pretty_len]).unwrap());
201
202 // ----------------------------------------------------------------
203 // 6. Size estimation — measure before committing to a buffer size
204 // ----------------------------------------------------------------
205
206 let n = nanojson::measure(|s| {
207 s.object_begin()?;
208 s.member("name")?; s.string("Alice")?;
209 s.member("level")?; s.integer(3)?;
210 s.object_end()
211 });
212 std::println!("\n`{{\"name\":\"Alice\",\"level\":3}}` is {n} bytes.");
213 // Use the measured size to pick N: serialize::<{n}>(...) or similar.
214}