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!