use crate::common::IdRange;
use super::{ids::*, storage::*, ExecutableDocument};
pub struct ExecutableAstWriter {
ast: ExecutableDocument,
directive_cursor: DirectiveId,
variable_definition_cursor: VariableDefinitionId,
}
impl ExecutableAstWriter {
pub fn new() -> Self {
ExecutableAstWriter {
ast: ExecutableDocument::default(),
directive_cursor: DirectiveId::new(0),
variable_definition_cursor: VariableDefinitionId::new(0),
}
}
pub fn finish(self) -> ExecutableDocument {
self.ast
}
pub fn operation_definition(
&mut self,
definition: OperationDefinitionRecord,
) -> ExecutableDefinitionId {
let id = OperationDefinitionId::new(self.ast.operations.len());
self.ast.operations.push(definition);
let definition_id = ExecutableDefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(ExecutableDefinitionRecord::Operation(id));
definition_id
}
pub fn fragment_definition(
&mut self,
definition: FragmentDefinitionRecord,
) -> ExecutableDefinitionId {
let id = FragmentDefinitionId::new(self.ast.fragments.len());
self.ast.fragments.push(definition);
let definition_id = ExecutableDefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(ExecutableDefinitionRecord::Fragment(id));
definition_id
}
pub fn variable_definition(
&mut self,
record: VariableDefinitionRecord,
) -> VariableDefinitionId {
let id = VariableDefinitionId::new(self.ast.variables.len());
self.ast.variables.push(record);
id
}
pub fn variable_definition_range(
&mut self,
expected_count: Option<usize>,
) -> IdRange<VariableDefinitionId> {
let start = self.variable_definition_cursor;
let end = VariableDefinitionId::new(self.ast.variables.len());
self.variable_definition_cursor = end;
let range = IdRange::new(start, end);
assert_eq!(range.len(), expected_count.unwrap_or_default());
range
}
pub fn type_reference(&mut self, ty: TypeRecord) -> TypeId {
let ty_id = TypeId::new(self.ast.types.len());
self.ast.types.push(ty);
ty_id
}
pub fn selection_set(
&mut self,
mut selection_set: Vec<SelectionRecord>,
) -> IdRange<SelectionId> {
let start_range = SelectionId::new(self.ast.selections.len());
self.ast.selections.append(&mut selection_set);
let end_range = SelectionId::new(self.ast.selections.len());
IdRange::new(start_range, end_range)
}
pub fn field_selection(&mut self, record: FieldSelectionRecord) -> FieldSelectionId {
let id = FieldSelectionId::new(self.ast.field_selections.len());
self.ast.field_selections.push(record);
id
}
pub fn fragment_spread(&mut self, record: FragmentSpreadRecord) -> FragmentSpreadId {
let id = FragmentSpreadId::new(self.ast.fragment_spreads.len());
self.ast.fragment_spreads.push(record);
id
}
pub fn inline_fragment(&mut self, record: InlineFragmentRecord) -> InlineFragmentId {
let id = InlineFragmentId::new(self.ast.inline_fragments.len());
self.ast.inline_fragments.push(record);
id
}
pub fn arguments(&mut self, mut records: Vec<ArgumentRecord>) -> IdRange<ArgumentId> {
let start = ArgumentId::new(self.ast.arguments.len());
self.ast.arguments.append(&mut records);
let end = ArgumentId::new(self.ast.arguments.len());
IdRange::new(start, end)
}
pub fn directive(&mut self, directive: DirectiveRecord) -> DirectiveId {
let id = DirectiveId::new(self.ast.directives.len());
self.ast.directives.push(directive);
id
}
pub fn directive_range(&mut self, expected_count: Option<usize>) -> IdRange<DirectiveId> {
let start = self.directive_cursor;
let end = DirectiveId::new(self.ast.directives.len());
self.directive_cursor = end;
let range = IdRange::new(start, end);
assert_eq!(range.len(), expected_count.unwrap_or_default());
range
}
pub fn value(&mut self, record: ValueRecord) -> ValueId {
let id = ValueId::new(self.ast.values.len());
self.ast.values.push(record);
id
}
pub fn block_string(&mut self, string: &str) -> BlockStringLiteralId {
let literal_id = BlockStringLiteralId::new(self.ast.block_strings.len());
self.ast.block_strings.push(string.into());
literal_id
}
pub fn ident(&mut self, ident: &str) -> StringId {
self.intern_string(ident)
}
pub fn intern_string(&mut self, string: &str) -> StringId {
let (id, _) = self.ast.strings.insert_full(string.into());
StringId::new(id)
}
pub fn intern_owned_string(&mut self, string: String) -> StringId {
let (id, _) = self.ast.strings.insert_full(string.into());
StringId::new(id)
}
}
impl Default for ExecutableAstWriter {
fn default() -> Self {
Self::new()
}
}