2016-05-17 6 views
1

私はいくつかのC++コードをRustに移植しようとしています。これは、数種類のスライス(文字列参照、遅延評価された文字列参照、物理ファイルの一部)から仮想(.mp4)ファイルを作成し、その結果に基づいてHTTP要求を処理します。 (。あなたは好奇心旺盛であれば、http.hFileSliceインタフェースとその具体的な実装を活用したMp4Fileを参照)Vec <MyTrait> Nヒープ割り当てなし?

ここで問題です:私はできるだけ少ないヒープ割り当てを必要とします。 resource::Sliceの実装がいくつかあるとしましょう。

pub trait Slice : Send + Sync { 
    /// Returns the length of the slice in bytes. 
    fn len(&self) -> u64; 

    /// Writes bytes indicated by `range` to `out.` 
    fn write_to(&self, range: &ByteRange, 
       out: &mut io::Write) -> io::Result<()>; 
} 

// (used below) 
struct SliceInfo<'a> { 
    range: ByteRange, 
    slice: &'a Slice, 
} 

/// A `Slice` composed of other `Slice`s.  
pub struct Slices<'a> { 
    len: u64, 
    slices: Vec<SliceInfo<'a>>, 
} 

impl<'a> Slices<'a> { 
    pub fn new() -> Slices<'a> { ... } 
    pub fn append(&mut self, slice: &'a resource::Slice) { ... } 
} 

impl<'a> Slice for Slices<'a> { ... } 

、できるだけ少数のヒープ割り当てとスライスのとてもたくさんを追加するためにそれらを使用します。そして、私はそれらのすべてを構成するものを作りたいです。簡略化されたこのようなもの:

struct ThingUsedWithinMp4Resource { 
    slice_a: resource::LazySlice, 
    slice_b: resource::LazySlice, 
    slice_c: resource::LazySlice, 
    slice_d: resource::FileSlice, 
} 

struct Mp4Resource { 
    slice_a: resource::StringSlice, 
    slice_b: resource::LazySlice, 
    slice_c: resource::StringSlice, 
    slice_d: resource::LazySlice, 
    things: Vec<ThingUsedWithinMp4Resource>, 
    slices: resource::Slices 
} 

impl Mp4Resource { 
    fn new() { 
     let mut f = Mp4Resource{slice_a: ..., 
           slice_b: ..., 
           slice_c: ..., 
           slices: resource::Slices::new()}; 
     // ...fill `things` with hundreds of things... 
     slices.append(&f.slice_a); 
     for thing in f.things { slices.append(&thing.slice_a); } 
     slices.append(&f.slice_b); 
     for thing in f.things { slices.append(&thing.slice_b); } 
     slices.append(&f.slice_c); 
     for thing in f.things { slices.append(&thing.slice_c); } 
     slices.append(&f.slice_d); 
     for thing in f.things { slices.append(&thing.slice_d); } 
     f; 
    } 
} 

これは機能しません。行を追加するとエラーが発生する "f.slice_ *の長さが十分に長くない"、 "参照はブロックで定義されている有効期限 'a ..."、 "...ですが、借用された値はブロックサフィックス次のステートメント "となります。私はこれが自己参照構造体についてはthis questionに似ていると思う。これは基本的には間接的なもので、これが何であるかです。そして明らかにそれは不可能です。

代わりに何をすることができますか?

私はappendresource::Slicesに所有権を与えることが幸せになるだろうと思うが、resource::Sliceは形質である、と形質が無サイズですので、私はVec<SliceInfo>で使用SliceInforesource::Sliceを置くことはできません。私は代わりにBox<resource::Slice>を行うことができますが、それは各スライスに別々のヒープ割り当てを意味します。私はそれを避けたいです。 (Mp4Resourceあたりのスライス数千ものが存在する場合があります。)

私は、列挙型をしているのようなものと思っています:

enum BasicSlice { 
    String(StringSlice), 
    Lazy(LazySlice), 
    File(FileSlice) 
}; 

をしてSliceInfoでそれを使用します。私はこの仕事をすることができると思う。しかし、それは間違いなく私のresource::Slicesクラスの有用性を制限します。期待していない状況で簡単に使用できるようにしたい、できれば毎回新しい列挙型を定義する必要はありません。

他のオプションはありますか?

+2

限定された寿命アイテムが構造体に含まれている場合、構造体の寿命も制限されます。 – WiSaGaN

+0

@WiSaGaN構造体に寿命が限定されたアイテムを含めることについて何が言いましたか?私の最初のアプローチは、そうでなければ構造体が存在する限り正確に生存するアイテムを含めることでした。しかし、私はその生涯を表現する方法がないと思うので、自己参照構造体は不可能です。とにかく、私は質問で言ったように、私は別の方法を見つけることができてうれしいです... –

+0

まあ、それはまったく真実を除いて。少なくともC++の言葉では、クラスのメンバは逆順で破棄されるように構築され、以前のメンバを参照する後のメンバがあります。それは安全なことです。もしそれが助けになるのであれば、私は2つの別々のヒープ割り当てでそれらを行うことができます。しかし、それは生涯はまだ関係なく通過する必要があるようだ... –

答えて

4

BasicSlice列挙型にUserの亜種を追加することができます。これはBox<SliceInfo>です。このようにして、特殊なケースのユーザーのみが余分な割り当てを行い、通常のパスは最適化されます。

関連する問題