Skip to content

Allow codec::Encoder and codec::Decoder to take any IoBuf[Mut] #577

@code-withAshish

Description

@code-withAshish

I’m working on a use case that involves interacting with RESP (Redis Serialization Protocol), and I’m using the redis-protocol crate—specifically the BytesFrame type.

I’m integrating this with compio’s codec API, whose Decoder trait is defined as:

fn decode(&mut self, buf: &[u8]) -> Result<Item, Error>;

The redis_protocol::decode_bytes API expects a &Bytes, so in my current implementation I’m forced to convert the incoming &[u8] into an owned Bytes on every call:

impl Decoder<BytesFrame> for RespCodec {
    type Error = RedisProtocolError;

    fn decode(&mut self, buf: &[u8]) -> Result<BytesFrame, Self::Error> {
        let buffer = Bytes::copy_from_slice(buf);

        match decode_bytes(&buffer) {
            Ok(Some((frame, _))) => Ok(frame),
            Ok(None) => {
                // not enough data to decode a full frame
                todo!()
            }
            Err(e) => Err(e),
        }
    }
}

This works functionally, but it requires copying the entire input buffer into a new Bytes allocation on every decode, which is potentially expensive—especially for a streaming protocol like RESP.

My questions are:

  1. Is this copying unavoidable given the Decoder trait’s &[u8] input and owned Item output?
  2. Is there a more idiomatic or zero-copy way to integrate redis-protocol’s decode_bytes with compio’s framing/codec infrastructure?
  3. Does compio provide a higher-level framing or buffer abstraction (e.g. based on BytesMut) that would allow incremental decoding and buffer advancement, rather than re-decoding from a copied slice each time?

In other words, am I fundamentally constrained by the Decoder trait’s signature here, or is there a better approach I should be using for RESP-style streaming decoding?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions