Skip to content

Why is ReadReady not implemented for &[u8]? #658

@MathiasPius

Description

@MathiasPius

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 :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions