use std::any::Any;
use std::fmt::{Debug, Display, Formatter};
use arcref::ArcRef;
use vortex_array::DeserializeMetadata;
use vortex_error::{VortexExpect, VortexResult};
use crate::{ExprRef, IntoExpr, VTable};
pub type ExprId = ArcRef<str>;
pub type ExprEncodingRef = ArcRef<dyn ExprEncoding>;
pub trait ExprEncoding: 'static + Send + Sync + Debug + private::Sealed {
fn as_any(&self) -> &dyn Any;
fn id(&self) -> ExprId;
fn build(&self, metadata: &[u8], children: Vec<ExprRef>) -> VortexResult<ExprRef>;
}
#[repr(transparent)]
pub struct ExprEncodingAdapter<V: VTable>(V::Encoding);
impl<V: VTable> ExprEncoding for ExprEncodingAdapter<V> {
fn as_any(&self) -> &dyn Any {
self
}
fn id(&self) -> ExprId {
V::id(&self.0)
}
fn build(&self, metadata: &[u8], children: Vec<ExprRef>) -> VortexResult<ExprRef> {
let metadata = <V::Metadata as DeserializeMetadata>::deserialize(metadata)?;
Ok(V::build(&self.0, &metadata, children)?.into_expr())
}
}
impl<V: VTable> Debug for ExprEncodingAdapter<V> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ExprEncoding")
.field("id", &self.id())
.finish()
}
}
impl Display for dyn ExprEncoding + '_ {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.id())
}
}
impl PartialEq for dyn ExprEncoding + '_ {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl Eq for dyn ExprEncoding + '_ {}
impl dyn ExprEncoding + '_ {
pub fn is<V: VTable>(&self) -> bool {
self.as_opt::<V>().is_some()
}
pub fn as_<V: VTable>(&self) -> &V::Encoding {
self.as_opt::<V>()
.vortex_expect("ExprEncoding is not of the expected type")
}
pub fn as_opt<V: VTable>(&self) -> Option<&V::Encoding> {
self.as_any()
.downcast_ref::<ExprEncodingAdapter<V>>()
.map(|e| &e.0)
}
}
mod private {
use super::*;
pub trait Sealed {}
impl<V: VTable> Sealed for ExprEncodingAdapter<V> {}
}