use crate::config::ComponentConfig;
use crate::context::CuContext;
use crate::copperlist::CopperList;
use crate::cubridge::{
BridgeChannel, BridgeChannelConfig, BridgeChannelInfo, BridgeChannelSet, CuBridge,
};
use crate::cutask::CuMsgPack;
use crate::cutask::{CuMsg, CuMsgPayload, CuSinkTask, CuSrcTask, Freezable};
use crate::reflect::{Reflect, TypePath};
use crate::{input_msg, output_msg};
use bincode::de::Decoder;
use bincode::enc::Encoder;
use bincode::error::{DecodeError, EncodeError};
use bincode::{Decode, Encode};
use core::marker::PhantomData;
use cu29_clock::CuTime;
use cu29_traits::{CopperListTuple, CuResult, ErasedCuStampedDataSet};
pub fn recorded_copperlist_timestamp<P: CopperListTuple>(
copperlist: &CopperList<P>,
) -> Option<CuTime> {
<CopperList<P> as ErasedCuStampedDataSet>::cumsgs(copperlist)
.into_iter()
.filter_map(|msg| Option::<CuTime>::from(msg.metadata().process_time().start))
.min()
}
pub enum CuTaskCallbackState<I, O> {
New(Option<ComponentConfig>),
Start,
Preprocess,
Process(I, O),
Postprocess,
Stop,
}
#[derive(PartialEq)]
pub enum SimOverride {
ExecutedBySim,
ExecuteByRuntime,
Errored(String),
}
pub enum CuBridgeLifecycleState {
New(Option<ComponentConfig>),
Start,
Preprocess,
Postprocess,
Stop,
}
#[derive(Reflect)]
#[reflect(no_field_bounds, from_reflect = false, type_path = false)]
pub struct CuSimSrcTask<T> {
#[reflect(ignore)]
boo: PhantomData<fn() -> T>,
state: bool,
}
impl<T: 'static> TypePath for CuSimSrcTask<T> {
fn type_path() -> &'static str {
"cu29_runtime::simulation::CuSimSrcTask"
}
fn short_type_path() -> &'static str {
"CuSimSrcTask"
}
fn type_ident() -> Option<&'static str> {
Some("CuSimSrcTask")
}
fn crate_name() -> Option<&'static str> {
Some("cu29_runtime")
}
fn module_path() -> Option<&'static str> {
Some("simulation")
}
}
impl<T> Freezable for CuSimSrcTask<T> {
fn freeze<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
Encode::encode(&self.state, encoder)
}
fn thaw<D: Decoder>(&mut self, decoder: &mut D) -> Result<(), DecodeError> {
self.state = Decode::decode(decoder)?;
Ok(())
}
}
impl<T: CuMsgPayload + 'static> CuSrcTask for CuSimSrcTask<T> {
type Resources<'r> = ();
type Output<'m> = output_msg!(T);
fn new(_config: Option<&ComponentConfig>, _resources: Self::Resources<'_>) -> CuResult<Self>
where
Self: Sized,
{
Ok(Self {
boo: PhantomData,
state: true,
})
}
fn process(&mut self, _ctx: &CuContext, _new_msg: &mut Self::Output<'_>) -> CuResult<()> {
unimplemented!(
"A placeholder for sim was called for a source, you need answer SimOverride to ExecutedBySim for the Process step."
)
}
}
impl<T> CuSimSrcTask<T> {
pub fn sim_tick(&mut self) {}
}
pub trait CuSimSinkInput {
type With<'m>: CuMsgPack
where
Self: 'm;
}
macro_rules! impl_sim_sink_input_tuple {
($($name:ident),+) => {
impl<$($name: CuMsgPayload),+> CuSimSinkInput for ($($name,)+) {
type With<'m> = input_msg!('m, $($name),+) where Self: 'm;
}
};
}
macro_rules! impl_sim_sink_input_up_to {
($first:ident $(, $rest:ident)* $(,)?) => {
impl_sim_sink_input_tuple!($first);
impl_sim_sink_input_up_to!(@accumulate ($first); $($rest),*);
};
(@accumulate ($($acc:ident),+);) => {};
(@accumulate ($($acc:ident),+); $next:ident $(, $rest:ident)*) => {
impl_sim_sink_input_tuple!($($acc),+, $next);
impl_sim_sink_input_up_to!(@accumulate ($($acc),+, $next); $($rest),*);
};
}
impl_sim_sink_input_up_to!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
#[derive(Reflect)]
#[reflect(no_field_bounds, from_reflect = false, type_path = false)]
pub struct CuSimSinkTask<I> {
#[reflect(ignore)]
boo: PhantomData<fn() -> I>,
}
impl<I: 'static> TypePath for CuSimSinkTask<I> {
fn type_path() -> &'static str {
"cu29_runtime::simulation::CuSimSinkTask"
}
fn short_type_path() -> &'static str {
"CuSimSinkTask"
}
fn type_ident() -> Option<&'static str> {
Some("CuSimSinkTask")
}
fn crate_name() -> Option<&'static str> {
Some("cu29_runtime")
}
fn module_path() -> Option<&'static str> {
Some("simulation")
}
}
impl<I> Freezable for CuSimSinkTask<I> {}
impl<I: CuSimSinkInput + 'static> CuSinkTask for CuSimSinkTask<I> {
type Resources<'r> = ();
type Input<'m> = <I as CuSimSinkInput>::With<'m>;
fn new(_config: Option<&ComponentConfig>, _resources: Self::Resources<'_>) -> CuResult<Self>
where
Self: Sized,
{
Ok(Self { boo: PhantomData })
}
fn process(&mut self, _ctx: &CuContext, _input: &Self::Input<'_>) -> CuResult<()> {
unimplemented!(
"A placeholder for sim was called for a sink, you need answer SimOverride to ExecutedBySim for the Process step."
)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum CuNoBridgeChannelId {}
pub struct CuNoBridgeChannels;
impl BridgeChannelSet for CuNoBridgeChannels {
type Id = CuNoBridgeChannelId;
const STATIC_CHANNELS: &'static [&'static dyn BridgeChannelInfo<Self::Id>] = &[];
}
#[derive(Reflect)]
#[reflect(no_field_bounds, from_reflect = false, type_path = false)]
pub struct CuSimBridge<Tx: BridgeChannelSet + 'static, Rx: BridgeChannelSet + 'static> {
#[reflect(ignore)]
boo: PhantomData<fn() -> (Tx, Rx)>,
}
impl<Tx: BridgeChannelSet + 'static, Rx: BridgeChannelSet + 'static> TypePath
for CuSimBridge<Tx, Rx>
{
fn type_path() -> &'static str {
"cu29_runtime::simulation::CuSimBridge"
}
fn short_type_path() -> &'static str {
"CuSimBridge"
}
fn type_ident() -> Option<&'static str> {
Some("CuSimBridge")
}
fn crate_name() -> Option<&'static str> {
Some("cu29_runtime")
}
fn module_path() -> Option<&'static str> {
Some("simulation")
}
}
impl<Tx: BridgeChannelSet + 'static, Rx: BridgeChannelSet + 'static> Freezable
for CuSimBridge<Tx, Rx>
{
}
impl<Tx: BridgeChannelSet + 'static, Rx: BridgeChannelSet + 'static> CuBridge
for CuSimBridge<Tx, Rx>
{
type Tx = Tx;
type Rx = Rx;
type Resources<'r> = ();
fn new(
_config: Option<&ComponentConfig>,
_tx_channels: &[BridgeChannelConfig<<Self::Tx as BridgeChannelSet>::Id>],
_rx_channels: &[BridgeChannelConfig<<Self::Rx as BridgeChannelSet>::Id>],
_resources: Self::Resources<'_>,
) -> CuResult<Self>
where
Self: Sized,
{
Ok(Self { boo: PhantomData })
}
fn send<'a, Payload>(
&mut self,
_ctx: &CuContext,
_channel: &'static BridgeChannel<<Self::Tx as BridgeChannelSet>::Id, Payload>,
_msg: &CuMsg<Payload>,
) -> CuResult<()>
where
Payload: CuMsgPayload + 'a,
{
Ok(())
}
fn receive<'a, Payload>(
&mut self,
_ctx: &CuContext,
_channel: &'static BridgeChannel<<Self::Rx as BridgeChannelSet>::Id, Payload>,
_msg: &mut CuMsg<Payload>,
) -> CuResult<()>
where
Payload: CuMsgPayload + 'a,
{
Ok(())
}
}