Blazing fast, fully spec-compliant, reusable parser combinators for standard GraphQL and GraphQL-like DSLs.
Smear is a high-performance GraphQL parser library built on parser combinators. It provides zero-copy parsing for the GraphQL draft specification and is designed to enable anyone to develop GraphQL-like Domain Specific Languages (DSLs) using reusable parser combinators.
- Thread-Safe & Concurrent: AST is
Send + Syncwhen using thread-safe source types, enabling parallel schema compilation and batched query processing across multiple threads - True Zero-Copy: All tokens and AST nodes hold slices into the original source—no string allocations, minimal memory footprint, maximum performance
- Dual Token Streams: Choose
SyntacticToken(fast, skips trivia) for servers orLosslessToken(complete, preserves all formatting) for tooling - Generic Over Source Types: Works seamlessly with
&str,&[u8],bytes::Bytes,hipstr::{HipStr, HipByt}, and custom source types - Highly Customizable: Three-layer scaffold architecture with reusable combinators for building custom GraphQL-like DSLs
- Draft Spec Compliant: Fully implements the GraphQL draft specification with comprehensive error reporting
- GraphQLx Included: Extended dialect with generics, imports, map types, namespacing, and type paths
no_stdCompatible: Works in embedded environments and WASM with optionalallocsupport
Smear's architecture offers unique advantages that set it apart from other Rust GraphQL parsers like apollo-parser, graphql-parser, async-graphql-parser, and cynic-parser:
Smear's AST is generic over the source type S. This means when you use a Send + Sync + 'static source type (like bytes::Bytes, or hipstr::{HipStr, HipByt}), the entire AST automatically becomes Send + Sync + 'static:
This unlocks powerful real-world capabilities:
For Schemas (TypeSystemDocument):
- Parallel schema compilation: Parse and validate multiple schema files concurrently
- Concurrent schema analysis: Run multiple linters/validators on the same schema in parallel
- Zero-copy schema sharing: Share parsed schemas across worker threads in GraphQL servers
For Queries (ExecutableDocument):
- Batched query processing: Parse a batch of queries, then spawn a task/thread for each query to handle them in parallel
- Concurrent request handling: Multi-threaded GraphQL servers can parse incoming queries on different threads simultaneously
- Parallel query analysis: Run validation, complexity analysis, and cost calculation concurrently
Choose the source type that fits your use case:
&str- Borrowed strings for single-threaded performance&[u8]- Byte slices for binary protocolsbytes::Bytes,hipstr::{HipStr, HipByt}- Cheap cloning with Arc-backed storage for concurrent processing
The three-layer scaffold architecture provides reusable generic AST node definitions, making it straightforward to build custom GraphQL-like domain-specific languages. GraphQLx (included) demonstrates this by adding generics, imports, type paths, and namespacing to GraphQL.
Unlike other Rust GraphQL parsers that only provide one token type, smear offers two complementary token streams to suit different use cases:
SyntacticToken (Fast) - For performance-critical execution:
- Skips trivia: Automatically filters out whitespace, comments, and commas
- Optimized for speed: Minimal memory footprint and fast parsing
- Use cases: GraphQL servers, query execution, schema compilation
- Zero-copy: All tokens reference the original source with no allocations
LosslessToken (Complete) - For tooling that preserves formatting:
- Preserves trivia: Includes all whitespace, comments, commas, and formatting
- Complete fidelity: Every character from the source is represented
- Use cases: Code formatters, linters, IDEs, syntax highlighters, refactoring tools
- CST-ready: Build Concrete Syntax Trees with perfect source reconstruction
// SyntacticToken for servers - fast execution
use smear::lexer::graphql::syntactic::SyntacticToken;
use logosky::TokenStream;
let source = "query { user { id } }";
let tokens = TokenStream::<SyntacticToken<&str>>::new(source);
// Only syntactically significant tokens (whitespace skipped)
// LosslessToken for tooling - preserves formatting
use smear::lexer::graphql::lossless::LosslessToken;
let tokens = TokenStream::<LosslessToken<&str>>::new(source);
// ALL tokens including spaces, comments, exact formattingThe Bottom Line: Use SyntacticToken when you need speed (servers, execution engines), and LosslessToken when you need perfect source preservation (formatters, linters, IDEs).
This dual-token architecture makes smear suitable for both GraphQL servers (using SyntacticToken for performance) and development tools (using LosslessToken for accurate code manipulation).
Smear follows a three-layer architecture designed for maximum reusability:
- Converts source code into zero-copy tokens
- Supports both GraphQL and GraphQLx tokens
- Generic over source type (
&str,&[u8], etc.)
- Uses parser combinators to build Abstract Syntax Trees or Concrete Syntax Trees
- Provides traits:
ParseStr,ParseBytesSlice,ParseBytes - Efficient error recovery and reporting
- Generic, reusable AST node definitions
- The foundation for building custom DSLs
- Shared between GraphQL and GraphQLx
| Feature | Description | Default |
|---|---|---|
std |
Standard library support | ✓ |
alloc |
Allocation support for no_std |
|
graphql |
Standard GraphQL parser | ✓ |
graphqlx |
Extended GraphQL parser | ✓ |
unstable |
Unstable features (required for GraphQLx) | |
smallvec |
Use smallvec for small collections |
✓ |
bytes |
Support bytes::Bytes source type |
|
bstr |
Support bstr::BStr source type |
|
hipstr |
Support hipstr::{HipStr, HipByt} source type |
Ideal for:
- High-performance GraphQL tools (IDEs, linters, formatters)
- Schema analysis and validation tools
- GraphQL servers needing fast query parsing
- Building custom GraphQL-like DSLs for domain-specific use cases
- Research projects exploring advanced type systems
Contributions are welcome! Please feel free to submit issues or pull requests.
Licensed under either of Apache License, Version 2.0 or MIT license at your option.Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.