Как я могу использовать ящик метеоролога, чтобы прочитать размер? - PullRequest
0 голосов
/ 05 ноября 2018

Я пишу библиотеку кодирования и хочу преобразовать slice в usize.

Я вижу метод read_uint, который выглядит многообещающим, хотя я не уверен, как получить размер регистра в качестве переменной, чтобы я мог поместить его в функцию.

Например, я хотел бы получить 32 на 32-битном процессоре и 64 на 64-битном процессоре.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

TL; DR есть веская причина не предоставлять функцию read_usize, поскольку она не согласована на разных архитектурах ЦП.


Это плохая идея. Обычно у вас есть какой-то протокол, который вы пытаетесь десериализовать. Этот формат не должен зависеть от архитектуры процессора, и поэтому вы не можете прочитать размер файла, потому что он зависит от процессора.

Предположим, у вас есть простой протокол, в котором сначала у вас есть размер массива, а затем n элементов.

+------+---------+
| size | ....... |
+------+---------+

Предположим, что протокол говорит, что ваш размер имеет длину 4 байта. Теперь вы хотите сделать то, что предложил Шепмастер, и прочитать размер в зависимости от вашей архитектуры.

В операционной системе x86_64 вы теперь прочитаете 8 байтов и, следовательно, проглотите первый элемент в вашем массиве.
На Atmega8 ваш usize будет 2 байта и, следовательно, займет только первые 2 байта вашего размера (который может быть нулевым, если имеется менее 65k элементов и порядок байтов BigEndian).

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

0 голосов
/ 05 ноября 2018

Один из способов - использовать mem::size_of, чтобы получить размер usize:

use byteorder::{ByteOrder, ReadBytesExt};

fn read_usize<B, R>(mut b: R) -> Result<usize, std::io::Error>
where
    B: ByteOrder,
    R: ReadBytesExt,
{
    b.read_uint::<B>(std::mem::size_of::<usize>()).map(|v| v as usize)
}

Другой вариант - иметь разные функции или реализации функций для разных архитектур:

fn read_usize<B, R>(mut b: R) -> Result<usize, std::io::Error>
where
    B: ByteOrder,
    R: ReadBytesExt,
{
    if cfg!(target_pointer_width = "64") {
        b.read_u64::<B>().map(|v| v as usize)
    } else if cfg!(target_pointer_width = "32") {
        b.read_u32::<B>().map(|v| v as usize)
    } else {
        b.read_u16::<B>().map(|v| v as usize)
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...