embedded_nal_tcpextensions/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#![no_std]
//! Extensions to [embedded_nal]'s TCP traits to make more precise use of TCP buffers.
//!
//! This is not intended to be a long-term extension of embedded-nal,
//! but more an experimenation playground for [#59]
//! where users and implementations can play (ideally behind unstable feature gates);
//! once this is mature it is hoped that it'll be taken up into embedded-nal.
//!
//! [#59]: https://github.com/rust-embedded-community/embedded-nal/issues/59
use embedded_nal::nb;
mod wrappers;
pub use wrappers::*;
/// A specialization of [embedded_nal::TcpClientStack] that allows nonblocking until a given number of bytes can
/// be read, and writing in an all-or-nothing way.
///
/// Stacks that can not provide this can be wrapped in [`BufferedStack::<_, 1152>::new()`] to gain
/// this capability at the cost of per-socket allocated buffers.
///
/// It is an early form of what should resolve
/// <https://github.com/rust-embedded-community/embedded-nal/issues/59>.
pub trait TcpExactStack: embedded_nal::TcpClientStack {
/// Capacity of the connection's TCP buffer.
///
/// Calls to [`receive_exact()`](TcpExactStack::receive_exact) can ask up to this many
/// bytes to be returned.
///
/// Checking this (possibly in static assertions) is important because applications that'd wait
/// for larger chunks of data than the TCP socket can buffer will deadlock -- the application
/// waits for the server to send more, but the stack tells the server to stop sending more
/// until the application processes the data.
///
/// (This is a per-stack-type property. Stacks where this is configurable per socket need to
/// report the smallest value, which is guaranteed to be usable with [`receive_exact()`](TcpExactStack::receive_exact) on every
/// instance. It is exposed this way to allow users to have suitable const-sized allocations
/// for the sockets they are built for.)
const RECVBUFLEN: usize;
/// Receive data from the stream.
///
/// Returns `Ok(())` if the whole buffer could be filled, or an error. If a packet has not been
/// received when called, or not enough data is present, then [`nb::Error::WouldBlock`] should
/// be returned.
///
/// # Panics
///
/// This may panic when buffer is larger than RECVBUFLEN.
fn receive_exact(
&mut self,
socket: &mut Self::TcpSocket,
buffer: &mut [u8],
) -> nb::Result<(), Self::Error>;
/// Capacity of the connection's TCP send buffer.
///
/// Calls to [`send_All()`](TcpExactStack::send_all) can send up to this many bytes.
const SENDBUFLEN: usize;
/// Send all this data to the stream.
///
/// Returns `Ok(())` if the whole buffer could be submitted, or an error. If the data can not
/// fit into the send buffer when called (especially, but not only, if the send buffer is
/// full), then [`nb::Error::WouldBlock`'] is returned.
///
/// # Panics
///
/// When the passed slice is larger than the advertised SENDBUFLEN, this may panic -- for the
/// worse alternative is to return WouldBlock indefinitely, as the message can't be put in the
/// send buffer no matter how empty it becomes.
fn send_all(
&mut self,
socket: &mut Self::TcpSocket,
buffer: &[u8],
) -> Result<(), embedded_nal::nb::Error<Self::Error>>;
}