-
Notifications
You must be signed in to change notification settings - Fork 245
Description
It seems trivial to implement, and it's currently forcing me to new-type my way around it.
Is there some gotcha I'm missing or is it just an oversight?
Problem
I'm writing a composable decoder scheme (optional crc, headers, prefix, etc.) which supports timeouts/incomplete data handling via ReadReady
,
Some stages of this (like the length prefix header), requires buffering of data, which is then passed on to subsequent decoding layers in place of the "real" underlying Read
structure.
The issue I'm facing is that I require ReadReady
from the input (for timeout/retry purposes):
pub trait Encoding {
type Output;
fn decode<Rx, E>(&self, rx: &mut Rx) -> Result<Self::Output, E>
where
Rx: Read + ReadReady + ErrorType<Error = E>;
}
Which means that my ideal length prefix implementation can't work:
struct LengthPrefix<T: Encoding> {
inner: T,
}
impl<T: Encoding> Encoding for LengthPrefix<T> {
type Output = <T as Encoding>::Output;
fn decode<Rx, E>(&self, rx: &mut Rx) -> Result<Self::Output, E>
where
Rx: Read + ReadReady + ErrorType<Error = E>,
{
let length: usize = /* read length prefix, not important for this */
// buffer the rest of the message, which we now know the length of
let mut buffer = [0u8; 255];
rx.read_exact(&mut buffer[..length])?;
// pass the buffered message on to the inner decoder
let mut slice = &buffer[..length];
self.inner.decode(&mut slice) // <-- Fails! `&[u8]` does not implement `ReadReady`
}
}
Workaround
For now, I've worked around this by implementing a bounded reader:
struct BoundedReader<'a>(&'a [u8]);
impl<'a> ErrorType for BoundedReader<'a> {
type Error = <&'a [u8] as ErrorType>::Error;
}
impl<'a> Read for BoundedReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let bytes = self.0.read(buf)?;
self.0.consume(bytes);
Ok(bytes)
}
}
impl<'a> ReadReady for BoundedReader<'a> {
fn read_ready(&mut self) -> Result<bool, Self::Error> {
Ok(!self.0.is_empty())
}
}
If I'm not totally off on this, I don't mind spending a couple of minutes writing implementation :)