use std::fmt;
use crate::{Error, Span};
mod lexer;
mod ty;
mod argument;
mod directive;
mod directive_argument;
mod member;
#[allow(unused_braces)]
mod parser;
pub use self::{
argument::ArgumentCoordinate, directive::DirectiveCoordinate,
directive_argument::DirectiveArgumentCoordinate, member::MemberCoordinate, ty::TypeCoordinate,
};
pub fn parse_schema_coordinate(input: &str) -> Result<SchemaCoordinate, Error> {
if input.trim().is_empty() {
return Err(Error::EmptySchemaCoordinate);
}
let lexer = lexer::Lexer::new(input);
Ok(parser::SchemaCoordinateParser::new().parse(input, lexer)?)
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub enum SchemaCoordinate {
Type(TypeCoordinate),
Member(MemberCoordinate),
Argument(ArgumentCoordinate),
Directive(DirectiveCoordinate),
DirectiveArgument(DirectiveArgumentCoordinate),
}
impl SchemaCoordinate {
pub fn ty(name: impl Into<String>) -> Self {
SchemaCoordinate::Type(TypeCoordinate::new(name))
}
pub fn member(ty: impl Into<String>, field: impl Into<String>) -> Self {
SchemaCoordinate::Member(MemberCoordinate::new(ty, field))
}
pub fn argument(
ty: impl Into<String>,
field: impl Into<String>,
argument: impl Into<String>,
) -> Self {
SchemaCoordinate::Argument(ArgumentCoordinate::new(ty, field, argument))
}
pub fn directive(name: impl Into<String>) -> Self {
SchemaCoordinate::Directive(DirectiveCoordinate::new(name))
}
pub fn directive_argument(name: impl Into<String>, argument: impl Into<String>) -> Self {
SchemaCoordinate::DirectiveArgument(DirectiveArgumentCoordinate::new(name, argument))
}
pub fn as_ty(&self) -> Option<&TypeCoordinate> {
match self {
SchemaCoordinate::Type(inner) => Some(inner),
_ => None,
}
}
pub fn is_ty(&self) -> bool {
matches!(self, SchemaCoordinate::Type(_))
}
pub fn as_member(&self) -> Option<&MemberCoordinate> {
match self {
SchemaCoordinate::Member(inner) => Some(inner),
_ => None,
}
}
pub fn is_member(&self) -> bool {
matches!(self, SchemaCoordinate::Member(_))
}
pub fn as_argument(&self) -> Option<&ArgumentCoordinate> {
match self {
SchemaCoordinate::Argument(inner) => Some(inner),
_ => None,
}
}
pub fn is_argument(&self) -> bool {
matches!(self, SchemaCoordinate::Argument(_))
}
pub fn as_directive(&self) -> Option<&DirectiveCoordinate> {
match self {
SchemaCoordinate::Directive(inner) => Some(inner),
_ => None,
}
}
pub fn is_directive(&self) -> bool {
matches!(self, SchemaCoordinate::Directive(_))
}
pub fn as_directive_argument(&self) -> Option<&DirectiveArgumentCoordinate> {
match self {
SchemaCoordinate::DirectiveArgument(inner) => Some(inner),
_ => None,
}
}
pub fn is_directive_argument(&self) -> bool {
matches!(self, SchemaCoordinate::DirectiveArgument(_))
}
}
impl fmt::Display for SchemaCoordinate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SchemaCoordinate::Type(inner) => write!(f, "{inner}"),
SchemaCoordinate::Member(inner) => write!(f, "{inner}"),
SchemaCoordinate::Argument(inner) => write!(f, "{inner}"),
SchemaCoordinate::Directive(inner) => write!(f, "{inner}"),
SchemaCoordinate::DirectiveArgument(inner) => write!(f, "{inner}"),
}
}
}
#[derive(Clone, Debug, Eq)]
pub struct Name {
span: Span,
value: Box<str>,
}
impl Name {
fn new(value: String) -> Self {
Name {
span: Span::default(),
value: value.into(),
}
}
}
impl PartialEq for Name {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl PartialOrd for Name {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Name {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.value.cmp(&other.value)
}
}
impl std::hash::Hash for Name {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.value.hash(state);
}
}