1#![forbid(unsafe_code)]
2
3pub mod cli;
4pub mod decode;
5pub mod encode;
6pub mod error;
7pub mod options;
8pub mod shared;
9
10#[cfg(feature = "wasm")]
11pub mod wasm;
12
13pub use decode::{
14 decode, decode_from_lines, decode_stream, decode_stream_sync, try_decode,
15 try_decode_from_lines, try_decode_stream, try_decode_stream_sync,
16};
17pub use encode::{encode, encode_lines, encode_stream_events};
18pub use options::{
19 DecodeOptions, DecodeStreamOptions, EncodeOptions, EncodeReplacer, ResolvedDecodeOptions,
20 ResolvedEncodeOptions,
21};
22
23pub fn json_to_toon(json: &str) -> crate::error::Result<String> {
30 let value: serde_json::Value =
31 serde_json::from_str(json).map_err(|e| crate::error::ToonError::json_parse(&e))?;
32 Ok(encode(value, None))
33}
34
35pub fn toon_to_json(toon: &str) -> crate::error::Result<String> {
42 let value = try_decode(toon, None)?;
43 let value = serde_json::Value::from(value);
44 serde_json::to_string(&value).map_err(|e| crate::error::ToonError::json_stringify(&e))
45}
46
47pub type JsonPrimitive = StringOrNumberOrBoolOrNull;
48pub type JsonObject = Vec<(String, JsonValue)>;
49pub type JsonArray = Vec<JsonValue>;
50
51#[derive(Debug, Clone, PartialEq)]
52pub enum JsonValue {
53 Primitive(JsonPrimitive),
54 Array(JsonArray),
55 Object(JsonObject),
56}
57
58#[derive(Debug, Clone, PartialEq)]
59pub enum JsonStreamEvent {
60 StartObject,
61 EndObject,
62 StartArray { length: usize },
63 EndArray,
64 Key { key: String, was_quoted: bool },
65 Primitive { value: JsonPrimitive },
66}
67
68#[derive(Debug, Clone, PartialEq)]
69pub enum StringOrNumberOrBoolOrNull {
70 String(String),
71 Number(f64),
72 Bool(bool),
73 Null,
74}
75
76impl StringOrNumberOrBoolOrNull {
77 #[must_use]
78 pub fn from_f64(value: f64) -> Self {
79 if !value.is_finite() {
80 return Self::Null;
81 }
82 if value == 0.0 {
83 return Self::Number(0.0);
84 }
85 Self::Number(value)
86 }
87}
88
89impl From<StringOrNumberOrBoolOrNull> for JsonValue {
90 fn from(value: StringOrNumberOrBoolOrNull) -> Self {
91 Self::Primitive(value)
92 }
93}
94
95impl From<String> for JsonValue {
96 fn from(value: String) -> Self {
97 Self::Primitive(StringOrNumberOrBoolOrNull::String(value))
98 }
99}
100
101impl From<&str> for JsonValue {
102 fn from(value: &str) -> Self {
103 Self::Primitive(StringOrNumberOrBoolOrNull::String(value.to_string()))
104 }
105}
106
107impl From<bool> for JsonValue {
108 fn from(value: bool) -> Self {
109 Self::Primitive(StringOrNumberOrBoolOrNull::Bool(value))
110 }
111}
112
113impl From<f64> for JsonValue {
114 fn from(value: f64) -> Self {
115 Self::Primitive(StringOrNumberOrBoolOrNull::from_f64(value))
116 }
117}
118
119#[allow(clippy::cast_precision_loss)]
120impl From<i64> for JsonValue {
121 fn from(value: i64) -> Self {
122 Self::Primitive(StringOrNumberOrBoolOrNull::Number(value as f64))
123 }
124}
125
126#[allow(clippy::use_self)]
127impl From<Vec<JsonValue>> for JsonValue {
128 fn from(value: Vec<JsonValue>) -> Self {
129 Self::Array(value)
130 }
131}
132
133impl From<JsonObject> for JsonValue {
134 fn from(value: JsonObject) -> Self {
135 Self::Object(value)
136 }
137}
138
139impl From<serde_json::Value> for JsonValue {
140 fn from(value: serde_json::Value) -> Self {
141 match value {
142 serde_json::Value::Null => Self::Primitive(StringOrNumberOrBoolOrNull::Null),
143 serde_json::Value::Bool(value) => {
144 Self::Primitive(StringOrNumberOrBoolOrNull::Bool(value))
145 }
146 serde_json::Value::Number(value) => {
147 let number = value
148 .as_f64()
149 .unwrap_or_else(|| value.to_string().parse::<f64>().unwrap_or(f64::NAN));
150 Self::Primitive(StringOrNumberOrBoolOrNull::from_f64(number))
151 }
152 serde_json::Value::String(value) => {
153 Self::Primitive(StringOrNumberOrBoolOrNull::String(value))
154 }
155 serde_json::Value::Array(values) => {
156 Self::Array(values.into_iter().map(Self::from).collect())
157 }
158 serde_json::Value::Object(map) => {
159 let mut entries = Vec::with_capacity(map.len());
160 for (key, value) in map {
161 entries.push((key, Self::from(value)));
162 }
163 Self::Object(entries)
164 }
165 }
166 }
167}
168
169impl From<JsonValue> for serde_json::Value {
170 fn from(value: JsonValue) -> Self {
171 match value {
172 JsonValue::Primitive(p) => match p {
173 StringOrNumberOrBoolOrNull::String(value) => Self::String(value),
174 StringOrNumberOrBoolOrNull::Number(value) => {
175 serde_json::Number::from_f64(value).map_or(Self::Null, Self::Number)
176 }
177 StringOrNumberOrBoolOrNull::Bool(value) => Self::Bool(value),
178 StringOrNumberOrBoolOrNull::Null => Self::Null,
179 },
180 JsonValue::Array(arr) => Self::Array(arr.into_iter().map(Self::from).collect()),
181 JsonValue::Object(obj) => {
182 let mut map = serde_json::Map::new();
183 for (key, val) in obj {
184 map.insert(key, Self::from(val));
185 }
186 Self::Object(map)
187 }
188 }
189 }
190}