【问题标题】:How do I use the byteorder crate to read a usize?如何使用 byteorder crate 读取 usize?
【发布时间】:2019-04-09 05:20:37
【问题描述】:

我正在编写一个编码库,我想将slice 转换为usize

我看到一个看起来很有希望的read_uint 方法,但我不确定如何将寄存器大小作为变量获取,以便将其放入函数中。

例如,我想在 32 位处理器上获得 32,在 64 位处理器上获得 64

【问题讨论】:

标签: rust


【解决方案1】:

一种方法是使用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)
    }
}

另见:

【讨论】:

  • 虽然这个答案在技术上是正确的(就像你的所有(?)答案一样)我不建议做这样的事情并指出,这通常不是一个想要的行为。
【解决方案2】:

TL;DR 有充分的理由不提供 read_usize 函数,因为它在不同的 cpu 架构上不一致。


这是个坏主意。通常,您有某种协议要尝试反序列化。这种格式应该独立于 cpu 架构,因此您无法读取使用大小,因为它依赖于 cpu。

假设您有一个简单的协议,您首先拥有数组的大小,然后是 n 元素。

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

假设协议说您的大小是 4 字节长。现在您想做 Shepmaster 建议的事情,并根据您的架构阅读使用情况。

在 x86_64 操作系统上,您现在将读取 8 个字节,因此会吞下数组中的第一个元素。
在 Atmega8 上,您的 usize 将是 2 个字节,因此只占用您大小的前 2 个字节(如果元素少于 65k 和 BigEndian 字节顺序,则可能为零)。

这就是没有read_usize函数的原因,是正确的。您需要决定您的大小有多长,从切片中读取确切的字节数,然后我们 as 将其转换为 usize

【讨论】:

  • 我同意,但是 OP 明确表示他们明白他们会在不同的平台上得到不同的结果。这是一个可以接受的设计决策,只要您了解权衡取舍。
  • 例如,“协议”可能是 RAM 的转储,不应该跨架构。
  • 在那种情况下它是有帮助的,是的。
  • @Shepmaster 在这种情况下,您根本不需要 ByteOrder。你的平台不会改变字节序;)
  • 为了记录,byteorder 扩展了ReadWrite 具有原始的读写功能(例如read_u32),因此仅在系统本机下工作时并非完全没用字节序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
相关资源
最近更新 更多