2015-06-15 14 views
5

Tôi đang cố gắng học Rust và quyết định viết chương trình chuyển đổi chuỗi hex thành u64.Cách thích hợp nhất để chuyển đổi nibbles thành u64 là gì?

Hiện tại, tôi đã phân tích cú pháp chuỗi thành một vectơ có giá trị u8, mỗi chuỗi đại diện cho bốn bit (hoặc "nibble"). Tôi đã viết đoạn mã sau để lấy Vec<u8> và trả về u64 tương ứng. Nó hoạt động (theo như thử nghiệm của tôi cho thấy), nhưng tôi không chắc chắn nếu nó là "thích hợp" cách trong Rust để đi về việc này.

fn convert_nibbles_to_u64(values: &Vec<u8>) -> u64 { 
    // We need to turn this buffer into a u64 now 
    let mut temp:u64 = 0; 
    for i in values { 
     temp = temp << 4; 

     unsafe { 
      // We need to unsafely convert a u8 to a u64. Note that 
      // the host endian-ness will matter here. 
      use std::mem; 
      let i_64_buffer = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,i.clone()]; 
      let i_64 = mem::transmute::<[u8; 8], u64>(i_64_buffer); 
      let i_64_be = u64::from_be(i_64); 
      temp = temp | i_64_be;   
     } 
    } 
    return temp; 
} 

Tôi cho rằng vấn đề chính tôi không biết làm thế nào khác để đúc một u8 đến một giá trị u64. Bạn có thể bình luận về các cách để cải thiện hoặc viết mã trong một phong cách mộc mạc, giống như Rust?

EDIT: Tôi đã thử (không thành công) lựa chọn thay thế sau vào khối không an toàn:

Or'ing với i như một u64:

temp = temp | i as u64; 
------ 
Compiler error: 
main.rs:115:23: 115:31 error: non-scalar cast: `&u8` as `u64` 
main.rs:115   temp = temp | i as u64; 

Or'ing với i trực tiếp:

temp = temp | i; 
------ 
Compiler error: 
main.rs:115:16: 115:24 error: the trait `core::ops::BitOr<&u8>` is not implemented for the type `u64` [E0277] 
main.rs:115   temp = temp | i; 
+0

có gì sai với 'i như u64'? –

+0

Vì vậy, trong mỗi 'u8' bạn chỉ sử dụng bốn bit. Vì vậy, nếu các bit của bạn là '[0b0000AAAA, 0b0000BBBB, 0b0000CCCC, 0b0000DDDD, 0b0000EEEE, 0b0000FFFF, 0b0000GGGG, 0b0000HHHH]' bạn muốn kết thúc bằng '0bAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHu64'. Tôi có đúng không? –

+0

@ChrisMorgan nếu đầu vào là [0xF, 0xE, 0xE, 0xD, 0xB, 0xE, 0xE, 0xF, 0xF, 0xE, 0xE, 0xD, 0xB, 0xE, 0xE, 0xF], đầu ra phải là 0xFEEDBEEFFEEDBEEFu64. – samoz

Trả lời

7

Sự cố của bạn là một vấn đề đơn giản: for i in values, trong đó values là loại &Vec<u8>, lặp lại trên tham chiếu cho mỗi giá trị; nghĩa là, i thuộc loại &u8. Việc thêm và thêm và như vậy với các tham chiếu không có ý nghĩa; bạn cần phải dereference nó, nhận được cơ bản u8. Cách đơn giản nhất để làm điều này đang viết nó thành mô hình các for vòng (đối với các for ngữ pháp là for PATTERN in EXPRESSION, tham khảo tài liệu về mô hình giải thích hơn nếu bạn cần nó, vì trường hợp đơn giản này, for &x in y { … } về cơ bản có nghĩa là for x in y { let x = *x; … }):

fn convert_nibbles_to_u64(values: &[u8]) -> u64 { 
    let mut out = 0; 
    for &i in values { 
     out = out << 4 | i as u64; 
    } 
    out 
} 

dạng toàn bộ một vòng lặp có thể được sử dụng sụp đổ Iterator.fold cũng vậy, như thế này:

fn convert_nibbles_to_u64(values: &[u8]) -> u64 { 
    values.iter().fold(0, |x, &i| x << 4 | i as u64) 
} 
+0

Rất đơn giản, cảm ơn sự giúp đỡ của bạn! Đây chính là lý do tại sao tôi đăng trên SO khi học một ngôn ngữ mới. "Bạn đang làm một cái gì đó không ai bao giờ làm, dừng lại đó." Làm việc như một say mê, nhờ @ ChrisMorgan! – samoz

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