Created
January 26, 2023 16:11
-
-
Save rbran/e7814fd6694ee37d54243236b77ff3cf to your computer and use it in GitHub Desktop.
Deku read from std::io::Read proposal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use deku::prelude::*; | |
#[derive(Debug, PartialEq, DekuRead)] | |
struct DekuStruct { | |
field_a: u8, | |
field_b: u16, | |
field_c: DekuEnum, | |
} | |
#[derive(Debug, PartialEq, DekuRead)] | |
#[deku(type = "u8")] | |
enum DekuEnum { | |
#[deku(id = "0")] | |
Var1, | |
#[deku(id = "1")] | |
Var2(u32), | |
} | |
trait DekuFromReader: Sized { | |
//Similar to from_bytes, but the rest is only one u8, in case the struct/enum | |
//is not byte complete, AKA `size_in_bits(type) % 8 != 0` | |
fn from_reader<R: std::io::Read>( | |
reader: R, | |
) -> Result<(u8, Self), DekuError>; | |
} | |
//Implementation generated by a macro | |
impl DekuFromReader for DekuStruct { | |
fn from_reader<R: std::io::Read>( | |
mut reader: R, | |
) -> Result<(u8, Self), DekuError> { | |
//condensate multiple reads for performance, or just use std::io::BufReader | |
let mut field_a_b = [0u8; 3]; | |
reader | |
.read_exact(&mut field_a_b) | |
.expect("TODO into DekuError"); | |
let field_a = field_a_b[0]; | |
let field_b = u16::from_be_bytes(field_a_b[1..3].try_into().unwrap()); | |
let (rest, field_c): (_, DekuEnum) = reader.deku_read()?; | |
let value = Self { | |
field_a, | |
field_b, | |
field_c, | |
}; | |
Ok((rest, value)) | |
} | |
} | |
//Implementation generated by a macro | |
impl DekuFromReader for DekuEnum { | |
fn from_reader<R: std::io::Read>( | |
mut reader: R, | |
) -> Result<(u8, Self), DekuError> { | |
let mut id = [0u8]; | |
reader.read_exact(&mut id).expect("TODO into DekuError"); | |
match id[0] { | |
0 => Ok((0, Self::Var1)), | |
1 => { | |
let mut value = [0u8; 4]; | |
reader.read_exact(&mut value).expect("TODO into DekuError"); | |
let value = u32::from_be_bytes(value); | |
Ok((0, Self::Var2(value))) | |
} | |
_ => Err(DekuError::IdVariantNotFound), | |
} | |
} | |
} | |
//blanked implementation | |
trait DekuReader { | |
fn deku_read<T: DekuFromReader>(&mut self) -> Result<(u8, T), DekuError>; | |
} | |
impl<R: std::io::Read> DekuReader for R { | |
fn deku_read<T: DekuFromReader>(&mut self) -> Result<(u8, T), DekuError> { | |
T::from_reader(self) | |
} | |
} | |
fn main() { | |
let mut file = | |
std::io::Cursor::new([0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x03]); | |
let (_rest, val) = file.deku_read::<DekuStruct>().unwrap(); | |
assert_eq!( | |
val, | |
DekuStruct { | |
field_a: 0x01, | |
field_b: 0x02, | |
field_c: DekuEnum::Var2(0x03), | |
} | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment