dem 0.2.3

GoldSrc demo parser and writer library
Documentation
use crate::types::{EntityState, SvcPacketEntities};

use super::*;

impl Doer for SvcPacketEntities {
    fn id(&self) -> u8 {
        40
    }

    fn parse(i: &[u8], aux: AuxRefCell) -> Result<Self> {
        let aux = aux.borrow();

        let mut br = BitReader::new(i);

        let entity_count = br.read_n_bit(16).to_owned();
        let mut entity_index = 0;
        let mut entity_states: Vec<EntityState> = vec![];

        loop {
            let footer = br.peek_n_bits(16).to_u16();
            if footer == 0 {
                br.read_n_bit(16);
                break;
            }

            let increment_entity_number = br.read_1_bit();
            let is_absolute_entity_index = if increment_entity_number {
                entity_index += 1;
                None
            } else {
                Some(br.read_1_bit())
            };
            let (absolute_entity_index, entity_index_difference) =
                if is_absolute_entity_index.is_some() {
                    if !is_absolute_entity_index.unwrap() {
                        let val = br.read_n_bit(6).to_owned();
                        entity_index += val.to_u16();
                        (None, Some(val))
                    } else {
                        let val = br.read_n_bit(11).to_owned();
                        entity_index = val.to_u16();
                        (Some(val), None)
                    }
                } else {
                    (None, None)
                };

            let has_custom_delta = br.read_1_bit();
            let has_baseline_index = br.read_1_bit();
            let baseline_index = if has_baseline_index {
                Some(br.read_n_bit(6).to_owned())
            } else {
                None
            };
            let between = entity_index > 0 && entity_index <= aux.max_client as u16;

            let delta = if between {
                parse_delta(
                    aux.delta_decoders.get("entity_state_player_t\0").unwrap(),
                    &mut br,
                )
            } else if has_custom_delta {
                parse_delta(
                    aux.delta_decoders.get("custom_entity_state_t\0").unwrap(),
                    &mut br,
                )
            } else {
                parse_delta(aux.delta_decoders.get("entity_state_t\0").unwrap(), &mut br)
            };

            entity_states.push(EntityState {
                entity_index,
                increment_entity_number,
                is_absolute_entity_index,
                absolute_entity_index,
                entity_index_difference,
                has_custom_delta,
                has_baseline_index,
                baseline_index,
                delta,
            })
        }

        let range = br.get_consumed_bytes();
        let (i, _) = take(range)(i)?;

        Ok((
            i,
            Self {
                entity_count,
                entity_states,
            },
        ))
    }

    fn write(&self, aux: AuxRefCell) -> ByteVec {
        let aux = aux.borrow();

        let mut writer = ByteWriter::new();
        let mut bw = BitWriter::new();

        writer.append_u8(self.id());

        bw.append_vec(&self.entity_count);

        for entity in &self.entity_states {
            bw.append_bit(entity.increment_entity_number);

            if !entity.increment_entity_number {
                bw.append_bit(entity.is_absolute_entity_index.unwrap());

                if entity.is_absolute_entity_index.unwrap() {
                    bw.append_vec(entity.absolute_entity_index.as_ref().unwrap());
                } else {
                    bw.append_vec(entity.entity_index_difference.as_ref().unwrap());
                }
            }

            bw.append_bit(entity.has_custom_delta);
            bw.append_bit(entity.has_baseline_index);

            if entity.has_baseline_index {
                bw.append_vec(entity.baseline_index.as_ref().unwrap());
            }

            let between = entity.entity_index > 0 && entity.entity_index <= aux.max_client as u16;
            if between {
                write_delta(
                    &entity.delta,
                    aux.delta_decoders.get("entity_state_player_t\0").unwrap(),
                    &mut bw,
                )
            } else if entity.has_custom_delta {
                write_delta(
                    &entity.delta,
                    aux.delta_decoders.get("custom_entity_state_t\0").unwrap(),
                    &mut bw,
                )
            } else {
                write_delta(
                    &entity.delta,
                    aux.delta_decoders.get("entity_state_t\0").unwrap(),
                    &mut bw,
                )
            }
        }

        use bitvec::bitvec;
        use bitvec::prelude::Lsb0;
        bw.append_vec(&bitvec![u8, Lsb0; 0; 16]);

        writer.append_u8_slice(&bw.get_u8_vec());

        writer.data
    }
}