Skip to content

Conversation

@Mrreadiness
Copy link

Implement from_parts() for FramedWrite and FramedRead.

Motivation

Thanks to #7566, FramedWrite and FramedRead can be transformed into FramedParts, but there is no way to create them back from parts, or to transform Framed into FramedRead or FramedWrite without losing progress in buffers.

My original problem was splitting Framed into both FramedRead and FramedWrite, to swap the codec for one of them with map_codec. I wish we could have something like into_split for Framed:

impl<T, U> Framed<T, U>
where
    T: AsyncRead + AsyncWrite,
    U: Clone,
{
    pub fn into_split(self) -> (FramedRead<ReadHalf<T>, U>, FramedWrite<WriteHalf<T>, U>) {
        let (r, w) = split(self.inner.inner);
        let read = FramedRead::from_parts(FramedParts {
            io: r,
            codec: self.inner.codec.clone(),
            read_buf: self.inner.state.read.buffer,
            write_buf: BytesMut::new(),
            _priv: (),
        });
        let write = FramedWrite::from_parts(FramedParts {
            io: w,
            codec: self.inner.codec,
            read_buf: BytesMut::new(),
            write_buf: self.inner.state.write.buffer,
            _priv: (),
        });
        return (read, write);
    }
}

But cloning of the codec doesn't feel right here. So, with from_parts, a user will have more control over the reader and writer reconstruction.

Solution

Implement from_parts() for FramedWrite and FramedRead, which builds those structures from FramedParts and preserves internal buffers.

@github-actions github-actions bot added the R-loom-util Run loom tokio-util tests on this PR label Dec 6, 2025
@ADD-SP ADD-SP added A-tokio-util Area: The tokio-util crate M-codec Module: tokio-util/codec labels Dec 7, 2025
Copy link
Member

@ADD-SP ADD-SP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would mind adding some tests for both from_parts and into_parts?

@ADD-SP ADD-SP added the S-waiting-on-author Status: awaiting some action (such as code changes) from the PR or issue author. label Dec 7, 2025
@Mrreadiness
Copy link
Author

@ADD-SP Thanks! I added tests as well.

I also noticed that FramedParts::new() forces the creation of parts with at least an Encoder codec. But it doesn't make much sense, because it could be used for Decoder without Encoder. Looks like it's just a historical mistake, and there was an attempt to remove this limitation (#5280), but it's a breaking change, so it was reverted.
That's why I added an alternative constructor: FramedParts::new_parts.

So, solving the task of splitting up Framed will look like:

let framed = Framed::from_parts(parts);
let FramedParts {
    io,
    read_buf,
    write_buf,
    ..
} = framed.into_parts();
let (io_read, io_write) = tokio::io::split(parts.io);
let mut read_parts = FramedParts::new_parts(io_read, Codec::new());
read_parts.read_buf = read_buf;
let framed_read = FramedRead::from_parts(read_parts);
let mut write_parts = FramedParts::new_parts(io_write, Codec::new());
write_parts.write_buf = write_buf;
let framed_write = FramedWrite::from_parts(read_parts);

It's far from perfect, but at least doable now.
If you see a better way to do such a split or even an ergonomic way to add it as a method of Framed, I will be happy to implement it.

@ADD-SP ADD-SP removed the S-waiting-on-author Status: awaiting some action (such as code changes) from the PR or issue author. label Dec 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-tokio-util Area: The tokio-util crate M-codec Module: tokio-util/codec R-loom-util Run loom tokio-util tests on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants