use ::toad_msg::Token;
use no_std_net::SocketAddr;
use crate::net::Addrd;
use crate::platform::{self, PlatformTypes};
pub mod runtime {
use ::toad_msg::Token;
use naan::prelude::{HKT1, HKT2};
use no_std_net::SocketAddr;
use super::ack::Ack;
use super::parse::Parse;
use super::provision_ids::{self, IdWithDefault, SocketAddrWithDefault};
use super::provision_tokens::ProvisionTokens;
use super::{buffer_responses, handle_acks, observe, retry};
use crate::net::Addrd;
use crate::platform::{Message, PlatformTypes};
use crate::req::Req;
use crate::resp::Resp;
use crate::time::Stamped;
type Map<M, K, V> = <M as HKT2>::T<K, V>;
type Array<A, T> = <A as HKT1>::T<T>;
type Clock<P> = <P as PlatformTypes>::Clock;
#[allow(missing_docs)]
pub type HandleAcks<M, S> = handle_acks::HandleAcks<S, Map<M, Addrd<Token>, ()>>;
#[allow(missing_docs)]
pub type Retry<P, A, S> = retry::Retry<S, Array<A, (retry::State<Clock<P>>, Addrd<Message<P>>)>>;
#[allow(missing_docs)]
pub type BufferResponses<P, M, S> =
buffer_responses::BufferResponses<S,
Map<M, (SocketAddr, Token, toad_msg::Type), Addrd<Resp<P>>>>;
#[allow(missing_docs)]
pub type ProvisionIds<P, M, A, S> =
provision_ids::ProvisionIds<P,
S,
Map<M,
SocketAddrWithDefault,
Array<A, Stamped<Clock<P>, IdWithDefault>>>>;
#[allow(missing_docs)]
pub type Observe<P, A, S> = observe::Observe<S,
Array<A, observe::Sub<P>>,
Array<A, Addrd<Req<P>>>,
observe::SubHash_TypePathQueryAccept<P>>;
#[rustfmt::skip]
pub type Runtime<P, Array, Map> =
Observe<P, Array,
BufferResponses<P, Map,
HandleAcks<Map,
Retry<P, Array,
Ack<
ProvisionTokens<
ProvisionIds<P, Map, Array,
Parse<
()
>>>>>>>>;
#[allow(missing_docs)]
#[cfg(feature = "std")]
pub mod std {
use crate::std::PlatformTypes;
pub type Runtime<Dtls> =
super::Runtime<PlatformTypes<Dtls>, naan::hkt::Vec, naan::hkt::BTreeMap>;
}
}
pub mod retry;
pub mod observe;
pub mod provision_tokens;
pub mod provision_ids;
pub mod handle_acks;
pub mod ack;
pub mod set_standard_options;
pub mod buffer_responses;
pub mod parse;
pub type StepOutput<T, E> = Option<nb::Result<T, E>>;
#[macro_export]
macro_rules! exec_inner_step {
($result:expr, $err:expr) => {
exec_inner_step!(run_anyway_when_would_block = false, $result, $err)
};
(run_anyway_when_would_block = $run_anyway_when_would_block:expr, $result:expr, $err:expr) => {
match $result {
| None => None,
| Some(Ok(t)) => Some(t),
| Some(Err(nb::Error::WouldBlock)) if $run_anyway_when_would_block => None,
| Some(Err(nb::Error::WouldBlock)) => return Some(Err(nb::Error::WouldBlock)),
| Some(Err(nb::Error::Other(e))) => return Some(Err(nb::Error::Other($err(e)))),
}
};
}
#[macro_export]
macro_rules! log {
($at:path, $effs:expr, $lvl:expr, $($arg:tt)*) => {{
use toad_array::Array;
type S = $crate::todo::String::<1000>;
let msg = S::fmt(format_args!($($arg)*));
let msg = S::fmt(format_args!("[{}] {}", stringify!($at), msg.as_str()));
$effs.push($crate::platform::Effect::Log($lvl, msg));
}};
}
#[macro_export]
macro_rules! _try {
(Result; $r:expr) => {_try!(Option<Result>; Some($r))};
(Option<Result>; $r:expr) => {_try!(Option<nb::Result>; $r.map(|r| r.map_err(nb::Error::Other)))};
(Option<nb::Result>; $r:expr) => {match $r {
None => return None,
Some(Err(e)) => return Some(Err(e)),
Some(Ok(a)) => a,
}};
}
pub use {_try, exec_inner_step, log};
pub trait Error: core::fmt::Debug {}
impl Error for () {}
pub trait Step<P: PlatformTypes>: Default {
type PollReq;
type PollResp;
type Error: Error + From<<Self::Inner as Step<P>>::Error>;
type Inner: Step<P>;
fn inner(&self) -> &Self::Inner;
fn poll_req(&self,
snap: &platform::Snapshot<P>,
effects: &mut P::Effects)
-> StepOutput<Self::PollReq, Self::Error>;
fn poll_resp(&self,
snap: &platform::Snapshot<P>,
effects: &mut P::Effects,
token: Token,
addr: SocketAddr)
-> StepOutput<Self::PollResp, Self::Error>;
fn notify<Path>(&self, path: Path, effects: &mut P::Effects) -> Result<(), Self::Error>
where Path: AsRef<str> + Clone
{
self.inner()
.notify(path, effects)
.map_err(Self::Error::from)
}
fn before_message_sent(&self,
snap: &platform::Snapshot<P>,
effects: &mut <P as PlatformTypes>::Effects,
msg: &mut Addrd<platform::Message<P>>)
-> Result<(), Self::Error> {
self.inner()
.before_message_sent(snap, effects, msg)
.map_err(Self::Error::from)
}
fn on_message_sent(&self,
snap: &platform::Snapshot<P>,
effects: &mut P::Effects,
msg: &Addrd<platform::Message<P>>)
-> Result<(), Self::Error> {
self.inner()
.on_message_sent(snap, effects, msg)
.map_err(Self::Error::from)
}
}
impl<P: PlatformTypes> Step<P> for () {
type PollReq = ();
type PollResp = ();
type Error = ();
type Inner = ();
fn inner(&self) -> &Self::Inner {
panic!("Step.inner invoked for unit (). This is incorrect and would likely cause recursion without return")
}
fn poll_req(&self,
_: &platform::Snapshot<P>,
_: &mut <P as PlatformTypes>::Effects)
-> StepOutput<(), ()> {
None
}
fn poll_resp(&self,
_: &platform::Snapshot<P>,
_: &mut P::Effects,
_: Token,
_: SocketAddr)
-> StepOutput<(), ()> {
None
}
fn notify<Path>(&self, _: Path, _: &mut P::Effects) -> Result<(), Self::Error>
where Path: AsRef<str>
{
Ok(())
}
fn before_message_sent(&self,
_: &platform::Snapshot<P>,
_: &mut P::Effects,
_: &mut Addrd<platform::Message<P>>)
-> Result<(), Self::Error> {
Ok(())
}
fn on_message_sent(&self,
_: &platform::Snapshot<P>,
_: &mut P::Effects,
_: &Addrd<platform::Message<P>>)
-> Result<(), Self::Error> {
Ok(())
}
}
#[cfg(test)]
pub mod test {
use embedded_time::Clock;
use super::*;
use crate::test;
use crate::test::ClockMock;
pub fn default_snapshot() -> platform::Snapshot<test::Platform> {
platform::Snapshot { time: ClockMock::new().try_now().unwrap(),
recvd_dgram: Some(crate::net::Addrd(Default::default(),
crate::test::dummy_addr())),
config: crate::config::Config::default() }
}
#[macro_export]
macro_rules! dummy_step {
({Step<PollReq = $poll_req_ty:ty, PollResp = $poll_resp_ty:ty, Error = $error_ty:ty>}) => {
use $crate::net::Addrd;
use $crate::{platform, step, test};
#[derive(Default)]
struct Dummy(());
static mut POLL_REQ_MOCK:
Option<Box<dyn Fn(&platform::Snapshot<test::Platform>,
&mut <test::Platform as platform::PlatformTypes>::Effects)
-> Option<::nb::Result<$poll_req_ty, $error_ty>>>> = None;
static mut POLL_RESP_MOCK:
Option<Box<dyn Fn(&platform::Snapshot<test::Platform>,
&mut <test::Platform as platform::PlatformTypes>::Effects,
::toad_msg::Token,
no_std_net::SocketAddr)
-> Option<::nb::Result<$poll_resp_ty, $error_ty>>>> = None;
static mut ON_MESSAGE_SENT_MOCK: Option<Box<dyn Fn(&platform::Snapshot<test::Platform>,
&Addrd<test::Message>)
-> Result<(), $error_ty>>> = None;
static mut BEFORE_MESSAGE_SENT_MOCK:
Option<Box<dyn Fn(&platform::Snapshot<test::Platform>, &mut <test::Platform as $crate::platform::PlatformTypes>::Effects,
&mut Addrd<test::Message>) -> Result<(), $error_ty>>> = None;
unsafe {
POLL_REQ_MOCK = Some(Box::new(|_, _| None));
POLL_RESP_MOCK = Some(Box::new(|_, _, _, _| None));
ON_MESSAGE_SENT_MOCK = Some(Box::new(|_, _| Ok(())));
BEFORE_MESSAGE_SENT_MOCK = Some(Box::new(|_, _, _| Ok(())));
}
impl Step<test::Platform> for Dummy {
type PollReq = $poll_req_ty;
type PollResp = $poll_resp_ty;
type Error = $error_ty;
type Inner = ();
fn inner(&self) -> &() {
&self.0
}
fn poll_req(&self,
a: &platform::Snapshot<test::Platform>,
b: &mut <test::Platform as platform::PlatformTypes>::Effects)
-> step::StepOutput<Self::PollReq, Self::Error> {
unsafe { POLL_REQ_MOCK.as_ref().unwrap()(a, b) }
}
fn poll_resp(&self,
a: &platform::Snapshot<test::Platform>,
b: &mut <test::Platform as platform::PlatformTypes>::Effects,
c: ::toad_msg::Token,
d: no_std_net::SocketAddr)
-> step::StepOutput<Self::PollResp, ()> {
unsafe { POLL_RESP_MOCK.as_ref().unwrap()(a, b, c, d) }
}
fn before_message_sent(&self,
snap: &platform::Snapshot<test::Platform>,
effs: &mut <test::Platform as $crate::platform::PlatformTypes>::Effects,
msg: &mut Addrd<test::Message>)
-> Result<(), Self::Error> {
unsafe { BEFORE_MESSAGE_SENT_MOCK.as_ref().unwrap()(snap, effs, msg) }
}
fn on_message_sent(&self,
snap: &platform::Snapshot<test::Platform>,
effects: &mut Vec<test::Effect>,
msg: &Addrd<test::Message>)
-> Result<(), Self::Error> {
unsafe { ON_MESSAGE_SENT_MOCK.as_ref().unwrap()(snap, msg) }
}
}
};
}
#[macro_export]
macro_rules! test_step_when {
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot:expr,
token = $token:expr,
addr = $addr:expr,
when (inner.poll_req = {$poll_req_fake:expr})
) => {
*$poll_req_mock = Some(Box::new($poll_req_fake))
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot:expr,
token = $token:expr,
addr = $addr:expr,
when (inner.poll_req => {$inner_step_returns:expr})
) => {
*$poll_req_mock = Some(Box::new(|_, _| $inner_step_returns))
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects_mut:expr,
snapshot = $snapshot:expr,
token = $token:expr,
addr = $addr:expr,
when (effects = {$effects:expr})
) => {
*$effects_mut = $effects
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot:expr,
token = $token:expr,
addr = $addr:expr,
when (inner.poll_resp => {$inner_step_returns:expr})
) => {
*$poll_resp_mock = Some(Box::new(|_, _, _, _| $inner_step_returns))
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot:expr,
token = $token:expr,
addr = $addr:expr,
when (inner.poll_resp = {$poll_resp_fake:expr})
) => {
*$poll_resp_mock = Some(Box::new($poll_resp_fake))
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot_mut:expr,
token = $token:expr,
addr = $addr:expr,
when (snapshot = {$snapshot:expr})
) => {
*$snapshot_mut = $snapshot
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot_mut:expr,
token = $token_mut:expr,
addr = $addr:expr,
when (poll_resp_token = {$token:expr})
) => {
*$token_mut = $token
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot_mut:expr,
token = $token:expr,
addr = $addr_mut:expr,
when (poll_resp_addr = {$addr:expr})
) => {
*$addr_mut = $addr
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot_mut:expr,
token = $token:expr,
addr = $addr_mut:expr,
when (inner.before_message_sent = {$before_message_sent:expr})
) => {
*$before_message_sent_mock = Some(Box::new($before_message_sent))
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot_mut:expr,
token = $token:expr,
addr = $addr_mut:expr,
when (inner.on_message_sent = {$on_message_sent:expr})
) => {
*$on_message_sent_mock = Some(Box::new($on_message_sent))
};
(
step = $step:expr,
poll_req_mock = $poll_req_mock:expr,
poll_resp_mock = $poll_resp_mock:expr,
before_message_sent_mock = $before_message_sent_mock:expr,
on_message_sent_mock = $on_message_sent_mock:expr,
effects = $effects:expr,
snapshot = $snapshot_mut:expr,
token = $token:expr,
addr = $addr_mut:expr,
when ({$f:expr})
) => {
$f($step)
};
}
#[macro_export]
macro_rules! test_step_expect {
(
step: $step_ty:ty = $step:expr,
snap = $__s:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (before_message_sent($snap:expr, _, $msg:expr) should satisfy {$assert_fn:expr})
) => {{
use $crate::net::Addrd;
use $crate::step::Step;
use $crate::test;
let mut msg = $msg;
let assert_fn: Box<dyn Fn(Addrd<test::Message>)> = Box::new($assert_fn);
$step.before_message_sent(&$snap, &mut $effects, &mut msg)
.unwrap();
assert_fn(msg)
}};
(
step: $step_ty:ty = $step:expr,
snap = $snap:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (on_message_sent(_, $msg:expr) should satisfy {$assert_fn:expr})
) => {{
use $crate::step::Step;
let assert_fn: Box<dyn Fn(Result<(), <$step_ty as Step<_>>::Error>)> = Box::new($assert_fn);
assert_fn($step.on_message_sent($snap, $effects, &$msg))
}};
(
step: $step_ty:ty = $step:expr,
snap = $_s:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (on_message_sent($snap:expr, $msg:expr) should satisfy {$assert_fn:expr})
) => {{
use $crate::step::Step;
let assert_fn: Box<dyn Fn(Result<(), <$step_ty as Step<_>>::Error>)> = Box::new($assert_fn);
assert_fn($step.on_message_sent(&$snap, $effects, &$msg))
}};
(
step: $step_ty:ty = $step:expr,
snap = $snap:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (poll_req(_, _) should satisfy {$assert_fn:expr})
) => {{
use $crate::step::{Step, StepOutput};
let assert_fn: Box<dyn Fn(StepOutput<<$step_ty as Step<_>>::PollReq,
<$step_ty as Step<_>>::Error>)> = Box::new($assert_fn);
assert_fn($step.poll_req($snap, $effects))
}};
(
step: $step_ty:ty = $step:expr,
snap = $_s:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (poll_req($snap:expr, _) should satisfy {$assert_fn:expr})
) => {{
use $crate::step::{Step, StepOutput};
let assert_fn: Box<dyn Fn(StepOutput<<$step_ty as Step<_>>::PollReq,
<$step_ty as Step<_>>::Error>)> = Box::new($assert_fn);
assert_fn($step.poll_req(&$snap, $effects))
}};
(
step: $step_ty:ty = $step:expr,
snap = $snap:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (poll_resp(_, _, _, _) should satisfy {$assert_fn:expr})
) => {{
use $crate::step::{Step, StepOutput};
let assert_fn: Box<dyn Fn(StepOutput<<$step_ty as Step<_>>::PollResp,
<$step_ty as Step<_>>::Error>)> = Box::new($assert_fn);
assert_fn($step.poll_resp($snap, $effects, $token, $addr))
}};
(
step: $step_ty:ty = $step:expr,
snap = $_s:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (poll_resp($snap:expr, _, _, _) should satisfy {$assert_fn:expr})
) => {{
use $crate::step::{Step, StepOutput};
let assert_fn: Box<dyn Fn(StepOutput<<$step_ty as Step<_>>::PollResp,
<$step_ty as Step<_>>::Error>)> = Box::new($assert_fn);
assert_fn($step.poll_resp(&$snap, $effects, $token, $addr))
}};
(
step: $step_ty:ty = $step:expr,
snap = $snap:expr,
effects = $effects:expr,
token = $_t:expr,
addr = $_a:expr,
expect (poll_resp(_, _, $token:expr, $addr:expr) should satisfy {$assert_fn:expr})
) => {{
use $crate::step::{Step, StepOutput};
let assert_fn: Box<dyn Fn(StepOutput<<$step_ty as Step<_>>::PollResp,
<$step_ty as Step<_>>::Error>)> = Box::new($assert_fn);
assert_fn($step.poll_resp($snap, $effects, $token, $addr))
}};
(
step: $step_ty:ty = $step:expr,
snap = $snap:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (effects == {$expect:expr})
) => {
assert_eq!($effects, &$expect)
};
(
step: $step_ty:ty = $step:expr,
snap = $snap:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (effects should satisfy {$f:expr})
) => {{
let f: Box<dyn Fn(&Vec<$crate::platform::Effect<$crate::test::Platform>>)> = Box::new($f);
f($effects)
}};
(
step: $step_ty:ty = $step:expr,
snap = $snap:expr,
effects = $effects:expr,
token = $token:expr,
addr = $addr:expr,
expect (before_message_sent(_, _, $msg:expr) should be ok with {$f:expr})
) => {{
let mut msg = $msg;
$step.before_message_sent(&$snap, &mut $effects, &mut msg)
.unwrap();
let f: Box<dyn Fn($crate::net::Addrd<$crate::test::Message>)> = Box::new($f);
f(msg)
}};
}
#[macro_export]
macro_rules! test_step {
(
GIVEN $step:ty where $inner:ty: $inner_step:tt;
WHEN $when_summary:ident [$($when:tt),*]
THEN $then_summary:ident [$($expect:tt),+]
) => {
paste::paste! {
#[test]
fn [<when_ $when_summary:lower _then_ $then_summary:lower>]() {
#![allow(unused_mut)]
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_unsafe)]
use $crate::{dummy_step, test_step_when, test_step_expect};
dummy_step!($inner_step);
let mut effects: <test::Platform as platform::PlatformTypes>::Effects = Default::default();
let mut snapshot: platform::Snapshot<test::Platform> = $crate::step::test::default_snapshot();
let mut token = ::toad_msg::Token(Default::default());
let mut addr = test::dummy_addr();
let mut step = $step::default();
unsafe {
$(
test_step_when!(
step = &step,
poll_req_mock = &mut POLL_REQ_MOCK,
poll_resp_mock = &mut POLL_RESP_MOCK,
before_message_sent_mock = &mut BEFORE_MESSAGE_SENT_MOCK,
on_message_sent_mock = &mut ON_MESSAGE_SENT_MOCK,
effects = &mut effects,
snapshot = &mut snapshot,
token = &mut token,
addr = &mut addr,
when $when
)
);*
};
$(
test_step_expect!(
step: $step = &mut step,
snap = &snapshot,
effects = &mut effects,
token = token,
addr = addr,
expect $expect
)
);+
}
}
};
}
pub use {dummy_step, test_step, test_step_when};
}