I'm working on a struct which can decode fonts, and it's working fine, but in order to clean up the code, I'm trying to move the const generics which Rust has provided.
Here's the current code:
// Read the next u32 from the Decoder's underlying reader.
fn read_u32(&mut self) -> DecodeResult<u32> {
let mut buffer = [0u8; 4];
match self.reader.read_exact(&mut buffer) {
Ok(_) => Ok(u32::from_be_bytes(buffer)),
Err(_) => Err(DecodeErr::UnexpectedEOF),
}
}
// Read the next u16 from the Decoder's underlying reader.
fn read_u16(&mut self) -> DecodeResult<u16> {
let mut buffer = [0u8; 2];
match self.reader.read_exact(&mut buffer) {
Ok(_) => Ok(u16::from_be_bytes(buffer)),
Err(_) => Err(DecodeErr::UnexpectedEOF),
}
}
In order to refactor this code, I would like to have a function (something like):
Thanks for the solution, but I wanted to achieve less code, and here it seems that I need to write more code Is this the only way to achieve what I'm trying to do?
The from_be_bytes functions are associated functions of u32 or u16, so it's not really possible to abstract over those, unless you define your own trait (or possibly find some in existing crates). You could compact your code by defining and using a macro, similar to how I used them in the trait implementation above.
macro_rules! read_uint_method {
($name:ident $uint:ident) => {
pub fn $name(&mut self) -> DecodeResult<$uint> {
let mut buffer = [0u8; std::mem::size_of::<$uint>()];
match self.reader.read_exact(&mut buffer) {
Ok(_) => Ok($uint::from_be_bytes(buffer)),
Err(_) => Err(DecodeErr::UnexpectedEOF),
}
}
}
}
impl .... {
/// Read the next u32 from the Decoder's underlying reader.
read_uint_method!(read_u32 u32);
/// Read the next u16 from the Decoder's underlying reader.
read_uint_method!(read_u16 u16);
}