use std::any::Any;
use std::borrow::Cow;
use std::fmt;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
use std::marker::PhantomData;
use std::ops::Deref;
use std::sync::Arc;
use vortex_array::SerializeMetadata;
use vortex_array::dtype::DType;
use vortex_error::VortexExpect;
use vortex_error::VortexResult;
use vortex_error::vortex_err;
use crate::plan::PlanChildren;
use crate::plan::PlanId;
use crate::plan::PlanVTable;
use crate::plan::display::PlanTreeDisplay;
struct PlanInner<D: ?Sized> {
id: PlanId,
dtype: DType,
row_count: u64,
children: PlanChildren,
data: D, }
#[derive(Clone)]
pub struct PlanRef(Arc<PlanInner<dyn DynPlan>>);
impl PlanRef {
fn from_inner<V: PlanVTable>(inner: Arc<PlanInner<PlanData<V>>>) -> Self {
let inner: Arc<PlanInner<dyn DynPlan>> = inner;
Self(inner)
}
fn dyn_plan(&self) -> &dyn DynPlan {
&self.0.data
}
pub fn ptr_eq(lhs: &Self, rhs: &Self) -> bool {
Arc::ptr_eq(&lhs.0, &rhs.0)
}
pub fn id(&self) -> PlanId {
self.0.id
}
pub fn dtype(&self) -> &DType {
&self.0.dtype
}
pub fn row_count(&self) -> u64 {
self.0.row_count
}
pub fn children(&self) -> &PlanChildren {
&self.0.children
}
pub fn child_count(&self) -> usize {
self.0.children.len()
}
pub fn child(&self, index: usize) -> VortexResult<Option<PlanRef>> {
self.0.children.get(index)
}
pub fn child_required(&self, index: usize) -> VortexResult<PlanRef> {
self.child(index)?
.ok_or_else(|| vortex_err!("Missing plan child {index}"))
}
pub fn with_children(&self, children: impl Into<PlanChildren>) -> VortexResult<PlanRef> {
self.dyn_plan().dyn_with_children(self, children.into())
}
pub fn child_name(&self, index: usize) -> Cow<'_, str> {
self.dyn_plan().dyn_child_name(self, index)
}
pub fn metadata(&self) -> Option<Vec<u8>> {
self.dyn_plan().dyn_metadata(self)
}
pub fn is<V: PlanVTable>(&self) -> bool {
self.dyn_plan().as_any().is::<PlanData<V>>()
}
pub fn as_<V: PlanVTable>(&self) -> &Plan<V> {
self.as_opt::<V>().vortex_expect("Failed to downcast")
}
pub fn as_opt<V: PlanVTable>(&self) -> Option<&Plan<V>> {
if !self.is::<V>() {
return None;
}
Some(unsafe { &*(std::ptr::from_ref(self).cast::<Plan<V>>()) })
}
pub fn display_tree(&self) -> PlanTreeDisplay<'_> {
PlanTreeDisplay::default_display(self)
}
pub fn tree_display_builder(&self) -> PlanTreeDisplay<'_> {
PlanTreeDisplay::new(self)
}
}
impl Display for PlanRef {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
write!(
formatter,
"{}({}, rows={})",
self.id(),
self.dtype(),
self.row_count()
)?;
self.dyn_plan().dyn_fmt(self, formatter)
}
}
impl Debug for PlanRef {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("Plan")
.field("id", &self.0.id)
.field("dtype", &self.0.dtype)
.field("row_count", &self.0.row_count)
.field("children", &self.0.children)
.field("data", &&self.0.data)
.finish()
}
}
pub struct PlanParts<V: PlanVTable> {
pub vtable: V,
pub dtype: DType,
pub row_count: u64,
pub children: PlanChildren,
pub data: V::PlanData,
}
impl<V: PlanVTable> PlanParts<V> {
pub fn into_typed(self) -> Plan<V> {
Plan::from_parts(self)
}
pub fn into_plan(self) -> PlanRef {
self.into_typed().into_plan()
}
}
#[repr(transparent)]
pub struct Plan<V: PlanVTable> {
inner: PlanRef,
_vtable: PhantomData<V>,
}
impl<V: PlanVTable> Plan<V> {
pub fn from_parts(parts: PlanParts<V>) -> Self {
let inner = Arc::new(PlanInner {
id: parts.vtable.id(),
dtype: parts.dtype,
row_count: parts.row_count,
children: parts.children,
data: PlanData {
vtable: parts.vtable,
data: parts.data,
},
});
Self {
inner: PlanRef::from_inner(inner),
_vtable: PhantomData,
}
}
fn typed_data(&self) -> &PlanData<V> {
self.inner
.dyn_plan()
.as_any()
.downcast_ref::<PlanData<V>>()
.vortex_expect("Typed plan contains the wrong vtable")
}
pub fn vtable(&self) -> &V {
&self.typed_data().vtable
}
pub fn data(&self) -> &V::PlanData {
&self.typed_data().data
}
pub fn dtype(&self) -> &DType {
self.inner.dtype()
}
pub fn row_count(&self) -> u64 {
self.inner.row_count()
}
pub fn children(&self) -> &PlanChildren {
self.inner.children()
}
pub fn child(&self, index: usize) -> VortexResult<Option<PlanRef>> {
self.inner.child(index)
}
pub fn child_required(&self, index: usize) -> VortexResult<PlanRef> {
self.inner.child_required(index)
}
pub fn to_plan(&self) -> PlanRef {
self.inner.clone()
}
pub fn into_plan(self) -> PlanRef {
self.inner
}
}
impl<V: PlanVTable> Clone for Plan<V> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
_vtable: PhantomData,
}
}
}
impl<V: PlanVTable> Debug for Plan<V> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.inner, formatter)
}
}
impl<V: PlanVTable> Display for Plan<V> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.inner, formatter)
}
}
impl<V: PlanVTable> Deref for Plan<V> {
type Target = V::PlanData;
fn deref(&self) -> &Self::Target {
self.data()
}
}
impl<V: PlanVTable> From<Plan<V>> for PlanRef {
fn from(value: Plan<V>) -> Self {
value.into_plan()
}
}
struct PlanData<V: PlanVTable> {
vtable: V,
data: V::PlanData,
}
impl<V: PlanVTable> Debug for PlanData<V> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("PlanData")
.field("vtable", &self.vtable)
.field("data", &self.data)
.finish()
}
}
#[doc(hidden)]
pub trait DynPlan: 'static + Send + Sync + Debug {
fn as_any(&self) -> &dyn Any;
fn dyn_fmt(&self, plan: &PlanRef, formatter: &mut Formatter<'_>) -> fmt::Result;
fn dyn_with_children(&self, plan: &PlanRef, children: PlanChildren) -> VortexResult<PlanRef>;
fn dyn_child_name<'a>(&'a self, plan: &'a PlanRef, index: usize) -> Cow<'a, str>;
fn dyn_metadata(&self, plan: &PlanRef) -> Option<Vec<u8>>;
}
impl<V: PlanVTable> DynPlan for PlanData<V> {
fn as_any(&self) -> &dyn Any {
self
}
fn dyn_fmt(&self, plan: &PlanRef, formatter: &mut Formatter<'_>) -> fmt::Result {
<V as PlanVTable>::fmt(plan.as_::<V>(), formatter)
}
fn dyn_with_children(&self, plan: &PlanRef, children: PlanChildren) -> VortexResult<PlanRef> {
let mut data = self.data.clone();
V::with_children(plan.as_::<V>(), &children, &mut data)?;
Ok(PlanParts {
vtable: self.vtable.clone(),
dtype: plan.dtype().clone(),
row_count: plan.row_count(),
children,
data,
}
.into_plan())
}
fn dyn_child_name<'a>(&'a self, plan: &'a PlanRef, index: usize) -> Cow<'a, str> {
V::child_name(plan.as_::<V>(), index)
}
fn dyn_metadata(&self, plan: &PlanRef) -> Option<Vec<u8>> {
V::metadata(plan.as_::<V>()).map(SerializeMetadata::serialize)
}
}