I'm trying to create a helper method to rust-capnp that takes a initialization function and returns a Vec<u8>
that contains a serialized version of the message.
fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
mut builder: capnp::message::Builder<A>,
init: F,
) -> Vec<u8>
where
'a: 'b,
A: for<'c> capnp::message::Allocator + 'a,
T: capnp::traits::FromPointerBuilder<'b> + 'b,
F: FnOnce(&'b mut T),
{
let serialized_length = {
let mut root = builder.init_root::<T>();
init(&mut root);
capnp::serialize::compute_serialized_size_in_words(&builder)
* std::mem::size_of::<capnp::Word>()
};
let mut buf = Vec::with_capacity(serialized_length);
buf.resize(serialized_length, 0);
capnp::serialize::write_message(Cursor::new(buf.as_mut_slice()), &builder).unwrap();
buf
}
pub(crate) fn construct_serialized_capnp<'a, 'b, T, F>(
dest: &DmaFile,
scratch_space: Option<&'a mut [u8]>,
init: F,
) -> Vec<u8>
where
'a: 'b,
T: capnp::traits::FromPointerBuilder<'b> + 'b,
F: FnOnce(&'b mut T),
{
match scratch_space {
Some(space) => construct_serialized_capnp_into(
capnp::message::Builder::new(capnp::message::ScratchSpaceHeapAllocator::new(space)),
init,
),
None => construct_serialized_capnp_into(capnp::message::Builder::new_default(), init),
}
}
This fails on 4 lines. init_root
fails with:
76 | fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
| -- lifetime `'b` defined here
...
87 | let mut root = builder.init_root::<T>();
| ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `builder` is borrowed for `'b`
...
95 | }
| - `builder` dropped here while still borrowed
Invoking the init
function fails with:
76 | fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
| -- lifetime `'b` defined here
...
88 | init(&mut root);
| -----^^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `root` is borrowed for `'b`
...
91 | };
| - `root` dropped here while still borrowed
And then two more about trying to borrow builder immutably because (as above indicates) I'm not getting Rust to interpret the borrow lifetime correctly:
error[E0502]: cannot borrow `builder` as immutable because it is also borrowed as mutable
|
76 | fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
| -- lifetime `'b` defined here
...
87 | let mut root = builder.init_root::<T>();
| ------------------------
| |
| mutable borrow occurs here
| argument requires that `builder` is borrowed for `'b`
88 | init(&mut root);
89 | capnp::serialize::compute_serialized_size_in_words(&builder)
| ^^^^^^^^ immutable borrow occurs here
error[E0502]: cannot borrow `builder` as immutable because it is also borrowed as mutable
|
76 | fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
| -- lifetime `'b` defined here
...
87 | let mut root = builder.init_root::<T>();
| ------------------------
| |
| mutable borrow occurs here
| argument requires that `builder` is borrowed for `'b`
...
93 | capnp::serialize::write_message(Cursor::new(buf.as_mut_slice()), &builder).unwrap();
| ^^^^^^^^ immutable borrow occurs here
Can any Rust/rust-capnp expert help me understand how to fix this (or confirm if it's impossible to implement a function like this)?
It compiles if you get rid of all the explicit lifetime parameters: