use smoltcp::phy::{
RxToken,
TxToken,
};
tiny_fn::tiny_fn! {
struct ByteWrap = FnOnce(b: &mut [u8]);
struct DynRxInner = FnOnce(f: ByteWrap);
struct DynTxInner = FnOnce(len: usize, f: ByteWrap);
}
pub struct DynRxToken<'a>(DynRxInner<'a>);
pub struct DynTxToken<'a>(DynTxInner<'a>);
impl<'a> DynRxToken<'a> {
#[inline]
pub fn new(rx: impl RxToken + 'a) -> Self {
Self(DynRxInner::new(move |f| {
rx.consume(move |b| {
f.call(b);
});
}))
}
}
impl RxToken for DynRxToken<'_> {
#[inline]
fn consume<R, F>(self, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
let mut result = None;
{
let result = &mut result;
let wrapped = ByteWrap::new(move |b| {
*result = Some(f(b));
});
self.0.call(wrapped);
}
result.unwrap()
}
}
impl<'a> DynTxToken<'a> {
#[inline]
pub fn new(t: impl TxToken + 'a) -> Self {
Self(DynTxInner::new(move |len, f| {
t.consume(len, move |b| {
f.call(b);
})
}))
}
#[inline]
pub fn send(self, buf: &[u8]) {
self.consume(buf.len(), |inner| inner.copy_from_slice(buf))
}
}
impl TxToken for DynTxToken<'_> {
#[inline]
fn consume<R, F>(self, len: usize, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
let mut result = None;
{
let result = &mut result;
self.0.call(
len,
ByteWrap::new(move |b| {
*result = Some(f(b));
}),
);
}
result.unwrap()
}
}