1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use crate::common::FilePosition;
use crate::idl::common::Span;
use crate::idl::errors::ParseError;
use crate::idl::namespace::{parse_namespace_content, Namespace};

#[derive(Debug, PartialEq)]
pub struct Document {
    pub ns: Namespace,
}

pub fn parse_document(input: &str) -> Result<Document, ParseError> {
    let span = Span::new(input);
    let result = parse_namespace_content(span);
    match result {
        Ok((span, parts)) if span.fragment() == &"" => Ok(Document {
            ns: Namespace {
                name: String::default(),
                position: FilePosition { line: 1, column: 1 },
                parts,
            },
        }),
        Ok((garbage, _)) => Err(ParseError::TrailingGarbage(garbage)),
        Err(error) => Err(ParseError::Nom(error)),
    }
}

#[test]
fn test_parse_document() {
    use crate::idl::field_option::FieldOption;
    use crate::idl::method::Method;
    use crate::idl::namespace::{Namespace, NamespacePart};
    use crate::idl::r#struct::{Field, Struct};
    use crate::idl::r#type::{Type, TypeRef};
    use crate::idl::service::Service;
    use crate::idl::value::Value;
    let content = "
        struct Person {
            name: String (length=1..50),
            age: Integer,
        }
        struct Group {
            name: String,
        }
        service Pinger {
            ping: None -> None,
            get_version: None -> String,
        }
    ";
    assert_eq!(
        parse_document(content),
        Ok(Document {
            ns: Namespace {
                name: "".to_string(),
                position: FilePosition { line: 1, column: 1 },
                parts: vec![
                    NamespacePart::Struct(Struct {
                        name: "Person".to_string(),
                        position: FilePosition { line: 2, column: 9 },
                        generics: vec![],
                        fields: vec![
                            Field {
                                name: "name".to_string(),
                                position: FilePosition {
                                    line: 3,
                                    column: 13
                                },
                                type_: Type::Ref(TypeRef {
                                    abs: false,
                                    ns: vec![],
                                    name: "String".to_string(),
                                    generics: vec![]
                                }),
                                optional: false,
                                options: vec![FieldOption {
                                    name: "length".to_string(),
                                    value: Value::Range(Some(1), Some(50))
                                }],
                            },
                            Field {
                                name: "age".to_string(),
                                position: FilePosition {
                                    line: 4,
                                    column: 13
                                },
                                type_: Type::Ref(TypeRef {
                                    abs: false,
                                    name: "Integer".to_string(),
                                    ns: vec![],
                                    generics: vec![],
                                }),
                                optional: false,
                                options: vec![],
                            },
                        ],
                    }),
                    NamespacePart::Struct(Struct {
                        name: "Group".to_string(),
                        position: FilePosition { line: 6, column: 9 },
                        generics: vec![],
                        fields: vec![Field {
                            name: "name".to_string(),
                            position: FilePosition {
                                line: 7,
                                column: 13
                            },
                            type_: Type::Ref(TypeRef {
                                abs: false,
                                name: "String".to_string(),
                                ns: vec![],
                                generics: vec![]
                            }),
                            optional: false,
                            options: vec![],
                        }],
                    }),
                    NamespacePart::Service(Service {
                        name: "Pinger".to_string(),
                        position: FilePosition { line: 9, column: 9 },
                        methods: vec![
                            Method {
                                name: "ping".to_string(),
                                input: None,
                                output: None,
                            },
                            Method {
                                name: "get_version".to_string(),
                                input: None,
                                output: Some(Type::Ref(TypeRef {
                                    abs: false,
                                    ns: vec![],
                                    name: "String".to_string(),
                                    generics: vec![]
                                })),
                            },
                        ],
                    }),
                ],
            },
        })
    )
}