use crate::{nb, TcpClientStack, TcpFullStack, UdpClientStack, UdpFullStack};
use core::cell::RefCell;
use core::net::SocketAddr;
pub struct SharableStack<T> {
stack: RefCell<T>,
}
impl<T> SharableStack<T> {
pub fn new(stack: T) -> Self {
SharableStack {
stack: RefCell::new(stack),
}
}
pub fn acquire(&self) -> SharedStack<T> {
SharedStack { stack: &self.stack }
}
}
pub struct SharedStack<'a, T> {
stack: &'a RefCell<T>,
}
macro_rules! forward {
($func:ident($($v:ident: $IT:ty),*) -> $T:ty) => {
fn $func(&mut self, $($v: $IT),*) -> $T {
self.stack.borrow_mut().$func($($v),*)
}
}
}
impl<'a, T> UdpClientStack for SharedStack<'a, T>
where
T: UdpClientStack,
{
type Error = T::Error;
type UdpSocket = T::UdpSocket;
forward! {socket() -> Result<Self::UdpSocket, Self::Error>}
forward! {connect(socket: &mut Self::UdpSocket, address: SocketAddr) -> Result<(), Self::Error>}
forward! {send(socket: &mut Self::UdpSocket, data: &[u8]) -> Result<(), nb::Error<<T as UdpClientStack>::Error>>}
forward! {receive(socket: &mut Self::UdpSocket, data: &mut [u8]) -> Result<(usize, SocketAddr), nb::Error<<T as UdpClientStack>::Error>>}
forward! {close(socket: Self::UdpSocket) -> Result<(), Self::Error>}
}
impl<'a, T> UdpFullStack for SharedStack<'a, T>
where
T: UdpFullStack,
{
forward! {bind(socket: &mut Self::UdpSocket, local_port: u16) -> Result<(), Self::Error>}
forward! {send_to(socket: &mut Self::UdpSocket, remote: SocketAddr, buffer: &[u8]) -> Result<(), nb::Error<<T as UdpClientStack>::Error>>}
}
impl<'a, T> TcpClientStack for SharedStack<'a, T>
where
T: TcpClientStack,
{
type TcpSocket = T::TcpSocket;
type Error = T::Error;
forward! {socket() -> Result<Self::TcpSocket, Self::Error>}
forward! {connect(socket: &mut Self::TcpSocket, address: SocketAddr) -> Result<(), nb::Error<<T as TcpClientStack>::Error>>}
forward! {send(socket: &mut Self::TcpSocket, data: &[u8]) -> Result<usize, nb::Error<<T as TcpClientStack>::Error>>}
forward! {receive(socket: &mut Self::TcpSocket, data: &mut [u8]) -> Result<usize, nb::Error<<T as TcpClientStack>::Error>>}
forward! {close(socket: Self::TcpSocket) -> Result<(), Self::Error>}
}
impl<'a, T> TcpFullStack for SharedStack<'a, T>
where
T: TcpFullStack,
{
forward! {bind(socket: &mut Self::TcpSocket, port: u16) -> Result<(), <T as TcpClientStack>::Error>}
forward! {listen(socket: &mut Self::TcpSocket) -> Result<(), <T as TcpClientStack>::Error>}
forward! {accept(socket: &mut Self::TcpSocket) -> Result<(<T as TcpClientStack>::TcpSocket, SocketAddr), nb::Error<<T as TcpClientStack>::Error>>}
}