I'm writing an encoding library and I'd like to convert a slice
into a usize
.
I see a read_uint
method that looks promising, though I'm unsure how to get the register size as a variable so I can put it in the function.
For example I'd like to get 32
on a 32 bit processor, and 64
on a 64 bit processor.
One way is to use mem::size_of
to get the size of a 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)
}
Another is to have different functions or function implementations for different architectures:
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)
}
}
See also:
- How to get the size of a user defined struct? (sizeof)
- How to check in Rust if architecture is 32 or 64 bit?
TL;DR there is a good reason for not providing a read_usize
function, because it is not consistent on different cpu-architectures.
This is a bad idea. Normally you have some kind of protocol you are trying to deserialize. This format should be independent from the cpu-architecture and therefore you can't read an usize, because it is cpu-dependent.
Let's assume you have a simple protocol where you first have the size of an array and afterwards n
elements.
+------+---------+
| size | ....... |
+------+---------+
Let's suppose the protocol says that your size is 4 byte long. Now you want to do the thing Shepmaster suggested and read the usize dependent on your architecture.
On a x86_64 OS you will now read 8 bytes and therefore swallow the first element in your array.
On a Atmega8 your usize would be 2 bytes and therefore only take the first 2 bytes of your size (which might be zero in case there are less than 65k elements and a BigEndian byte-order).
This is the reason why there is no read_usize
function and it is correct. You need to decide how long your size is, read the exact amount of bytes from your slice and then us as
to convert that into an usize
.