Skip to main content

simple_example/
simple_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")]
12use serde::{Deserialize, Serialize};
13use std::error::Error;
14use std::mem::size_of;
15
16#[cfg(feature = "serde")]
17use zcstring::serde_json_from_zcstring;
18use zcstring::ZCString;
19
20// parse JSON containing borrowed pointers to ParsedLog::owner
21// and/or owned de-escapified data
22#[derive(Debug)]
23#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
24struct LogEntry {
25    level: ZCString,
26    message: ZCString,
27}
28
29fn show(label: &str, source: &str, s: &str) {
30    println!("  Field: {}", label);
31    println!("    Value: {:?}", s);
32
33    // memory position of s
34    let s_start = s.as_ptr() as usize;
35    println!("    Address: 0x{:x}", s_start);
36
37    // bounds of source
38    let source_start = source.as_ptr() as usize;
39    let source_end = source_start + source.len();
40
41    if s_start >= source_start && s_start < source_end {
42        println!("    Value falls within source");
43    } else {
44        println!("    Value doesn't fall within source");
45    }
46}
47
48fn main() -> Result<(), Box<dyn Error>> {
49    // ZCString creation
50    println!("From str: {:?}", ZCString::from("str"));
51    #[cfg(feature = "std")]
52    println!("From String: {:?}", ZCString::from(String::from("str")));
53    println!("New ZCString: {:?}", ZCString::new());
54
55    // how big is a ZCString member in a structure as compared &str?
56
57    // we expect the same size. Why? &str is a fat pointer and
58    // ZString is a Substr which is a thin pointer to an ArcStr plus
59    // a range consisting of two u32s
60    println!("size_of &str: {}", size_of::<&str>());
61    println!("size_of ZCString: {}", size_of::<ZCString>());
62
63    #[cfg(feature = "serde")]
64    {
65        // example JSON data feed
66        let input = [
67            literal!(r#"{"level": "error", "message": "Connection lost"}"#),
68            literal!(r#"{"level": "warning", "message": "Cat on keyboard"}"#),
69            literal!(r#"{"level": "info", "message": "Crow pecked camera"}"#),
70            literal!(r#"{"level": "error", "message": "Raven pecked camera, now offline"}"#),
71            // in this case the address of message should not fall within
72            // the memory address range of the raw json
73            literal!(r#"{"level": "error", "message": "Escaped \" "}"#),
74        ];
75
76        let items = input
77            .into_iter()
78            .map(|line| -> Result<LogEntry, Box<dyn Error>> {
79                // our special wrapper for JSON parsing
80                let entry = serde_json_from_zcstring::<LogEntry>(ZCString::from(line.clone()))?;
81
82                // show values and memory layout
83                println!("------");
84
85                println!("Log Line: {}", line);
86                println!(
87                    "  Log Line Location: 0x{:x} - 0x{:x}",
88                    line.as_ptr() as usize,
89                    line.as_ptr() as usize + line.len(),
90                );
91
92                show("level", &line, &entry.level);
93                show("message", &line, &entry.message);
94
95                // now serialize - Ok we could do a zero-alloc deserialize but
96                //                 not right now...
97                println!("  Serialized: {}", serde_json::to_string(&entry)?);
98                println!("");
99
100                Ok(entry)
101            })
102            .collect::<Result<Vec<LogEntry>, _>>()?;
103
104        println!("items size: {}\n", items.len());
105    }
106
107    Ok(())
108}