Can I create a structure that can be built from either a slice or a custom buffer?
I'll try to be as clear as possible. Suppose I:
struct Foo<'a> {
buffer: &'a [u8],
}
impl<'a> Foo<'a> {
fn create_builder() -> FooBuilder {
FooBuilder::new()
}
fn from_slice(slice: &[u8]) -> Foo {
Foo { buffer: slice }
}
}
struct FooBuilder {
in_progress_buffer: Vec<u8>,
}
impl FooBuilder {
fn new() -> FooBuilder {
FooBuilder { in_progress_buffer: Vec::new() }
}
fn push(&mut self, item: u8) {
self.in_progress_buffer.push(item);
}
fn build_foo(self) -> Foo {
Foo { buffer: self.in_progress_buffer }
}
}
fn main() {
// Option1: Gradually construct Foo from FooBuilder
let mut foo_builder = FooBuilder::new();
foo_builder.push(7);
let foo = foo_builder.build_foo();
// Option2: Construct Foo from a slice
let v = vec![7];
let foo2 = Foo::from_slice(&v);
}
This gives a compile error:
error[E0106]: missing lifetime specifier --> src/main.rs:28:27 | 28 | fn build_foo(self) -> Foo { | ^^^ expected lifetime parameter | = help: this function return type contains a borrowed value, but there is no value for it to be borrowed from = help: consider giving it a 'static lifetime
Is this pattern possible? How can I fix the compilation error? I'm not sure what the lifecycle specifier is, since in version FooBuilder
, FooBuilder
owns the buffer, and I don't want to force users to Foo
maintain FooBuilder
in the scope for the full duration of Foo
use
source to share
You can use std::borrow::Cow
; as docs :
it can enclose and provide immutable access to borrowed data and clone data lazily when mutation or property is required
use std::borrow::Cow;
struct Foo<'a> {
buffer: Cow<'a, [u8]>,
}
impl<'a> Foo<'a> {
fn create_builder() -> FooBuilder {
FooBuilder::new()
}
fn from_slice(slice: &[u8]) -> Foo {
Foo { buffer: slice.into() } // note .into()
}
}
struct FooBuilder {
in_progress_buffer: Vec<u8>,
}
impl<'a> FooBuilder {
fn new() -> FooBuilder {
FooBuilder { in_progress_buffer: Vec::new() }
}
fn push(&mut self, item: u8) {
self.in_progress_buffer.push(item);
}
fn build_foo(self) -> Foo<'a> {
Foo { buffer: self.in_progress_buffer.into() } // note .into()
}
}
Also, you will need to make it foo_builder
mutable in order to be able to execute push
on it.
source to share