2015-06-15 23 views
5

Rust'u öğrenmeye çalışıyorum ve bir hex dizesini bir u64'e dönüştüren bir program yazmaya karar verdim. Şu anda, her biri dört bit (veya "nibble") temsil eden bir u8 değerinin vektörüne dize ayrıştırdım. Bir Vec<u8> almak ve karşılık gelen bir u64 döndürmek için aşağıdaki kodu yazdım. Çalışır (benim testlerim gösterdiğim kadarıyla), ama bunu yapmak için Rust'ta "uygun" bir yol olup olmadığından emin değilim. Nibbles'i u64'e dönüştürmenin en uygun yolu nedir?

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; 
} 

Ben u64 değere u8 döküm başka nasıl bilmiyorum ana konu varsayalım. Kodu daha idiomatik Rust benzeri bir tarzda geliştirmek veya yazmak için yollar üzerine yorum yapabilir misiniz?

DÜZENLEME:

iu64 bir şekilde ile Or'ing:

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; 

şirketinden i ile Or'ing: güvensiz blok için aşağıdaki (başarısız) alternatifler çalıştılar

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

u64' olarak 'i nesi var? –

+0

Yani, her bir 'u8'de sadece 4 bit kullanıyorsunuz. Bu yüzden bitleriniz '0bAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHu64' ile sonlandırmak istiyorsanız' [0b0000AAAA, 0b0000BBBB, 0b0000CCCC, 0b0000DDDD, 0b0000EEEE, 0b0000FFFF, 0b0000GGGG, 0b0000HHHH] 'dır. Doğrumuyum? –

+0

@ChrisMorgan giriş ise [0xF, 0xE, 0xE, 0xD, 0xB, 0xE, 0xE, 0xF, 0xF, 0xE, 0xE, 0xD, 0xB, 0xE, 0xE, 0xF], çıkış 0xFEEDBEEFFEEDBEEFu64 olmalıdır. – samoz

cevap

7

Sorununuz basit bir: for i in values, nerede values tür 012'dir, her bir değere başvuru üzerinden yinelenir; Yani, i, &u8 tipindedir. Oring ve ekleme ve bunun gibi referanslar mantıklı değil; Altında yatan u8 almak, bunu dereferans gerekir. Bunu yapmanın en kolay yolu for döngünün desen haline yazıyor (for gramer for PATTERN in EXPRESSION olduğu için de gerekirse, daha açıklama için kalıplarına belgelerine bakın; bu basit bir durum için, for &x in y { … } temelde for x in y { let x = *x; … } anlamına gelir):

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

bir döngünün tüm form şöyle de Iterator.fold kullanılarak çöktü edilebilir:

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

Vay çok basit, yardımlarınız için teşekkürler! Bu yüzden tam olarak yeni bir dil öğrenirken yazıyorum. "Kimsenin yapmadığı bir şey yapıyorsun, onu durdur." Bir çekicilik gibi çalışır, teşekkürler @ChrisMorgan! – samoz

İlgili konular