(Possible pre-pre-RFC) "ReadFrame" + "WriteFrame" Trait?

While working on a DTLS implementation, and looking at a few depending/related projects, i discovered that there's a real absence of a "Framed Reader/Writer", the current Read+Write trait assumes a stream of data, and models reading/writing partial chunks entirely off of that.

However, UdpSocket does not implement Write + Read (for good reason), yet i still would like it to be somewhat generic to address through a trait bound, but that's where i discovered there is no trait bound of this type.

What i'm looking for is something along the lines of "Write/Read either an entire frame/chunk of bytes, or nothing at all", an ethernet/UDP frame, a websocket frame, or another "frame" of data.

In the case of UDP, these frames may be unordered/unreliable, but they would be framed. In the case of WebSockets, they'd be ordered and reliable.

Thus, the only functionality that this trait would give is "I will read/write either one frame of data as I see it.", which is a lot weaker than Read+Write, but could still be helpful, as it guarantees a bound of ordered bytes, outside of which these bounds can arrive in any order. This could make protocols with in-band sequencing (aforementioned DTLS, CoAP, or even TCP/IP on top of Ethernet framing) able to generically use this API.

Has such an API ever been considered? If not, would there be interest in such a thing?

There is a (afaik unused) crate that defines a trait similar to this for async contexts: async-datagram. It's not quite fully general since it is send_to/recv_from so encodes the expectation that a single socket is able to talk to multiple addresses (though I guess you could have type Receiver = () for a WebSocket).

There's also another encoding I've seen used for this in the async world:

Stream<Item = io::Result<impl AsRef<[u8]>>>
 + Sink<impl AsRef<[u8]>, Error = io::Error>

in the sync world this would be the equivalent of something like

Iterator<Item = io::Result<impl AsRef<[u8]>>>
 + FnMut(impl AsRef<[u8]>) -> io::Result<()>
1 Like

Are you looking into something like this? FramedRead in tokio_util::codec - Rust

No, while the name and some of the API do look like what I’m trying to achieve, this is essentially a streamed decoder internim object. I’m specifically looking for a trait which says “this object can give/take chunks of bytes” in the same way the Read trait currently says “this object can give bytes”.