1extern crate std;
22
23use nanojson::{Parser};
24
25#[derive(Debug)]
28enum Record {
29 Reading { sensor: SensorId, value: i64 },
30 Alert { sensor: SensorId, code: i64 },
31 Heartbeat,
32}
33
34#[derive(Debug, PartialEq, Copy, Clone)]
35enum SensorId {
36 Temp,
37 Humidity,
38 Unknown,
39}
40
41fn copy_str<const N: usize>(s: &str) -> ([u8; N], usize) {
46 let mut arr = [0u8; N];
47 let len = s.len().min(N);
48 arr[..len].copy_from_slice(&s.as_bytes()[..len]);
49 (arr, len)
50}
51
52fn bstr<const N: usize>(arr: &[u8; N], len: usize) -> &str {
53 core::str::from_utf8(&arr[..len]).unwrap_or("")
54}
55
56fn parse_sensor_id(s: &str) -> SensorId {
57 match s {
58 "temp" => SensorId::Temp,
59 "humidity" => SensorId::Humidity,
60 _ => SensorId::Unknown,
61 }
62}
63
64fn parse_record(json: &mut Parser) -> Record {
67 let mut type_arr = [0u8; 16]; let mut type_len = 0usize;
68 let mut sensor_arr= [0u8; 16]; let mut sensor_len= 0usize;
69 let mut value: Option<i64> = None;
70 let mut code: Option<i64> = None;
71
72 while let Some(key) = json.member().unwrap() {
73 match key {
74 "type" => {
75 let s = json.string().unwrap();
76 let (a, l) = copy_str::<16>(s);
77 type_arr = a; type_len = l;
78 }
79 "sensor" => {
80 let s = json.string().unwrap();
81 let (a, l) = copy_str::<16>(s);
82 sensor_arr = a; sensor_len = l;
83 }
84 "value" => {
85 value = json.integer().ok();
86 }
87 "code" => {
88 code = json.integer().ok();
89 }
90 _ => { json.null().ok(); }
91 }
92 }
93 json.object_end().unwrap();
94
95 let type_str = bstr(&type_arr, type_len);
96 let sensor_str = bstr(&sensor_arr, sensor_len);
97
98 match type_str {
99 "reading" => Record::Reading {
100 sensor: parse_sensor_id(sensor_str),
101 value: value.unwrap_or(0),
102 },
103 "alert" => Record::Alert {
104 sensor: parse_sensor_id(sensor_str),
105 code: code.unwrap_or(0),
106 },
107 "heartbeat" => Record::Heartbeat,
108 other => panic!("unknown record type: {other}"),
109 }
110}
111
112fn print_records(records: &[Option<Record>], count: usize) {
113 std::println!("Parsed {count} records:");
114 for i in 0..count {
115 if let Some(r) = &records[i] {
116 match r {
117 Record::Reading { sensor, value } => {
118 let (int, frac) = (value / 100, value.abs() % 100);
119 std::println!(" [{i}] Reading {sensor:?}: {int}.{frac:02}");
120 }
121 Record::Alert { sensor, code } => {
122 std::println!(" [{i}] Alert {sensor:?}: code {code}");
123 }
124 Record::Heartbeat => {
125 std::println!(" [{i}] Heartbeat");
126 }
127 }
128 }
129 }
130}
131
132fn main() {
133 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 std::println!("\n=== no_std tier ===");
193
194 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 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 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}
257
258#[cfg(test)] #[test] fn test_main() { main() }