Skip to main content

toon/encode/
mod.rs

1pub mod encoders;
2pub mod folding;
3pub mod normalize;
4pub mod primitives;
5pub mod replacer;
6
7#[cfg(feature = "async-stream")]
8pub mod async_encode;
9
10#[cfg(feature = "async-stream")]
11pub use async_encode::{
12    AsyncEncodeEventStream, AsyncEncodeStream, encode_async, encode_events_async,
13    encode_lines_async,
14};
15
16use crate::encode::normalize::normalize_json_value;
17use crate::encode::replacer::apply_replacer;
18use crate::options::{EncodeOptions, resolve_encode_options};
19use crate::shared::validation::is_valid_unquoted_key;
20use crate::{JsonStreamEvent, JsonValue};
21
22pub fn encode(input: impl Into<JsonValue>, options: Option<EncodeOptions>) -> String {
23    let lines = encode_lines(input, options);
24    lines.join("\n")
25}
26
27pub fn encode_lines(input: impl Into<JsonValue>, options: Option<EncodeOptions>) -> Vec<String> {
28    let resolved = resolve_encode_options(options);
29    let normalized = normalize_json_value(input.into());
30    let replaced = if let Some(replacer) = &resolved.replacer {
31        apply_replacer(&normalized, replacer)
32    } else {
33        normalized
34    };
35    encoders::encode_json_value(&replaced, &resolved)
36}
37
38/// Encode a JSON value into a stream of events.
39///
40/// This produces the same event sequence that `decode_stream_sync` would emit
41/// when decoding the TOON representation of this JSON value.
42#[must_use]
43pub fn encode_stream_events(
44    input: impl Into<JsonValue>,
45    options: Option<EncodeOptions>,
46) -> Vec<JsonStreamEvent> {
47    let resolved = resolve_encode_options(options);
48    let normalized = normalize_json_value(input.into());
49    let replaced = if let Some(replacer) = &resolved.replacer {
50        apply_replacer(&normalized, replacer)
51    } else {
52        normalized
53    };
54
55    let mut events = Vec::new();
56    emit_events(&replaced, &mut events);
57    events
58}
59
60fn emit_events(value: &JsonValue, events: &mut Vec<JsonStreamEvent>) {
61    match value {
62        JsonValue::Primitive(p) => {
63            events.push(JsonStreamEvent::Primitive { value: p.clone() });
64        }
65        JsonValue::Array(arr) => {
66            events.push(JsonStreamEvent::StartArray { length: arr.len() });
67            for item in arr {
68                emit_events(item, events);
69            }
70            events.push(JsonStreamEvent::EndArray);
71        }
72        JsonValue::Object(obj) => {
73            events.push(JsonStreamEvent::StartObject);
74            for (key, val) in obj {
75                events.push(JsonStreamEvent::Key {
76                    key: key.clone(),
77                    was_quoted: !is_valid_unquoted_key(key),
78                });
79                emit_events(val, events);
80            }
81            events.push(JsonStreamEvent::EndObject);
82        }
83    }
84}