Skip to main content

wasm_wave/
parser.rs

1//! Parsing types
2
3use core::{error::Error, fmt::Display};
4
5use alloc::{
6    boxed::Box,
7    collections::BTreeMap,
8    format,
9    string::{String, ToString},
10    vec::Vec,
11};
12
13use crate::{
14    WasmValue,
15    ast::{Node, NodeType},
16    lex::{FuncNameLexer, FuncNameToken, Keyword, Lexer, Span, Token},
17    untyped::{UntypedFuncCall, UntypedValue},
18};
19
20const MAX_DEPTH: usize = 100;
21
22/// A Web Assembly Value Encoding parser.
23pub struct Parser<'source> {
24    lex: Lexer<'source>,
25    curr: Option<Token>,
26    depth: usize,
27}
28
29impl<'source> Parser<'source> {
30    /// Returns a new Parser of the given source.
31    pub fn new(source: &'source str) -> Self {
32        Self::with_lexer(Lexer::new(source))
33    }
34
35    /// Returns a new Parser with the given [`Lexer`].
36    pub fn with_lexer(lexer: Lexer<'source>) -> Self {
37        Self {
38            lex: lexer,
39            curr: None,
40            depth: 0,
41        }
42    }
43
44    /// Parses a WAVE-encoded value of the given [`crate::wasm::WasmType`] into a
45    /// corresponding [`WasmValue`].
46    pub fn parse_value<V: WasmValue>(&mut self, ty: &V::Type) -> Result<V, ParserError> {
47        let node = self.parse_node()?;
48        node.to_wasm_value(ty, self.lex.source())
49    }
50
51    /// Parses a WAVE-encoded value into an [`UntypedValue`].
52    pub fn parse_raw_value(&mut self) -> Result<UntypedValue<'source>, ParserError> {
53        let node = self.parse_node()?;
54        Ok(UntypedValue::new(self.lex.source(), node))
55    }
56
57    /// Returns an error if any significant input remains unparsed.
58    pub fn finish(&mut self) -> Result<(), ParserError> {
59        match self.lex.clone().spanned().next() {
60            None => Ok(()),
61            Some((_, span)) => Err(ParserError::new(
62                ParserErrorKind::TrailingCharacters,
63                span.clone(),
64            )),
65        }
66    }
67
68    fn parse_node(&mut self) -> Result<Node, ParserError> {
69        if self.depth >= MAX_DEPTH {
70            return Err(ParserError::new(
71                ParserErrorKind::NestingTooDeep,
72                self.lex.span(),
73            ));
74        }
75        self.depth += 1;
76        let result = self.parse_node_inner();
77        self.depth -= 1;
78        result
79    }
80
81    fn parse_node_inner(&mut self) -> Result<Node, ParserError> {
82        Ok(match self.advance()? {
83            Token::Number => self.leaf_node(NodeType::Number),
84            Token::Char => self.leaf_node(NodeType::Char),
85            Token::String => self.leaf_node(NodeType::String),
86            Token::MultilineString => self.leaf_node(NodeType::MultilineString),
87            Token::ParenOpen => self.parse_tuple()?,
88            Token::BracketOpen => self.parse_list()?,
89            Token::BraceOpen => self.parse_braces()?,
90            Token::LabelOrKeyword => match Keyword::decode(self.slice()) {
91                Some(Keyword::True) => self.leaf_node(NodeType::BoolTrue),
92                Some(Keyword::False) => self.leaf_node(NodeType::BoolFalse),
93                Some(Keyword::Some) => self.parse_option(NodeType::OptionSome)?,
94                Some(Keyword::None) => self.parse_option(NodeType::OptionNone)?,
95                Some(Keyword::Ok) => self.parse_result(NodeType::ResultOk)?,
96                Some(Keyword::Err) => self.parse_result(NodeType::ResultErr)?,
97                Some(Keyword::Inf | Keyword::Nan) => self.leaf_node(NodeType::Number),
98                None => self.parse_label_maybe_payload()?,
99            },
100            Token::BraceClose
101            | Token::ParenClose
102            | Token::BracketClose
103            | Token::Colon
104            | Token::Comma => return Err(self.unexpected_token()),
105        })
106    }
107
108    fn parse_tuple(&mut self) -> Result<Node, ParserError> {
109        let start = self.span().start;
110        let children = self.parse_comma_separated_nodes(Token::ParenClose)?;
111        let span = start..self.span().end;
112        if children.is_empty() {
113            return Err(ParserError::new(ParserErrorKind::EmptyTuple, span));
114        }
115        Ok(Node::new(NodeType::Tuple, span, children))
116    }
117
118    fn parse_list(&mut self) -> Result<Node, ParserError> {
119        let start = self.span().start;
120        let children = self.parse_comma_separated_nodes(Token::BracketClose)?;
121        Ok(Node::new(NodeType::List, start..self.span().end, children))
122    }
123
124    fn parse_braces(&mut self) -> Result<Node, ParserError> {
125        let start = self.span().start;
126        self.advance()?;
127
128        match self.token() {
129            // Handle empty record or map (`{:}`)
130            Token::Colon => {
131                self.advance()?; // Advance to `}`
132                self.expect_token(Token::BraceClose)?;
133                return Ok(Node::new(NodeType::TupleSet, start..self.span().end, []));
134            }
135            // Handle empty flags or map (`{}`)
136            Token::BraceClose => {
137                return Ok(Node::new(NodeType::EmptySet, start..self.span().end, []));
138            }
139            _ => (),
140        }
141
142        // Check for a following `:` to distinguish records and maps from flags,
143        // which can only be labels
144        if self.token() != Token::LabelOrKeyword || self.next_is(Token::Colon) {
145            self.finish_tuple_set(start)
146        } else {
147            self.finish_flags(start)
148        }
149    }
150
151    fn finish_tuple_set(&mut self, start: usize) -> Result<Node, ParserError> {
152        let mut children = Vec::with_capacity(2);
153        loop {
154            // Parse record field label or map key
155            let key = self.parse_key()?;
156            // Parse colon
157            self.advance()?;
158            self.expect_token(Token::Colon)?;
159            // Parse value
160            let value = self.parse_node()?;
161            children.extend([key, value]);
162            // Parse comma or closing brace
163            match self.advance()? {
164                Token::Comma => {
165                    self.advance()?;
166                    if self.token() == Token::BraceClose {
167                        break;
168                    }
169                }
170                Token::BraceClose => break,
171                _ => return Err(self.unexpected_token()),
172            }
173        }
174        Ok(Node::new(
175            NodeType::TupleSet,
176            start..self.span().end,
177            children,
178        ))
179    }
180
181    fn finish_flags(&mut self, start: usize) -> Result<Node, ParserError> {
182        let mut flags = BTreeMap::new();
183        loop {
184            // Parse flag label
185            let label = self.parse_label()?;
186            // Insert and check for duplicate flags
187            let span = label.span();
188            let flag = self.slice().trim_start_matches('%');
189            if flags.insert(flag, label).is_some() {
190                return Err(ParserError::with_detail(
191                    ParserErrorKind::DuplicateFlag,
192                    span,
193                    format!("{flag:?}"),
194                ));
195            }
196            match self.advance()? {
197                Token::Comma => {
198                    self.advance()?;
199                    if self.token() == Token::BraceClose {
200                        break;
201                    }
202                }
203                Token::BraceClose => break,
204                _ => return Err(self.unexpected_token()),
205            }
206        }
207        Ok(Node::new(
208            NodeType::Flags,
209            start..self.span().end,
210            flags.into_values(),
211        ))
212    }
213
214    fn parse_label_maybe_payload(&mut self) -> Result<Node, ParserError> {
215        let start = self.span().start;
216        let label = self.parse_label()?;
217        if self.next_is(Token::ParenOpen) {
218            self.advance()?;
219            let payload = self.parse_node()?;
220            self.advance()?;
221            self.expect_token(Token::ParenClose)?;
222            Ok(Node::new(
223                NodeType::VariantWithPayload,
224                start..self.span().end,
225                [label, payload],
226            ))
227        } else {
228            Ok(label)
229        }
230    }
231
232    fn parse_option(&mut self, ty: NodeType) -> Result<Node, ParserError> {
233        let start = self.span().start;
234        let payload = match ty {
235            NodeType::OptionSome => {
236                self.advance()?;
237                self.expect_token(Token::ParenOpen)?;
238                let payload = self.parse_node()?;
239                self.advance()?;
240                self.expect_token(Token::ParenClose)?;
241                Some(payload)
242            }
243            NodeType::OptionNone => None,
244            _ => unreachable!(),
245        };
246        Ok(Node::new(ty, start..self.span().end, payload))
247    }
248
249    fn parse_result(&mut self, ty: NodeType) -> Result<Node, ParserError> {
250        let start = self.span().start;
251        let mut payload = None;
252        if self.next_is(Token::ParenOpen) {
253            self.advance()?;
254            self.expect_token(Token::ParenOpen)?;
255            payload = Some(self.parse_node()?);
256            self.advance()?;
257            self.expect_token(Token::ParenClose)?;
258        }
259        Ok(Node::new(ty, start..self.span().end, payload))
260    }
261
262    fn parse_label(&mut self) -> Result<Node, ParserError> {
263        self.expect_token(Token::LabelOrKeyword)?;
264        Ok(self.leaf_node(NodeType::Label))
265    }
266
267    /// Parses a record field label or map key. Keywords are labels here, so
268    /// that, e.g., `true` can be a field or a `bool` key.
269    fn parse_key(&mut self) -> Result<Node, ParserError> {
270        let ty = match self.token() {
271            Token::LabelOrKeyword => NodeType::Label,
272            Token::Number => NodeType::Number,
273            Token::Char => NodeType::Char,
274            Token::String => NodeType::String,
275            Token::MultilineString => NodeType::MultilineString,
276            _ => return Err(self.unexpected_token()),
277        };
278        Ok(self.leaf_node(ty))
279    }
280
281    fn advance(&mut self) -> Result<Token, ParserError> {
282        let token = match self.lex.next() {
283            Some(Ok(token)) => token,
284            Some(Err(span)) => {
285                let span = span.unwrap_or_else(|| self.lex.span());
286                return Err(ParserError::new(ParserErrorKind::InvalidToken, span));
287            }
288            None => {
289                return Err(ParserError::new(
290                    ParserErrorKind::UnexpectedEnd,
291                    self.lex.span(),
292                ));
293            }
294        };
295        self.curr = Some(token);
296        Ok(token)
297    }
298
299    fn token(&self) -> Token {
300        self.curr.unwrap()
301    }
302
303    fn span(&self) -> Span {
304        self.lex.span()
305    }
306
307    fn slice(&self) -> &'source str {
308        &self.lex.source()[self.span()]
309    }
310
311    fn next_is(&mut self, token: Token) -> bool {
312        self.lex.clone().next().and_then(|res| res.ok()) == Some(token)
313    }
314
315    fn expect_token(&self, token: Token) -> Result<(), ParserError> {
316        if self.token() == token {
317            Ok(())
318        } else {
319            Err(self.unexpected_token())
320        }
321    }
322
323    fn unexpected_token(&self) -> ParserError {
324        ParserError::with_detail(ParserErrorKind::UnexpectedToken, self.span(), self.token())
325    }
326
327    fn parse_comma_separated_nodes(&mut self, end_token: Token) -> Result<Vec<Node>, ParserError> {
328        let mut nodes = Vec::new();
329        if self.next_is(end_token) {
330            self.advance()?;
331            return Ok(nodes);
332        }
333        loop {
334            nodes.push(self.parse_node()?);
335
336            match self.advance()? {
337                Token::Comma => {
338                    if self.next_is(end_token) {
339                        self.advance()?;
340                        break;
341                    }
342                }
343                _ => {
344                    self.expect_token(end_token)?;
345                    break;
346                }
347            }
348        }
349        Ok(nodes)
350    }
351
352    fn leaf_node(&self, ty: NodeType) -> Node {
353        Node::new(ty, self.span(), [])
354    }
355}
356
357/// A WAVE parsing error.
358#[derive(Debug)]
359pub struct ParserError {
360    kind: ParserErrorKind,
361    span: Span,
362    detail: Option<String>,
363    source: Option<Box<dyn Error + Send + Sync + 'static>>,
364}
365
366impl ParserError {
367    pub(crate) fn new(kind: ParserErrorKind, span: Span) -> Self {
368        Self {
369            kind,
370            span,
371            detail: None,
372            source: None,
373        }
374    }
375
376    pub(crate) fn with_detail(kind: ParserErrorKind, span: Span, detail: impl Display) -> Self {
377        Self {
378            kind,
379            span,
380            detail: Some(detail.to_string()),
381            source: None,
382        }
383    }
384
385    pub(crate) fn with_source(
386        kind: ParserErrorKind,
387        span: Span,
388        source: impl Into<Box<dyn Error + Send + Sync>>,
389    ) -> Self {
390        Self {
391            kind,
392            span,
393            detail: None,
394            source: Some(source.into()),
395        }
396    }
397
398    /// Returns the [`ParserErrorKind`] of this error.
399    pub fn kind(&self) -> ParserErrorKind {
400        self.kind
401    }
402
403    /// Returns the [`Span`] of this error.
404    pub fn span(&self) -> Span {
405        self.span.clone()
406    }
407
408    /// Returns any detail string for this error.
409    pub fn detail(&self) -> Option<&str> {
410        self.detail.as_deref()
411    }
412}
413
414impl Display for ParserError {
415    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
416        if let Some(source) = &self.source {
417            write!(f, "{}: {} at {:?}", self.kind, source, self.span)
418        } else if let Some(detail) = &self.detail {
419            write!(f, "{}: {} at {:?}", self.kind, detail, self.span)
420        } else {
421            write!(f, "{} at {:?}", self.kind, self.span)
422        }
423    }
424}
425
426impl Error for ParserError {
427    fn source(&self) -> Option<&(dyn Error + 'static)> {
428        Some(self.source.as_deref()? as _)
429    }
430}
431
432/// Parses a function name followed by a WAVE-encoded, parenthesized,
433/// comma-separated sequence of values into an [`UntypedFuncCall`].
434pub fn parse_raw_func_call<'source>(
435    source: &'source str,
436) -> Result<UntypedFuncCall<'source>, ParserError> {
437    let mut name_parser = FuncNameParser::with_lexer(FuncNameLexer::new(source));
438    let _func_name = name_parser.advance()?;
439    let name = name_parser.lex.span();
440
441    let mut params_parser = Parser::with_lexer(name_parser.lex.morph());
442    params_parser.advance()?;
443    params_parser.expect_token(Token::ParenOpen)?;
444
445    let params = if params_parser.next_is(Token::ParenClose) {
446        params_parser.advance()?;
447        None
448    } else {
449        Some(params_parser.parse_tuple()?)
450    };
451    params_parser.finish()?;
452    Ok(UntypedFuncCall::new(source, name, params))
453}
454
455struct FuncNameParser<'source> {
456    lex: FuncNameLexer<'source>,
457    curr: Option<FuncNameToken>,
458}
459impl<'source> FuncNameParser<'source> {
460    fn with_lexer(lex: FuncNameLexer<'source>) -> Self {
461        Self { lex, curr: None }
462    }
463    fn advance(&mut self) -> Result<FuncNameToken, ParserError> {
464        let token = match self.lex.next() {
465            Some(Ok(token)) => token,
466            Some(Err(span)) => {
467                let span = span.unwrap_or_else(|| self.lex.span());
468                return Err(ParserError::new(ParserErrorKind::InvalidToken, span));
469            }
470            None => {
471                return Err(ParserError::new(
472                    ParserErrorKind::UnexpectedEnd,
473                    self.lex.span(),
474                ));
475            }
476        };
477        self.curr = Some(token);
478        Ok(token)
479    }
480}
481/// The kind of a WAVE parsing error.
482#[derive(Clone, Copy, Debug, PartialEq)]
483#[non_exhaustive]
484#[allow(missing_docs)]
485pub enum ParserErrorKind {
486    EmptyTuple,
487    MultipleChars,
488    InvalidEscape,
489    InvalidMultilineString,
490    InvalidParams,
491    InvalidToken,
492    InvalidType,
493    InvalidValue,
494    TrailingCharacters,
495    UnexpectedEnd,
496    UnexpectedToken,
497    DuplicateField,
498    DuplicateFlag,
499    WasmValueError,
500    NestingTooDeep,
501}
502
503impl Display for ParserErrorKind {
504    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
505        let msg = match self {
506            ParserErrorKind::EmptyTuple => "empty tuple",
507            ParserErrorKind::MultipleChars => "multiple characters in char value",
508            ParserErrorKind::InvalidEscape => "invalid character escape",
509            ParserErrorKind::InvalidMultilineString => "invalid multiline string",
510            ParserErrorKind::InvalidParams => "invalid params",
511            ParserErrorKind::InvalidToken => "invalid token",
512            ParserErrorKind::InvalidType => "invalid value type",
513            ParserErrorKind::InvalidValue => "invalid value",
514            ParserErrorKind::TrailingCharacters => "trailing characters after value",
515            ParserErrorKind::UnexpectedEnd => "unexpected end of input",
516            ParserErrorKind::UnexpectedToken => "unexpected token",
517            ParserErrorKind::DuplicateField => "duplicate field",
518            ParserErrorKind::DuplicateFlag => "duplicate flag",
519            ParserErrorKind::WasmValueError => "error converting Wasm value",
520            ParserErrorKind::NestingTooDeep => "value nesting too deep",
521        };
522        write!(f, "{msg}")
523    }
524}
525
526#[cfg(test)]
527mod tests {
528    use super::*;
529    use crate::value::{Type, Value};
530
531    #[test]
532    fn parse_option_or_result() {
533        let ty = Type::option(Type::BOOL);
534        assert_eq!(
535            parse_value("some(true)", &ty),
536            Value::make_option(&ty, Some(Value::make_bool(true))).unwrap()
537        );
538        let ty = Type::result(Some(Type::BOOL), None);
539        assert_eq!(
540            parse_value("ok(false)", &ty),
541            Value::make_result(&ty, Ok(Some(Value::make_bool(false)))).unwrap()
542        );
543    }
544
545    #[test]
546    fn parse_flat_option_or_result() {
547        let ty = Type::option(Type::BOOL);
548        assert_eq!(
549            parse_value("true", &ty),
550            Value::make_option(&ty, Some(Value::make_bool(true))).unwrap()
551        );
552        let ty = Type::result(Some(Type::BOOL), None);
553        assert_eq!(
554            parse_value("false", &ty),
555            Value::make_result(&ty, Ok(Some(Value::make_bool(false)))).unwrap()
556        );
557    }
558
559    #[test]
560    fn parse_record_reordering() {
561        let ty = Type::record([("red", Type::S32), ("green", Type::CHAR)]).unwrap();
562        // Parse the fields in the order they appear in the type.
563        assert_eq!(
564            parse_value("{red: 0, green: 'a'}", &ty),
565            Value::make_record(
566                &ty,
567                [
568                    ("red", Value::make_s32(0)),
569                    ("green", Value::make_char('a'))
570                ]
571            )
572            .unwrap()
573        );
574        // Parse the fields in reverse order.
575        assert_eq!(
576            parse_value("{green: 'a', red: 0}", &ty),
577            Value::make_record(
578                &ty,
579                [
580                    ("red", Value::make_s32(0)),
581                    ("green", Value::make_char('a'))
582                ]
583            )
584            .unwrap()
585        );
586    }
587
588    #[test]
589    fn parse_record_with_optional_fields() {
590        let field_ty = Type::option(Type::CHAR);
591        let ty = Type::record([("red", Type::S32), ("green", field_ty.clone())]).unwrap();
592        // Explicit `some`.
593        assert_eq!(
594            parse_value("{red: 0, green: some('a')}", &ty),
595            Value::make_record(
596                &ty,
597                [
598                    ("red", Value::make_s32(0)),
599                    (
600                        "green",
601                        Value::make_option(&field_ty, Some(Value::make_char('a'))).unwrap()
602                    )
603                ]
604            )
605            .unwrap()
606        );
607        // Flattened `some`.
608        assert_eq!(
609            parse_value("{red: 0, green: 'a'}", &ty),
610            Value::make_record(
611                &ty,
612                [
613                    ("red", Value::make_s32(0)),
614                    (
615                        "green",
616                        Value::make_option(&field_ty, Some(Value::make_char('a'))).unwrap()
617                    )
618                ]
619            )
620            .unwrap()
621        );
622        // Explicit `none`.
623        assert_eq!(
624            parse_value("{red: 0, green: none}", &ty),
625            Value::make_record(
626                &ty,
627                [
628                    ("red", Value::make_s32(0)),
629                    ("green", Value::make_option(&field_ty, None).unwrap())
630                ]
631            )
632            .unwrap()
633        );
634        // Implied `none`.
635        assert_eq!(
636            parse_value("{red: 0}", &ty),
637            Value::make_record(
638                &ty,
639                [
640                    ("red", Value::make_s32(0)),
641                    ("green", Value::make_option(&field_ty, None).unwrap())
642                ]
643            )
644            .unwrap()
645        );
646    }
647
648    #[test]
649    fn parse_flag_reordering() {
650        let ty = Type::flags(["hot", "cold"]).unwrap();
651        // Parse the flags in the order they appear in the type.
652        assert_eq!(
653            parse_value("{hot, cold}", &ty),
654            Value::make_flags(&ty, ["hot", "cold"]).unwrap()
655        );
656        // Parse the flags in reverse order.
657        assert_eq!(
658            parse_value("{cold, hot}", &ty),
659            Value::make_flags(&ty, ["hot", "cold"]).unwrap()
660        );
661    }
662
663    #[test]
664    fn parse_flags_in_type_order() {
665        // Keeps flags in the order `make_flags` gives them, like
666        // `wasmtime::component::Val` does, unlike `Value`, which sorts them.
667        #[derive(Clone)]
668        struct Flags(Vec<String>);
669
670        impl WasmValue for Flags {
671            type Type = Type;
672
673            fn kind(&self) -> crate::wasm::WasmTypeKind {
674                crate::wasm::WasmTypeKind::Flags
675            }
676
677            fn make_flags<'a>(
678                _ty: &Type,
679                names: impl IntoIterator<Item = &'a str>,
680            ) -> Result<Self, crate::wasm::WasmValueError> {
681                Ok(Self(names.into_iter().map(String::from).collect()))
682            }
683        }
684
685        let ty = Type::flags(["read", "write", "exec"]).unwrap();
686        for input in ["{write, exec}", "{exec, write}", "{%exec, write}"] {
687            let Flags(names) = Parser::new(input).parse_value(&ty).unwrap();
688            assert_eq!(names, ["write", "exec"], "for {input:?}");
689        }
690    }
691
692    #[test]
693    fn reject_record_missing_commas() {
694        let ty = Type::record([("red", Type::S32), ("green", Type::CHAR)]).unwrap();
695
696        for input in [
697            r#"{"red": 1 "green": 'a'}"#,
698            r#"{"red":1"green":'a'}"#,
699            "{\"red\": 1\n\"green\": 'a'}",
700        ] {
701            let err = Parser::new(input).parse_value::<Value>(&ty).unwrap_err();
702            assert_eq!(err.kind(), ParserErrorKind::UnexpectedToken);
703        }
704    }
705
706    #[test]
707    fn reject_map_missing_commas() {
708        let ty = Type::map(Type::STRING, Type::U32).unwrap();
709        for input in [
710            r#"{"a": 1 "b": 2}"#,
711            r#"{"a":1"b":2}"#,
712            "{\"a\": 1\n\"b\": 2}",
713        ] {
714            let err = Parser::new(input).parse_value::<Value>(&ty).unwrap_err();
715            assert_eq!(err.kind(), ParserErrorKind::UnexpectedToken);
716        }
717
718        let ty = Type::map(Type::S8, Type::BOOL).unwrap();
719        for input in ["{-1: true 1: false}", "{-1:true-2:false}"] {
720            let err = Parser::new(input).parse_value::<Value>(&ty).unwrap_err();
721            assert_eq!(err.kind(), ParserErrorKind::UnexpectedToken);
722        }
723    }
724
725    #[test]
726    fn reject_flags_missing_commas() {
727        let ty = Type::flags(["read", "write", "exec"]).unwrap();
728        for input in [
729            "{read write}",
730            "{read write exec}",
731            "{read, write exec}",
732            "{%read write}",
733            "{read\nwrite}",
734            "{read // comment\nwrite}",
735        ] {
736            let err = Parser::new(input).parse_value::<Value>(&ty).unwrap_err();
737            assert_eq!(err.kind(), ParserErrorKind::UnexpectedToken);
738        }
739    }
740
741    #[test]
742    fn reject_missing_commas_untyped() {
743        // The commas are also required before any type is known.
744        for input in [
745            "{a: 1 b: 2}",
746            "{a:0b:\"\"}",
747            "{a b}",
748            "{a b c}",
749            r#"{"a": 1 "b": 2}"#,
750            "{1: 2 3: 4}",
751            "{a: {b: 1 c: 2}}",
752            "{a: [{b: 1 c: 2}]}",
753        ] {
754            let err = Parser::new(input).parse_raw_value().unwrap_err();
755            assert_eq!(err.kind(), ParserErrorKind::UnexpectedToken);
756        }
757    }
758
759    #[test]
760    fn accept_commas_between_and_after_entries() {
761        let ty = Type::record([("red", Type::S32), ("green", Type::CHAR)]).unwrap();
762        for input in [
763            "{red: 0, green: 'a'}",
764            "{red: 0, green: 'a',}",
765            "{ red : 0 , green : 'a' , }",
766            "{red: 0 // c\n, green: 'a'}",
767        ] {
768            Parser::new(input).parse_value::<Value>(&ty).unwrap();
769        }
770        let ty = Type::flags(["read", "write"]).unwrap();
771        for input in [
772            "{read, write}",
773            "{read, write,}",
774            "{ read , write , }",
775            "{read}",
776            "{read,}",
777        ] {
778            Parser::new(input).parse_value::<Value>(&ty).unwrap();
779        }
780    }
781
782    #[test]
783    fn reject_record_unknown_fields() {
784        let ty = Type::record([("red", Type::S32), ("green", Type::CHAR)]).unwrap();
785        for input in [
786            "{red: 0, green: 'a', blue: 1}",
787            "{blue: 1, red: 0, green: 'a'}",
788            // The value of an unknown field is not checked against anything.
789            "{red: 0, green: 'a', blue: 300}",
790            "{red: 0, green: 'a', blue: {x: 1, x: 2}}",
791        ] {
792            let err = Parser::new(input).parse_value::<Value>(&ty).unwrap_err();
793            assert_eq!(err.kind(), ParserErrorKind::InvalidValue);
794        }
795    }
796
797    #[test]
798    fn parse_percent_identifiers() {
799        let ty = Type::record([
800            ("red", Type::S32),
801            ("green", Type::CHAR),
802            ("color-42-2A-5d", Type::BOOL),
803        ])
804        .unwrap();
805        // Test identifiers with '%' prefixes.
806        assert_eq!(
807            parse_value("{ %red: 0, %green: 'a', %color-42-2A-5d: true }", &ty),
808            Value::make_record(
809                &ty,
810                [
811                    ("red", Value::make_s32(0)),
812                    ("green", Value::make_char('a')),
813                    ("color-42-2A-5d", Value::make_bool(true))
814                ]
815            )
816            .unwrap()
817        );
818    }
819
820    #[test]
821    fn parse_prefixed_keyword_variant_cases() {
822        let ty = Type::list(
823            Type::variant([
824                ("true", Some(Type::U8)),
825                ("false", None),
826                ("inf", Some(Type::U8)),
827                ("nan", None),
828                ("some", Some(Type::U8)),
829                ("none", None),
830                ("ok", Some(Type::U8)),
831                ("err", None),
832            ])
833            .unwrap(),
834        );
835        parse_value(
836            "[%true(1), %false, %inf(1), %nan, %some(1), %none, %ok(1), %err]",
837            &ty,
838        );
839    }
840
841    #[test]
842    fn reject_unprefixed_keyword_enum_cases() {
843        let cases = ["true", "false", "inf", "nan", "none", "ok", "err"];
844        let ty = Type::enum_ty(cases).unwrap();
845        for case in cases {
846            let err = Parser::new(case).parse_value::<Value>(&ty).unwrap_err();
847            assert_eq!(err.kind(), ParserErrorKind::InvalidType);
848        }
849    }
850
851    #[test]
852    fn parse_unprefixed_keyword_fields() {
853        let ty = Type::record([
854            ("true", Type::U8),
855            ("false", Type::U8),
856            ("inf", Type::U8),
857            ("nan", Type::U8),
858            ("some", Type::U8),
859            ("none", Type::U8),
860            ("ok", Type::U8),
861            ("err", Type::U8),
862        ])
863        .unwrap();
864        parse_value(
865            "{true: 1, false: 1, inf: 1, nan: 1, some: 1, none: 1, ok: 1, err: 1}",
866            &ty,
867        );
868    }
869
870    #[test]
871    fn parse_unprefixed_keyword_flags() {
872        let ty = Type::flags(["true", "false", "inf", "nan", "some", "none", "ok", "err"]).unwrap();
873        parse_value("{true, false, inf, nan, some, none, ok, err}", &ty);
874    }
875
876    #[test]
877    fn reject_unprefixed_some_variant_case() {
878        let ty = Type::variant([("some", Some(Type::U8))]).unwrap();
879        let err = Parser::new("some(1)")
880            .parse_value::<Value>(&ty)
881            .unwrap_err();
882        assert_eq!(err.kind(), ParserErrorKind::InvalidType);
883    }
884
885    #[test]
886    fn parse_maps() {
887        let ty = Type::map(Type::STRING, Type::U32).unwrap();
888        let entry =
889            |key: &str, value: u32| (Value::make_string(key.into()), Value::make_u32(value));
890        assert_eq!(parse_value("{}", &ty), Value::make_map(&ty, []).unwrap());
891        assert_eq!(
892            parse_value(r#"{"a": 1}"#, &ty),
893            Value::make_map(&ty, [entry("a", 1)]).unwrap()
894        );
895        // Entry order is preserved and trailing commas are permitted.
896        assert_eq!(
897            parse_value(r#"{ "b" : 2, "a": 1, }"#, &ty),
898            Value::make_map(&ty, [entry("b", 2), entry("a", 1)]).unwrap()
899        );
900
901        let ty = Type::map(Type::S8, Type::BOOL).unwrap();
902        assert_eq!(
903            parse_value("{-1: true, 1: false}", &ty),
904            Value::make_map(
905                &ty,
906                [
907                    (Value::make_s8(-1), Value::make_bool(true)),
908                    (Value::make_s8(1), Value::make_bool(false)),
909                ]
910            )
911            .unwrap()
912        );
913
914        // Keyword keys are `bool` keys, not record fields.
915        let ty = Type::map(Type::BOOL, Type::option(Type::BOOL)).unwrap();
916        assert_eq!(
917            parse_value("{true: none, false: some(false)}", &ty),
918            Value::make_map(
919                &ty,
920                [
921                    (
922                        Value::make_bool(true),
923                        Value::make_option(&Type::option(Type::BOOL), None).unwrap()
924                    ),
925                    (
926                        Value::make_bool(false),
927                        Value::make_option(
928                            &Type::option(Type::BOOL),
929                            Some(Value::make_bool(false))
930                        )
931                        .unwrap()
932                    ),
933                ]
934            )
935            .unwrap()
936        );
937    }
938
939    #[test]
940    fn reject_invalid_maps() {
941        let ty = Type::map(Type::STRING, Type::U32).unwrap();
942        for (input, kind) in [
943            // Wrong key type
944            ("{1: 1}", ParserErrorKind::InvalidType),
945            ("{'a': 1}", ParserErrorKind::InvalidType),
946            ("{a: 1}", ParserErrorKind::InvalidType),
947            // Wrong value type
948            (r#"{"a": "b"}"#, ParserErrorKind::InvalidType),
949            // Lists and flags are not maps
950            ("[]", ParserErrorKind::InvalidType),
951            (r#"[("a", 1)]"#, ParserErrorKind::InvalidType),
952            ("{a}", ParserErrorKind::InvalidType),
953            // Mixed flags and map entries
954            (r#"{"a"}"#, ParserErrorKind::UnexpectedToken),
955            (r#"{"a": 1, b}"#, ParserErrorKind::UnexpectedToken),
956            (r#"{a, "b": 1}"#, ParserErrorKind::UnexpectedToken),
957            // Missing key or value
958            (r#"{"a":}"#, ParserErrorKind::UnexpectedToken),
959            ("{: 1}", ParserErrorKind::UnexpectedToken),
960            (r#"{"a": 1: 2}"#, ParserErrorKind::UnexpectedToken),
961        ] {
962            let err = Parser::new(input).parse_value::<Value>(&ty).unwrap_err();
963            assert_eq!(err.kind(), kind, "for {input:?}: {err}");
964        }
965
966        // Map keys are not record fields
967        let ty = Type::record([("a", Type::U32)]).unwrap();
968        let err = Parser::new(r#"{"a": 1}"#)
969            .parse_value::<Value>(&ty)
970            .unwrap_err();
971        assert_eq!(err.kind(), ParserErrorKind::InvalidType);
972    }
973
974    #[test]
975    fn reject_deeply_nested_values() {
976        let deep = MAX_DEPTH + 1;
977        let cases = [
978            ("[".repeat(deep) + &"]".repeat(deep), "nested lists"),
979            ("(".repeat(deep) + "0" + &")".repeat(deep), "nested tuples"),
980            (
981                "some(".repeat(deep) + "0" + &")".repeat(deep),
982                "nested some()",
983            ),
984            ("ok(".repeat(deep) + "0" + &")".repeat(deep), "nested ok()"),
985            (
986                "{a:".repeat(deep) + "0" + &"}".repeat(deep),
987                "nested records",
988            ),
989            (
990                "v(".repeat(deep) + "0" + &")".repeat(deep),
991                "nested variant payloads",
992            ),
993        ];
994        for (input, desc) in cases {
995            let err = UntypedValue::parse(&input)
996                .expect_err(&alloc::format!("{desc} should be rejected"));
997            assert_eq!(
998                err.kind(),
999                ParserErrorKind::NestingTooDeep,
1000                "wrong error kind for {desc}"
1001            );
1002        }
1003    }
1004
1005    #[test]
1006    fn reject_deeply_nested_func_call_params() {
1007        let deep = MAX_DEPTH + 1;
1008        let input = alloc::format!("f({}0{})", "some(".repeat(deep), ")".repeat(deep));
1009        let err = match UntypedFuncCall::parse(&input) {
1010            Ok(_) => panic!("deeply nested func call params should be rejected"),
1011            Err(err) => err,
1012        };
1013        assert_eq!(err.kind(), ParserErrorKind::NestingTooDeep);
1014    }
1015
1016    fn parse_value(input: &str, ty: &Type) -> Value {
1017        Parser::new(input)
1018            .parse_value(ty)
1019            .unwrap_or_else(|err| panic!("error decoding {input:?}: {err}"))
1020    }
1021}