Skip to content

Commit

Permalink
remove need for ParseResult
Browse files Browse the repository at this point in the history
  • Loading branch information
JoviDeCroock committed May 23, 2024
1 parent cd93b2c commit fb7ff6c
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 45 deletions.
9 changes: 4 additions & 5 deletions src/schema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@
//!
//! [More information on the Schema struct.](Schema)
pub mod build_client_schema;
pub mod introspection;
#[allow(clippy::module_inception)]
pub mod schema;
mod sdl;
mod schema;
mod schema_reference;

pub mod build_client_schema;
pub mod introspection;
pub mod sdl;
pub use build_client_schema::BuildClientSchema;
pub use introspection::{IntrospectionQuery, IntrospectionSchema};
pub use schema::*;
pub use schema_reference::*;
pub use sdl::*;
57 changes: 26 additions & 31 deletions src/schema/sdl/finalizers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,62 @@ use bumpalo::collections::Vec;
use hashbrown::HashMap;

use super::parse_ast::*;
use super::parser::ParseResult;
use crate::ast::ASTContext;
use crate::schema::{
SchemaField, SchemaFields, SchemaInputField, SchemaInputObject, SchemaInterface, SchemaInterfaces, SchemaObject, SchemaPossibleTypes, SchemaType, SchemaUnion, TypeRef
};

fn convert_to_schema_field<'a>(ctx: &'a ASTContext, name: &'a str, field: &'a SchemaFieldPlaceholder) -> ParseResult<SchemaField<'a>> {
fn convert_to_schema_field<'a>(ctx: &'a ASTContext, name: &'a str, field: &'a SchemaFieldPlaceholder) -> SchemaField<'a> {
let mut arguments = HashMap::new_in(&ctx.arena);
for (name, argument) in field.arguments.arguments.iter() {
arguments.insert(
*name,
SchemaInputField {
name,
input_type: map_input_type(&ctx, argument.input_type)?,
input_type: map_input_type(&ctx, argument.input_type),
},
);
}

Ok(SchemaField {
SchemaField {
name,
arguments,
output_type: map_output_type(&ctx, field.output_type)?,
})
output_type: map_output_type(&ctx, field.output_type),
}
}

fn map_input_type<'a>(
arena: &'a ASTContext,
wrapper: &'a TypeWrapper<'a>,
) -> ParseResult<&'a TypeRef<'a>> {
) -> &'a TypeRef<'a> {
match wrapper {
TypeWrapper::NonNull(inner) => {
Ok(arena.alloc(TypeRef::NonNullType(map_input_type(arena, inner)?)))
arena.alloc(TypeRef::NonNullType(map_input_type(arena, inner)))
}

TypeWrapper::List(inner) => {
Ok(arena.alloc(TypeRef::ListType(map_input_type(arena, inner)?)))
arena.alloc(TypeRef::ListType(map_input_type(arena, inner)))
}

TypeWrapper::Named(name) => {
// Todo check if this is necessary? (relates to schema change)
Ok(arena.alloc(TypeRef::Type(name)))
arena.alloc(TypeRef::Type(name))
}
}
}

fn map_output_type<'a>(
arena: &'a ASTContext,
wrapper: &'a TypeWrapper<'a>,
) -> ParseResult<&'a TypeRef<'a>> {
) -> &'a TypeRef<'a> {
match wrapper {
TypeWrapper::NonNull(inner) => {
Ok(arena.alloc(TypeRef::NonNullType(map_output_type(arena, inner)?)))
arena.alloc(TypeRef::NonNullType(map_output_type(arena, inner)))
}

TypeWrapper::List(inner) => {
Ok(arena.alloc(TypeRef::ListType(map_output_type(arena, inner)?)))
arena.alloc(TypeRef::ListType(map_output_type(arena, inner)))
}

TypeWrapper::Named(name) => {
Ok(arena.alloc(TypeRef::Type(name)))
arena.alloc(TypeRef::Type(name))
}
}
}
Expand All @@ -71,12 +67,12 @@ fn map_output_type<'a>(
pub(super) fn initialize_type_definition<'a>(
ctx: &'a ASTContext,
typ: &'a TypeDefinition<'a>,
) -> ParseResult<&'a SchemaType<'a>> {
) -> &'a SchemaType<'a> {
match typ {
TypeDefinition::ObjectTypeDefinition(obj) => {
let mut fields = HashMap::new_in(&ctx.arena);
for field in obj.fields.fields.iter() {
let schema_field = convert_to_schema_field(ctx, field.0, field.1)?;
let schema_field = convert_to_schema_field(ctx, field.0, field.1);
fields.insert(*field.0, ctx.alloc(schema_field));
}

Expand All @@ -85,11 +81,11 @@ pub(super) fn initialize_type_definition<'a>(
interfaces.push(*interface)
}

Ok(ctx.arena.alloc(SchemaType::Object(ctx.arena.alloc(SchemaObject {
ctx.arena.alloc(SchemaType::Object(ctx.arena.alloc(SchemaObject {
name: obj.name,
fields,
interfaces
}))))
})))
}
TypeDefinition::InputObjectTypeDefinition(obj) => {
let mut fields = HashMap::new_in(&ctx.arena);
Expand All @@ -98,41 +94,40 @@ pub(super) fn initialize_type_definition<'a>(
*name,
SchemaInputField {
name,
input_type: map_input_type(&ctx, input_field.input_type)?,
input_type: map_input_type(&ctx, input_field.input_type),
},
);
}

Ok(ctx.arena.alloc(SchemaType::InputObject(ctx.arena.alloc(SchemaInputObject {
ctx.arena.alloc(SchemaType::InputObject(ctx.arena.alloc(SchemaInputObject {
name: obj.name,
fields
}))))
})))
}
TypeDefinition::EnumTypeDefinition(e) => Ok(ctx.arena.alloc(SchemaType::Enum(e))),
TypeDefinition::ScalarTypeDefinition(s) => Ok(ctx.arena.alloc(SchemaType::Scalar(s))),
TypeDefinition::EnumTypeDefinition(e) => ctx.arena.alloc(SchemaType::Enum(e)),
TypeDefinition::ScalarTypeDefinition(s) => ctx.arena.alloc(SchemaType::Scalar(s)),

TypeDefinition::InterfaceTypeDefinition(i) => {
let mut schema_interface = SchemaInterface::new(ctx, i.name);
for field in i.fields.fields.iter() {
let schema_field = convert_to_schema_field(ctx, field.0, field.1)?;
let schema_field = convert_to_schema_field(ctx, field.0, field.1);
schema_interface.add_field(ctx, schema_field);
}

for obj in i.interfaces.iter() {
// TODO: add possible_types
schema_interface.add_interface(ctx, *obj);
}

Ok(ctx.arena.alloc(SchemaType::Interface(
ctx.arena.alloc(SchemaType::Interface(
ctx.arena.alloc(schema_interface),
)))
))
},
TypeDefinition::UnionTypeDefinition(u) => {
let mut schema_union = SchemaUnion::new(ctx, u.name);
for obj in u.types.iter() {
schema_union.add_possible_type(ctx, *obj);
}
Ok(ctx.arena.alloc(SchemaType::Union(ctx.arena.alloc(schema_union))))
ctx.arena.alloc(SchemaType::Union(ctx.arena.alloc(schema_union)))
}
}
}
7 changes: 5 additions & 2 deletions src/schema/sdl/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
mod error;
mod finalizers;
mod lexer;
mod parse_ast;
mod parser;

#[cfg(test)]
mod tests;

pub mod error;
pub mod parser;
6 changes: 6 additions & 0 deletions src/schema/sdl/parse_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ pub(super) enum TypeDefinition<'a> {
UnionTypeDefinition(SchemaUnionPlaceholder<'a>),
}

// https://github.com/graphql/graphql-spec/blob/main/spec/Section%203%20--%20Type%20System.md#directives
// #[derive(Debug, Clone)]
// pub(super) enum DirectiveDefinition<'a> {
// DirectiveDefinition(&'a str),
// }

impl<'a> TypeDefinition<'a> {
pub(crate) fn name(&self) -> &'a str {
match self {
Expand Down
14 changes: 7 additions & 7 deletions src/schema/sdl/parser.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
//! Note: The arena allocs in betwen are necessary and can be thought of as boxing, just on the arena:
//! Normally, to have a finite enum size (as is required for recursive enums like `TypeWrapper`), you `Box`
//! variants, which is a heap allocation. Here, we "box" by allocating on the arena. This is necessary because
//! Box is not `Copy`, but in this crate `Copy` is a requirement to seamlessly work with the arena datastructures.
use super::{
error::{syntax, syntax_err, SchemaError}, finalizers::initialize_type_definition, parse_ast::*
};
Expand Down Expand Up @@ -152,6 +147,7 @@ const DEFAULT_SCALARS: [&str; 5] = [
impl<'a> private::ParseFromCtx<'a> for Schema<'a> {
#[inline]
fn parse_from_ctx(ctx: &mut private::ParserContext<'a>) -> ParseResult<Self> {
// TODO: support directives
let mut schema = Schema::default_in(&ctx.ast_ctx.arena);
let mut schema_def = None;
let mut type_defs = Vec::new_in(&ctx.ast_ctx.arena);
Expand Down Expand Up @@ -181,11 +177,15 @@ impl<'a> private::ParseFromCtx<'a> for Schema<'a> {
for typ in type_defs.into_iter() {
schema.types.insert(
typ.name(),
initialize_type_definition(&ctx.ast_ctx, ctx.ast_ctx.alloc(typ))?,
initialize_type_definition(&ctx.ast_ctx, ctx.ast_ctx.alloc(typ)),
);
}

// find root types
for (name, typ) in schema.types.iter() {
// TODO: this pass will be used to validate the existence of all references
}

// fill in the root types
if let Some(query_type) = schema_def
.map_or(Some("Query"), |def| def.query_root_type_name)
.and_then(|name| schema.types.get(name))
Expand Down

0 comments on commit fb7ff6c

Please sign in to comment.