use crate::common::IdRange;
use crate::AstLookup;
use super::{ids::*, storage::*};
use super::{DefinitionRecord, TypeSystemDocument};
pub struct TypeSystemAstWriter {
ast: TypeSystemDocument,
field_id_cursor: FieldDefinitionId,
input_value_id_cursor: InputValueDefinitionId,
enum_value_id_cursor: EnumValueDefinitionId,
directive_id_cursor: DirectiveId,
argument_id_cursor: ArgumentId,
}
impl TypeSystemAstWriter {
pub fn new() -> Self {
TypeSystemAstWriter {
ast: Default::default(),
field_id_cursor: FieldDefinitionId::new(0),
input_value_id_cursor: InputValueDefinitionId::new(0),
enum_value_id_cursor: EnumValueDefinitionId::new(0),
directive_id_cursor: DirectiveId::new(0),
argument_id_cursor: ArgumentId::new(0),
}
}
pub fn update(ast: TypeSystemDocument) -> Self {
TypeSystemAstWriter {
field_id_cursor: FieldDefinitionId::new(ast.field_definitions.len()),
input_value_id_cursor: InputValueDefinitionId::new(ast.input_value_definitions.len()),
directive_id_cursor: DirectiveId::new(ast.directives.len()),
enum_value_id_cursor: EnumValueDefinitionId::new(ast.enum_value_definitions.len()),
argument_id_cursor: ArgumentId::new(ast.arguments.len()),
ast,
}
}
pub fn finish(self) -> TypeSystemDocument {
self.ast
}
pub fn store_description(
&mut self,
definition: DefinitionId,
description: Option<StringLiteralId>,
) {
if let Some(description) = description {
match *self.ast.lookup(definition) {
DefinitionRecord::Schema(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::Scalar(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::Object(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::Interface(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::Union(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::Enum(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::InputObject(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::SchemaExtension(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::ScalarExtension(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::ObjectExtension(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::InterfaceExtension(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::UnionExtension(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::EnumExtension(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::InputObjectExtension(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
DefinitionRecord::Directive(id) => {
self.ast.lookup_mut(id).description = Some(description);
}
}
}
}
pub fn schema_definition(&mut self, definition: SchemaDefinitionRecord) -> DefinitionId {
let id = SchemaDefinitionId::new(self.ast.schema_definitions.len());
self.ast.schema_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast.definitions.push(DefinitionRecord::Schema(id));
definition_id
}
pub fn root_operation_definitions(
&mut self,
definitions: Vec<RootOperationTypeDefinitionRecord>,
) -> IdRange<RootOperationTypeDefinitionId> {
let start_id =
RootOperationTypeDefinitionId::new(self.ast.root_operation_definitions.len());
self.ast.root_operation_definitions.extend(definitions);
let end_id = RootOperationTypeDefinitionId::new(self.ast.root_operation_definitions.len());
IdRange::new(start_id, end_id)
}
pub fn scalar_definition(&mut self, definition: ScalarDefinitionRecord) -> DefinitionId {
let id = ScalarDefinitionId::new(self.ast.scalar_definitions.len());
self.ast.scalar_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast.definitions.push(DefinitionRecord::Scalar(id));
definition_id
}
pub fn object_definition(&mut self, definition: ObjectDefinitionRecord) -> DefinitionId {
let id = ObjectDefinitionId::new(self.ast.object_definitions.len());
self.ast.object_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast.definitions.push(DefinitionRecord::Object(id));
definition_id
}
pub fn field_definition(&mut self, definition: FieldDefinitionRecord) -> FieldDefinitionId {
let definition_id = FieldDefinitionId::new(self.ast.field_definitions.len());
self.ast.field_definitions.push(definition);
definition_id
}
pub fn field_definition_range(
&mut self,
expected_count: Option<usize>,
) -> IdRange<FieldDefinitionId> {
let start = self.field_id_cursor;
let end = FieldDefinitionId::new(self.ast.field_definitions.len());
self.field_id_cursor = end;
let range = IdRange::new(start, end);
if let Some(expected_count) = expected_count {
assert_eq!(range.len(), expected_count);
}
range
}
pub fn interface_definition(&mut self, definition: InterfaceDefinitionRecord) -> DefinitionId {
let id = InterfaceDefinitionId::new(self.ast.interface_definitions.len());
self.ast.interface_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast.definitions.push(DefinitionRecord::Interface(id));
definition_id
}
pub fn union_definition(&mut self, definition: UnionDefinitionRecord) -> DefinitionId {
let id = UnionDefinitionId::new(self.ast.union_definitions.len());
self.ast.union_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast.definitions.push(DefinitionRecord::Union(id));
definition_id
}
pub fn enum_definition(&mut self, definition: EnumDefinitionRecord) -> DefinitionId {
let id = EnumDefinitionId::new(self.ast.enum_definitions.len());
self.ast.enum_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast.definitions.push(DefinitionRecord::Enum(id));
definition_id
}
pub fn enum_value_definition(
&mut self,
definition: EnumValueDefinitionRecord,
) -> EnumValueDefinitionId {
let id = EnumValueDefinitionId::new(self.ast.enum_value_definitions.len());
self.ast.enum_value_definitions.push(definition);
id
}
pub fn enum_value_definition_range(
&mut self,
expected_count: Option<usize>,
) -> IdRange<EnumValueDefinitionId> {
let start = self.enum_value_id_cursor;
let end = EnumValueDefinitionId::new(self.ast.enum_value_definitions.len());
self.enum_value_id_cursor = end;
let range = IdRange::new(start, end);
assert_eq!(range.len(), expected_count.unwrap_or_default());
range
}
pub fn input_object_definition(
&mut self,
definition: InputObjectDefinitionRecord,
) -> DefinitionId {
let id = InputObjectDefinitionId::new(self.ast.input_object_definitions.len());
self.ast.input_object_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast.definitions.push(DefinitionRecord::InputObject(id));
definition_id
}
pub fn input_value_definition(
&mut self,
definition: InputValueDefinitionRecord,
) -> InputValueDefinitionId {
let definition_id = InputValueDefinitionId::new(self.ast.input_value_definitions.len());
self.ast.input_value_definitions.push(definition);
definition_id
}
pub fn input_value_definition_range(
&mut self,
expected_count: Option<usize>,
) -> IdRange<InputValueDefinitionId> {
let start = self.input_value_id_cursor;
let end = InputValueDefinitionId::new(self.ast.input_value_definitions.len());
self.input_value_id_cursor = end;
let range = IdRange::new(start, end);
assert_eq!(range.len(), expected_count.unwrap_or_default());
range
}
pub fn schema_extension(&mut self, definition: SchemaDefinitionRecord) -> DefinitionId {
let id = SchemaDefinitionId::new(self.ast.schema_definitions.len());
self.ast.schema_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(DefinitionRecord::SchemaExtension(id));
definition_id
}
pub fn scalar_extension(&mut self, definition: ScalarDefinitionRecord) -> DefinitionId {
let id = ScalarDefinitionId::new(self.ast.scalar_definitions.len());
self.ast.scalar_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(DefinitionRecord::ScalarExtension(id));
definition_id
}
pub fn object_extension(&mut self, definition: ObjectDefinitionRecord) -> DefinitionId {
let id = ObjectDefinitionId::new(self.ast.object_definitions.len());
self.ast.object_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(DefinitionRecord::ObjectExtension(id));
definition_id
}
pub fn interface_extension(&mut self, definition: InterfaceDefinitionRecord) -> DefinitionId {
let id = InterfaceDefinitionId::new(self.ast.interface_definitions.len());
self.ast.interface_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(DefinitionRecord::InterfaceExtension(id));
definition_id
}
pub fn union_extension(&mut self, definition: UnionDefinitionRecord) -> DefinitionId {
let id = UnionDefinitionId::new(self.ast.union_definitions.len());
self.ast.union_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(DefinitionRecord::UnionExtension(id));
definition_id
}
pub fn enum_extension(&mut self, definition: EnumDefinitionRecord) -> DefinitionId {
let id = EnumDefinitionId::new(self.ast.enum_definitions.len());
self.ast.enum_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(DefinitionRecord::EnumExtension(id));
definition_id
}
pub fn input_object_extension(
&mut self,
definition: InputObjectDefinitionRecord,
) -> DefinitionId {
let id = InputObjectDefinitionId::new(self.ast.input_object_definitions.len());
self.ast.input_object_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast
.definitions
.push(DefinitionRecord::InputObjectExtension(id));
definition_id
}
pub fn directive_definition(&mut self, definition: DirectiveDefinitionRecord) -> DefinitionId {
let id = DirectiveDefinitionId::new(self.ast.directive_definitions.len());
self.ast.directive_definitions.push(definition);
let definition_id = DefinitionId::new(self.ast.definitions.len());
self.ast.definitions.push(DefinitionRecord::Directive(id));
definition_id
}
pub fn directive_range(&mut self, expected_count: Option<usize>) -> IdRange<DirectiveId> {
let start = self.directive_id_cursor;
let end = DirectiveId::new(self.ast.directives.len());
self.directive_id_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.type_references.len());
self.ast.type_references.push(ty);
ty_id
}
pub fn directive(&mut self, directive: DirectiveRecord) -> DirectiveId {
let id = DirectiveId::new(self.ast.directives.len());
self.ast.directives.push(directive);
id
}
pub fn argument(&mut self, argument: ArgumentRecord) -> ArgumentId {
let id = ArgumentId::new(self.ast.arguments.len());
self.ast.arguments.push(argument);
id
}
pub fn argument_range(&mut self, expected_count: Option<usize>) -> IdRange<ArgumentId> {
let start = self.argument_id_cursor;
let end = ArgumentId::new(self.ast.arguments.len());
self.argument_id_cursor = end;
let range = IdRange::new(start, end);
assert_eq!(range.len(), expected_count.unwrap_or_default());
range
}
pub fn value(&mut self, value: ValueRecord) -> ValueId {
let id = ValueId::new(self.ast.values.len());
self.ast.values.push(value);
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 TypeSystemAstWriter {
fn default() -> Self {
Self::new()
}
}