use crate::datasets::{Dataset, DatasetMeta};
use super::stable::StableTuple;
use crate::error::PondError;
pub(crate) fn ptr_to_id<T: ?Sized>(r: &T) -> usize {
r as *const T as *const () as usize
}
pub struct DatasetRef<'a> {
pub id: usize,
pub meta: &'a dyn DatasetMeta,
pub name: Option<&'a str>,
}
impl<'a> DatasetRef<'a> {
pub fn from_ref<T: Dataset + Send + Sync>(ds: &'a T) -> Self {
Self {
id: ptr_to_id(ds),
meta: ds,
name: None,
}
}
}
impl core::fmt::Debug for DatasetRef<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("DatasetRef")
.field("id", &self.id)
.field("is_param", &self.meta.is_param())
.field("name", &self.name)
.finish()
}
}
impl Clone for DatasetRef<'_> {
fn clone(&self) -> Self { *self }
}
impl Copy for DatasetRef<'_> {}
#[derive(Debug, Clone, Copy)]
pub enum DatasetEvent {
BeforeLoad,
AfterLoad,
BeforeSave,
AfterSave,
}
pub trait StepInfo: Send + Sync {
fn name(&self) -> &'static str;
fn is_leaf(&self) -> bool;
fn type_string(&self) -> &'static str;
fn for_each_child<'a>(&'a self, f: &mut dyn FnMut(&'a dyn StepInfo));
fn for_each_input<'s>(&'s self, f: &mut dyn FnMut(&DatasetRef<'s>));
fn for_each_output<'s>(&'s self, f: &mut dyn FnMut(&DatasetRef<'s>));
}
pub trait RunnableStep<E>: StepInfo {
fn call(&self, on_event: &mut dyn FnMut(&DatasetRef<'_>, DatasetEvent)) -> Result<(), E>;
fn for_each_child_step<'a>(&'a self, f: &mut dyn FnMut(&'a dyn RunnableStep<E>));
fn as_pipeline_info(&self) -> &dyn StepInfo;
#[cfg(feature = "std")]
fn boxed<'a>(self) -> std::boxed::Box<dyn RunnableStep<E> + Send + Sync + 'a>
where
Self: Sized + Send + Sync + 'a,
{
std::boxed::Box::new(self)
}
}
impl<T: StepInfo + ?Sized> StepInfo for &T {
fn name(&self) -> &'static str { (**self).name() }
fn is_leaf(&self) -> bool { (**self).is_leaf() }
fn type_string(&self) -> &'static str { (**self).type_string() }
fn for_each_child<'a>(&'a self, f: &mut dyn FnMut(&'a dyn StepInfo)) {
(**self).for_each_child(f);
}
fn for_each_input<'s>(&'s self, f: &mut dyn FnMut(&DatasetRef<'s>)) {
(**self).for_each_input(f);
}
fn for_each_output<'s>(&'s self, f: &mut dyn FnMut(&DatasetRef<'s>)) {
(**self).for_each_output(f);
}
}
impl<E, T: RunnableStep<E> + ?Sized> RunnableStep<E> for &T {
fn call(&self, on_event: &mut dyn FnMut(&DatasetRef<'_>, DatasetEvent)) -> Result<(), E> {
(**self).call(on_event)
}
fn for_each_child_step<'a>(&'a self, f: &mut dyn FnMut(&'a dyn RunnableStep<E>)) {
(**self).for_each_child_step(f);
}
fn as_pipeline_info(&self) -> &dyn StepInfo { (**self).as_pipeline_info() }
}
pub trait NodeInput: StableTuple {
type Args: StableTuple;
fn load_data(&self, on_event: &mut dyn FnMut(&DatasetRef<'_>, DatasetEvent)) -> Result<Self::Args, PondError>;
fn for_each_input<'s>(&'s self, f: &mut dyn FnMut(&DatasetRef<'s>));
}
impl NodeInput for () {
type Args = ();
fn load_data(&self, _on_event: &mut dyn FnMut(&DatasetRef<'_>, DatasetEvent)) -> Result<Self::Args, PondError> {
Ok(())
}
fn for_each_input<'s>(&'s self, _f: &mut dyn FnMut(&DatasetRef<'s>)) {}
}
macro_rules! impl_node_input {
($($T:ident $idx:tt),+) => {
impl<$($T: Dataset + Send + Sync),+> NodeInput for ($(&$T,)+)
where
$(PondError: From<$T::Error>,)+
{
type Args = ($($T::LoadItem,)+);
#[allow(non_snake_case)]
fn load_data(&self, on_event: &mut dyn FnMut(&DatasetRef<'_>, DatasetEvent)) -> Result<Self::Args, PondError> {
$(
let ds = DatasetRef::from_ref(self.$idx);
on_event(&ds, DatasetEvent::BeforeLoad);
let $T = self.$idx.load()?;
on_event(&ds, DatasetEvent::AfterLoad);
)+
Ok(($($T,)+))
}
fn for_each_input<'s>(&'s self, f: &mut dyn FnMut(&DatasetRef<'s>)) {
$(f(&DatasetRef::from_ref(self.$idx));)+
}
}
};
}
impl_node_input!(T0 0);
impl_node_input!(T0 0, T1 1);
impl_node_input!(T0 0, T1 1, T2 2);
impl_node_input!(T0 0, T1 1, T2 2, T3 3);
impl_node_input!(T0 0, T1 1, T2 2, T3 3, T4 4);
impl_node_input!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5);
impl_node_input!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6);
impl_node_input!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7);
impl_node_input!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8);
impl_node_input!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9);
pub trait NodeOutput: StableTuple {
type Output: StableTuple;
fn save_data(&self, output: Self::Output, on_event: &mut dyn FnMut(&DatasetRef<'_>, DatasetEvent)) -> Result<(), PondError>;
fn for_each_output<'s>(&'s self, f: &mut dyn FnMut(&DatasetRef<'s>));
}
impl NodeOutput for () {
type Output = ();
fn save_data(&self, _output: Self::Output, _on_event: &mut dyn FnMut(&DatasetRef<'_>, DatasetEvent)) -> Result<(), PondError> {
Ok(())
}
fn for_each_output<'s>(&'s self, _f: &mut dyn FnMut(&DatasetRef<'s>)) {}
}
macro_rules! impl_node_output {
($($T:ident $idx:tt),+) => {
impl<$($T: Dataset + Send + Sync),+> NodeOutput for ($(&$T,)+)
where
$(PondError: From<$T::Error>,)+
{
type Output = ($($T::SaveItem,)+);
fn save_data(&self, output: Self::Output, on_event: &mut dyn FnMut(&DatasetRef<'_>, DatasetEvent)) -> Result<(), PondError> {
$({
let ds = DatasetRef::from_ref(self.$idx);
on_event(&ds, DatasetEvent::BeforeSave);
self.$idx.save(output.$idx)?;
on_event(&ds, DatasetEvent::AfterSave);
})+
Ok(())
}
fn for_each_output<'s>(&'s self, f: &mut dyn FnMut(&DatasetRef<'s>)) {
$(f(&DatasetRef::from_ref(self.$idx));)+
}
}
};
}
impl_node_output!(T0 0);
impl_node_output!(T0 0, T1 1);
impl_node_output!(T0 0, T1 1, T2 2);
impl_node_output!(T0 0, T1 1, T2 2, T3 3);
impl_node_output!(T0 0, T1 1, T2 2, T3 3, T4 4);
impl_node_output!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5);
impl_node_output!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6);
impl_node_output!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7);
impl_node_output!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8);
impl_node_output!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9);