diff --git a/src/GraphQLParser.Benchmarks/BinaryTest.graphql b/src/GraphQLParser.Benchmarks/BinaryTest.graphql
new file mode 100644
index 00000000..ca03f5ab
Binary files /dev/null and b/src/GraphQLParser.Benchmarks/BinaryTest.graphql differ
diff --git a/src/GraphQLParser.Benchmarks/GraphQLParser.Benchmarks.csproj b/src/GraphQLParser.Benchmarks/GraphQLParser.Benchmarks.csproj
index f9e2b055..5eacd042 100644
--- a/src/GraphQLParser.Benchmarks/GraphQLParser.Benchmarks.csproj
+++ b/src/GraphQLParser.Benchmarks/GraphQLParser.Benchmarks.csproj
@@ -8,16 +8,26 @@
true
+
+
+
+
+
+
+ PreserveNewest
+
+
+
-
+
-
+
diff --git a/src/GraphQLParser.Benchmarks/LexerBenchmark.cs b/src/GraphQLParser.Benchmarks/LexerBenchmark.cs
index dbcef69f..d0d6b8de 100644
--- a/src/GraphQLParser.Benchmarks/LexerBenchmark.cs
+++ b/src/GraphQLParser.Benchmarks/LexerBenchmark.cs
@@ -1,4 +1,6 @@
using BenchmarkDotNet.Attributes;
+using GraphQLParser.Exceptions;
+using System.IO;
namespace GraphQLParser.Benchmarks
{
@@ -7,6 +9,7 @@ namespace GraphQLParser.Benchmarks
#endif
public class LexerBenchmark
{
+ private static readonly string Binary = File.ReadAllText("BinaryTest.graphql");
private const string KitchenSink = @"
query queryName($foo: ComplexType, $site: Site = MOBILE) {
whoever123is: node(id: [123, 456]) {
@@ -70,5 +73,18 @@ public void LexKitchenSink()
resetPosition = token.End;
}
}
+
+ [Benchmark]
+ public void ParseBinaryFile()
+ {
+ try
+ {
+ var parser = new Parser(new Lexer());
+ parser.Parse(new Source(Binary));
+ }
+ catch (GraphQLSyntaxErrorException)
+ {
+ }
+ }
}
}
diff --git a/src/GraphQLParser/AST/GraphQLListValue.cs b/src/GraphQLParser/AST/GraphQLListValue.cs
index 41c708d6..04919661 100644
--- a/src/GraphQLParser/AST/GraphQLListValue.cs
+++ b/src/GraphQLParser/AST/GraphQLListValue.cs
@@ -4,7 +4,7 @@
public class GraphQLListValue : GraphQLValue
{
- private ASTNodeKind kindField;
+ private readonly ASTNodeKind kindField;
public GraphQLListValue(ASTNodeKind kind)
{
diff --git a/src/GraphQLParser/Exceptions/GraphQLSyntaxErrorException.cs b/src/GraphQLParser/Exceptions/GraphQLSyntaxErrorException.cs
index a6dad2b7..f47ff149 100644
--- a/src/GraphQLParser/Exceptions/GraphQLSyntaxErrorException.cs
+++ b/src/GraphQLParser/Exceptions/GraphQLSyntaxErrorException.cs
@@ -2,6 +2,7 @@
{
using System;
using System.Linq;
+ using System.Text;
public class GraphQLSyntaxErrorException : Exception
{
@@ -49,13 +50,48 @@ private static string LeftPad(int length, string str)
private static string ReplaceWithUnicodeRepresentation(string str)
{
+ if (!HasReplacementCharacter(str))
+ return str;
+
+ var buffer = new StringBuilder(str.Length);
+
foreach (var code in str)
{
- if (code < 0x0020 && code != 0x0009 && code != 0x000A && code != 0x000D)
- str = str.Replace(string.Empty + code, "\\u" + ((int)code).ToString("D4"));
+ if (IsReplacementCharacter(code))
+ {
+ buffer.Append(GetUnicodeRepresentation(code));
+ }
+ else
+ {
+ buffer.Append(code);
+ }
}
- return str;
+ return buffer.ToString();
+ }
+
+ private static bool HasReplacementCharacter(string str)
+ {
+ foreach (var code in str)
+ {
+ if (IsReplacementCharacter(code))
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool IsReplacementCharacter(char code) => code < 0x0020 && code != 0x0009 && code != 0x000A && code != 0x000D;
+
+ private static string GetUnicodeRepresentation(char code)
+ {
+ switch (code)
+ {
+ case '\0':
+ return "\\u0000";
+ default:
+ return "\\u" + ((int)code).ToString("D4");
+ }
}
}
}
\ No newline at end of file
diff --git a/src/GraphQLParser/LexerContext.cs b/src/GraphQLParser/LexerContext.cs
index 3dc2f5c5..75e7a17f 100644
--- a/src/GraphQLParser/LexerContext.cs
+++ b/src/GraphQLParser/LexerContext.cs
@@ -6,7 +6,7 @@
public class LexerContext : IDisposable
{
private int currentIndex;
- private ISource source;
+ private readonly ISource source;
public LexerContext(ISource source, int index)
{
diff --git a/src/GraphQLParser/ParserContext.cs b/src/GraphQLParser/ParserContext.cs
index 3e4e60e2..01e32030 100644
--- a/src/GraphQLParser/ParserContext.cs
+++ b/src/GraphQLParser/ParserContext.cs
@@ -689,7 +689,6 @@ private GraphQLValue ParseNameValue(bool isConstant)
$"Unexpected {this.currentToken}", this.source, this.currentToken.Start);
}
-
private GraphQLValue ParseObject(bool isConstant)
{
var comment = GetComment();