Skip to main content

px_wsdom_ts_parse/parser/
field.rs

1use winnow::{
2    combinator::{alt, delimited, opt, separated_pair},
3    PResult, Parser,
4};
5
6use super::{
7    ts_type::TsType,
8    util::{quote_backslash_escape, token, token_word, word1, Parsable},
9};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Field<'a> {
13    pub name: FieldName<'a>,
14    pub readonly: bool,
15    pub optional: bool,
16    pub ty: TsType<'a>,
17}
18impl<'a> Parsable<'a> for Field<'a> {
19    fn parse(input: &mut &'a str) -> PResult<Self> {
20        separated_pair(
21            (
22                opt(token_word("readonly")),
23                FieldName::parse,
24                opt(token('?')),
25            ),
26            token(':'),
27            TsType::parse,
28        )
29        .parse_next(input)
30        .map(|((readonly, name, optional), ty)| Self {
31            readonly: readonly.is_some(),
32            name,
33            optional: optional.is_some(),
34            ty,
35        })
36    }
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum FieldName<'a> {
41    Name(&'a str),
42    Wildcard { name: &'a str, ty: TsType<'a> },
43}
44impl<'a> Parsable<'a> for FieldName<'a> {
45    fn parse(input: &mut &'a str) -> PResult<Self> {
46        alt((
47            word1.map(Self::Name),
48            quote_backslash_escape('"').map(Self::Name),
49            delimited(
50                token('['),
51                separated_pair(word1, token(':'), TsType::parse),
52                token(']'),
53            )
54            .map(|(name, ty)| Self::Wildcard { name, ty }),
55        ))
56        .parse_next(input)
57    }
58}