sharksforarms / deku

Declarative binary reading and writing: bit-level, symmetric, serialization/deserialization
Apache License 2.0
1.05k stars 54 forks source link

DRAFT: Add DekuWriterMut #442

Open wcampbell0x2a opened 1 month ago

wcampbell0x2a commented 1 month ago

Example that this allows. Basically, when you write, you can read from a Reader!

pub enum Data {
    /// On read: Save current stream_position() as `Offset`, seek `header.filesize`
    /// This will be used to seek this this position if we want to extract *just* this file
    Offset(u64),
    /// On write: Write `Reader` to write buffer
    Reader(Box<dyn ReadSeek>),
}

impl DekuReader<'_, u32> for Data {
    fn from_reader_with_ctx<R: Read + Seek>(
        reader: &mut Reader<R>,
        filesize: u32,
    ) -> Result<Data, DekuError> {
        let reader = reader.as_mut();

        // Save the current offset, this is where the file exists for reading later
        let current_pos = reader.stream_position().unwrap();

        // Seek past that file
        let position = filesize as i64 + pad_to_4(filesize as usize) as i64;
        let _ = reader.seek(SeekFrom::Current(position));

        Ok(Self::Offset(current_pos))
    }
}

impl DekuWriterMut for Data {
    fn to_writer_mut<W: Write + Seek>(
        &mut self,
        writer: &mut Writer<W>,
        _: (),
    ) -> Result<(), DekuError> {
        if let Self::Reader(reader) = self {
            // read from reader
            let mut data = vec![];
            reader.read_to_end(&mut data).unwrap();

            // write to deku
            data.to_writer(writer, ())?;

            // add padding
            for _ in 0..pad_to_4(data.len()) {
                0_u8.to_writer(writer, ())?;
            }
        } else {
            panic!("ah");
        }

        Ok(())
    }
}

#[derive(DekuWriteMut)]
pub struct Object {
    // other fields
    data: Data,
}

TODO

github-actions[bot] commented 1 month ago

Benchmark for e52c5f4

Click to view benchmark | Test | Base | PR | % | |------|--------------|------------------|---| | deku_read_bits | **1261.4±13.10ns** | 1295.9±19.04ns | **+2.74%** | | deku_read_byte | 3.4±0.09ns | 3.4±0.08ns | 0.00% | | deku_read_enum | 2.6±0.18ns | 2.6±0.17ns | 0.00% | | deku_read_vec | 33.2±0.44ns | 33.1±0.54ns | -0.30% | | deku_write_bits | **153.9±2.69ns** | 164.7±4.54ns | **+7.02%** | | deku_write_byte | 24.5±0.41ns | 24.6±0.51ns | +0.41% | | deku_write_enum | 22.7±0.38ns | 22.7±0.42ns | 0.00% | | deku_write_vec | 444.0±16.35ns | 443.0±7.05ns | -0.23% |