Skip to main content

json_example/
json_example.rs

1// Copyright (c) 2026 CyberNestSticks LLC
2// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
3// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
4// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
5// option. This file may not be copied, modified, or distributed
6// except according to those terms.
7
8// Author: Lawrence (Larry) Foard
9
10use arcstr::literal;
11#[cfg(feature = "serde_json")]
12use serde::{Deserialize, Serialize};
13use std::error::Error;
14
15#[cfg(feature = "serde_json")]
16use zcstring::serde_json_from_zcstring;
17use zcstring::ZCString;
18
19// parse JSON containing borrowed pointers to ParsedLog::owner
20// and/or owned de-escapified data
21#[derive(Debug)]
22#[cfg_attr(feature = "serde_json", derive(Deserialize, Serialize))]
23struct LogEntry {
24    level: ZCString,
25    message: ZCString,
26}
27
28fn show(label: &str, source: &str, s: &str) {
29    println!("  Field: {}", label);
30    println!("    Value: {:?}", s);
31
32    // memory position of s
33    let s_start = s.as_ptr() as usize;
34    println!("    Address: 0x{:x}", s_start);
35
36    // bounds of source
37    let source_start = source.as_ptr() as usize;
38    let source_end = source_start + source.len();
39
40    if s_start >= source_start && s_start < source_end {
41        println!("    Value falls within source");
42    } else {
43        println!("    Value doesn't fall within source");
44    }
45}
46
47fn main() -> Result<(), Box<dyn Error>> {
48    #[cfg(feature = "serde_json")]
49    {
50        // example JSON data feed
51        let input = [
52            literal!(r#"{"level": "error", "message": "Connection lost"}"#),
53            literal!(r#"{"level": "warning", "message": "Cat on keyboard"}"#),
54            literal!(r#"{"level": "info", "message": "Crow pecked camera"}"#),
55            literal!(r#"{"level": "error", "message": "Raven pecked camera, now offline"}"#),
56            // in this case the address of message should not fall within
57            // the memory address range of the raw json
58            literal!(r#"{"level": "error", "message": "Escaped \" "}"#),
59        ];
60
61        let items = input
62            .into_iter()
63            .map(|line| -> Result<LogEntry, Box<dyn Error>> {
64                // our special wrapper for JSON parsing
65                let entry = serde_json_from_zcstring::<LogEntry>(ZCString::from(line.clone()))?;
66
67                // show values and memory layout
68                println!("------");
69
70                println!("Log Line: {}", line);
71                println!(
72                    "  Log Line Location: 0x{:x} - 0x{:x}",
73                    line.as_ptr() as usize,
74                    line.as_ptr() as usize + line.len(),
75                );
76
77                show("level", &line, &entry.level);
78                show("message", &line, &entry.message);
79
80                // now serialize - Ok we could do a zero-alloc deserialize but
81                //                 not right now...
82                println!("  Serialized: {}", serde_json::to_string(&entry)?);
83                println!("");
84
85                Ok(entry)
86            })
87            .collect::<Result<Vec<LogEntry>, _>>()?;
88
89        println!("items size: {}\n", items.len());
90    }
91
92    Ok(())
93}