use std::{marker::PhantomData, ops::Deref, sync::Arc};
use interface::{Data, Left, Read, Right, UniqueIdentifier, Update, Write};
pub enum Split {}
pub enum Merge {}
pub struct LeftRight<U, S, V = U>
where
U: UniqueIdentifier,
V: UniqueIdentifier,
{
i: usize,
n: Option<usize>,
data: Arc<U::DataType>,
left: Arc<U::DataType>,
right: Arc<U::DataType>,
state: PhantomData<S>,
u: PhantomData<U>,
v: PhantomData<V>,
}
impl<T, U, V> LeftRight<U, Split, V>
where
T: Copy,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
pub fn split_at(i: usize) -> Self {
Self {
i,
n: Default::default(),
data: Default::default(),
left: Default::default(),
right: Default::default(),
state: PhantomData,
u: PhantomData,
v: PhantomData,
}
}
pub fn split_chunks_at(n: usize, i: usize) -> Self {
Self {
i,
n: Some(n),
data: Default::default(),
left: Default::default(),
right: Default::default(),
state: PhantomData,
u: PhantomData,
v: PhantomData,
}
}
}
impl<T, U, V> From<&LeftRight<U, Split>> for LeftRight<U, Merge, V>
where
T: Copy,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
fn from(split: &LeftRight<U, Split>) -> Self {
Self {
i: split.i,
n: split.n,
data: Default::default(),
left: Default::default(),
right: Default::default(),
state: PhantomData,
u: PhantomData,
v: PhantomData,
}
}
}
pub fn split_merge_at<U, V>(i: usize) -> (LeftRight<U, Split, V>, LeftRight<U, Merge, V>)
where
U: UniqueIdentifier,
V: UniqueIdentifier,
<U as UniqueIdentifier>::DataType: Default,
<V as UniqueIdentifier>::DataType: Default,
{
(
LeftRight::<U, Split, V> {
i,
n: Default::default(),
data: Default::default(),
left: Default::default(),
right: Default::default(),
state: PhantomData,
u: PhantomData,
v: PhantomData,
},
LeftRight::<U, Merge, V> {
i,
n: Default::default(),
data: Default::default(),
left: Default::default(),
right: Default::default(),
state: PhantomData,
u: PhantomData,
v: PhantomData,
},
)
}
pub fn split_merge_chunks_at<U, V>(
n: usize,
i: usize,
) -> (LeftRight<U, Split, V>, LeftRight<U, Merge, V>)
where
U: UniqueIdentifier,
V: UniqueIdentifier,
<U as UniqueIdentifier>::DataType: Default,
<V as UniqueIdentifier>::DataType: Default,
{
(
LeftRight::<U, Split, V> {
i,
n: Some(n),
data: Default::default(),
left: Default::default(),
right: Default::default(),
state: PhantomData,
u: PhantomData,
v: PhantomData,
},
LeftRight::<U, Merge, V> {
i,
n: Some(n),
data: Default::default(),
left: Default::default(),
right: Default::default(),
state: PhantomData,
u: PhantomData,
v: PhantomData,
},
)
}
impl<T, U, S, V> Update for LeftRight<U, S, V>
where
T: Copy + Send + Sync,
S: Send + Sync,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
}
impl<T, U, V> Read<U> for LeftRight<U, Split, V>
where
T: Copy + Send + Sync,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
fn read(&mut self, data: Data<U>) {
self.data = data.as_arc();
}
}
impl<T, U, V> Write<Left<U>> for LeftRight<U, Split, V>
where
T: Copy + Send + Sync,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
fn write(&mut self) -> Option<Data<Left<U>>> {
Some(
if let Some(n) = self.n {
self.data
.chunks(n)
.flat_map(|data| data[..self.i].to_vec())
.collect::<Vec<_>>()
} else {
self.data[..self.i].to_vec()
}
.into(),
)
}
}
impl<T, U, V> Write<Right<U>> for LeftRight<U, Split, V>
where
T: Copy + Send + Sync,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
fn write(&mut self) -> Option<Data<Right<U>>> {
Some(
if let Some(n) = self.n {
self.data
.chunks(n)
.flat_map(|data| data[self.i..].to_vec())
.collect::<Vec<_>>()
} else {
self.data[self.i..].to_vec()
}
.into(),
)
}
}
impl<T, U, V> Read<Left<U>> for LeftRight<U, Merge, V>
where
T: Copy + Send + Sync,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
fn read(&mut self, data: Data<Left<U>>) {
self.left = data.as_arc();
}
}
impl<T, U, V> Read<Right<U>> for LeftRight<U, Merge, V>
where
T: Copy + Send + Sync,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
fn read(&mut self, data: Data<Right<U>>) {
self.right = data.as_arc();
}
}
impl<T, U, V> Write<V> for LeftRight<U, Merge, V>
where
T: Copy + Send + Sync,
U: UniqueIdentifier<DataType = Vec<T>>,
V: UniqueIdentifier<DataType = Vec<T>>,
{
fn write(&mut self) -> Option<Data<V>> {
Some(
if let Some(n) = self.n {
self.left
.chunks(self.i)
.zip(self.right.chunks(n - self.i))
.flat_map(|(left, right)| {
let mut data = left.to_vec();
data.extend_from_slice(right);
data
})
.collect::<Vec<T>>()
} else {
let mut data = self.left.deref().to_vec();
data.extend_from_slice(&self.right);
data
}
.into(),
)
}
}
#[cfg(test)]
mod tests {
use std::error::Error;
use interface::UID;
use crate::{print::Print, signals::Signals};
use super::*;
enum U {}
impl UniqueIdentifier for U {
type DataType = Vec<usize>;
}
#[derive(UID)]
pub enum S {}
#[derive(UID)]
pub enum M {}
#[test]
fn split_at() {
let data: Vec<_> = (1..=5).into_iter().collect();
let mut split = LeftRight::<U, Split>::split_at(2);
<LeftRight<U, Split> as Read<U>>::read(&mut split, data.into());
let left = <LeftRight<U, Split> as Write<Left<U>>>::write(&mut split);
dbg!(&left);
let right = <LeftRight<U, Split> as Write<Right<U>>>::write(&mut split);
dbg!(&right);
let mut merge: LeftRight<U, Merge> = (&split).into();
<LeftRight<U, Merge> as Read<Left<U>>>::read(&mut merge, left.unwrap());
<LeftRight<U, Merge> as Read<Right<U>>>::read(&mut merge, right.unwrap());
let merged_data = <LeftRight<U, Merge> as Write<U>>::write(&mut merge);
dbg!(merged_data);
}
#[test]
fn split_chunks_at() {
let data: Vec<_> = (1..=5).into_iter().collect::<Vec<_>>().repeat(3);
let mut split = LeftRight::<U, Split>::split_chunks_at(5, 2);
<LeftRight<U, Split> as Read<U>>::read(&mut split, data.into());
let left = <LeftRight<U, Split> as Write<Left<U>>>::write(&mut split);
dbg!(&left);
let right = <LeftRight<U, Split> as Write<Right<U>>>::write(&mut split);
dbg!(&right);
let mut merge: LeftRight<U, Merge> = (&split).into();
<LeftRight<U, Merge> as Read<Left<U>>>::read(&mut merge, left.unwrap());
<LeftRight<U, Merge> as Read<Right<U>>>::read(&mut merge, right.unwrap());
let merged_data = <LeftRight<U, Merge> as Write<U>>::write(&mut merge);
dbg!(merged_data);
}
#[tokio::test(flavor = "multi_thread")]
async fn model() -> Result<(), Box<dyn Error>> {
use gmt_dos_actors::prelude::*;
let mut signal: Initiator<_> = Signals::new(10, 10).into();
let (split, _merge) = split_merge_at::<S, M>(5);
let mut split_actor: Actor<_> = split.into();
let mut left: Terminator<_> = Print::<Vec<f64>>::default().into();
let mut right: Terminator<_> = Print::<Vec<f64>>::default().into();
let _ = signal
.add_output()
.build::<S>()
.into_input(&mut split_actor)?;
let _ = split_actor
.add_output()
.build::<Left<S>>()
.into_input(&mut left)?;
let _ = split_actor
.add_output()
.build::<Right<S>>()
.into_input(&mut right)?;
model!(signal, split_actor, left, right)
.check()?
.flowchart();
Ok(())
}
}