I've created a repro using notional concepts, so it does seem a little bit contrived! However I essentially have a Rust FlatBuffer that wraps a reference to a slice of bytes.
I want to parse these bytes into a new slice (by reference), wrap them up in a struct that implements some dyn trait, then pass this struct into a closure in order to avoid any heap allocations.
However, I'm struggling to annotate the correct lifetime for "SomeMetadataThingy" since it is bound by both the lifetime of the original slice of bytes, as well as the lifetime of the stack-allocated "first" and "second" objects.
Here is the playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=da18c6fb6d7fad843a5e1e1671b3f48b
struct Bytes<'a> {
// The raw bytes of the message.
bytes: &'a [u8],
}
trait WithMetadata<M> {
// Invoke the closure with a parsed metadata object.
fn with_metadata<F, T>(&self, f: F) -> T
where
F: FnOnce(&M) -> T;
}
trait SomeDynTrait {}
impl SomeDynTrait for Bytes<'_> {}
// Some parsed metadata object
struct SomeMetadataThingy<'a> {
first: &'a dyn SomeDynTrait,
second: &'a dyn SomeDynTrait,
}
impl<'meta, 'bytes> WithMetadata<SomeMetadataThingy<'meta>> for Bytes<'bytes> where 'bytes: 'meta, Self: 'meta {
fn with_metadata<F, T>(&self, f: F) -> T
where
F: FnOnce(&SomeMetadataThingy<'meta>) -> T,
{
let first = Bytes {
bytes: &self.bytes[0..2],
};
let second = Bytes {
bytes: &self.bytes[2..],
};
let parsed = SomeMetadataThingy {
first: &first,
second: &second,
};
f(&parsed)
}
}