Как преобразовать два примитива u8 в примитив u16? - PullRequest
0 голосов
/ 09 мая 2018

Я читаю двоичный файл в программу Rust, используя Vec<u8> в качестве буфера. Два байта в потоке представляют собой байты с прямым порядком байтов u16.

Пока что единственный способ, который я выяснил, как преобразовать в примитив u16, заключается в преобразовании двух элементов в String сначала, и это выглядит ужасно .

Код:

let vector: Vec<u8> = [1, 16].to_vec();
let vector0: String = format!("{:02x}", vector[0]);
let vector1: String = format!("{:02x}", vector[1]);
let mut vector_combined = String::new();
vector_combined = vector_combined + &vector0.clone();
vector_combined = vector_combined + &vector1.clone();
let number: u16 = u16::from_str_radix(&vector_combined.to_string(), 16).unwrap();

println!("vector[0]: 0x{:02x}", vector[0]);
println!("vector[1]: 0x{:02x}", vector[1]);
println!("number: 0x{:04x}", number);

Выход:

vector[0]: 0x01
vector[1]: 0x10
number: 0x0110

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Если у вас на самом деле было два разных u8 с, обычное решение включает в себя побитовую манипуляцию, в частности, сдвиг и побитовое ИЛИ. Это требует нулевого распределения кучи и очень эффективно:

let number = ((vector[0] as u16) << 8) | vector[1] as u16;

И графическое объяснение:

             A0                   B0
        +--------+           +--------+
        |XXXXXXXX|           |YYYYYYYY|
        +-------++           +-------++
                |                    |
 A1 = A0 as u16 |     B1 = B0 as u16 |
+---------------v+   +---------------v+
|00000000XXXXXXXX|   |00000000YYYYYYYY|
+---------------++   +---------------++
                |                    |
   A2 = A1 << 8 |                    |
+---------------v+                   |
|XXXXXXXX00000000|                   |
+---------------++                   |
                |              +--+  |
                +-------------->OR<--+
                               +-++
                                 |
                     V = A2 | B1 |
                 +----------+----v+
                 |XXXXXXXXYYYYYYYY|
                 +----------------+

Однако вы действительно смотрите на свою проблему слишком узко. У вас нет двух u8, у вас есть &[u8].

В этом случае используйте ящик с метеорологом :

extern crate byteorder;

use byteorder::{ByteOrder, LittleEndian};

fn main() {
    let data = [1, 16];
    let v = LittleEndian::read_u16(&data);
    println!("{}", v);
}

Это показывает его мощность, когда вы хотите обработать чтение через буфер:

extern crate byteorder;

use byteorder::{BigEndian, LittleEndian, ReadBytesExt};

fn main() {
    let data = [1, 16, 1, 2];
    let mut current = &data[..];

    let v1 = current.read_u16::<LittleEndian>();
    let v2 = current.read_u16::<BigEndian>();

    println!("{:?}, {:?}", v1, v2); // Ok(4097), Ok(258)
}

Как видите, вы должны осознавать порядковый номер ваших входных данных.

Смотри также:


Бесплатный обзор кода на исходное сообщение:

  • Нет необходимости использовать to_vec здесь, используйте vec! вместо.

  • Нет необходимости указывать подавляющее большинство типов.

let vector = [1u8, 16].to_vec();

let vector0 = format!("{:02x}", vector[0]);
let vector1 = format!("{:02x}", vector[1]);
let mut vector_combined = String::new();
vector_combined = vector_combined + &vector0.clone();
vector_combined = vector_combined + &vector1.clone();
let number = u16::from_str_radix(&vector_combined.to_string(), 16).unwrap();
  • Нет необходимости клонировать строки перед обращением к ним при добавлении.
  • Нет необходимости преобразовывать String в ... другой String в from_str_radix.
let vector0 = format!("{:02x}", vector[0]);
let vector1 = format!("{:02x}", vector[1]);
let mut vector_combined = String::new();
vector_combined = vector_combined + &vector0;
vector_combined = vector_combined + &vector1;
let number = u16::from_str_radix(&vector_combined, 16).unwrap();
  • Нет необходимости создавать пустой String для добавления, просто используйте vector0
let vector0 = format!("{:02x}", vector[0]);
let vector1 = format!("{:02x}", vector[1]);
let vector_combined = vector0 + &vector1;
let number = u16::from_str_radix(&vector_combined, 16).unwrap();
  • Нет необходимости создавать две строки, одна будет делать:
let vector_combined = format!("{:02x}{:02x}", vector[0], vector[1]);
let number = u16::from_str_radix(&vector_combined, 16).unwrap();

Конечно, это все еще не правильное решение, но оно лучше .

0 голосов
/ 09 мая 2018

Вы можете умножить первый элемент, чтобы переместить его в старший байт, а затем добавить второй элемент. Просто нужно дополнительное кастинг:

let a: u8 = 1;
let b: u8 = 2;
let c: u16 = (a as u16 * 256) + b as u16;
println!("c: {}", c); // c: 258
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...