1use crate::binary::Recv;
10use crate::error::TypeError;
11use crate::json::{self, Kind, Open, Sink, Stop};
12use crate::numeric::{numeric_in, numeric_out};
13
14const VERSION: u8 = 1;
16
17enum Node {
18 Scalar(String),
20 Array(Vec<usize>),
21 Object(Vec<(String, usize)>),
23}
24
25#[derive(Default)]
26struct Tree {
27 nodes: Vec<Node>,
28 open: Vec<(usize, Option<String>)>,
30 root: Option<usize>,
31}
32
33impl Tree {
34 fn attach(&mut self, node: usize) {
36 let Some((parent, key)) = self.open.last_mut() else {
37 self.root = Some(node);
38 return;
39 };
40 match &mut self.nodes[*parent] {
41 Node::Array(items) => items.push(node),
42 Node::Object(fields) => fields.push((key.take().unwrap_or_default(), node)),
43 Node::Scalar(_) => {}
44 }
45 }
46
47 fn print(&self, out: &mut String) {
49 let Some(root) = self.root else { return };
50 let mut stack = vec![(root, 0usize)];
52 while let Some((node, at)) = stack.pop() {
53 let child = match &self.nodes[node] {
54 Node::Scalar(text) => {
55 out.push_str(text);
56 continue;
57 }
58 Node::Array(items) => {
59 if at == 0 {
60 out.push('[');
61 }
62 let Some(&child) = items.get(at) else {
63 out.push(']');
64 continue;
65 };
66 if at > 0 {
67 out.push_str(", ");
68 }
69 child
70 }
71 Node::Object(fields) => {
72 if at == 0 {
73 out.push('{');
74 }
75 let Some((key, child)) = fields.get(at) else {
76 out.push('}');
77 continue;
78 };
79 if at > 0 {
80 out.push_str(", ");
81 }
82 escape(key, out);
83 out.push_str(": ");
84 *child
85 }
86 };
87 stack.push((node, at + 1));
88 stack.push((child, 0));
89 }
90 }
91}
92
93impl Sink for Tree {
94 fn open(&mut self, open: Open) -> Result<(), TypeError> {
95 let node = self.nodes.len();
96 self.nodes.push(match open {
97 Open::Array => Node::Array(Vec::new()),
98 Open::Object => Node::Object(Vec::new()),
99 });
100 self.open.push((node, None));
101 Ok(())
102 }
103
104 fn close(&mut self, _: Open) -> Result<(), TypeError> {
105 let Some((node, _)) = self.open.pop() else { return Ok(()) };
106 if let Node::Object(fields) = &mut self.nodes[node] {
107 unique(fields);
108 }
109 self.attach(node);
110 Ok(())
111 }
112
113 fn key(&mut self, key: &str) -> Result<(), TypeError> {
114 if let Some((_, slot)) = self.open.last_mut() {
115 *slot = Some(key.to_owned());
116 }
117 Ok(())
118 }
119
120 fn scalar(&mut self, kind: Kind, token: &str, text: &str) -> Result<(), TypeError> {
121 let mut out = String::new();
122 match kind {
123 Kind::String => escape(text, &mut out),
124 Kind::Number => {
125 let mut bytes = Vec::new();
126 numeric_out(&numeric_in(token, -1)?, &mut bytes);
127 out = String::from_utf8(bytes).unwrap_or_default();
128 }
129 _ => out.push_str(token),
130 }
131 let node = self.nodes.len();
132 self.nodes.push(Node::Scalar(out));
133 self.attach(node);
134 Ok(())
135 }
136}
137
138fn unique(fields: &mut Vec<(String, usize)>) {
140 let order = |a: &str, b: &str| a.len().cmp(&b.len()).then_with(|| a.cmp(b));
141 fields.sort_by(|a, b| order(&a.0, &b.0));
143 let mut kept: Vec<(String, usize)> = Vec::with_capacity(fields.len());
144 for field in fields.drain(..) {
145 match kept.last_mut() {
146 Some(last) if last.0 == field.0 => *last = field,
147 _ => kept.push(field),
148 }
149 }
150 *fields = kept;
151}
152
153pub fn escape(text: &str, out: &mut String) {
155 out.push('"');
156 for c in text.chars() {
157 match c {
158 '\u{8}' => out.push_str("\\b"),
159 '\u{c}' => out.push_str("\\f"),
160 '\n' => out.push_str("\\n"),
161 '\r' => out.push_str("\\r"),
162 '\t' => out.push_str("\\t"),
163 '"' => out.push_str("\\\""),
164 '\\' => out.push_str("\\\\"),
165 c if u32::from(c) < 0x20 => out.push_str(&format!("\\u{:04x}", u32::from(c))),
166 c => out.push(c),
167 }
168 }
169 out.push('"');
170}
171
172pub fn jsonb_in(s: &str) -> Result<String, TypeError> {
174 let mut tree = Tree::default();
175 match json::parse(s, true, &mut tree) {
176 Ok(()) => {}
177 Err(Stop::Syntax(fail)) => return Err(json::syntax(s, fail)),
178 Err(Stop::Action(error)) => return Err(error),
179 }
180 let mut out = String::with_capacity(s.len());
181 tree.print(&mut out);
182 Ok(out)
183}
184
185pub fn jsonb_recv(bytes: &[u8]) -> Result<String, TypeError> {
187 let mut recv = Recv::new(bytes);
188 match recv.bytes(1)?[0] {
189 VERSION => jsonb_in(recv.text()?),
190 version => Err(TypeError::new(
191 rupg_common::SqlState::INTERNAL_ERROR,
192 format!("unsupported jsonb version number {version}"),
193 )),
194 }
195}
196
197pub fn jsonb_send(text: &str, out: &mut Vec<u8>) {
199 out.push(VERSION);
200 out.extend_from_slice(text.as_bytes());
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206
207 fn out(s: &str) -> String {
208 jsonb_in(s).unwrap()
209 }
210
211 fn fails(s: &str) -> (String, String, String) {
212 let error = jsonb_in(s).unwrap_err();
213 (error.sqlstate.as_str().to_owned(), error.message, error.detail.unwrap_or_default())
214 }
215
216 #[test]
217 fn a_value_prints_in_the_form_of_postgres() {
218 assert_eq!(out(r#"{"b":1,"a":[1,2]}"#), r#"{"a": [1, 2], "b": 1}"#);
219 assert_eq!(out(r#"{"aa":1,"b":2,"a":3}"#), r#"{"a": 3, "b": 2, "aa": 1}"#);
220 assert_eq!(out(r#"{"a":1,"a":2,"b":{"c":1,"c":[]}}"#), r#"{"a": 2, "b": {"c": []}}"#);
221 assert_eq!(out(" [ ] "), "[]");
222 assert_eq!(out("{}"), "{}");
223 assert_eq!(out("[1.50, 1e2, -0, 1E-3, -0.0, 2.5e+1]"), "[1.50, 100, 0, 0.001, 0.0, 25]");
224 assert_eq!(out(" true "), "true");
225 assert_eq!(out("null"), "null");
226 assert_eq!(out(r#""aé\/\"\n\u0001😀""#), "\"a\u{e9}/\\\"\\n\\u0001\u{1f600}\"");
227 assert_eq!(out(r#"[{"é":1,"z":2}]"#), r#"[{"z": 2, "é": 1}]"#);
228 }
229
230 #[test]
231 fn the_errors_are_the_errors_of_postgres() {
232 let syntax = |detail: &str| {
233 ("22P02".to_owned(), "invalid input syntax for type json".to_owned(), detail.to_owned())
234 };
235 assert_eq!(fails("[1 2]"), syntax(r#"Expected "," or "]", but found "2"."#));
236 assert_eq!(
237 fails(r#"["\ud800"]"#),
238 syntax("Unicode low surrogate must follow a high surrogate.")
239 );
240 assert_eq!(
241 fails(r#""\ude00""#),
242 syntax("Unicode low surrogate must follow a high surrogate.")
243 );
244 assert_eq!(
245 fails(r#""\ud800\ud800""#),
246 syntax("Unicode high surrogate must not follow a high surrogate.")
247 );
248 assert_eq!(
249 fails(r#""\ud800x""#),
250 syntax("Unicode low surrogate must follow a high surrogate.")
251 );
252 assert_eq!(
253 fails(r#"["\u0000"]"#),
254 (
255 "22P05".to_owned(),
256 "unsupported Unicode escape sequence".to_owned(),
257 "\\u0000 cannot be converted to text.".to_owned()
258 )
259 );
260 assert_eq!(fails(r#"{"a": 1 "\u0000"}"#).0, "22P05");
262 assert!(json::json_in(r#"["\u0000", "\ud800"]"#).is_ok());
263 assert_eq!(fails("[1e999999\x1d]"), syntax("Token \"\x1d\" is invalid."));
265 assert_eq!(fails(r#"{"a":1e999999 x}"#), syntax(r#"Token "x" is invalid."#));
266 assert_eq!(fails(r#"1e999999 "b"#), syntax(r#"Token ""b" is invalid."#));
267 let overflow =
268 ("22003".to_owned(), "value overflows numeric format".to_owned(), String::new());
269 assert_eq!(fails("[1e999999,\x1d]"), overflow);
270 assert_eq!(fails(r#"{"a":1e999999 "b"}"#), overflow);
271 }
272
273 #[test]
274 fn deep_nesting_needs_no_recursion() {
275 let deep = format!("{}{}", "[".repeat(100_000), "]".repeat(100_000));
276 assert_eq!(out(&deep), deep);
277 }
278
279 #[test]
280 fn the_binary_format_is_a_version_byte_and_the_text() {
281 let mut bytes = Vec::new();
282 jsonb_send(r#"{"a": 1}"#, &mut bytes);
283 assert_eq!(bytes, b"\x01{\"a\": 1}");
284 assert_eq!(jsonb_recv(b"\x01{\"b\":1,\"a\":2}").unwrap(), r#"{"a": 2, "b": 1}"#);
285 assert_eq!(
286 jsonb_recv(b"\x02{}").unwrap_err().message,
287 "unsupported jsonb version number 2"
288 );
289 let empty = jsonb_recv(b"").unwrap_err();
290 assert_eq!(empty.sqlstate, rupg_common::SqlState::PROTOCOL_VIOLATION);
291 }
292
293 #[test]
295 fn the_binary_format_checks_the_encoding_first() {
296 let message = |bytes: &[u8]| {
297 let error = jsonb_recv(bytes).unwrap_err();
298 assert_eq!(error.sqlstate, rupg_common::SqlState::CHARACTER_NOT_IN_REPERTOIRE);
299 error.message
300 };
301 let mut big = vec![1];
302 big.extend_from_slice(&[b'9'; 59]);
303 big.extend_from_slice(b"\x15\0");
304 assert_eq!(message(&big), "invalid byte sequence for encoding \"UTF8\": 0x00");
305 assert_eq!(message(b"\x01[1,\0"), "invalid byte sequence for encoding \"UTF8\": 0x00");
306 assert_eq!(message(b"\x01\xfe"), "invalid byte sequence for encoding \"UTF8\": 0xfe");
307 }
308}