2017-06-21 4 views
3

私は可能な限り明確にしようとします。のは、私が持っているとしましょう:スライスと所有バッファの両方から構築できる構造体を使用できますか?

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); 
} 

これはコンパイルエラーを与える:

error[E0106]: missing lifetime specifier 
    --> src/main.rs:28:27 
    | 
28 |  fn build_foo(self) -> Foo { 
    |       ^^^ expected lifetime parameter 
    | 
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from 
    = help: consider giving it a 'static lifetime 

が可能、このパターンですか?コンパイルエラーを修正するにはどうすればよいですか? FooBuilderバージョンでは、FooBuilderがバッファを所有している、と私は全期間FooのスコープでFooBuilderを保つためにFooユーザーを強制したくないので、私は与えるためにどのような生涯指定わからないが

+1

一見すると、['CoW'](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html)を使うことができるようです。 :) –

+0

なぜFooはバッファを所有していないのですか? – Boiethios

+0

@Boiethios Fooをスライスからデシリアライズすることを許可したいと思います。 Fooはスライスを検査するメソッドを提供します(例えば、バッファ内のいくつのアイテムが42に設定されているか)が、バッファを変更することはありません – Shmoopy

答えて

2

を使用していますstd::borrow::Cowを使用できます。 docs状態として:

it can enclose and provide immutable access to borrowed data, and clone the data lazily when mutation or ownership 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() 
    } 
} 

加えて、あなたはそれにpushを実行できるようにするために可変foo_builderを行う必要があります。

+0

これは完璧ですね、ありがとう! – Shmoopy

関連する問題