1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! Zero-copy event-stream parser.
//!
//! Tokenize a Ktav document into a linear sequence of [`ParseEvent`]s
//! delivered to a user callback — no intermediate tree, no per-compound
//! allocation. Object keys and single-line scalars are borrowed straight
//! from the input string; the events you receive carry `&'a str` slices
//! into the original buffer.
//!
//! Internally this is the same path that powers [`crate::from_str`]: the
//! flat-event stream is the hot deserialization route. Exposing it
//! publicly lets callers build their own consumers (custom DOMs,
//! streaming validators, partial extractors) without paying for serde.
//!
//! Dotted keys (`a.b.c: 10`) are resolved at tokenize time into
//! synthetic `Key` + `BeginObject` / … / `EndObject` triples, so a
//! callback never has to know they existed — it sees the same shape as
//! a fully-spelled nested object.
//!
//! ## Example
//!
//! See [`parse_events`] for a runnable example.
pub use ;
pub use parse_events as parse_events_raw;
use Bump;
use crateResult;
/// A single token emitted by [`parse_events`].
///
/// Each variant either is unit (compound brackets, `Null`, `Bool`) or
/// carries a `&'a str` slice borrowed from the input buffer. Compound
/// values are bracketed by `BeginObject` / `EndObject` (or
/// `BeginArray` / `EndArray`) pairs in the stream; an [`ParseEvent::Key`]
/// is always immediately followed by its value event (which may itself
/// open a nested compound).
///
/// The whole document is wrapped in an outer `BeginObject` / `EndObject`
/// pair, even if the source is empty — Ktav documents are an implicit
/// top-level object.
///
/// # Numeric scalars
///
/// `Integer` and `Float` carry the *textual* literal (with any leading
/// `+` already stripped). They appear when the source used the typed
/// markers `:i` / `:f`. Plain numeric-looking scalars without the marker
/// arrive as [`ParseEvent::Str`] — Ktav has no implicit numeric type
/// inference at the lexer level; the deserializer is responsible for
/// trying `&str → number` parses where the visitor wants a number.
/// Tokenize `input` and invoke `callback` with each [`ParseEvent`] in
/// document order.
///
/// Events borrow `&str` slices from `input` where possible (object
/// keys, plain scalars). Multi-line scalars and `+`-stripped typed
/// numbers are allocated in a temporary bump arena owned by this call;
/// their slices live as long as the call itself, which is sufficient
/// because the callback only sees them by reference through
/// `ParseEvent<'_>`.
///
/// The whole document is bracketed by an outer
/// `BeginObject` / `EndObject` pair (Ktav documents are an implicit
/// top-level object).
///
/// # Errors
///
/// Returns the same [`crate::Error::Structured`] kinds as
/// [`crate::parse`] / [`crate::from_str`] — invalid keys, duplicate
/// keys, dotted-key conflicts, unbalanced brackets, etc. The callback
/// is not invoked for events past the failure point.
///
/// # Examples
///
/// ```
/// use ktav::thin::{parse_events, ParseEvent};
/// use std::collections::HashMap;
///
/// let src = "port: 8080\nhost: example.com\n";
///
/// let mut depth = 0_usize;
/// let mut flat: HashMap<String, String> = HashMap::new();
/// let mut last_key: Option<String> = None;
///
/// parse_events(src, |ev| match ev {
/// ParseEvent::BeginObject => depth += 1,
/// ParseEvent::EndObject => depth -= 1,
/// ParseEvent::Key(k) if depth == 1 => last_key = Some(k.to_string()),
/// ParseEvent::Str(s) => {
/// if let Some(k) = last_key.take() {
/// flat.insert(k, s.to_string());
/// }
/// }
/// _ => {}
/// })
/// .unwrap();
///
/// assert_eq!(flat.get("port").map(String::as_str), Some("8080"));
/// assert_eq!(flat.get("host").map(String::as_str), Some("example.com"));
/// ```