use derive_new::new;
use std::cell::RefCell;
use std::fmt::{Debug, Display};
use std::rc::Rc;
use tinyvec::TinyVec;
pub use crate::graph::GraphState;
pub use crate::time::*;
pub type Burst<T> = TinyVec<[T; 1]>;
#[macro_export]
macro_rules! burst {
() => {
::tinyvec::TinyVec::new()
};
($($item:expr),* $(,)?) => {
::tinyvec::tiny_vec!($($item),*)
};
}
pub enum Dep<T> {
Active(Rc<dyn Stream<T>>),
Passive(Rc<dyn Stream<T>>),
}
impl<T> Dep<T> {
pub fn stream(&self) -> &Rc<dyn Stream<T>> {
match self {
Dep::Active(s) | Dep::Passive(s) => s,
}
}
pub fn is_active(&self) -> bool {
matches!(self, Dep::Active(_))
}
#[must_use]
pub fn as_node(&self) -> Rc<dyn Node>
where
T: 'static,
{
self.stream().clone().as_node()
}
}
#[derive(new, Default)]
pub struct UpStreams {
pub active: Vec<Rc<dyn Node>>,
pub passive: Vec<Rc<dyn Node>>,
}
impl UpStreams {
pub fn none() -> UpStreams {
UpStreams::new(Vec::new(), Vec::new())
}
}
#[doc(hidden)]
pub trait Element: Debug + Clone + Default + 'static {}
impl<T> Element for T where T: Debug + Clone + Default + 'static {}
pub trait MutableNode {
fn cycle(&mut self, state: &mut GraphState) -> anyhow::Result<bool>;
fn upstreams(&self) -> UpStreams;
#[allow(unused_variables)]
fn setup(&mut self, state: &mut GraphState) -> anyhow::Result<()> {
Ok(())
}
#[allow(unused_variables)]
fn start(&mut self, state: &mut GraphState) -> anyhow::Result<()> {
Ok(())
}
#[allow(unused_variables)]
fn stop(&mut self, state: &mut GraphState) -> anyhow::Result<()> {
Ok(())
}
#[allow(unused_variables)]
fn teardown(&mut self, state: &mut GraphState) -> anyhow::Result<()> {
Ok(())
}
fn type_name(&self) -> String {
tynm::type_name::<Self>()
}
}
impl Display for dyn Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.type_name())
}
}
impl<T> Debug for dyn Stream<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.type_name())
}
}
pub trait Node: MutableNode {
fn cycle(&self, state: &mut GraphState) -> anyhow::Result<bool>;
fn setup(&self, state: &mut GraphState) -> anyhow::Result<()>;
fn start(&self, state: &mut GraphState) -> anyhow::Result<()>;
fn stop(&self, state: &mut GraphState) -> anyhow::Result<()>;
fn teardown(&self, state: &mut GraphState) -> anyhow::Result<()>;
}
pub trait StreamPeekRef<T: Clone>: MutableNode {
fn peek_ref(&self) -> &T;
fn clone_from_cell_ref(&self, cell_ref: std::cell::Ref<'_, T>) -> T {
cell_ref.clone()
}
}
pub trait StreamPeek<T> {
fn peek_value(&self) -> T;
fn peek_ref_cell(&self) -> std::cell::Ref<'_, T>;
}
pub trait Stream<T>: Node + StreamPeek<T> + AsNode {}
impl<NODE: MutableNode> Node for RefCell<NODE> {
fn cycle(&self, state: &mut GraphState) -> anyhow::Result<bool> {
self.borrow_mut().cycle(state)
}
fn setup(&self, state: &mut GraphState) -> anyhow::Result<()> {
self.borrow_mut().setup(state)
}
fn start(&self, state: &mut GraphState) -> anyhow::Result<()> {
self.borrow_mut().start(state)
}
fn stop(&self, state: &mut GraphState) -> anyhow::Result<()> {
self.borrow_mut().stop(state)
}
fn teardown(&self, state: &mut GraphState) -> anyhow::Result<()> {
self.borrow_mut().teardown(state)
}
}
impl<NODE: MutableNode> MutableNode for RefCell<NODE> {
fn cycle(&mut self, graph_state: &mut GraphState) -> anyhow::Result<bool> {
self.borrow_mut().cycle(graph_state)
}
fn upstreams(&self) -> UpStreams {
self.borrow().upstreams()
}
fn start(&mut self, state: &mut GraphState) -> anyhow::Result<()> {
self.borrow_mut().start(state)
}
fn stop(&mut self, state: &mut GraphState) -> anyhow::Result<()> {
self.borrow_mut().stop(state)
}
fn type_name(&self) -> String {
self.borrow().type_name()
}
}
impl<STREAM, T> StreamPeek<T> for RefCell<STREAM>
where
STREAM: StreamPeekRef<T>,
T: Clone,
{
fn peek_ref_cell(&self) -> std::cell::Ref<'_, T> {
std::cell::Ref::map(self.borrow(), |strm| strm.peek_ref())
}
fn peek_value(&self) -> T {
self.borrow().clone_from_cell_ref(self.peek_ref_cell())
}
}
impl<STREAM, T> Stream<T> for RefCell<STREAM>
where
STREAM: StreamPeekRef<T> + 'static,
T: Clone + 'static,
{
}
pub trait AsNode {
#[must_use]
fn as_node(self: Rc<Self>) -> Rc<dyn Node>;
}
impl<NODE: Node + 'static> AsNode for NODE {
fn as_node(self: Rc<Self>) -> Rc<dyn Node> {
self
}
}
pub trait AsStream<T> {
#[must_use]
fn as_stream(self: Rc<Self>) -> Rc<dyn Stream<T>>;
}
impl<T, STREAM: Stream<T> + 'static> AsStream<T> for STREAM {
fn as_stream(self: Rc<Self>) -> Rc<dyn Stream<T>> {
self
}
}
pub trait IntoNode {
#[must_use]
fn into_node(self) -> Rc<dyn Node>;
}
impl<NODE: MutableNode + 'static> IntoNode for NODE {
fn into_node(self) -> Rc<dyn Node> {
Rc::new(RefCell::new(self))
}
}
pub trait IntoStream<T> {
#[must_use]
fn into_stream(self) -> Rc<dyn Stream<T>>;
}
impl<T, STREAM> IntoStream<T> for STREAM
where
T: Clone + 'static,
STREAM: StreamPeekRef<T> + 'static,
{
fn into_stream(self) -> Rc<dyn Stream<T>> {
Rc::new(RefCell::new(self))
}
}