Hi community !
I have a Vec<u32>
and I need to read u64, i32, u32, f32 from it. Currently to do this I use std::io::Cursor
, so first of all I convert the Vec<u32>
data into Vec<u8>
:
let data: Vec<u8> = {
let buffer: Vec<u32> = update_blocks.values().cloned().collect();
buffer.iter().flat_map(|&num| num.to_le_bytes().to_vec()).collect()
};
and next I use this data
in Cursor
. But probably there exists some more compact way in Rust that will let me read all needed data directly from Vec<u32>
?
Could somebody suggest something more optimized ?
Use bytemuck
to cast from &[u32]
to &[u8]
.
5 Likes
Well, since all of your data types have a size that is a multiple of 4, you don't need any conversion to a sequence of u8
. You can get all of your types just using built-in operations and the standard library: Playground
pub fn read_u32(slice: &mut &[u32]) -> Option<u32> {
let &[first, ref rest @ ..] = *slice else { return None };
*slice = rest;
Some(first)
}
pub fn read_i32(slice: &mut &[u32]) -> Option<i32> {
let &[first, ref rest @ ..] = *slice else { return None };
*slice = rest;
Some(first as i32)
}
pub fn read_f32(slice: &mut &[u32]) -> Option<f32> {
let &[first, ref rest @ ..] = *slice else { return None };
*slice = rest;
Some(f32::from_bits(first))
}
pub fn read_u64(slice: &mut &[u32]) -> Option<u64> {
let &[lo, hi, ref rest @ ..] = *slice else { return None };
*slice = rest;
Some(u64::from(lo) | (u64::from(hi) << 32))
}
Anyway, your original code is full of useless allocation and copying. You could just do
let data: Vec<u8> = update_blocks
.values()
.copied()
.flat_map(u32::to_le_bytes)
.collect();
and still be more efficient than what you currently have.
Furthermore, the call to update_blocks.values()
suggests that you don't actually have a Vec<u32>
to begin with, but you have a HashMap
or BTreeMap
where the values are u32
. In this case, you don't need to create a slice at all. Just use the returned values
iterator and call .next()
on it, mapping the appropriate conversion over the returned Option<u32>
: Playground
let value: u32 = iter.next()?;
let value: i32 = iter.next()? as i32;
let value: u64 = {
let lo = iter.next()?;
let hi = iter.next()?;
u64::from(lo) | (u64::from(hi) << 32)
};
let value: f32 = iter.next()?.from_bits();
7 Likes
Thank you very much for detailed explanation. I like your solution.