Skip to content

Commit 796583c

Browse files
authored
Added consume_definition (#42)
1 parent 2e8ca0c commit 796583c

File tree

4 files changed

+47
-3
lines changed

4 files changed

+47
-3
lines changed

src/query/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl<'a> Document<'a, String> {
1919
// To support both reference and owned values in the AST,
2020
// all string data is represented with the ::common::Str<'a, T: Text<'a>>
2121
// wrapper type.
22-
// This type must carry the liftetime of the query string,
22+
// This type must carry the lifetime of the query string,
2323
// and is stored in a PhantomData value on the Str type.
2424
// When using owned String types, the actual lifetime of
2525
// the Ast nodes is 'static, since no references are kept,

src/query/grammar.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,20 @@ pub fn parse_query<'a, S>(s: &'a str) -> Result<Document<'a, S>, ParseError>
206206
Ok(doc)
207207
}
208208

209+
/// Parses a single ExecutableDefinition and returns an AST as well as the
210+
/// remainder of the input which is unparsed
211+
pub fn consume_definition<'a, S>(s: &'a str) -> Result<(Definition<'a, S>, &'a str), ParseError> where S: Text<'a> {
212+
let tokens = TokenStream::new(s);
213+
let (doc, tokens) = parser(definition).parse(tokens)?;
214+
215+
Ok((doc, &s[tokens.offset()..]))
216+
}
217+
209218
#[cfg(test)]
210219
mod test {
211220
use crate::position::Pos;
212221
use crate::query::grammar::*;
213-
use super::parse_query;
222+
use super::{parse_query, consume_definition};
214223

215224
fn ast(s: &str) -> Document<String> {
216225
parse_query::<String>(&s).unwrap().to_owned()
@@ -292,6 +301,35 @@ mod test {
292301
}
293302

294303
#[test]
304+
fn consume_single_query() {
305+
let (query, remainder) = consume_definition::<String>("query { a } query { b }").unwrap();
306+
assert!(matches!(query, Definition::Operation(_)));
307+
assert_eq!(remainder, "query { b }");
308+
}
309+
310+
#[test]
311+
fn consume_full_text() {
312+
let (query, remainder) = consume_definition::<String>("query { a }").unwrap();
313+
assert!(matches!(query, Definition::Operation(_)));
314+
assert_eq!(remainder, "");
315+
}
316+
317+
#[test]
318+
fn consume_single_query_preceding_non_graphql() {
319+
let (query, remainder) =
320+
consume_definition::<String>("query { a } where a > 1 => 10.0").unwrap();
321+
assert!(matches!(query, Definition::Operation(_)));
322+
assert_eq!(remainder, "where a > 1 => 10.0");
323+
}
324+
325+
#[test]
326+
fn consume_fails_without_operation() {
327+
let err = consume_definition::<String>("where a > 1 => 10.0")
328+
.expect_err("Expected parse to fail with an error");
329+
let err = format!("{}", err);
330+
assert_eq!(err, "query parse error: Parse error at 1:1\nUnexpected `where[Name]`\nExpected `{`, `query`, `mutation`, `subscription` or `fragment`\n");
331+
}
332+
295333
fn recursion_too_deep() {
296334
let query = format!("{}(b: {}{}){}", "{ a".repeat(30), "[".repeat(25), "]".repeat(25), "}".repeat(30));
297335
let result = parse_query::<&str>(&query);

src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ mod format;
66
mod grammar;
77

88

9-
pub use self::grammar::parse_query;
9+
pub use self::grammar::{parse_query, consume_definition};
1010
pub use self::error::ParseError;
1111
pub use self::ast::*;

src/tokenizer.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ pub struct TokenStream<'a> {
3333
recursion_limit: usize,
3434
}
3535

36+
impl TokenStream<'_> {
37+
pub(crate) fn offset(&self) -> usize {
38+
self.off
39+
}
40+
}
41+
3642
#[derive(Clone, Debug, PartialEq)]
3743
pub struct Checkpoint {
3844
position: Pos,

0 commit comments

Comments
 (0)