Skip to main content

nextjson/formats/
ron.rs

1//! RON codec (Rusty Object Notation).
2//!
3//! Supports maps `{key: value, ...}`, sequences `[a, b]`, tuples `(a, b)`,
4//! quoted and bare strings, `Some(x)` / `None` / `()` optionals, booleans,
5//! and numbers. Structs with named fields are decoded as maps.
6
7use alloc::borrow::Cow;
8use alloc::string::{String, ToString};
9use alloc::vec::Vec;
10
11use crate::de::{token_name, FormatDecoder, Mark, NsonDeserialize, Token};
12use crate::error::{Error, Result};
13use crate::formats::Format;
14use crate::number::Number;
15use crate::ser::{FormatEncoder, NsonSerialize};
16use crate::write::Write;
17
18/// RON format marker.
19#[derive(Clone, Copy, Debug)]
20pub struct Ron;
21
22impl Format for Ron {
23    const NAME: &'static str = "ron";
24    const MIME: &'static str = "text/ron";
25    const EXTENSIONS: &'static [&'static str] = &["ron"];
26    const BINARY: bool = false;
27
28    fn encode<T: NsonSerialize + ?Sized>(self, value: &T) -> Result<Vec<u8>> {
29        let mut encoder = RonEncoder::new(Vec::new());
30        let mut checked = crate::ser::CheckedEncoder::new(&mut encoder);
31        T::nextencode(value, &mut checked)?;
32        checked.finish()?;
33        encoder.writer.write_all(&encoder.buf)?;
34        Ok(core::mem::take(&mut encoder.buf))
35    }
36
37    fn decode<'de, T: NsonDeserialize<'de>>(self, input: &'de [u8]) -> Result<T> {
38        let mut decoder = RonDecoder::new(input);
39        let value = T::nextdecode(&mut decoder)?;
40        decoder.expect_end()?;
41        Ok(value)
42    }
43}
44
45// ---------------------------------------------------------------------------
46// Encoder
47// ---------------------------------------------------------------------------
48
49/// Streaming RON encoder.
50pub struct RonEncoder<W: Write> {
51    writer: W,
52    buf: Vec<u8>,
53    /// Container frames: whether each open container is an array and whether
54    /// its first entry has been written yet.
55    frames: Vec<(bool, bool)>,
56}
57
58impl<W: Write> RonEncoder<W> {
59    /// Create a RON encoder over `writer`.
60    pub fn new(writer: W) -> Self {
61        RonEncoder {
62            writer,
63            buf: Vec::with_capacity(512),
64            frames: Vec::new(),
65        }
66    }
67
68    /// Separator before an array element.
69    fn value_sep(&mut self) -> Result<()> {
70        if let Some((is_array, first)) = self.frames.last_mut() {
71            if *is_array {
72                if *first {
73                    *first = false;
74                } else {
75                    self.buf.push(b',');
76                    self.buf.push(b' ');
77                }
78            }
79        }
80        Ok(())
81    }
82
83    /// Separator before an object key.
84    fn key_sep(&mut self) -> Result<()> {
85        if let Some((is_array, first)) = self.frames.last_mut() {
86            if !*is_array {
87                if *first {
88                    *first = false;
89                } else {
90                    self.buf.push(b',');
91                    self.buf.push(b' ');
92                }
93            }
94        }
95        Ok(())
96    }
97
98    fn write_quoted(&mut self, s: &str) {
99        self.buf.push(b'"');
100        for &b in s.as_bytes() {
101            match b {
102                b'"' => self.buf.extend_from_slice(b"\\\""),
103                b'\\' => self.buf.extend_from_slice(b"\\\\"),
104                b'\n' => self.buf.extend_from_slice(b"\\n"),
105                b'\t' => self.buf.extend_from_slice(b"\\t"),
106                b'\r' => self.buf.extend_from_slice(b"\\r"),
107                0x08 => self.buf.extend_from_slice(b"\\b"),
108                0x0C => self.buf.extend_from_slice(b"\\f"),
109                other => self.buf.push(other),
110            }
111        }
112        self.buf.push(b'"');
113    }
114
115    /// Flush and return the underlying writer.
116    pub fn finish(mut self) -> Result<W> {
117        self.writer.write_all(&self.buf)?;
118        self.buf.clear();
119        self.writer.flush()?;
120        Ok(self.writer)
121    }
122}
123
124impl<W: Write> FormatEncoder for RonEncoder<W> {
125    type Error = crate::error::Error;
126
127    fn begin_array(&mut self) -> Result<(), Self::Error> {
128        self.value_sep()?;
129        self.frames.push((true, true));
130        self.buf.push(b'[');
131        Ok(())
132    }
133
134    fn separator(&mut self) -> Result<(), Self::Error> {
135        Ok(())
136    }
137
138    fn end_array(&mut self) -> Result<(), Self::Error> {
139        self.frames.pop();
140        self.buf.push(b']');
141        Ok(())
142    }
143
144    fn begin_object(&mut self) -> Result<(), Self::Error> {
145        self.value_sep()?;
146        self.frames.push((false, true));
147        self.buf.push(b'{');
148        Ok(())
149    }
150
151    fn key(&mut self, key: &str) -> Result<(), Self::Error> {
152        self.key_sep()?;
153        self.write_quoted(key);
154        self.buf.push(b':');
155        self.buf.push(b' ');
156        Ok(())
157    }
158
159    fn end_object(&mut self) -> Result<(), Self::Error> {
160        self.frames.pop();
161        self.buf.push(b'}');
162        Ok(())
163    }
164
165    fn write_null(&mut self) -> Result<(), Self::Error> {
166        self.value_sep()?;
167        self.buf.extend_from_slice(b"None");
168        Ok(())
169    }
170
171    fn write_bool(&mut self, value: bool) -> Result<(), Self::Error> {
172        self.value_sep()?;
173        self.buf
174            .extend_from_slice(if value { b"true" } else { b"false" });
175        Ok(())
176    }
177
178    fn write_str(&mut self, value: &str) -> Result<(), Self::Error> {
179        self.value_sep()?;
180        self.write_quoted(value);
181        Ok(())
182    }
183
184    fn write_char(&mut self, value: char) -> Result<(), Self::Error> {
185        self.value_sep()?;
186        self.write_quoted(&value.to_string());
187        Ok(())
188    }
189
190    fn write_number(&mut self, value: &Number) -> Result<(), Self::Error> {
191        self.value_sep()?;
192        self.buf.extend_from_slice(number_bytes(value).as_bytes());
193        Ok(())
194    }
195
196    fn write_i64(&mut self, value: i64) -> Result<(), Self::Error> {
197        self.value_sep()?;
198        self.buf.extend_from_slice(value.to_string().as_bytes());
199        Ok(())
200    }
201
202    fn write_u64(&mut self, value: u64) -> Result<(), Self::Error> {
203        self.value_sep()?;
204        self.buf.extend_from_slice(value.to_string().as_bytes());
205        Ok(())
206    }
207
208    fn write_i128(&mut self, value: i128) -> Result<(), Self::Error> {
209        self.value_sep()?;
210        self.buf.extend_from_slice(value.to_string().as_bytes());
211        Ok(())
212    }
213
214    fn write_u128(&mut self, value: u128) -> Result<(), Self::Error> {
215        self.value_sep()?;
216        self.buf.extend_from_slice(value.to_string().as_bytes());
217        Ok(())
218    }
219
220    fn write_f64(&mut self, value: f64) -> Result<(), Self::Error> {
221        self.value_sep()?;
222        self.buf.extend_from_slice(value.to_string().as_bytes());
223        Ok(())
224    }
225
226    fn write_f32(&mut self, value: f32) -> Result<(), Self::Error> {
227        self.write_f64(value as f64)
228    }
229}
230
231fn number_bytes(n: &Number) -> String {
232    match n {
233        Number::I64(v) => v.to_string(),
234        Number::U64(v) => v.to_string(),
235        Number::I128(v) => v.to_string(),
236        Number::U128(v) => v.to_string(),
237        Number::F64(v) => v.to_string(),
238    }
239}
240
241// ---------------------------------------------------------------------------
242// Decoder
243// ---------------------------------------------------------------------------
244
245/// Streaming RON decoder.
246pub struct RonDecoder<'de> {
247    input: &'de [u8],
248    pos: usize,
249    lookahead: Option<Token<'de>>,
250    scratch: String,
251    /// Container frames: the expected closing byte and whether it is an object.
252    frames: Vec<(u8, bool)>,
253    /// Unclosed `)` from a `Some(...)` wrapper around a container.
254    pending_parens: usize,
255    /// Nesting of `Some(...)` wrappers (a token-level recursion that the
256    /// container depth check does not cover).
257    some_depth: u32,
258    depth: u32,
259    max_depth: u32,
260}
261
262impl<'de> RonDecoder<'de> {
263    /// Create a decoder over `input`.
264    pub fn new(input: &'de [u8]) -> Self {
265        RonDecoder {
266            input,
267            pos: 0,
268            lookahead: None,
269            scratch: String::new(),
270            frames: Vec::new(),
271            pending_parens: 0,
272            some_depth: 0,
273            depth: 0,
274            max_depth: 128,
275        }
276    }
277
278    /// Validate that the whole input was consumed.
279    pub fn end(&mut self) -> Result<()> {
280        self.expect_end()
281    }
282
283    fn expect_end(&mut self) -> Result<()> {
284        self.skip_ws()?;
285        if self.lookahead.is_none() && self.pos >= self.input.len() {
286            Ok(())
287        } else {
288            Err(Error::custom("ron: trailing bytes after value"))
289        }
290    }
291
292    fn skip_ws(&mut self) -> Result<()> {
293        while self.pos < self.input.len()
294            && matches!(self.input[self.pos], b' ' | b'\t' | b'\n' | b'\r')
295        {
296            self.pos += 1;
297        }
298        Ok(())
299    }
300
301    fn peek_byte(&mut self) -> Result<u8> {
302        self.skip_ws()?;
303        self.input
304            .get(self.pos)
305            .copied()
306            .ok_or_else(|| Error::custom("ron: unexpected end of input"))
307    }
308
309    fn read_quoted(&mut self) -> Result<String> {
310        self.pos += 1; // opening quote
311        self.scratch.clear();
312        loop {
313            if self.pos >= self.input.len() {
314                return Err(Error::custom("ron: unterminated string"));
315            }
316            match self.input[self.pos] {
317                b'"' => {
318                    self.pos += 1;
319                    return Ok(core::mem::take(&mut self.scratch));
320                }
321                b'\\' => {
322                    self.pos += 1;
323                    if self.pos >= self.input.len() {
324                        return Err(Error::custom("ron: unterminated escape"));
325                    }
326                    let c = match self.input[self.pos] {
327                        b'n' => '\n',
328                        b't' => '\t',
329                        b'r' => '\r',
330                        b'"' => '"',
331                        b'\\' => '\\',
332                        b'b' => '\u{8}',
333                        b'f' => '\u{c}',
334                        other => other as char,
335                    };
336                    self.scratch.push(c);
337                    self.pos += 1;
338                }
339                b => {
340                    let len = utf8_len(b).ok_or_else(|| Error::custom("ron: invalid utf-8"))?;
341                    let chunk = self
342                        .input
343                        .get(self.pos..self.pos + len)
344                        .ok_or_else(|| Error::custom("ron: truncated utf-8"))?;
345                    let s = core::str::from_utf8(chunk)
346                        .map_err(|_| Error::custom("ron: invalid utf-8"))?;
347                    self.scratch.push_str(s);
348                    self.pos += len;
349                }
350            }
351        }
352    }
353
354    fn read_ident(&mut self) -> Result<String> {
355        let start = self.pos;
356        while self.pos < self.input.len() {
357            let b = self.input[self.pos];
358            if b.is_ascii_alphanumeric() || b == b'_' || b == b'-' || b == b'.' {
359                self.pos += 1;
360            } else {
361                break;
362            }
363        }
364        let raw = &self.input[start..self.pos];
365        Ok(core::str::from_utf8(raw)
366            .map_err(|_| Error::custom("ron: invalid identifier"))?
367            .to_string())
368    }
369
370    /// Body of `Some(...)`: consume the wrapping parentheses and unwrap the
371    /// inner token. `some_depth` (checked by the caller) bounds the recursion.
372    fn read_some_body(&mut self) -> Result<Token<'de>> {
373        self.skip_ws()?;
374        if self.input.get(self.pos) == Some(&b'(') {
375            self.pos += 1;
376            let inner = self.read_token()?;
377            match inner {
378                Token::BeginArray | Token::BeginObject => {
379                    self.pending_parens += 1;
380                }
381                _ => {
382                    self.skip_ws()?;
383                    if self.input.get(self.pos) == Some(&b')') {
384                        self.pos += 1;
385                    }
386                }
387            }
388            Ok(inner)
389        } else {
390            Err(Error::custom("ron: expected '(' after Some"))
391        }
392    }
393
394    fn read_number_text(&mut self) -> Result<String> {
395        let start = self.pos;
396        if self.input.get(self.pos) == Some(&b'-') {
397            self.pos += 1;
398        }
399        while self.pos < self.input.len() {
400            let b = self.input[self.pos];
401            if b.is_ascii_digit() || matches!(b, b'.' | b'e' | b'E' | b'+' | b'-') {
402                self.pos += 1;
403            } else {
404                break;
405            }
406        }
407        Ok(core::str::from_utf8(&self.input[start..self.pos])
408            .map_err(|_| Error::custom("ron: invalid number"))?
409            .to_string())
410    }
411
412    fn read_token(&mut self) -> Result<Token<'de>> {
413        let b = self.peek_byte()?;
414        match b {
415            b'[' => {
416                self.pos += 1;
417                self.frames.push((b']', false));
418                Ok(Token::BeginArray)
419            }
420            b']' => {
421                self.pos += 1;
422                if self.frames.last().map(|f| f.0) == Some(b']') {
423                    Ok(Token::EndArray)
424                } else {
425                    Err(Error::custom("ron: mismatched ']'"))
426                }
427            }
428            b'{' => {
429                self.pos += 1;
430                self.frames.push((b'}', true));
431                Ok(Token::BeginObject)
432            }
433            b'}' => {
434                self.pos += 1;
435                if self.frames.last().map(|f| f.0) == Some(b'}') {
436                    Ok(Token::EndObject)
437                } else {
438                    Err(Error::custom("ron: mismatched '}'"))
439                }
440            }
441            b'(' => {
442                // Tuple or struct form: decide by peeking for `ident:`.
443                self.pos += 1;
444                let is_struct = self.looks_like_struct()?;
445                self.frames.push((b')', is_struct));
446                if is_struct {
447                    Ok(Token::BeginObject)
448                } else {
449                    Ok(Token::BeginArray)
450                }
451            }
452            b')' => {
453                self.pos += 1;
454                match self.frames.last() {
455                    Some((b')', true)) => Ok(Token::EndObject),
456                    Some((b')', false)) => Ok(Token::EndArray),
457                    _ => Err(Error::custom("ron: mismatched ')'")),
458                }
459            }
460            b'"' => Ok(Token::Str(Cow::Owned(self.read_quoted()?))),
461            b'-' | b'0'..=b'9' | b'+' => {
462                let text = self.read_number_text()?;
463                Ok(Token::Number(parse_ron_number(&text)?))
464            }
465            b'a'..=b'z' | b'A'..=b'Z' | b'_' => {
466                let ident = self.read_ident()?;
467                match ident.as_str() {
468                    "None" => Ok(Token::Null),
469                    "Some" => {
470                        // `Some(...)` unwraps to the inner value. A container
471                        // inner value closes with `)` after its own end. The
472                        // recursion is bounded like container nesting.
473                        if self.some_depth >= self.max_depth {
474                            return Err(Error::custom("ron: recursion limit exceeded"));
475                        }
476                        self.some_depth += 1;
477                        let result = self.read_some_body();
478                        self.some_depth -= 1;
479                        result
480                    }
481                    "true" => Ok(Token::Bool(true)),
482                    "false" => Ok(Token::Bool(false)),
483                    _ => Ok(Token::Str(Cow::Owned(ident))),
484                }
485            }
486            other => Err(Error::custom(alloc::format!(
487                "ron: unexpected byte 0x{other:02x}"
488            ))),
489        }
490    }
491
492    /// After consuming `(`, decide whether it is a struct (`ident:`) or a
493    /// tuple.
494    fn looks_like_struct(&mut self) -> Result<bool> {
495        let saved = self.pos;
496        self.skip_ws()?;
497        // Empty tuple `()` -> array.
498        if self.input.get(self.pos) == Some(&b')') {
499            self.pos = saved;
500            return Ok(false);
501        }
502        // Peek an identifier followed by `:`.
503        let mut i = self.pos;
504        while i < self.input.len()
505            && (self.input[i].is_ascii_alphanumeric() || self.input[i] == b'_')
506        {
507            i += 1;
508        }
509        while i < self.input.len() && matches!(self.input[i], b' ' | b'\t' | b'\n' | b'\r') {
510            i += 1;
511        }
512        let is_struct = self.input.get(i) == Some(&b':');
513        self.pos = saved;
514        Ok(is_struct)
515    }
516}
517
518fn parse_ron_number(text: &str) -> Result<Number> {
519    if let Ok(v) = text.parse::<i64>() {
520        return Ok(Number::from(v));
521    }
522    if let Ok(v) = text.parse::<u64>() {
523        return Ok(Number::from(v));
524    }
525    if let Ok(v) = text.parse::<f64>() {
526        return Ok(Number::F64(v));
527    }
528    Err(Error::custom(alloc::format!(
529        "ron: invalid number {text:?}"
530    )))
531}
532
533fn utf8_len(b: u8) -> Option<usize> {
534    match b {
535        0x00..=0x7F => Some(1),
536        0xC0..=0xDF => Some(2),
537        0xE0..=0xEF => Some(3),
538        0xF0..=0xF7 => Some(4),
539        _ => None,
540    }
541}
542
543impl<'de> FormatDecoder<'de> for RonDecoder<'de> {
544    type Error = crate::error::Error;
545
546    fn begin_object(&mut self) -> Result<(), Self::Error> {
547        self.enter_container()?;
548        match self.next_token()? {
549            Token::BeginObject => Ok(()),
550            other => Err(Error::invalid_type("a struct/map", token_name(&other))),
551        }
552    }
553
554    fn end_object(&mut self) -> Result<(), Self::Error> {
555        self.leave_container()?;
556        let r = match self.next_token()? {
557            Token::EndObject => Ok(()),
558            other => Err(Error::invalid_type("'}' or ')'", token_name(&other))),
559        };
560        self.frames.pop();
561        self.consume_pending_paren()?;
562        r
563    }
564
565    fn object_key(&mut self) -> Result<Option<Cow<'de, str>>, Self::Error> {
566        if matches!(self.peek_token()?, Token::EndObject) {
567            return Ok(None);
568        }
569        let key = match self.next_token()? {
570            Token::Str(s) => s,
571            other => return Err(Error::invalid_type("a string key", token_name(&other))),
572        };
573        self.skip_ws()?;
574        if self.input.get(self.pos) == Some(&b':') {
575            self.pos += 1;
576        }
577        Ok(Some(key))
578    }
579
580    fn object_entry_sep(&mut self) -> Result<bool, Self::Error> {
581        self.skip_ws()?;
582        if self.input.get(self.pos) == Some(&b',') {
583            self.pos += 1;
584        }
585        Ok(!matches!(self.peek_token()?, Token::EndObject))
586    }
587
588    fn begin_array(&mut self) -> Result<(), Self::Error> {
589        self.enter_container()?;
590        match self.next_token()? {
591            Token::BeginArray => Ok(()),
592            other => Err(Error::invalid_type("a sequence", token_name(&other))),
593        }
594    }
595
596    fn end_array(&mut self) -> Result<(), Self::Error> {
597        self.leave_container()?;
598        let r = match self.next_token()? {
599            Token::EndArray => Ok(()),
600            other => Err(Error::invalid_type("']' or ')'", token_name(&other))),
601        };
602        self.frames.pop();
603        self.consume_pending_paren()?;
604        r
605    }
606
607    fn array_has_more(&mut self) -> Result<bool, Self::Error> {
608        Ok(!matches!(self.peek_token()?, Token::EndArray))
609    }
610
611    fn array_entry_sep(&mut self) -> Result<bool, Self::Error> {
612        self.skip_ws()?;
613        if self.input.get(self.pos) == Some(&b',') {
614            self.pos += 1;
615        }
616        self.array_has_more()
617    }
618
619    fn unit(&mut self) -> Result<(), Self::Error> {
620        match self.next_token()? {
621            Token::Null => Ok(()),
622            other => Err(Error::invalid_type("null", token_name(&other))),
623        }
624    }
625
626    fn bool(&mut self) -> Result<bool, Self::Error> {
627        match self.next_token()? {
628            Token::Bool(b) => Ok(b),
629            other => Err(Error::invalid_type("bool", token_name(&other))),
630        }
631    }
632
633    fn number(&mut self) -> Result<Number, Self::Error> {
634        match self.next_token()? {
635            Token::Number(n) => Ok(n),
636            other => Err(Error::invalid_type("number", token_name(&other))),
637        }
638    }
639
640    fn string(&mut self) -> Result<Cow<'de, str>, Self::Error> {
641        match self.next_token()? {
642            Token::Str(s) => Ok(s),
643            other => Err(Error::invalid_type("string", token_name(&other))),
644        }
645    }
646
647    fn char(&mut self) -> Result<char, Self::Error> {
648        match self.next_token()? {
649            Token::Str(s) => {
650                let mut chars = s.chars();
651                match (chars.next(), chars.next()) {
652                    (Some(c), None) => Ok(c),
653                    _ => Err(Error::invalid_type("a single-character string", "string")),
654                }
655            }
656            other => Err(Error::invalid_type("char", token_name(&other))),
657        }
658    }
659
660    fn skip_value(&mut self) -> Result<(), Self::Error> {
661        match self.peek_token()? {
662            Token::BeginObject => {
663                self.begin_object()?;
664                while self.object_key()?.is_some() {
665                    self.skip_value()?;
666                    if !self.object_entry_sep()? {
667                        break;
668                    }
669                }
670                self.end_object()
671            }
672            Token::BeginArray => {
673                self.begin_array()?;
674                while self.array_has_more()? {
675                    self.skip_value()?;
676                    if !self.array_entry_sep()? {
677                        break;
678                    }
679                }
680                self.end_array()
681            }
682            _ => {
683                self.next_token()?;
684                Ok(())
685            }
686        }
687    }
688
689    fn peek_token(&mut self) -> Result<Token<'de>, Self::Error> {
690        if self.lookahead.is_none() {
691            self.lookahead = Some(self.read_token()?);
692        }
693        Ok(self.lookahead.as_ref().expect("set").clone())
694    }
695
696    fn next_token(&mut self) -> Result<Token<'de>, Self::Error> {
697        if let Some(t) = self.lookahead.take() {
698            return Ok(t);
699        }
700        self.read_token()
701    }
702
703    fn save(&self) -> Mark {
704        Mark {
705            pos: self.pos,
706            depth: self.depth,
707            frame_len: self.frames.len(),
708        }
709    }
710
711    fn restore(&mut self, mark: Mark) {
712        self.pos = mark.pos;
713        self.lookahead = None;
714        self.frames.truncate(mark.frame_len);
715        self.depth = mark.depth;
716    }
717}
718
719impl<'de> RonDecoder<'de> {
720    fn enter_container(&mut self) -> Result<()> {
721        if self.depth >= self.max_depth {
722            return Err(Error::custom("ron: recursion limit exceeded"));
723        }
724        self.depth += 1;
725        Ok(())
726    }
727
728    fn leave_container(&mut self) -> Result<()> {
729        self.depth = self.depth.saturating_sub(1);
730        Ok(())
731    }
732
733    fn consume_pending_paren(&mut self) -> Result<()> {
734        if self.pending_parens > 0 {
735            self.skip_ws()?;
736            if self.input.get(self.pos) == Some(&b')') {
737                self.pos += 1;
738                self.pending_parens -= 1;
739            } else {
740                return Err(Error::custom("ron: expected ')' after Some(...)"));
741            }
742        }
743        Ok(())
744    }
745}