tokio-rs / bytes

Utilities for working with bytes
MIT License
1.91k stars 288 forks source link

Allow creating custom Bytes instances using constructor that takes an Arc<dyn Any> #571

Closed rklaehn closed 1 year ago

rklaehn commented 2 years ago

I have a situation where I have a memory mapped file and want to pass a slice of it around unencumbered by lifetimes, but without copying. I have looked into the Bytes crate, but could not use it since there is no way to create a custom Bytes instance.

See https://github.com/tokio-rs/bytes/issues/526 and https://github.com/tokio-rs/bytes/issues/437 .

I ended up writing my own bytes like struct that is a byte slice and an Arc<dyn Any>. See Blob .

This works very similar to Bytes, except that the reference counting is done by the Arc<dyn Any> instead of a custom VTable. There is a Constructor where you pass in a slice and an Arc<dyn Any> and promise that the slice will be valid as long as whatever the Arc<dyn Any> points to is kept alive.

You could easily implement a custom VTable for this approach and expose a similar method in the Bytes crate. I think it is a pretty minimal way to allow for custom Bytes instances without having to expose internals like the VTable.

I guess you would have to do the same for Rc for completeness sake, but still it is much less surface area than approaches that require to make the VTable public, and also quite convenient for the user.

Here is how it is used:

        use memmap::MmapOptions;
        use std::{io::Write, sync::Arc};
        // create a large file
        let mut large_file = tempfile().unwrap();
        large_file.write_all(&[0u8; 1024 * 1024])?;
        // map it and wrap the MMap in an arc
        let mmap =  Arc::new(unsafe { MmapOptions::new().map(&large_file).unwrap() });
        // create a bytes that points to a part of the large file, without allocation
        // the Bytes instance keeps the mmap alive as long as needed
        let slice = unsafe { Bytes::custom_new(&mmap[10..10000], mmap.clone()); };
rklaehn commented 2 years ago

Note: I am not saying that this is the best way forward. Any of the other two ( #526 and #437 ) would also do.

It would just be great if there was any way to create a Bytes for something like a memory mapped buffer without copying.

Darksonn commented 1 year ago

Closing as duplicate of #437.