use crate::GqlType;
type MeetFn = fn(&GqlType, &GqlType) -> Option<GqlType>;
pub(crate) fn list_concat_type(lhs: &GqlType, rhs: &GqlType, meet: MeetFn) -> Option<GqlType> {
let (Some(lhs_inner), Some(rhs_inner)) = (list_element_type(lhs), list_element_type(rhs))
else {
return None;
};
let max_len = match (list_max_len(lhs), list_max_len(rhs)) {
(Some(lhs_max), Some(rhs_max)) => lhs_max.checked_add(rhs_max),
_ => None,
};
meet(lhs_inner, rhs_inner).map(|inner| list_type(inner, max_len))
}
pub(crate) fn list_union_type(lhs: &GqlType, rhs: &GqlType, meet: MeetFn) -> Option<GqlType> {
let (Some(lhs_inner), Some(rhs_inner)) = (list_element_type(lhs), list_element_type(rhs))
else {
return None;
};
let max_len = match (list_max_len(lhs), list_max_len(rhs)) {
(Some(lhs_max), Some(rhs_max)) => Some(lhs_max.max(rhs_max)),
_ => None,
};
meet(lhs_inner, rhs_inner).map(|ty| list_type(ty, max_len))
}
pub(crate) fn list_element_type(ty: &GqlType) -> Option<&GqlType> {
match ty {
GqlType::List(inner)
| GqlType::BoundedList {
element_type: inner,
..
} => Some(inner),
_ => None,
}
}
pub(crate) fn list_max_len(ty: &GqlType) -> Option<u64> {
match ty {
GqlType::BoundedList { max_len, .. } => Some(*max_len),
_ => None,
}
}
pub(crate) fn list_type(element_type: GqlType, max_len: Option<u64>) -> GqlType {
match max_len {
Some(max_len) => GqlType::BoundedList {
element_type: Box::new(element_type),
max_len,
},
None => GqlType::List(Box::new(element_type)),
}
}