use std::hash::{Hash, Hasher};
use selene_core::{
DbString, DecimalType, MAX_BYTE_STRING_TYPE_LENGTH, MAX_CHARACTER_STRING_TYPE_LENGTH,
};
#[derive(Clone, Debug, Eq, Hash, PartialEq, serde::Deserialize, serde::Serialize)]
#[non_exhaustive]
pub enum GqlType {
Any,
AnyProperty,
ClosedDynamicUnion(Vec<GqlType>),
String,
CharacterString(CharacterStringType),
Boolean,
Integer,
Float,
Int8,
Int16,
Int32,
Int64,
Int128,
Uint8,
Uint16,
Uint32,
Uint64,
Uint128,
USmallInt,
Uint,
UBigInt,
SmallInt,
BigInt,
Decimal,
DecimalExact(DecimalType),
Float32,
Float64,
Real,
Double,
Bytes,
ByteString(ByteStringType),
Uuid,
Json,
ZonedDateTime,
LocalDateTime,
Date,
ZonedTime,
LocalTime,
Duration,
DurationYearToMonth,
DurationDayToSecond,
Vector,
Record(RecordType),
List(Box<GqlType>),
BoundedList {
element_type: Box<GqlType>,
max_len: u64,
},
NotNull(Box<GqlType>),
Path,
GraphRef,
NodeRef,
EdgeRef,
TableRef(BindingTableType),
Null,
Nothing,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq, serde::Deserialize, serde::Serialize)]
pub enum BindingTableType {
Any,
Closed(Vec<(DbString, GqlType)>),
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct CharacterStringType {
pub min_len: u64,
pub max_len: u64,
pub form: CharacterStringTypeForm,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub enum CharacterStringTypeForm {
StringMax,
StringMinMax,
CharFixed,
VarcharMax,
}
impl CharacterStringType {
#[must_use]
pub const fn new(min_len: u64, max_len: u64, form: CharacterStringTypeForm) -> Option<Self> {
if max_len == 0 || min_len > max_len || max_len > MAX_CHARACTER_STRING_TYPE_LENGTH {
return None;
}
Some(Self {
min_len,
max_len,
form,
})
}
#[must_use]
pub const fn is_fixed_length(&self) -> bool {
self.min_len == self.max_len
}
}
impl PartialEq for CharacterStringType {
fn eq(&self, other: &Self) -> bool {
self.min_len == other.min_len && self.max_len == other.max_len
}
}
impl Eq for CharacterStringType {}
impl Hash for CharacterStringType {
fn hash<H: Hasher>(&self, state: &mut H) {
self.min_len.hash(state);
self.max_len.hash(state);
}
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct ByteStringType {
pub min_len: u64,
pub max_len: u64,
pub form: ByteStringTypeForm,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub enum ByteStringTypeForm {
BytesMax,
BytesMinMax,
BinaryFixed,
VarbinaryMax,
}
impl ByteStringType {
#[must_use]
pub const fn new(min_len: u64, max_len: u64, form: ByteStringTypeForm) -> Option<Self> {
if max_len == 0 || min_len > max_len || max_len > MAX_BYTE_STRING_TYPE_LENGTH {
return None;
}
Some(Self {
min_len,
max_len,
form,
})
}
#[must_use]
pub const fn is_fixed_length(&self) -> bool {
self.min_len == self.max_len
}
}
impl PartialEq for ByteStringType {
fn eq(&self, other: &Self) -> bool {
self.min_len == other.min_len && self.max_len == other.max_len
}
}
impl Eq for ByteStringType {}
impl Hash for ByteStringType {
fn hash<H: Hasher>(&self, state: &mut H) {
self.min_len.hash(state);
self.max_len.hash(state);
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq, serde::Deserialize, serde::Serialize)]
#[non_exhaustive]
pub enum RecordType {
Open,
Closed(Vec<(DbString, GqlType)>),
}
impl GqlType {
#[must_use]
pub fn strip_not_null(&self) -> &Self {
let mut ty = self;
while let Self::NotNull(inner) = ty {
ty = inner;
}
ty
}
#[must_use]
pub fn is_duration(&self) -> bool {
matches!(
self.strip_not_null(),
Self::Duration | Self::DurationYearToMonth | Self::DurationDayToSecond
)
}
}