jam1garner / binrw

A Rust crate for helping parse and rebuild binary data using ✨macro magic✨.
https://binrw.rs
MIT License
545 stars 35 forks source link

BinWrite trait cannot be made into an Object #245

Closed sempervictus closed 6 months ago

sempervictus commented 6 months ago

Trying to sort out implementation of AsyncRead and AsyncWrite for the BinRead and BinWrite traits, i ran into a fun compiler message saying

the trait `BinWrite` cannot be made into an object
`BinWrite` cannot be made into an objectrustc[Click for full compiler diagnostic](rust-analyzer-diagnostics-view:/diagnostic%20message%20%5B14%5D?14#file...)
mod.rs(47, 10): for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

My choices here are to implement async for binrw, hack up a bunch of Stream conversions into std with blocking runners, or rewrite everything to legacy sync code and then rewrite it back sometime down the line when async is more widely supported... so figure trying to tackle asyncrw seemed the most productive but that error message looks like doing this would require some internal reorganization. I'm looking into implementing future/await as an interface for this but it looks like we need those traits in the mix to work with async runtimes around the byte ops (or more specifically, the streams on which this library operates).

sempervictus commented 6 months ago

The read side doesn't seem to throw errors:

impl Unpin for dyn BinRead {}
impl AsyncRead for dyn BinRead {
    fn poll_read(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<binrw::io::Result<()>> {
        AsyncRead::poll_read(Pin::new(&mut self), cx, buf)
    }
}

the write side gets upset by the dyn and Unpin pieces:

impl Unpin for dyn BinWrite {}
impl AsyncWrite for dyn BinWrite {
    fn poll_write(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<binrw::io::Result<usize>> {
        AsyncWrite::poll_write(Pin::new(&mut self), cx, buf)
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<binrw::io::Result<()>> {
        AsyncWrite::poll_flush(Pin::new(&mut self), cx)
    }

    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<binrw::io::Result<()>> {
        AsyncWrite::poll_shutdown(Pin::new(&mut self), cx)
    }
}
csnover commented 6 months ago

I’m sorry, I don’t understand this ticket. It looks like you are trying to implement tokio traits on binrw objects, which means you must be editing binrw directly, but then this isn’t a bug with binrw. How can I help you? Please also see https://github.com/jam1garner/binrw/discussions/178.

csnover commented 6 months ago

I’ll close this issue for now since it seems like there is nothing to be done from this side. If you can provide more information that will turn this into an actionable ticket, please feel free to reply any time!