2015-04-21 14 views
8

Tôi đang cố gắng tìm ra cách chuyển đổi giống như Rust nhất từ ​​một véc tơ sang mảng và ngược lại. Các macro này sẽ hoạt động và thậm chí có thể được tạo chung với một số khối không an toàn, nhưng tất cả đều cảm thấy rất không giống như Rust.Chuyển đổi vec-tơ thành mảng và quay lại

Tôi sẽ đánh giá cao mọi đầu vào và giữ không có cú đấm, tôi nghĩ rằng mã này là xa đẹp hoặc tối ưu. Tôi chỉ chơi với Rust trong một vài tuần và đuổi theo các bản phát hành và tài liệu để thực sự đánh giá cao sự giúp đỡ.

macro_rules! convert_u8vec_to_array { 
    ($container:ident, $size:expr) => {{ 
    if $container.len() != $size { 
      None 
    } else { 
     use std::mem; 
     let mut arr : [_; $size] = unsafe { mem::uninitialized() }; 
     for element in $container.into_iter().enumerate() { 
      let old_val = mem::replace(&mut arr[element.0],element.1); 
      unsafe { mem::forget(old_val) }; 
     } 
     Some(arr) 
     } 
    }}; 
} 

fn array_to_vec(arr: &[u8]) -> Vec<u8> { 
    let mut vector = Vec::new(); 
    for i in arr.iter() { 
     vector.push(*i); 
    } 
    vector 
} 

fn vector_as_u8_4_array(vector: Vec<u8>) -> [u8;4] { 
    let mut arr = [0u8;4]; 
    for i in (0..4) { 
     arr[i] = vector[i]; 
    } 
    arr 
} 
+3

Một điểm về thuật ngữ chuẩn: 'Vec ': vectơ; '[T]': lát; '[T; N] ': mảng. –

+5

Để chuyển từ một slice (hoặc một mảng thành một slice) sang một 'Vec', sử dụng [' From'] (http://doc.rust-lang.org/std/convert/trait.From.html): 'let z: Vec <_> = From :: from (& array [..])' – Shepmaster

+0

Cảm ơn cả hai bạn về đầu vào. Nhiều đánh giá cao. – dirvine

Trả lời

7

Mã này có vẻ tốt với tôi, mặc dù có một điều an toàn rất quan trọng cần lưu ý: không thể có cơn hoảng loạn trong khi arr không được khởi tạo đầy đủ. Chạy destructors trên uninitialised bộ nhớ có thể dễ dàng dẫn được undefined hành vi, và, đặc biệt, điều này có nghĩa rằng into_iternext phương pháp của nó sẽ không bao giờ hoảng sợ (tôi tin rằng nó là không thể cho các phần của iterator để hoảng sợ cho các khó khăn của mã).

Điều đó nói rằng, người ta có thể thể hiện thành ngữ replace/forget với một hàm duy nhất: std::ptr::write.

for (idx, element) in $container.into_iter().enumerate() { 
    ptr::write(&mut arr[idx], element); 
} 

Mặc dù, tôi sẽ viết nó như:

for (place, element) in arr.iter_mut().zip($container.into_iter()) { 
    ptr::write(place, element); 
} 

Tương tự như vậy, người ta có thể áp dụng một vài tiện ích iterator đến u8 phiên bản chuyên ngành:

fn array_to_vec(arr: &[u8]) -> Vec<u8> { 
    arr.iter().cloned().collect() 
} 
fn vector_as_u8_4_array(vector: Vec<u8>) -> [u8;4] { 
    let mut arr = [0u8;4]; 
    for (place, element) in arr.iter_mut().zip(vector.iter()) { 
     *place = *element; 
    } 
    arr 
} 

Mặc dù là người đầu tiên có lẽ là tốt hơn được viết là arr.to_vec() và thứ hai là

let mut arr = [0u8; 4]; 
std::slice::bytes::copy_memory(&vector, &mut arr); 
arr 

Mặc dù that function hiện không ổn định và do đó chỉ có thể sử dụng được hàng đêm.

Các vấn đề liên quan