/rust/registry/src/index.crates.io-1949cf8c6b5b557f/async-graphql-parser-7.0.16/src/parse/utils.rs
Line | Count | Source |
1 | | use pest::iterators::{Pair, Pairs}; |
2 | | |
3 | | use super::Rule; |
4 | | use crate::Result; |
5 | | |
6 | 0 | pub(super) fn next_if_rule<'a>(pairs: &mut Pairs<'a, Rule>, rule: Rule) -> Option<Pair<'a, Rule>> { |
7 | 0 | if pairs.peek().is_some_and(|pair| pair.as_rule() == rule) { |
8 | 0 | Some(pairs.next().unwrap()) |
9 | | } else { |
10 | 0 | None |
11 | | } |
12 | 0 | } |
13 | 0 | pub(super) fn parse_if_rule<T>( |
14 | 0 | pairs: &mut Pairs<Rule>, |
15 | 0 | rule: Rule, |
16 | 0 | f: impl FnOnce(Pair<Rule>) -> Result<T>, |
17 | 0 | ) -> Result<Option<T>> { |
18 | 0 | next_if_rule(pairs, rule).map(f).transpose() |
19 | 0 | } Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<async_graphql_value::ConstValue>, async_graphql_parser::parse::executable::parse_variable_definition::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<async_graphql_value::ConstValue>, async_graphql_parser::parse::service::parse_input_value_definition::{closure#1}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<async_graphql_value::Name>, async_graphql_parser::parse::executable::parse_field::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<async_graphql_value::Name>, async_graphql_parser::parse::executable::parse_named_operation_definition::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<alloc::string::String>, async_graphql_parser::parse::service::parse_type_definition::{closure#6}::{closure#0}::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<alloc::string::String>, async_graphql_parser::parse::service::parse_type_definition::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<alloc::string::String>, async_graphql_parser::parse::service::parse_field_definition::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<alloc::string::String>, async_graphql_parser::parse::service::parse_directive_definition::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<alloc::string::String>, async_graphql_parser::parse::service::parse_input_value_definition::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<async_graphql_parser::types::executable::SelectionSet>, async_graphql_parser::parse::executable::parse_field::{closure#2}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<async_graphql_parser::pos::Positioned<async_graphql_parser::types::executable::TypeCondition>, async_graphql_parser::parse::executable::parse_inline_fragment::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_value::Name>>, async_graphql_parser::parse::service::parse_type_definition::{closure#3}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_value::Name>>, async_graphql_parser::parse::service::parse_type_definition::{closure#5}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_value::Name>>, async_graphql_parser::parse::service::parse_type_definition::{closure#1}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::ConstDirective>>, async_graphql_parser::parse::parse_opt_const_directives::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::Directive>>, async_graphql_parser::parse::parse_opt_directives::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::executable::VariableDefinition>>, async_graphql_parser::parse::executable::parse_named_operation_definition::{closure#1}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::service::FieldDefinition>>, async_graphql_parser::parse::service::parse_type_definition::{closure#2}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::service::FieldDefinition>>, async_graphql_parser::parse::service::parse_type_definition::{closure#4}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::service::EnumValueDefinition>>, async_graphql_parser::parse::service::parse_type_definition::{closure#6}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::service::InputValueDefinition>>, async_graphql_parser::parse::service::parse_type_definition::{closure#7}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::service::InputValueDefinition>>, async_graphql_parser::parse::service::parse_field_definition::{closure#1}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<async_graphql_parser::pos::Positioned<async_graphql_parser::types::service::InputValueDefinition>>, async_graphql_parser::parse::service::parse_directive_definition::{closure#1}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<(async_graphql_parser::pos::Positioned<async_graphql_value::Name>, async_graphql_parser::pos::Positioned<async_graphql_value::ConstValue>)>, async_graphql_parser::parse::parse_const_directive::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<(async_graphql_parser::pos::Positioned<async_graphql_value::Name>, async_graphql_parser::pos::Positioned<async_graphql_value::Value>)>, async_graphql_parser::parse::parse_directive::{closure#0}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<alloc::vec::Vec<(async_graphql_parser::pos::Positioned<async_graphql_value::Name>, async_graphql_parser::pos::Positioned<async_graphql_value::Value>)>, async_graphql_parser::parse::executable::parse_field::{closure#1}>Unexecuted instantiation: async_graphql_parser::parse::utils::parse_if_rule::<(), async_graphql_parser::parse::service::parse_directive_definition::{closure#2}> |
20 | | |
21 | 0 | pub(super) fn exactly_one<T>(iter: impl IntoIterator<Item = T>) -> T { |
22 | 0 | let mut iter = iter.into_iter(); |
23 | 0 | let res = iter.next().unwrap(); |
24 | 0 | debug_assert!(iter.next().is_none()); |
25 | 0 | res |
26 | 0 | } |
27 | | |
28 | 0 | pub(super) fn block_string_value(raw: &str) -> String { |
29 | | // Split the string by either \r\n, \r or \n |
30 | 0 | let lines: Vec<_> = raw |
31 | 0 | .split("\r\n") |
32 | 0 | .flat_map(|s| s.split(['\r', '\n'].as_ref())) |
33 | 0 | .collect(); |
34 | | |
35 | | // Find the common indent |
36 | 0 | let common_indent = lines |
37 | 0 | .iter() |
38 | 0 | .skip(1) |
39 | 0 | .copied() |
40 | 0 | .filter_map(|line| line.find(|c| c != '\t' && c != ' ')) |
41 | 0 | .min() |
42 | 0 | .unwrap_or(0); |
43 | | |
44 | 0 | let line_has_content = |line: &str| line.as_bytes().iter().any(|&c| c != b'\t' && c != b' '); |
45 | | |
46 | 0 | let first_contentful_line = lines |
47 | 0 | .iter() |
48 | 0 | .copied() |
49 | 0 | .position(line_has_content) |
50 | 0 | .unwrap_or(lines.len()); |
51 | 0 | let ending_lines_start = lines |
52 | 0 | .iter() |
53 | 0 | .copied() |
54 | 0 | .rposition(line_has_content) |
55 | 0 | .map_or(0, |i| i + 1); |
56 | | |
57 | 0 | lines |
58 | 0 | .iter() |
59 | 0 | .copied() |
60 | 0 | .enumerate() |
61 | 0 | .take(ending_lines_start) |
62 | 0 | .skip(first_contentful_line) |
63 | | // Remove the common indent, but not on the first line |
64 | 0 | .map(|(i, line)| { |
65 | 0 | if i != 0 && line.len() >= common_indent { |
66 | 0 | &line[common_indent..] |
67 | | } else { |
68 | 0 | line |
69 | | } |
70 | 0 | }) |
71 | | // Put a newline between each line |
72 | 0 | .enumerate() |
73 | 0 | .flat_map(|(i, line)| { |
74 | 0 | if i == 0 { [].as_ref() } else { ['\n'].as_ref() } |
75 | 0 | .iter() |
76 | 0 | .copied() |
77 | 0 | .chain(line.chars()) |
78 | 0 | }) |
79 | 0 | .collect() |
80 | 0 | } |
81 | | |
82 | | #[test] |
83 | | fn test_block_string_value() { |
84 | | assert_eq!(block_string_value(""), ""); |
85 | | assert_eq!(block_string_value("\r\n"), ""); |
86 | | assert_eq!(block_string_value("\r\r\r\r\n\n\r\n\r\r"), ""); |
87 | | assert_eq!(block_string_value("abc"), "abc"); |
88 | | assert_eq!( |
89 | | block_string_value("line 1\r\n line 2\n line 3\r line 4"), |
90 | | "line 1\nline 2\n line 3\n line 4" |
91 | | ); |
92 | | assert_eq!( |
93 | | block_string_value("\r\r some text\r\n \n \n "), |
94 | | "some text" |
95 | | ); |
96 | | assert_eq!( |
97 | | block_string_value( |
98 | | r#" |
99 | | a |
100 | | b |
101 | | |
102 | | c |
103 | | "# |
104 | | ), |
105 | | "a\nb\n\nc" |
106 | | ); |
107 | | } |
108 | | |
109 | 0 | pub(super) fn string_value(s: &str) -> String { |
110 | 0 | let mut chars = s.chars(); |
111 | | |
112 | 0 | std::iter::from_fn(|| { |
113 | 0 | Some(match chars.next()? { |
114 | 0 | '\\' => match chars.next().expect("backslash at end") { |
115 | 0 | c @ '\"' | c @ '\\' | c @ '/' => c, |
116 | 0 | 'b' => '\x08', |
117 | 0 | 'f' => '\x0C', |
118 | 0 | 'n' => '\n', |
119 | 0 | 'r' => '\r', |
120 | 0 | 't' => '\t', |
121 | 0 | 'u' => std::char::from_u32( |
122 | 0 | (0..4) |
123 | 0 | .map(|_| chars.next().unwrap().to_digit(16).unwrap()) |
124 | 0 | .fold(0, |acc, digit| acc * 16 + digit), |
125 | | ) |
126 | 0 | .unwrap(), |
127 | 0 | _ => unreachable!(), |
128 | | }, |
129 | 0 | other => other, |
130 | | }) |
131 | 0 | }) |
132 | 0 | .collect() |
133 | 0 | } |
134 | | |
135 | | #[test] |
136 | | fn test_string_value() { |
137 | | assert_eq!(string_value("abc"), "abc"); |
138 | | assert_eq!(string_value("\\n\\b\\u2a1A"), "\n\x08\u{2A1A}"); |
139 | | assert_eq!(string_value("\\\"\\\\"), "\"\\"); |
140 | | } |