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
//! # Ktav — a plain configuration format
//!
//! JSON5-shaped, but with no quotes, no commas, and dotted keys for nesting.
//! A document is an implicit top-level object. Native `serde` integration:
//! any type implementing `Serialize` / `Deserialize` (including
//! `#[derive]`-generated ones) round-trips through Ktav out of the box.
//!
//! ## Syntax
//!
//! ```text
//! # comment — any line starting with '#'
//! key: value — scalar; `key` may be a dotted path (a.b.c: 10)
//! key:: value — scalar; value is ALWAYS a literal string
//! key: { ... } — multi-line object; `}` closes on its own line
//! key: [ ... ] — multi-line array; `]` closes on its own line
//! key: {} / key: [] — empty compound, inline
//! :: value — (inside an array) literal-string item
//! ```
//!
//! ## Structured errors
//!
//! The parser returns [`Error::Structured`] for every parse failure since
//! `0.1.5`. Each [`ErrorKind`] variant carries a 1-based `line` and a
//! byte-offset [`Span`] you can slice the original input with.
//!
//! ```
//! use ktav::{parse, Error, ErrorKind};
//!
//! // The first line anchors the document as an Object; the malformed
//! // `port:8080` on line 2 then errors with a `MissingSeparatorSpace`
//! // (a first-line `port:8080` would now be a top-level Array
//! // bare-scalar item — spec § 5.0.1).
//! let src = "anchor: ok\nport:8080\n";
//! match parse(src) {
//! Ok(_) => unreachable!(),
//! Err(Error::Structured(ErrorKind::MissingSeparatorSpace { line, span, .. })) => {
//! assert_eq!(line, 2);
//! // The span covers the offending body chunk glued to the marker.
//! assert_eq!(span.slice(src), Some("8080"));
//! }
//! Err(other) => panic!("unexpected error: {other:?}"),
//! }
//! ```
//!
//! ## Example
//!
//! See [`tests/doc_example.rs`](../tests/doc_example.rs) for the executed
//! version of this snippet — it exercises the full parse → struct → render
//! → parse round-trip:
//!
//! ```rust,ignore
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Upstream {
//! host: String,
//! port: u16,
//! }
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct Config {
//! port: u16,
//! upstreams: Vec<Upstream>,
//! }
//!
//! let text = "\
//! port: 8080
//!
//! upstreams: [
//! {
//! host: a.example
//! port: 1080
//! }
//! {
//! host: b.example
//! port: 1080
//! }
//! ]
//! ";
//! let cfg: Config = ktav::from_str(text).unwrap();
//! assert_eq!(cfg.port, 8080);
//! assert_eq!(cfg.upstreams.len(), 2);
//!
//! let back = ktav::to_string(&cfg).unwrap();
//! let round: Config = ktav::from_str(&back).unwrap();
//! assert_eq!(cfg, round);
//! ```
pub use ;
pub use ;
pub use ;
use fs;
use Path;
use DeserializeOwned;
use Serialize;
/// Parse a Ktav document from a string into a raw [`Value`]. Useful when
/// you want to inspect or manipulate the document generically. For
/// deserializing into a user type, prefer [`from_str`].
/// Parse a Ktav document from a string and deserialize it into `T`. Uses
/// the zero-copy event path: the parser tokenizes the document into a
/// flat `Vec<Event>` (object keys and single-line scalars are borrowed
/// directly from `s`), and serde walks that vec linearly without ever
/// materialising a tree. Compound nesting is bracketed by
/// `BeginObject`/`EndObject` events instead of nested allocations.
/// Parse a Ktav document from a file path and deserialize it into `T`.
/// Serialize `value` as a Ktav document string. Uses the direct text
/// serializer — no `Value` intermediate.
Sized + Serialize>
/// Serialize `value` as a Ktav document and write it to `path`.
Sized + Serialize, P: >
/// Render a [`Value`] with **every scalar coerced to a String** —
/// typed integers (`:i`), typed floats (`:f`), booleans, and null
/// are flattened to their textual form and emitted via the raw-
/// marker `::`. Compounds (Object / Array) preserve their structure;
/// only leaf scalars are coerced. The output round-trips back
/// through the parser as the same set of String scalars.
///
/// Useful for "everything is a string" dumps — e.g. for downstream
/// consumers that don't understand typed markers, or for diff-
/// friendly canonical text.