I have a struct that holds metadata about a block of data, and the data itself (usually 1MB in size). I currently use serde & bincode to serialize, and everything works; however, I'm copying 1MB of data each time. I want to use serde's borrowing capabilities to prevent this copy. The problem is that someone must own the underlying data. My thought is to put the data into an Arc
, then have an inner struct that represents the block. This is what I've come up with:
use owning_ref::{OwningRef, ArcRef};
#[derive(Deserialize, Serialize)]
struct InnerBlock<'a> {
id: u64,
#[serde(borrow)]
data: &'a[u8]
}
struct Block<'a> {
inner: OwningRef<Arc<Vec<u8>>, InnerBlock<'a>>,
raw_data: Arc<Vec<u8>>
}
Then when I want to read this block from a file (for example) I'd have something like the following:
fn read_block_from_file<'a>() -> Block<'a> {
let mut f = OpenOptions::new().read(true).open("/dev/zero").unwrap();
let mut buff = vec![0; 1024];
f.read_exact(&mut buff);
let raw_data = Arc::new(buff);
let or = ArcRef::new(raw_data.clone());
let inner = or.map(|b| {
let i : InnerBlock = bincode::deserialize(b.as_slice()).unwrap();
&i
});
Block { inner, raw_data }
}
However, I get the following error from the compiler:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:28:53
|
28 | let i : InnerBlock = bincode::deserialize(b.as_slice()).unwrap();
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 27:24...
--> src/main.rs:27:24
|
27 | let inner = or.map(|b| {
| ________________________^
28 | | let i : InnerBlock = bincode::deserialize(b.as_slice()).unwrap();
29 | | &i
30 | | });
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:28:51
|
28 | let i : InnerBlock = bincode::deserialize(b.as_slice()).unwrap();
| ^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 19:25...
--> src/main.rs:19:25
|
19 | fn read_block_from_file<'a>() -> Block<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:32:5
|
32 | Block { inner, raw_data }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Block<'a>`
found `Block<'_>`
Not sure if there is a way to do this w/Serde. Any help would be greatly appreciated!