use std::ops::{Deref, DerefMut};
use toasty_core::stmt;
#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq)]
pub(crate) enum SelectItem {
ExprReference(stmt::ExprReference),
CountStar,
}
impl SelectItem {
#[track_caller]
pub(crate) fn as_expr_reference_unwrap(&self) -> &stmt::ExprReference {
match self {
SelectItem::ExprReference(r) => r,
other => panic!("expected ExprReference, got {other:?}"),
}
}
pub(crate) fn infer_ty(&self, cx: &stmt::ExprContext<'_>) -> stmt::Type {
match self {
SelectItem::ExprReference(expr_reference) => cx.infer_expr_reference_ty(expr_reference),
SelectItem::CountStar => stmt::Type::U64,
}
}
pub(crate) fn to_expr(self) -> stmt::Expr {
match self {
SelectItem::ExprReference(expr_reference) => stmt::Expr::from(expr_reference),
SelectItem::CountStar => stmt::Expr::count_star(),
}
}
}
impl From<stmt::ExprReference> for SelectItem {
fn from(value: stmt::ExprReference) -> Self {
SelectItem::ExprReference(value)
}
}
#[derive(Debug, Default, Clone)]
pub(crate) struct SelectItems(indexmap::IndexSet<SelectItem>);
impl SelectItems {
pub(crate) fn new() -> Self {
Self(indexmap::IndexSet::new())
}
pub(crate) fn try_get_index_of_expr_reference(
&self,
expr_reference: impl Into<stmt::ExprReference>,
) -> Option<usize> {
let item = SelectItem::ExprReference(expr_reference.into());
self.0.get_index_of(&item)
}
pub(crate) fn get_index_of_expr_reference(
&self,
expr_reference: impl Into<stmt::ExprReference>,
) -> usize {
self.try_get_index_of_expr_reference(expr_reference)
.unwrap()
}
pub(crate) fn get_index_of_count_star(&self) -> usize {
self.0.get_index_of(&SelectItem::CountStar).unwrap()
}
pub(crate) fn infer_record_list_ty(&self, cx: &stmt::ExprContext<'_>) -> stmt::Type {
let field_tys = self.0.iter().map(|item| item.infer_ty(cx)).collect();
stmt::Type::list(stmt::Type::Record(field_tys))
}
pub(crate) fn extract_expr_references(&self) -> indexmap::IndexSet<stmt::ExprReference> {
self.0
.iter()
.map(|item| *item.as_expr_reference_unwrap())
.collect()
}
}
impl<'a> IntoIterator for &'a SelectItems {
type Item = &'a SelectItem;
type IntoIter = indexmap::set::Iter<'a, SelectItem>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl Deref for SelectItems {
type Target = indexmap::IndexSet<SelectItem>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for SelectItems {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}