protoql/
parser.rs

1use std::fmt::{Formatter, Write};
2
3use nom::{
4    branch::alt,
5    bytes::complete::{escaped, tag},
6    character::complete::{
7        self as character, alpha1, alphanumeric1, digit1, multispace0, multispace1, none_of, one_of,
8    },
9    combinator::{all_consuming, cut, map, map_res, opt, recognize},
10    error::{context, VerboseError, VerboseErrorKind},
11    multi::{many0, many0_count, separated_list0, separated_list1},
12    sequence::{delimited, pair, terminated, tuple},
13    IResult, Offset,
14};
15
16use prototk::FieldNumber;
17use zerror_core::ErrorCore;
18
19use crate::{
20    DataType, Direction, Error, Field, FieldDefinition, Identifier, Join, Key, KeyDataType,
21    KeyLiteral, Map, Object, Query, QueryFilter, Table, TableSet,
22};
23
24////////////////////////////////////////// error handling //////////////////////////////////////////
25
26type ParseResult<'a, T> = IResult<&'a str, T, VerboseError<&'a str>>;
27
28#[derive(Clone, Eq, PartialEq)]
29pub struct ParseError {
30    string: String,
31}
32
33impl std::fmt::Debug for ParseError {
34    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
35        writeln!(fmt, "{}", self.string)
36    }
37}
38
39impl std::fmt::Display for ParseError {
40    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
41        writeln!(fmt, "{}", self.string)
42    }
43}
44
45impl From<String> for ParseError {
46    fn from(string: String) -> Self {
47        Self { string }
48    }
49}
50
51pub fn interpret_verbose_error(input: &'_ str, err: VerboseError<&'_ str>) -> ParseError {
52    let mut result = String::new();
53    let mut index = 0;
54    for (substring, kind) in err.errors.iter() {
55        let offset = input.offset(substring);
56        let prefix = &input.as_bytes()[..offset];
57        // Count the number of newlines in the first `offset` bytes of input
58        let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1;
59        // Find the line that includes the subslice:
60        // Find the *last* newline before the substring starts
61        let line_begin = prefix
62            .iter()
63            .rev()
64            .position(|&b| b == b'\n')
65            .map(|pos| offset - pos)
66            .unwrap_or(0);
67        // Find the full line after that newline
68        let line = input[line_begin..]
69            .lines()
70            .next()
71            .unwrap_or(&input[line_begin..])
72            .trim_end();
73        // The (1-indexed) column number is the offset of our substring into that line
74        let column_number = line.offset(substring) + 1;
75        match kind {
76            VerboseErrorKind::Char(c) => {
77                if let Some(actual) = substring.chars().next() {
78                    write!(
79                        &mut result,
80                        "{index}: at line {line_number}:\n\
81                 {line}\n\
82                 {caret:>column$}\n\
83                 expected '{expected}', found {actual}\n\n",
84                        index = index,
85                        line_number = line_number,
86                        line = line,
87                        caret = '^',
88                        column = column_number,
89                        expected = c,
90                        actual = actual,
91                    )
92                    .unwrap();
93                } else {
94                    write!(
95                        &mut result,
96                        "{index}: at line {line_number}:\n\
97                 {line}\n\
98                 {caret:>column$}\n\
99                 expected '{expected}', got end of input\n\n",
100                        index = index,
101                        line_number = line_number,
102                        line = line,
103                        caret = '^',
104                        column = column_number,
105                        expected = c,
106                    )
107                    .unwrap();
108                }
109                index += 1;
110            }
111            VerboseErrorKind::Context(s) => {
112                write!(
113                    &mut result,
114                    "{index}: at line {line_number}, in {context}:\n\
115               {line}\n\
116               {caret:>column$}\n\n",
117                    index = index,
118                    line_number = line_number,
119                    context = s,
120                    line = line,
121                    caret = '^',
122                    column = column_number,
123                )
124                .unwrap();
125                index += 1;
126            }
127            // Swallow these.   They are ugly.
128            VerboseErrorKind::Nom(_) => {}
129        };
130    }
131    ParseError {
132        string: result.trim().to_string(),
133    }
134}
135
136///////////////////////////////////////////// TableSet /////////////////////////////////////////////
137
138pub fn identifier(input: &str) -> ParseResult<Identifier> {
139    context(
140        "identifier",
141        map(
142            recognize(pair(
143                alt((alpha1, tag("_"))),
144                many0_count(alt((alphanumeric1, tag("_")))),
145            )),
146            |ident: &str| Identifier {
147                ident: ident.to_string(),
148            },
149        ),
150    )(input)
151}
152
153pub fn identifier_list(input: &str) -> ParseResult<Vec<Identifier>> {
154    context(
155        "identifier list",
156        terminated(
157            separated_list1(
158                tag(","),
159                map(tuple((ws0, identifier, ws0)), |(_, ident, _)| ident),
160            ),
161            opt(tag(",")),
162        ),
163    )(input)
164}
165
166pub fn key_data_type(input: &str) -> ParseResult<KeyDataType> {
167    let (input, recognized) = context(
168        "key data type",
169        alt((
170            tag("unit"),
171            tag("fixed32"),
172            tag("fixed64"),
173            tag("sfixed32"),
174            tag("sfixed64"),
175            tag("string"),
176        )),
177    )(input)?;
178    Ok((
179        input,
180        match recognized {
181            "unit" => KeyDataType::unit,
182            "fixed32" => KeyDataType::fixed32,
183            "fixed64" => KeyDataType::fixed64,
184            "sfixed32" => KeyDataType::sfixed32,
185            "sfixed64" => KeyDataType::sfixed64,
186            "string" => KeyDataType::string,
187            _ => {
188                panic!("logic error");
189            }
190        },
191    ))
192}
193
194pub fn data_type(input: &str) -> ParseResult<DataType> {
195    let (input, recognized) = context(
196        "data type",
197        alt((
198            tag("unit"),
199            tag("int32"),
200            tag("int64"),
201            tag("uint32"),
202            tag("uint64"),
203            tag("sint32"),
204            tag("sint64"),
205            tag("fixed32"),
206            tag("fixed64"),
207            tag("sfixed32"),
208            tag("sfixed64"),
209            tag("timestamp_micros"),
210            tag("float"),
211            tag("double"),
212            tag("bool"),
213            tag("bytes16"),
214            tag("bytes32"),
215            tag("bytes64"),
216            tag("bytes"),
217            tag("string"),
218            tag("message"),
219        )),
220    )(input)?;
221    Ok((
222        input,
223        match recognized {
224            "unit" => DataType::unit,
225            "int32" => DataType::int32,
226            "int64" => DataType::int64,
227            "uint32" => DataType::uint32,
228            "uint64" => DataType::uint64,
229            "sint32" => DataType::sint32,
230            "sint64" => DataType::sint64,
231            "fixed32" => DataType::fixed32,
232            "fixed64" => DataType::fixed64,
233            "sfixed32" => DataType::sfixed32,
234            "sfixed64" => DataType::sfixed64,
235            "timestamp_micros" => DataType::timestamp_micros,
236            "float" => DataType::float,
237            "double" => DataType::double,
238            "bool" => DataType::Bool,
239            "bytes" => DataType::bytes,
240            "bytes16" => DataType::bytes16,
241            "bytes32" => DataType::bytes32,
242            "bytes64" => DataType::bytes64,
243            "string" => DataType::string,
244            "message" => DataType::message,
245            _ => {
246                panic!("logic error");
247            }
248        },
249    ))
250}
251
252pub fn field_number(input: &str) -> ParseResult<FieldNumber> {
253    context("field number", map_res(character::u32, FieldNumber::new))(input)
254}
255
256pub fn key(input: &str) -> ParseResult<Key> {
257    context(
258        "key type",
259        map_res(
260            tuple((
261                ws0,
262                key_data_type,
263                ws1,
264                identifier,
265                ws0,
266                tag("="),
267                ws0,
268                field_number,
269            )),
270            |(_, ty, _, ident, _, _, _, number)| Key::new(ident, number, ty, Direction::Forward),
271        ),
272    )(input)
273}
274
275pub fn field(input: &str) -> ParseResult<Field> {
276    context(
277        "field type",
278        alt((
279            map_res(
280                tuple((
281                    ws0,
282                    context("breakout", tag("breakout")),
283                    ws1,
284                    cut(data_type),
285                    ws1,
286                    identifier,
287                    ws0,
288                    tag("="),
289                    ws0,
290                    field_number,
291                )),
292                |(_, _, _, ty, _, ident, _, _, _, number)| Field::new(ident, number, ty, true),
293            ),
294            map_res(
295                tuple((
296                    ws0,
297                    data_type,
298                    ws1,
299                    identifier,
300                    ws0,
301                    tag("="),
302                    ws0,
303                    field_number,
304                )),
305                |(_, ty, _, ident, _, _, _, number)| Field::new(ident, number, ty, false),
306            ),
307        )),
308    )(input)
309}
310
311pub fn object(input: &str) -> ParseResult<Object> {
312    context(
313        "object type",
314        map_res(
315            tuple((
316                ws0,
317                tag("object"),
318                cut(ws1),
319                cut(identifier),
320                cut(ws0),
321                cut(tag("=")),
322                cut(ws0),
323                cut(field_number),
324                cut(ws0),
325                cut(tag("{")),
326                cut(ws0),
327                cut(table_field_list),
328                cut(ws0),
329                cut(tag("}")),
330            )),
331            |(_, _, _, ident, _, _, _, number, _, _, _, fields, _, _)| {
332                Object::new(ident, number, fields)
333            },
334        ),
335    )(input)
336}
337
338pub fn map_field(input: &str) -> ParseResult<Map> {
339    context(
340        "map type",
341        map_res(
342            tuple((
343                ws0,
344                tag("map"),
345                cut(ws1),
346                cut(key),
347                cut(ws0),
348                cut(tag("{")),
349                cut(ws0),
350                cut(table_field_list),
351                cut(ws0),
352                cut(tag("}")),
353            )),
354            |(_, _, _, key, _, _, _, fields, _, _)| Map::new(key, fields),
355        ),
356    )(input)
357}
358
359pub fn join(input: &str) -> ParseResult<Join> {
360    context(
361        "join field",
362        map_res(
363            tuple((
364                ws0,
365                tag("join"),
366                cut(ws1),
367                cut(identifier),
368                cut(ws0),
369                cut(tag("=")),
370                cut(ws0),
371                cut(field_number),
372                cut(ws1),
373                cut(tag("on")),
374                cut(ws1),
375                cut(identifier),
376                cut(ws0),
377                cut(tag("(")),
378                cut(ws0),
379                cut(identifier_list),
380                cut(ws0),
381                cut(tag(")")),
382            )),
383            |(_, _, _, key, _, _, _, number, _, _, _, table, _, _, _, idents, _, _)| {
384                Join::new(key, number, table, idents)
385            },
386        ),
387    )(input)
388}
389
390pub fn field_definition(input: &str) -> ParseResult<FieldDefinition> {
391    context(
392        "field definition",
393        alt((
394            map(field, FieldDefinition::Field),
395            map(object, FieldDefinition::Object),
396            map(map_field, FieldDefinition::Map),
397            map(join, FieldDefinition::Join),
398        )),
399    )(input)
400}
401
402pub fn key_field_list(input: &str) -> ParseResult<Vec<Key>> {
403    context(
404        "key fields",
405        terminated(
406            separated_list0(
407                tag(","),
408                map_res(
409                    tuple((
410                        ws0,
411                        key_data_type,
412                        cut(ws1),
413                        cut(identifier),
414                        cut(ws0),
415                        cut(tag("=")),
416                        cut(ws0),
417                        cut(field_number),
418                    )),
419                    |(_, ty, _, ident, _, _, _, number)| {
420                        Key::new(ident, number, ty, Direction::Forward)
421                    },
422                ),
423            ),
424            opt(tag(",")),
425        ),
426    )(input)
427}
428
429pub fn table_field_list(input: &str) -> ParseResult<Vec<FieldDefinition>> {
430    context(
431        "fields",
432        map(
433            many0(tuple((ws0, field_definition, ws0, tag(";")))),
434            |fmjs: Vec<((), FieldDefinition, (), &str)>| {
435                fmjs.into_iter().map(|f| f.1).collect::<Vec<_>>()
436            },
437        ),
438    )(input)
439}
440
441pub fn table(input: &str) -> ParseResult<Table> {
442    context(
443        "table definition",
444        map_res(
445            tuple((
446                ws0,
447                context("table keyword", tag("table")),
448                cut(ws1),
449                context("table identifier", cut(identifier)),
450                cut(ws0),
451                cut(tag("(")),
452                cut(ws0),
453                cut(key_field_list),
454                cut(ws0),
455                cut(tag(")")),
456                cut(ws0),
457                cut(tag("@")),
458                cut(ws0),
459                context("table number", cut(field_number)),
460                cut(ws0),
461                context("opening brace", cut(tag("{"))),
462                cut(ws0),
463                context("table body", cut(table_field_list)),
464                cut(ws0),
465                context("closing brace", cut(tag("}"))),
466                cut(ws0),
467            )),
468            |(_, _, _, ident, _, _, _, key, _, _, _, _, _, number, _, _, _, fields, _, _, _)| {
469                Table::new(ident, number, key, fields)
470            },
471        ),
472    )(input)
473}
474
475pub fn table_set(input: &str) -> ParseResult<TableSet> {
476    context(
477        "table set",
478        map_res(
479            many0(alt((map(tuple((ws0, table, ws0)), |(_, t, _)| t),))),
480            TableSet::new,
481        ),
482    )(input)
483}
484
485/////////////////////////////////////////////// Query //////////////////////////////////////////////
486
487pub fn unescape(input: &str) -> String {
488    let mut out: Vec<char> = Vec::new();
489    let mut prev_was_escape = false;
490    for c in input.chars() {
491        if prev_was_escape && (c == '\"' || c == '\\') {
492            out.push(c);
493            prev_was_escape = false;
494        } else if c == '\\' {
495            prev_was_escape = true;
496        } else {
497            out.push(c);
498        }
499    }
500    out.into_iter().collect()
501}
502
503pub fn string_literal(input: &str) -> ParseResult<KeyLiteral> {
504    context(
505        "string literal",
506        map(
507            delimited(
508                tag("\""),
509                cut(alt((
510                    escaped(none_of(r#"\""#), '\\', one_of(r#"\""#)),
511                    tag(""),
512                ))),
513                tag("\""),
514            ),
515            |x: &str| KeyLiteral::string { value: unescape(x) },
516        ),
517    )(input)
518}
519
520fn number_to_typed(input: &str) -> Result<KeyLiteral, Error> {
521    if let Ok(x) = str::parse::<i32>(input) {
522        Ok(KeyLiteral::sfixed32 { value: x })
523    } else if let Ok(x) = str::parse::<u32>(input) {
524        Ok(KeyLiteral::fixed32 { value: x })
525    } else if let Ok(x) = str::parse::<i64>(input) {
526        Ok(KeyLiteral::sfixed64 { value: x })
527    } else if let Ok(x) = str::parse::<u64>(input) {
528        Ok(KeyLiteral::fixed64 { value: x })
529    } else {
530        Err(Error::InvalidNumberLiteral {
531            core: ErrorCore::default(),
532            as_str: input.to_string(),
533        })
534    }
535}
536
537pub fn number_literal(input: &str) -> ParseResult<KeyLiteral> {
538    context(
539        "number literal",
540        map_res(recognize(tuple((opt(tag("-")), digit1))), number_to_typed),
541    )(input)
542}
543
544pub fn query_exprs(input: &str) -> ParseResult<Vec<Query>> {
545    context(
546        "query expression",
547        terminated(separated_list0(tag(","), map(query, |x| x)), opt(tag(","))),
548    )(input)
549}
550
551pub fn query_filter(input: &str) -> ParseResult<QueryFilter> {
552    context(
553        "query filter",
554        alt((
555            map(tuple((ws0, number_literal)), |(_, x)| {
556                QueryFilter::Equals(x)
557            }),
558            map(tuple((ws0, string_literal)), |(_, x)| {
559                QueryFilter::Equals(x)
560            }),
561        )),
562    )(input)
563}
564
565pub fn query(input: &str) -> ParseResult<Query> {
566    context(
567        "query",
568        alt((
569            map_res(
570                tuple((
571                    ws0,
572                    identifier,
573                    ws0,
574                    tag("["),
575                    cut(ws0),
576                    cut(query_filter),
577                    ws0,
578                    tag("]"),
579                    ws0,
580                    tag("{"),
581                    ws0,
582                    cut(query_exprs),
583                    ws0,
584                    tag("}"),
585                    ws0,
586                )),
587                |(_, ident, _, _, _, filter, _, _, __, _, _, exprs, _, _, _)| {
588                    Query::from_filter_and_exprs(ident, filter, exprs)
589                },
590            ),
591            map_res(
592                tuple((
593                    ws0,
594                    identifier,
595                    ws0,
596                    tag("{"),
597                    cut(ws0),
598                    cut(query_exprs),
599                    ws0,
600                    tag("}"),
601                    ws0,
602                )),
603                |(_, ident, _, _, _, exprs, _, _, _)| Query::from_exprs(ident, exprs),
604            ),
605            map_res(tuple((ws0, identifier, ws0)), |(_, ident, _)| {
606                Query::new(ident)
607            }),
608        )),
609    )(input)
610}
611
612///////////////////////////////////////////// parse_all ////////////////////////////////////////////
613
614pub fn parse_all<T, F: Fn(&str) -> ParseResult<T> + Copy>(
615    f: F,
616) -> impl Fn(&str) -> Result<T, ParseError> {
617    move |input| {
618        let (rem, t) = match all_consuming(f)(input) {
619            Ok((rem, t)) => (rem, t),
620            Err(err) => match err {
621                nom::Err::Incomplete(_) => {
622                    panic!("all_consuming combinator should be all consuming");
623                }
624                nom::Err::Error(err) | nom::Err::Failure(err) => {
625                    return Err(interpret_verbose_error(input, err));
626                }
627            },
628        };
629        if rem.is_empty() {
630            Ok(t)
631        } else {
632            panic!("all_consuming combinator should be all consuming");
633        }
634    }
635}
636
637////////////////////////////////////////////// private /////////////////////////////////////////////
638
639fn ws0(input: &str) -> ParseResult<()> {
640    map(multispace0, |_| ())(input)
641}
642
643fn ws1(input: &str) -> ParseResult<()> {
644    map(multispace1, |_| ())(input)
645}
646
647/////////////////////////////////////////////// tests //////////////////////////////////////////////
648
649#[cfg(test)]
650mod test {
651    use nom::combinator::{complete, cut};
652
653    use super::*;
654
655    fn parse_error(s: &'static str) -> ParseError {
656        ParseError {
657            string: s.to_string(),
658        }
659    }
660
661    fn interpret_error_for_test<'a, T, F: FnMut(&'a str) -> ParseResult<'a, T>>(
662        mut f: F,
663    ) -> impl FnMut(&'a str) -> Result<T, ParseError> {
664        move |input| match f(input) {
665            Ok((_, t)) => Ok(t),
666            Err(err) => match err {
667                nom::Err::Error(err) | nom::Err::Failure(err) => {
668                    Err(interpret_verbose_error(input, err))
669                }
670                nom::Err::Incomplete(_) => {
671                    panic!("incomplete should never happen in tests");
672                }
673            },
674        }
675    }
676
677    #[test]
678    fn identifier9() {
679        assert_eq!(
680            Identifier::must("__identifier9"),
681            parse_all(identifier)("__identifier9").unwrap(),
682        );
683    }
684
685    #[test]
686    fn identifier_empty() {
687        assert_eq!(
688            parse_error(
689                r#"0: at line 1, in identifier:
690
691^"#
692            ),
693            interpret_error_for_test(cut(complete(all_consuming(identifier))))("").unwrap_err()
694        );
695    }
696
697    #[test]
698    fn identifier_dashes() {
699        assert_eq!(
700            parse_error(
701                r#"0: at line 1, in identifier:
702-not-identifier
703^"#
704            ),
705            interpret_error_for_test(cut(complete(all_consuming(identifier))))("-not-identifier")
706                .unwrap_err()
707        );
708    }
709
710    #[test]
711    fn identifier_starts_with_number() {
712        assert_eq!(
713            parse_error(
714                r#"0: at line 1, in identifier:
7159identifier__
716^"#
717            ),
718            interpret_error_for_test(cut(complete(all_consuming(identifier))))("9identifier__")
719                .unwrap_err()
720        );
721    }
722
723    #[test]
724    fn all_data_type() {
725        assert_eq!(
726            DataType::unit,
727            interpret_error_for_test(cut(complete(all_consuming(data_type))))("unit").unwrap()
728        );
729        assert_eq!(
730            DataType::int32,
731            interpret_error_for_test(cut(complete(all_consuming(data_type))))("int32").unwrap()
732        );
733        assert_eq!(
734            DataType::int64,
735            interpret_error_for_test(cut(complete(all_consuming(data_type))))("int64").unwrap()
736        );
737        assert_eq!(
738            DataType::uint32,
739            interpret_error_for_test(cut(complete(all_consuming(data_type))))("uint32").unwrap()
740        );
741        assert_eq!(
742            DataType::uint64,
743            interpret_error_for_test(cut(complete(all_consuming(data_type))))("uint64").unwrap()
744        );
745        assert_eq!(
746            DataType::sint32,
747            interpret_error_for_test(cut(complete(all_consuming(data_type))))("sint32").unwrap()
748        );
749        assert_eq!(
750            DataType::sint64,
751            interpret_error_for_test(cut(complete(all_consuming(data_type))))("sint64").unwrap()
752        );
753        assert_eq!(
754            DataType::fixed32,
755            interpret_error_for_test(cut(complete(all_consuming(data_type))))("fixed32").unwrap()
756        );
757        assert_eq!(
758            DataType::fixed64,
759            interpret_error_for_test(cut(complete(all_consuming(data_type))))("fixed64").unwrap()
760        );
761        assert_eq!(
762            DataType::sfixed32,
763            interpret_error_for_test(cut(complete(all_consuming(data_type))))("sfixed32").unwrap()
764        );
765        assert_eq!(
766            DataType::sfixed64,
767            interpret_error_for_test(cut(complete(all_consuming(data_type))))("sfixed64").unwrap()
768        );
769        assert_eq!(
770            DataType::float,
771            interpret_error_for_test(cut(complete(all_consuming(data_type))))("float").unwrap()
772        );
773        assert_eq!(
774            DataType::double,
775            interpret_error_for_test(cut(complete(all_consuming(data_type))))("double").unwrap()
776        );
777        assert_eq!(
778            DataType::Bool,
779            interpret_error_for_test(cut(complete(all_consuming(data_type))))("bool").unwrap()
780        );
781        assert_eq!(
782            DataType::bytes,
783            interpret_error_for_test(cut(complete(all_consuming(data_type))))("bytes").unwrap()
784        );
785        assert_eq!(
786            DataType::bytes16,
787            interpret_error_for_test(cut(complete(all_consuming(data_type))))("bytes16").unwrap()
788        );
789        assert_eq!(
790            DataType::bytes32,
791            interpret_error_for_test(cut(complete(all_consuming(data_type))))("bytes32").unwrap()
792        );
793        assert_eq!(
794            DataType::bytes64,
795            interpret_error_for_test(cut(complete(all_consuming(data_type))))("bytes64").unwrap()
796        );
797        assert_eq!(
798            DataType::string,
799            interpret_error_for_test(cut(complete(all_consuming(data_type))))("string").unwrap()
800        );
801        assert_eq!(
802            DataType::message,
803            interpret_error_for_test(cut(complete(all_consuming(data_type))))("message").unwrap()
804        );
805    }
806
807    #[test]
808    fn bad_data_type() {
809        assert_eq!(
810            parse_error(
811                r#"0: at line 1, in field number:
812notatype
813^"#
814            ),
815            interpret_error_for_test(cut(complete(all_consuming(field_number))))("notatype")
816                .unwrap_err()
817        );
818    }
819
820    #[test]
821    fn field_number1() {
822        assert_eq!(
823            FieldNumber::must(1),
824            interpret_error_for_test(cut(complete(all_consuming(field_number))))("1").unwrap()
825        );
826    }
827
828    #[test]
829    fn field_number42() {
830        assert_eq!(
831            FieldNumber::must(42),
832            interpret_error_for_test(cut(complete(all_consuming(field_number))))("42").unwrap()
833        );
834    }
835
836    #[test]
837    fn field_number_invalid() {
838        assert_eq!(
839            parse_error(
840                r#"0: at line 1, in field number:
84119000
842^"#
843            ),
844            interpret_error_for_test(cut(complete(all_consuming(field_number))))("19000")
845                .unwrap_err()
846        );
847    }
848
849    #[test]
850    fn field_bytes32_identifier9_42() {
851        assert_eq!(
852            Field {
853                ident: Identifier::must("__identifier9"),
854                number: FieldNumber::must(42),
855                ty: DataType::bytes32,
856                breakout: false,
857            },
858            parse_all(field)("bytes32 __identifier9 = 42").unwrap(),
859        );
860    }
861
862    #[test]
863    fn field_breakout_bytes32_identifier9_42() {
864        assert_eq!(
865            Field {
866                ident: Identifier::must("__identifier9"),
867                number: FieldNumber::must(42),
868                ty: DataType::bytes32,
869                breakout: true,
870            },
871            interpret_error_for_test(cut(complete(all_consuming(field))))(
872                "breakout bytes32 __identifier9 = 42"
873            )
874            .unwrap(),
875        );
876    }
877
878    #[test]
879    fn field_keyword_bytes32_identifier9_42() {
880        assert_eq!(
881            parse_error(
882                r#"0: at line 1, in data type:
883keyword bytes32 __identifier9 = 42
884^
885
8861: at line 1, in field type:
887keyword bytes32 __identifier9 = 42
888^"#
889            ),
890            interpret_error_for_test(cut(complete(all_consuming(field))))(
891                "keyword bytes32 __identifier9 = 42"
892            )
893            .unwrap_err(),
894        );
895    }
896
897    #[test]
898    fn object_identifer9_42() {
899        assert_eq!(
900            Object::new(
901                Identifier::must("__identifier9"),
902                FieldNumber::must(42),
903                vec![]
904            )
905            .unwrap(),
906            interpret_error_for_test(cut(complete(all_consuming(object))))(
907                "object __identifier9 = 42 {}"
908            )
909            .unwrap(),
910        );
911    }
912
913    #[test]
914    fn object_identifer9_42_whitespace() {
915        assert_eq!(
916            Object::new(
917                Identifier::must("__identifier9"),
918                FieldNumber::must(42),
919                vec![]
920            )
921            .unwrap(),
922            interpret_error_for_test(cut(complete(all_consuming(object))))(
923                "
924                                                                           object
925                                                                           __identifier9
926                                                                           =
927                                                                           42
928                                                                           {
929                                                                           }"
930            )
931            .unwrap(),
932        );
933    }
934
935    #[test]
936    fn object_identifer9_42_minimal_whitespace() {
937        assert_eq!(
938            Object::new(
939                Identifier::must("__identifier9"),
940                FieldNumber::must(42),
941                vec![]
942            )
943            .unwrap(),
944            interpret_error_for_test(cut(complete(all_consuming(object))))(
945                "object __identifier9=42{}"
946            )
947            .unwrap(),
948        );
949    }
950
951    #[test]
952    fn object_identifer9_42_with_field() {
953        assert_eq!(
954            Object::new(
955                Identifier::must("__identifier9"),
956                FieldNumber::must(42),
957                vec![FieldDefinition::Field(Field {
958                    ident: Identifier::must("field"),
959                    number: FieldNumber::must(1),
960                    ty: DataType::string,
961                    breakout: false
962                }),],
963            )
964            .unwrap(),
965            interpret_error_for_test(cut(complete(all_consuming(object))))(
966                "object __identifier9 = 42 {
967                    string field = 1;
968                }"
969            )
970            .unwrap(),
971        );
972    }
973
974    #[test]
975    fn object_identifer9_42_missing_field_number() {
976        assert_eq!(
977            parse_error(
978                r#"0: at line 1, in object type:
979object __identifier9 {}
980^"#
981            ),
982            interpret_error_for_test(cut(complete(all_consuming(object))))(
983                "object __identifier9 {}"
984            )
985            .unwrap_err(),
986        );
987    }
988
989    #[test]
990    fn map_string_identifer9_42() {
991        assert_eq!(
992            Map::new(
993                Key::new(
994                    Identifier::must("__identifier9"),
995                    FieldNumber::must(42),
996                    KeyDataType::string,
997                    Direction::Forward,
998                )
999                .unwrap(),
1000                vec![]
1001            )
1002            .unwrap(),
1003            interpret_error_for_test(cut(complete(all_consuming(map_field))))(
1004                "map string __identifier9 = 42 {}"
1005            )
1006            .unwrap(),
1007        );
1008    }
1009
1010    #[test]
1011    fn map_missing_datatype_identifer9_42() {
1012        assert_eq!(
1013            parse_error(
1014                r#"0: at line 1, in key data type:
1015map __identifier9 = 42 {}
1016    ^
1017
10181: at line 1, in key type:
1019map __identifier9 = 42 {}
1020    ^
1021
10222: at line 1, in map type:
1023map __identifier9 = 42 {}
1024^"#
1025            ),
1026            interpret_error_for_test(cut(complete(all_consuming(map_field))))(
1027                "map __identifier9 = 42 {}"
1028            )
1029            .unwrap_err(),
1030        );
1031    }
1032
1033    #[test]
1034    fn map_string_missing_identifier_42() {
1035        assert_eq!(
1036            parse_error(
1037                r#"0: at line 1, in identifier:
1038map string = 42 {}
1039           ^
1040
10411: at line 1, in key type:
1042map string = 42 {}
1043    ^
1044
10452: at line 1, in map type:
1046map string = 42 {}
1047^"#
1048            ),
1049            interpret_error_for_test(cut(complete(all_consuming(map_field))))("map string = 42 {}")
1050                .unwrap_err(),
1051        );
1052    }
1053
1054    #[test]
1055    fn field_definition_field_bytes32_identifier9_42() {
1056        assert_eq!(
1057            FieldDefinition::Field(Field {
1058                ident: Identifier::must("__identifier9"),
1059                number: FieldNumber::must(42),
1060                ty: DataType::bytes32,
1061                breakout: false,
1062            }),
1063            parse_all(field_definition)("bytes32 __identifier9 = 42").unwrap(),
1064        );
1065    }
1066
1067    #[test]
1068    fn field_definition_field_breakout_bytes32_identifier9_42() {
1069        assert_eq!(
1070            FieldDefinition::Field(Field {
1071                ident: Identifier::must("__identifier9"),
1072                number: FieldNumber::must(42),
1073                ty: DataType::bytes32,
1074                breakout: true,
1075            }),
1076            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1077                "breakout bytes32 __identifier9 = 42"
1078            )
1079            .unwrap(),
1080        );
1081    }
1082
1083    #[test]
1084    fn field_definition_field_keyword_bytes32_identifier9_42() {
1085        assert_eq!(
1086            parse_error(
1087                r#"0: at line 1, in join field:
1088keyword bytes32 __identifier9 = 42
1089^
1090
10911: at line 1, in field definition:
1092keyword bytes32 __identifier9 = 42
1093^"#
1094            ),
1095            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1096                "keyword bytes32 __identifier9 = 42"
1097            )
1098            .unwrap_err(),
1099        );
1100    }
1101
1102    #[test]
1103    fn field_definition_object_identifer9_42() {
1104        assert_eq!(
1105            FieldDefinition::Object(
1106                Object::new(
1107                    Identifier::must("__identifier9"),
1108                    FieldNumber::must(42),
1109                    vec![]
1110                )
1111                .unwrap()
1112            ),
1113            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1114                "object __identifier9 = 42 {}"
1115            )
1116            .unwrap(),
1117        );
1118    }
1119
1120    #[test]
1121    fn field_definition_object_identifer9_42_whitespace() {
1122        assert_eq!(
1123            FieldDefinition::Object(
1124                Object::new(
1125                    Identifier::must("__identifier9"),
1126                    FieldNumber::must(42),
1127                    vec![]
1128                )
1129                .unwrap()
1130            ),
1131            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1132                "
1133                                                                           object
1134                                                                           __identifier9
1135                                                                           =
1136                                                                           42
1137                                                                           {
1138                                                                           }"
1139            )
1140            .unwrap(),
1141        );
1142    }
1143
1144    #[test]
1145    fn field_definition_object_identifer9_42_minimal_whitespace() {
1146        assert_eq!(
1147            FieldDefinition::Object(
1148                Object::new(
1149                    Identifier::must("__identifier9"),
1150                    FieldNumber::must(42),
1151                    vec![]
1152                )
1153                .unwrap()
1154            ),
1155            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1156                "object __identifier9=42{}"
1157            )
1158            .unwrap(),
1159        );
1160    }
1161
1162    #[test]
1163    fn field_definition_object_identifer9_42_missing_field_number() {
1164        assert_eq!(
1165            parse_error(
1166                r#"0: at line 1, in object type:
1167object __identifier9 {}
1168^
1169
11701: at line 1, in field definition:
1171object __identifier9 {}
1172^"#
1173            ),
1174            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1175                "object __identifier9 {}"
1176            )
1177            .unwrap_err(),
1178        );
1179    }
1180
1181    #[test]
1182    fn field_definition_map_string_identifer9_42() {
1183        assert_eq!(
1184            FieldDefinition::Map(
1185                Map::new(
1186                    Key::new(
1187                        Identifier::must("__identifier9"),
1188                        FieldNumber::must(42),
1189                        KeyDataType::string,
1190                        Direction::Forward,
1191                    )
1192                    .unwrap(),
1193                    vec![]
1194                )
1195                .unwrap()
1196            ),
1197            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1198                "map string __identifier9 = 42 {}"
1199            )
1200            .unwrap(),
1201        );
1202    }
1203
1204    #[test]
1205    fn field_definition_map_missing_datatype_identifer9_42() {
1206        assert_eq!(
1207            parse_error(
1208                r#"0: at line 1, in key data type:
1209map __identifier9 = 42 {}
1210    ^
1211
12121: at line 1, in key type:
1213map __identifier9 = 42 {}
1214    ^
1215
12162: at line 1, in map type:
1217map __identifier9 = 42 {}
1218^
1219
12203: at line 1, in field definition:
1221map __identifier9 = 42 {}
1222^"#
1223            ),
1224            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1225                "map __identifier9 = 42 {}"
1226            )
1227            .unwrap_err(),
1228        );
1229    }
1230
1231    #[test]
1232    fn field_definition_map_string_missing_identifier_42() {
1233        assert_eq!(
1234            parse_error(
1235                r#"0: at line 1, in identifier:
1236map string = 42 {}
1237           ^
1238
12391: at line 1, in key type:
1240map string = 42 {}
1241    ^
1242
12432: at line 1, in map type:
1244map string = 42 {}
1245^
1246
12473: at line 1, in field definition:
1248map string = 42 {}
1249^"#
1250            ),
1251            interpret_error_for_test(cut(complete(all_consuming(field_definition))))(
1252                "map string = 42 {}"
1253            )
1254            .unwrap_err(),
1255        );
1256    }
1257
1258    #[test]
1259    fn field_definition_join_key_success() {
1260        assert_eq!(
1261            FieldDefinition::Join(Join {
1262                ident: Identifier::must("spam"),
1263                number: FieldNumber::must(42),
1264                join_table: Identifier::must("Spam"),
1265                join_keys: vec![Identifier::must("a"), Identifier::must("b")],
1266            }),
1267            parse_all(field_definition)("join spam = 42 on Spam (a, b)").unwrap(),
1268        );
1269    }
1270
1271    #[test]
1272    fn empty_table() {
1273        let key = vec![Key::new(
1274            Identifier::must("some_key"),
1275            FieldNumber::must(1),
1276            KeyDataType::string,
1277            Direction::Forward,
1278        )
1279        .unwrap()];
1280        assert_eq!(
1281            Table::new(
1282                Identifier::must("__identifier9"),
1283                FieldNumber::must(2),
1284                key,
1285                vec![]
1286            )
1287            .unwrap(),
1288            interpret_error_for_test(cut(complete(all_consuming(table))))(
1289                "table __identifier9 (string some_key= 1) @ 2 {}"
1290            )
1291            .unwrap()
1292        );
1293    }
1294
1295    #[test]
1296    fn table_error_no_number() {
1297        // We expect this table that lacks a table number to error out.
1298        const BAD_TABLE: &str = "table __identifier9 (string some_key= 1) {
1299            breakout string last_seen = 4;
1300        }";
1301        assert_eq!(
1302            parse_error(
1303                r#"0: at line 1, in table definition:
1304table __identifier9 (string some_key= 1) {
1305^"#
1306            ),
1307            interpret_error_for_test(cut(complete(all_consuming(table))))(BAD_TABLE).unwrap_err()
1308        );
1309    }
1310
1311    #[test]
1312    fn table_error_bad_field() {
1313        // TODO(rescrv): Make this have a better error message.
1314        const BAD_TABLE: &str = "table __identifier9 (string some_key= 1) @ 1 {
1315            breakout not_a_type last_seen = 4;
1316        }";
1317        assert_eq!(
1318            parse_error(
1319                r#"0: at line 2, in data type:
1320            breakout not_a_type last_seen = 4;
1321                     ^
1322
13231: at line 2, in field type:
1324            breakout not_a_type last_seen = 4;
1325            ^
1326
13272: at line 2, in field definition:
1328            breakout not_a_type last_seen = 4;
1329            ^
1330
13313: at line 2, in fields:
1332            breakout not_a_type last_seen = 4;
1333            ^
1334
13354: at line 2, in table body:
1336            breakout not_a_type last_seen = 4;
1337            ^
1338
13395: at line 1, in table definition:
1340table __identifier9 (string some_key= 1) @ 1 {
1341^"#
1342            ),
1343            interpret_error_for_test(cut(complete(all_consuming(table))))(BAD_TABLE).unwrap_err()
1344        );
1345    }
1346
1347    #[test]
1348    fn table_set_with_joins() {
1349        const TABLE_SET: &str = r#"
1350            table User (string user_id = 1) @ 1 {
1351                string email = 2;
1352                join avatar = 3 on Avatar (email);
1353                map string sessions = 4 {
1354                    join session = 1 on Session (user_id, sessions);
1355                };
1356            }
1357
1358            table Avatar (string email = 1) @ 2 {
1359                string url = 2;
1360            }
1361
1362            table Session (string user_id = 1, string session_id = 2) @ 3 {
1363                timestamp_micros first_valid = 3;
1364                timestamp_micros expires = 4;
1365            }
1366        "#;
1367        let user = Table::new(
1368            Identifier::must("User"),
1369            FieldNumber::must(1),
1370            vec![Key::new(
1371                Identifier::must("user_id"),
1372                FieldNumber::must(1),
1373                KeyDataType::string,
1374                Direction::Forward,
1375            )
1376            .unwrap()],
1377            vec![
1378                FieldDefinition::Field(
1379                    Field::new(
1380                        Identifier::must("email"),
1381                        FieldNumber::must(2),
1382                        DataType::string,
1383                        false,
1384                    )
1385                    .unwrap(),
1386                ),
1387                FieldDefinition::Join(
1388                    Join::new(
1389                        Identifier::must("avatar"),
1390                        FieldNumber::must(3),
1391                        Identifier::must("Avatar"),
1392                        vec![Identifier::must("email")],
1393                    )
1394                    .unwrap(),
1395                ),
1396                FieldDefinition::Map(
1397                    Map::new(
1398                        Key::new(
1399                            Identifier::must("sessions"),
1400                            FieldNumber::must(4),
1401                            KeyDataType::string,
1402                            Direction::Forward,
1403                        )
1404                        .unwrap(),
1405                        vec![FieldDefinition::Join(
1406                            Join::new(
1407                                Identifier::must("session"),
1408                                FieldNumber::must(1),
1409                                Identifier::must("Session"),
1410                                vec![Identifier::must("user_id"), Identifier::must("sessions")],
1411                            )
1412                            .unwrap(),
1413                        )],
1414                    )
1415                    .unwrap(),
1416                ),
1417            ],
1418        )
1419        .unwrap();
1420        let avatar = Table::new(
1421            Identifier::must("Avatar"),
1422            FieldNumber::must(2),
1423            vec![Key::new(
1424                Identifier::must("email"),
1425                FieldNumber::must(1),
1426                KeyDataType::string,
1427                Direction::Forward,
1428            )
1429            .unwrap()],
1430            vec![FieldDefinition::Field(
1431                Field::new(
1432                    Identifier::must("url"),
1433                    FieldNumber::must(2),
1434                    DataType::string,
1435                    false,
1436                )
1437                .unwrap(),
1438            )],
1439        )
1440        .unwrap();
1441        let session = Table::new(
1442            Identifier::must("Session"),
1443            FieldNumber::must(3),
1444            vec![
1445                Key::new(
1446                    Identifier::must("user_id"),
1447                    FieldNumber::must(1),
1448                    KeyDataType::string,
1449                    Direction::Forward,
1450                )
1451                .unwrap(),
1452                Key::new(
1453                    Identifier::must("session_id"),
1454                    FieldNumber::must(2),
1455                    KeyDataType::string,
1456                    Direction::Forward,
1457                )
1458                .unwrap(),
1459            ],
1460            vec![
1461                FieldDefinition::Field(
1462                    Field::new(
1463                        Identifier::must("first_valid"),
1464                        FieldNumber::must(3),
1465                        DataType::timestamp_micros,
1466                        false,
1467                    )
1468                    .unwrap(),
1469                ),
1470                FieldDefinition::Field(
1471                    Field::new(
1472                        Identifier::must("expires"),
1473                        FieldNumber::must(4),
1474                        DataType::timestamp_micros,
1475                        false,
1476                    )
1477                    .unwrap(),
1478                ),
1479            ],
1480        )
1481        .unwrap();
1482        assert_eq!(
1483            TableSet::new(vec![user, avatar, session,],).unwrap(),
1484            interpret_error_for_test(cut(complete(all_consuming(table_set))))(TABLE_SET).unwrap()
1485        );
1486    }
1487
1488    #[test]
1489    fn table_set_with_zero_key() {
1490        const TABLE_SET: &str = r#"
1491            table Global () @ 1 {
1492                bytes config = 1;
1493            }
1494        "#;
1495        let global = Table::new(
1496            Identifier::must("Global"),
1497            FieldNumber::must(1),
1498            vec![],
1499            vec![FieldDefinition::Field(
1500                Field::new(
1501                    Identifier::must("config"),
1502                    FieldNumber::must(1),
1503                    DataType::bytes,
1504                    false,
1505                )
1506                .unwrap(),
1507            )],
1508        )
1509        .unwrap();
1510        assert_eq!(
1511            TableSet::new(vec![global]).unwrap(),
1512            interpret_error_for_test(cut(complete(all_consuming(table_set))))(TABLE_SET).unwrap()
1513        );
1514    }
1515
1516    #[test]
1517    fn table_set_with_object() {
1518        const TABLE_SET: &str = r#"
1519            table ObjectTest () @ 1 {
1520                object obj = 1 {
1521                    uint64 x = 1;
1522                    uint64 y = 2;
1523                };
1524            }
1525        "#;
1526        let global = Table::new(
1527            Identifier::must("ObjectTest"),
1528            FieldNumber::must(1),
1529            vec![],
1530            vec![FieldDefinition::Object(
1531                Object::new(
1532                    Identifier::must("obj"),
1533                    FieldNumber::must(1),
1534                    vec![
1535                        FieldDefinition::Field(Field {
1536                            ident: Identifier::must("x"),
1537                            number: FieldNumber::must(1),
1538                            ty: DataType::uint64,
1539                            breakout: false,
1540                        }),
1541                        FieldDefinition::Field(Field {
1542                            ident: Identifier::must("y"),
1543                            number: FieldNumber::must(2),
1544                            ty: DataType::uint64,
1545                            breakout: false,
1546                        }),
1547                    ],
1548                )
1549                .unwrap(),
1550            )],
1551        )
1552        .unwrap();
1553        assert_eq!(
1554            TableSet::new(vec![global]).unwrap(),
1555            interpret_error_for_test(cut(complete(all_consuming(table_set))))(TABLE_SET).unwrap()
1556        );
1557    }
1558
1559    #[test]
1560    fn typical_query() {
1561        assert_eq!(
1562            Query::from_exprs(
1563                Identifier::must("User"),
1564                vec![
1565                    Query::new(Identifier::must("name")).unwrap(),
1566                    Query::new(Identifier::must("email")).unwrap(),
1567                    Query::from_exprs(
1568                        Identifier::must("password"),
1569                        vec![
1570                            Query::new(Identifier::must("algorithm")).unwrap(),
1571                            Query::new(Identifier::must("salt")).unwrap(),
1572                            Query::new(Identifier::must("hash")).unwrap(),
1573                        ]
1574                    )
1575                    .unwrap(),
1576                    Query::from_exprs(
1577                        Identifier::must("sessions"),
1578                        vec![Query::new(Identifier::must("expires_us")).unwrap(),]
1579                    )
1580                    .unwrap(),
1581                ]
1582            )
1583            .unwrap(),
1584            interpret_error_for_test(cut(complete(all_consuming(query))))(
1585                r#"User {
1586                    name,
1587                    email,
1588                    password {
1589                        algorithm,
1590                        salt,
1591                        hash,
1592                    },
1593                    sessions {
1594                        expires_us,
1595                    },
1596                }"#
1597            )
1598            .unwrap(),
1599        );
1600    }
1601
1602    #[test]
1603    fn parse_string_literal() {
1604        assert_eq!(
1605            KeyLiteral::string {
1606                value: "".to_string()
1607            },
1608            interpret_error_for_test(cut(complete(all_consuming(string_literal))))(r#""""#)
1609                .unwrap(),
1610        );
1611        assert_eq!(
1612            KeyLiteral::string {
1613                value: r#"""#.to_string()
1614            },
1615            interpret_error_for_test(cut(complete(all_consuming(string_literal))))(r#""\"""#)
1616                .unwrap(),
1617        );
1618        assert_eq!(
1619            KeyLiteral::string {
1620                value: r#"\"#.to_string()
1621            },
1622            interpret_error_for_test(cut(complete(all_consuming(string_literal))))(r#""\\""#)
1623                .unwrap(),
1624        );
1625        assert_eq!(
1626            KeyLiteral::string {
1627                value: r#""hello""world""#.to_string()
1628            },
1629            interpret_error_for_test(cut(complete(all_consuming(string_literal))))(
1630                r#""\"hello\"\"world\"""#
1631            )
1632            .unwrap(),
1633        );
1634    }
1635
1636    #[test]
1637    fn parse_number_literal() {
1638        assert_eq!(
1639            KeyLiteral::sfixed32 { value: 0 },
1640            interpret_error_for_test(cut(complete(all_consuming(number_literal))))("0").unwrap(),
1641        );
1642        assert_eq!(
1643            KeyLiteral::sfixed32 { value: i32::MIN },
1644            interpret_error_for_test(cut(complete(all_consuming(number_literal))))("-2147483648")
1645                .unwrap(),
1646        );
1647        assert_eq!(
1648            KeyLiteral::sfixed32 { value: i32::MAX },
1649            interpret_error_for_test(cut(complete(all_consuming(number_literal))))("2147483647")
1650                .unwrap(),
1651        );
1652        assert_eq!(
1653            KeyLiteral::fixed32 { value: u32::MAX },
1654            interpret_error_for_test(cut(complete(all_consuming(number_literal))))("4294967295")
1655                .unwrap(),
1656        );
1657        assert_eq!(
1658            KeyLiteral::sfixed64 { value: i64::MIN },
1659            interpret_error_for_test(cut(complete(all_consuming(number_literal))))(
1660                "-9223372036854775808"
1661            )
1662            .unwrap(),
1663        );
1664        assert_eq!(
1665            KeyLiteral::sfixed64 { value: i64::MAX },
1666            interpret_error_for_test(cut(complete(all_consuming(number_literal))))(
1667                "9223372036854775807"
1668            )
1669            .unwrap(),
1670        );
1671        assert_eq!(
1672            KeyLiteral::fixed64 { value: u64::MAX },
1673            interpret_error_for_test(cut(complete(all_consuming(number_literal))))(
1674                "18446744073709551615"
1675            )
1676            .unwrap(),
1677        );
1678    }
1679
1680    #[test]
1681    fn parse_query_filter() {
1682        assert_eq!(
1683            QueryFilter::Equals(KeyLiteral::string {
1684                value: "".to_string()
1685            }),
1686            interpret_error_for_test(cut(complete(all_consuming(query_filter))))(r#""""#).unwrap(),
1687        );
1688        assert_eq!(
1689            QueryFilter::Equals(KeyLiteral::string {
1690                value: r#"""#.to_string()
1691            }),
1692            interpret_error_for_test(cut(complete(all_consuming(query_filter))))(r#""\"""#)
1693                .unwrap(),
1694        );
1695        assert_eq!(
1696            QueryFilter::Equals(KeyLiteral::string {
1697                value: r#"\"#.to_string()
1698            }),
1699            interpret_error_for_test(cut(complete(all_consuming(query_filter))))(r#""\\""#)
1700                .unwrap(),
1701        );
1702        assert_eq!(
1703            QueryFilter::Equals(KeyLiteral::string {
1704                value: r#""hello""world""#.to_string()
1705            }),
1706            interpret_error_for_test(cut(complete(all_consuming(query_filter))))(
1707                r#""\"hello\"\"world\"""#
1708            )
1709            .unwrap(),
1710        );
1711        assert_eq!(
1712            QueryFilter::Equals(KeyLiteral::sfixed32 { value: 0 }),
1713            interpret_error_for_test(cut(complete(all_consuming(query_filter))))("0").unwrap(),
1714        );
1715        assert_eq!(
1716            QueryFilter::Equals(KeyLiteral::sfixed32 { value: i32::MIN }),
1717            interpret_error_for_test(cut(complete(all_consuming(query_filter))))("-2147483648")
1718                .unwrap(),
1719        );
1720        assert_eq!(
1721            QueryFilter::Equals(KeyLiteral::sfixed32 { value: i32::MAX }),
1722            interpret_error_for_test(cut(complete(all_consuming(query_filter))))("2147483647")
1723                .unwrap(),
1724        );
1725        assert_eq!(
1726            QueryFilter::Equals(KeyLiteral::fixed32 { value: u32::MAX }),
1727            interpret_error_for_test(cut(complete(all_consuming(query_filter))))("4294967295")
1728                .unwrap(),
1729        );
1730        assert_eq!(
1731            QueryFilter::Equals(KeyLiteral::sfixed64 { value: i64::MIN }),
1732            interpret_error_for_test(cut(complete(all_consuming(query_filter))))(
1733                "-9223372036854775808"
1734            )
1735            .unwrap(),
1736        );
1737        assert_eq!(
1738            QueryFilter::Equals(KeyLiteral::sfixed64 { value: i64::MAX }),
1739            interpret_error_for_test(cut(complete(all_consuming(query_filter))))(
1740                "9223372036854775807"
1741            )
1742            .unwrap(),
1743        );
1744        assert_eq!(
1745            QueryFilter::Equals(KeyLiteral::fixed64 { value: u64::MAX }),
1746            interpret_error_for_test(cut(complete(all_consuming(query_filter))))(
1747                "18446744073709551615"
1748            )
1749            .unwrap(),
1750        );
1751    }
1752
1753    #[test]
1754    fn typical_query_with_filter() {
1755        assert_eq!(
1756            Query::from_exprs(
1757                Identifier::must("User"),
1758                vec![
1759                    Query::new(Identifier::must("name")).unwrap(),
1760                    Query::new(Identifier::must("email")).unwrap(),
1761                    Query::from_exprs(
1762                        Identifier::must("password"),
1763                        vec![
1764                            Query::new(Identifier::must("algorithm")).unwrap(),
1765                            Query::new(Identifier::must("salt")).unwrap(),
1766                            Query::new(Identifier::must("hash")).unwrap(),
1767                        ]
1768                    )
1769                    .unwrap(),
1770                    Query::from_filter_and_exprs(
1771                        Identifier::must("sessions"),
1772                        QueryFilter::Equals(KeyLiteral::string {
1773                            value: "some-key".to_string()
1774                        }),
1775                        vec![Query::new(Identifier::must("expires_us")).unwrap(),]
1776                    )
1777                    .unwrap(),
1778                ]
1779            )
1780            .unwrap(),
1781            interpret_error_for_test(cut(complete(all_consuming(query))))(
1782                r#"User {
1783                    name,
1784                    email,
1785                    password {
1786                        algorithm,
1787                        salt,
1788                        hash,
1789                    },
1790                    sessions ["some-key"] {
1791                        expires_us,
1792                    },
1793                }"#
1794            )
1795            .unwrap(),
1796        );
1797    }
1798
1799    #[test]
1800    fn query_error_bad_key() {
1801        assert_eq!(
1802            parse_error(
1803                r#"0: at line 9, in string literal:
1804                    sessions [some-key"] {
1805                              ^
1806
18071: at line 9, in query filter:
1808                    sessions [some-key"] {
1809                              ^
1810
18112: at line 8, in query:
1812                    },
1813                      ^
1814
18153: at line 2, in query expression:
1816                    name,
1817                    ^
1818
18194: at line 1, in query:
1820User {
1821^"#
1822            ),
1823            interpret_error_for_test(cut(complete(all_consuming(query))))(
1824                r#"User {
1825                    name,
1826                    email,
1827                    password {
1828                        algorithm,
1829                        salt,
1830                        hash,
1831                    },
1832                    sessions [some-key"] {
1833                        expires_us,
1834                    },
1835                }"#
1836            )
1837            .unwrap_err()
1838        );
1839    }
1840}