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
24type 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 let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1;
59 let line_begin = prefix
62 .iter()
63 .rev()
64 .position(|&b| b == b'\n')
65 .map(|pos| offset - pos)
66 .unwrap_or(0);
67 let line = input[line_begin..]
69 .lines()
70 .next()
71 .unwrap_or(&input[line_begin..])
72 .trim_end();
73 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 VerboseErrorKind::Nom(_) => {}
129 };
130 }
131 ParseError {
132 string: result.trim().to_string(),
133 }
134}
135
136pub 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
485pub 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
612pub 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
637fn ws0(input: &str) -> ParseResult<()> {
640 map(multispace0, |_| ())(input)
641}
642
643fn ws1(input: &str) -> ParseResult<()> {
644 map(multispace1, |_| ())(input)
645}
646
647#[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 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 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}