แปลง Vec <Vec <u8>> เป็น & [& [u8]] [ซ้ำ]

Nov 08 2020

ฉันมีฟังก์ชั่นที่ใช้จำนวนของสตริงไบต์บาง: แต่ต้องการที่จะเรียกว่ามีข้อโต้แย้งของพิมพ์&[&[u8]] Vec<Vec<u8>>การเรียกใช้ฟังก์ชันดังนี้:

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

แปลงfooเป็นชิ้น แต่ไม่ใช่ค่าที่มีอยู่ มีวิธีการแปลงนี้อย่างง่ายดายและมีประสิทธิภาพหรือไม่? หรือฉันสามารถเปลี่ยนประเภทของอาร์กิวเมนต์ของฟังก์ชันเพื่อหลีกเลี่ยงกรณีเช่นนี้ได้หรือไม่

คำตอบ

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

วิธีหนึ่งในการจัดการกรณีนี้โดยไม่ต้องจัดสรรเพิ่มเติมVecคือใช้AsRef<[u8]>:

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

ภายในฟังก์ชันคุณสามารถใช้.as_ref()เพื่อแปลงอาร์กิวเมนต์แต่ละรายการเป็น&[u8]ไฟล์.

( สนามเด็กเล่น )

2 Locke Nov 08 2020 at 16:11

จากมุมมองของความทรงจำสิ่งนี้ไม่สมเหตุสมผลเท่าไหร่ ในการสร้างชิ้นส่วนข้อมูลที่ถูกแบ่งจะต้องมีอยู่ในหน่วยความจำก่อน อย่างไรก็ตามในการแบ่งส่วน&[u8]ก่อนอื่นคุณต้องมีโครงสร้างข้อมูลที่ต้องการVec<&[u8]>นำชิ้นส่วนมา

กล่าวอีกนัยหนึ่งในการทำเช่นนี้คุณต้องจัดสรรพื้นที่สำหรับVec<&[u8]>หรือ[&[u8]; N]และเติมด้วยชิ้นส่วนก่อน สิ่งนี้ค่อนข้างเอาชนะจุดประสงค์ของการใช้ชิ้นส่วนเนื่องจากชิ้นส่วนนั้นหมายถึงหน่วยความจำอ้างอิงที่มีอยู่ในสถานที่ ลองใช้&[Vec<u8>]สำหรับฟังก์ชันของคุณแทน

หากการแบ่งส่วนในชั้นที่สองมีความสำคัญหรือคุณไม่สามารถแก้ไขฟังก์ชันได้คุณสามารถทำสิ่งต่อไปนี้เพื่อแปลงVec<Vec<u8>>เป็น&[&[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[..]);