2017-07-25 2 views
0

私は小さな文字列の最適化とカスタムString様構造体のナイーブな実装を構築しようとしていました。今、労働組合が安定ルーストに許可されていることを、私は次のコードを思い付いた:安定した錆に生の可変ポインタをどのように割り当てることができますか?

struct Large { 
    capacity: usize, 
    buffer: *mut u8, 
} 

struct Small([u8; 16]); 

union Container { 
    large: Large, 
    small: Small, 
} 

struct MyString { 
    len: usize, 
    container: Container, 
} 

私はどのよう*mut u8を割り当てるための方法を見つけるように見えることはできません。安定した錆で行うことは可能ですか? alloc::heapを使用するように見えますが、夜間にのみ利用できます。 Box::into_raw()について

+0

FWIWでは、 'String'自体が公開する特定のメソッドのために、' SSO 'を使用することはできません。あなたは完全なAPIを複製することはできませんが、うまくいけばそれがあなたのユースケースを妨げることはありません。 – Shepmaster

答えて

2

あなたの代わりに、単一のu8u8のコレクションを割り当てたい場合は、あなたがVecを作成して、そのようなas_mut_ptrを呼び出すのと同じ構成の部分、に変換することができます

use std::mem; 

fn main() { 
    let mut foo = vec![0; 1024]; // or Vec::<u8>::with_capacity(1024); 

    let ptr = foo.as_mut_ptr(); 
    let cap = foo.capacity(); 
    let len = foo.len(); 
    mem::forget(foo); // Avoid calling the destructor! 

    let foo_again = unsafe { Vec::from_raw_parts(ptr, len, cap) }; // Rebuild it to drop it 
    // Do *NOT* use `ptr`/`cap`/`len` anymore 
} 

割り振りは少しでも苦痛です。あなたが戻っVecに変換する必要があり、全体のダンス転送を行うと、後方

言われていること、あなたのLarge構造体は、容量は異なるだろうlengthを、欠けているように見えると思います。あなたはそれを書く代わりにVecを使用することができます。これは階層構造の中に少しあります。

フルStringを持つこと、それは長さが二重にカウントされることに少し非効率的であったとしても、多くの方が簡単ではない場合、私はまた、参照してください

union Container { 
    large: String, 
    small: Small, 
} 

...不思議:

+1

長さフィールドは、 'Large'または' Small'も含む 'MyString'にあります。 – interjay

+0

@interjayああ、確かに。 – Shepmaster

+0

これはまさに私が探していたものです!ありがとうございました!どういうわけか私は割り当てと割り当て解除にVecを使うことができないことに気がつきました。 –

1

何?

struct TypeMatches(*mut u8); 
TypeMatches(Box::into_raw(Box::new(0u8))); 

これが本当に必要なのかどうかをコードスニペットから判断するのは難しいです。あなたは、おそらく実際のアロケータをしたい、とあなたはthis exampleのように、asキャストでlibc::mallocを使用することができます。

+0

これは単一の 'u8'を割り当てます。 OPは複数のバッファを必要とします。 – interjay

+0

@interjayそれは当てはまりますが、尋ねられた質問は単にポインタ*をどのように割り当てるかであり、これはそれに対する有効な答えです。私は、検索エンジンから来る人々がこの質問と回答を見つけることができると期待しています。 – Shepmaster

2

安定割り当てAPIを提供memalloc crateがあります。次に、それをポインタを抽出し、Vec::with_capacityでメモリを割り当てることにより実現しています:

let vec = Vec::with_capacity(cap); 
let ptr = buf.as_mut_ptr(); 
mem::forget(vec); 

Vec::from_raw_partsを使用し、メモリを解放します。

関連する問題