Konwertuj Vec <Vec <u8>> na & [& [u8]] [duplicate]

Nov 08 2020

Mam funkcję, która przyjmuje pewną liczbę ciągów bajtów: &[&[u8]]ale chcę ją wywołać z argumentem typu Vec<Vec<u8>>. Wywołanie funkcji w ten sposób:

let foo: Vec<Vec<u8>> = Vec::new();
bar(&foo[..]);

konwertuje foona plasterek, ale nie zawiera wartości. Czy istnieje sposób na łatwe i wydajne wykonanie tej konwersji? Czy mogę zmienić typ argumentu funkcji, aby uniknąć takich przypadków?

Odpowiedzi

2 L.F. Nov 08 2020 at 19:35

Jednym ze sposobów obsługi tego przypadku bez przydzielania dodatkowego Vecjest użycie AsRef<[u8]>:

fn bar<S: AsRef<[u8]>>(args: &[S]) {
    // ...
}

Wewnątrz funkcji możesz .as_ref()przekonwertować każdy z argumentów na plik &[u8].

( plac zabaw )

2 Locke Nov 08 2020 at 16:11

Z punktu widzenia pamięci nie ma to większego sensu. Aby utworzyć wycinek, dane do wycięcia muszą najpierw istnieć w pamięci. Jednak aby wziąć kawałek &[u8], najpierw musisz mieć jakąś strukturę danych, taką jak Vec<&[u8]>wzięcie wycinka.

Innymi słowy, aby to zrobić, musisz najpierw przeznaczyć miejsce na Vec<&[u8]>lub [&[u8]; N]i wypełnić je plasterkami. To nieco przeczy celowi używania plasterków, ponieważ plasterki są przeznaczone do istniejącej pamięci referencyjnej. &[Vec<u8>]Zamiast tego rozważ użycie dla swojej funkcji.

Jeśli posiadanie plasterków na drugiej warstwie jest ważne lub nie możesz edytować funkcji, możesz wykonać następujące czynności, aby przekonwertować Vec<Vec<u8>>na &[&[u8]]:

let foo: Vec<Vec<u8>> = Vec::new();

// Allocate Vec of references to slices
let tmp: Vec<&[u8]> = foo.iter().map(|x| &x[..]).collect();

// Take slice of temporary Vec
bar(&tmp[..]);