bytes icon indicating copy to clipboard operation
bytes copied to clipboard

BytesMut does not implement io::Write

Open Ten0 opened this issue 4 years ago • 9 comments

Is there any particular reason why BytesMut does not implement std::io::Write? Vec<u8> has it implemented. It looks like BytesMut should support that as well.

(NB: BytesMut has std::fmt::Write implemented, I'm talking about io::Write here, which is a different trait)

Ten0 avatar Aug 08 '20 23:08 Ten0

It's implemented, but only through bytes::buf::BufMutExt trait (method writer).

fanatid avatar Aug 09 '20 15:08 fanatid

Thank you, had not noticed, I can remove my own wrapper now ^^' Looks to me like BytesMut could still implement it directly, it would make the interface easier.

Ten0 avatar Aug 09 '20 16:08 Ten0

It does seem like it could be implemented... I can't remember, I feel it used to be. Did we remove it?

seanmonstar avatar Aug 09 '20 16:08 seanmonstar

Came across this today and just wanted to update for future readers that in 0.6.0, BytesMut::writer is available, the ext traits have been removed. Perhaps this should be closed?

octylFractal avatar Oct 22 '20 08:10 octylFractal

Can we bring back the writer in BufMutExt?

Consider the use case where one is using both BufMut methods, and wants to also use Write methods. writer() consumes the BufMut, after which one would have to go through get_mut() to access the BufMut,

If the use case involves using both BufMut methods and Write methods on a given instance, BufMutExt would be a good fit.

rich-murphey avatar Jan 28 '21 00:01 rich-murphey

Came across this today and just wanted to update for future readers that in 0.6.0, BytesMut::writer is available, the ext traits have been removed. Perhaps this should be closed?

It still looks like it could be implemented directly on BufMut, no?

Ten0 avatar Jan 28 '21 01:01 Ten0

yea, directly on BytesMut, could look something like:

impl std::io::Write for BytesMut {
    fn write(&mut self, src: &[u8]) -> std::io::Result<usize> {
        self.extend_from_slice(src);
        Ok(src.len())
    }
    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

The docs do say that Buf and BufMut "serve different purposes" from Read and Write.

However, while working with actix-web, the HTTP Response object takes body composed of Bytes. To efficiently construct Bytes, I use a BytesMut, where portions of the protocol framing are best handled by buf.put_*(), while other parts are handled by serde::to_writer(), which wants a Write object.

It'd be nice to have a direct implementation somewhat similar to how Vec implements Write, if that's reasonable of course.

rich-murphey avatar Jan 28 '21 05:01 rich-murphey

I'd be glad to write a PR if needed. Are there design concerns about this?

For example, should Write be implemented on a separate BytesMutExt trait to keep it separate, or should it be directly on BytesMut? The reason as ask is... writer() eventually moved from the extension to directly on BytesMut. If that's where Write would eventually end up, it may be helpful if it's there from the start.

Here's why. Look at the current stable actix-web 3.3.2 for example. It uses bytes version 0.5.3 released December 12, 2019. Sol there's the possibility that changes such as this may delayed for dependent crates, and the impact of changing ti from BytesMutExt to BytesMut could occur long afterward.

rich-murphey avatar Jan 29 '21 01:01 rich-murphey

I submitted a PR #478 to implement Write for BytesMut. It uses the same trait impl as Vec does.

rich-murphey avatar Feb 07 '21 04:02 rich-murphey