Skip to main content

stringify_sized_as

Function stringify_sized_as 

Source
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
Hide additional 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}