diff --git a/Cargo.lock b/Cargo.lock index d21a594..a756f7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -259,7 +259,6 @@ dependencies = [ "protobuf", "protobuf-codegen", "serde", - "smallvec", "snap", "thiserror", "tracing", diff --git a/cs2-demo/Cargo.toml b/cs2-demo/Cargo.toml index 9514646..b47adee 100644 --- a/cs2-demo/Cargo.toml +++ b/cs2-demo/Cargo.toml @@ -14,7 +14,6 @@ snap = "1.1" thiserror = "1.0" tracing = "0.1" paste = "1.0" -smallvec = "1.13.1" [build-dependencies] protobuf-codegen = "3.2" diff --git a/cs2-demo/src/entity.rs b/cs2-demo/src/entity.rs index 432980f..60f4737 100644 --- a/cs2-demo/src/entity.rs +++ b/cs2-demo/src/entity.rs @@ -185,17 +185,17 @@ impl Entity { fps.clear(); loop { fp.read(reader)?; - if fp.finished { + if fp.len() == 0 { break; } fps.push(fp.clone()); } for fp in fps { - let (prop, field) = self.property(&fp.data); + let (prop, field) = self.property(fp.data()); *prop = (field.decoder())(reader)?; if enabled!(Level::TRACE) { - let (prop, field, name) = self.get_property(&fp.data); + let (prop, field, name) = self.get_property(fp.data()); match field { Field::Value(_) | Field::Array(_) | Field::Vector(_) => { trace!("{fp} {}: {} = {}", name, field.ctype(), prop.unwrap()) diff --git a/cs2-demo/src/entity/fieldpath.rs b/cs2-demo/src/entity/fieldpath.rs index 2a62925..dae15c3 100644 --- a/cs2-demo/src/entity/fieldpath.rs +++ b/cs2-demo/src/entity/fieldpath.rs @@ -2,24 +2,48 @@ use bitstream_io::huffman::{compile_read_tree, ReadHuffmanTree}; use bitstream_io::{BitRead, HuffmanRead, LittleEndian}; use std::sync::OnceLock; -use smallvec::SmallVec; use crate::{read::ValveBitReader, BitReader}; -#[derive(Debug, Clone)] -pub(super) struct FieldPath { +#[derive(Clone)] +pub struct FieldPath { /// Indices into the serializer. - pub(super) data: SmallVec<[i32; 6]>, - /// Indicates if this is the last field path for an entity. - pub(super) finished: bool, + data: [i32; 6], + /// Number of elements in data. + len: i32, } impl FieldPath { + pub fn len(&self) -> i32 { + self.len + } + + pub fn data(&self) -> &[i32] { + &self.data[..self.len as usize] + } + + fn push(&mut self, value: i32) { + self.data[self.len as usize] = value; + self.len += 1; + assert!(self.len <= 6); + } + + fn pop(&mut self) { + self.len -= 1; + assert!(self.len >= 0); + } + + fn truncate(&mut self, new_len: usize) { + self.len = new_len as i32; + } + + fn last(&mut self) -> &mut i32 { + &mut self.data[self.len as usize - 1] + } + pub(super) fn new() -> Self { - let mut data = SmallVec::new(); - data.push(-1); - let finished = false; - Self { data, finished } + let data = [-1, 0, 0, 0, 0, 0]; + Self { data, len: 1 } } pub(super) fn read(&mut self, reader: &mut BitReader) -> std::io::Result<()> { @@ -79,9 +103,11 @@ impl FieldPath { impl std::fmt::Display for FieldPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.data[0])?; - for e in &self.data[1..] { - write!(f, "/{}", e)?; + if self.len() > 0 { + write!(f, "{}", self.data[0])?; + for e in &self.data[1..self.len as usize] { + write!(f, "/{}", e)?; + } } Ok(()) } @@ -110,27 +136,27 @@ impl FieldPathBitReader for BitReader<'_> { } fn PlusOne(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 1; + *f.last() += 1; Ok(()) } fn PlusTwo(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 2; + *f.last() += 2; Ok(()) } fn PlusThree(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 3; + *f.last() += 3; Ok(()) } fn PlusFour(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 4; + *f.last() += 4; Ok(()) } fn PlusN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read_fp_bitvar()? + 5; + *f.last() += reader.read_fp_bitvar()? + 5; Ok(()) } @@ -138,7 +164,7 @@ fn PushOneLeftDeltaZeroRightZero( f: &mut FieldPath, _reader: &mut BitReader, ) -> std::io::Result<()> { - f.data.push(0); + f.push(0); Ok(()) } @@ -146,13 +172,13 @@ fn PushOneLeftDeltaZeroRightNonZero( f: &mut FieldPath, reader: &mut BitReader, ) -> std::io::Result<()> { - f.data.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); Ok(()) } fn PushOneLeftDeltaOneRightZero(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 1; - f.data.push(0); + *f.last() += 1; + f.push(0); Ok(()) } @@ -160,20 +186,20 @@ fn PushOneLeftDeltaOneRightNonZero( f: &mut FieldPath, reader: &mut BitReader, ) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 1; - f.data.push(reader.read_fp_bitvar()?); + *f.last() += 1; + f.push(reader.read_fp_bitvar()?); Ok(()) } fn PushOneLeftDeltaNRightZero(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read_fp_bitvar()?; - f.data.push(0); + *f.last() += reader.read_fp_bitvar()?; + f.push(0); Ok(()) } fn PushOneLeftDeltaNRightNonZero(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read_fp_bitvar()? + 2; - f.data.push(reader.read_fp_bitvar()? + 1); + *f.last() += reader.read_fp_bitvar()? + 2; + f.push(reader.read_fp_bitvar()? + 1); Ok(()) } @@ -181,8 +207,8 @@ fn PushOneLeftDeltaNRightNonZeroPack6Bits( f: &mut FieldPath, reader: &mut BitReader, ) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read::(3)? + 2; - f.data.push(reader.read::(3)? + 1); + *f.last() += reader.read::(3)? + 2; + f.push(reader.read::(3)? + 1); Ok(()) } @@ -190,176 +216,176 @@ fn PushOneLeftDeltaNRightNonZeroPack8Bits( f: &mut FieldPath, reader: &mut BitReader, ) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read::(4)? + 2; - f.data.push(reader.read::(4)? + 1); + *f.last() += reader.read::(4)? + 2; + f.push(reader.read::(4)? + 1); Ok(()) } fn PushTwoLeftDeltaZero(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); Ok(()) } fn PushTwoLeftDeltaOne(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 1; - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); + *f.last() += 1; + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); Ok(()) } fn PushTwoLeftDeltaN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read_ubitvar()? as i32 + 2; - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); + *f.last() += reader.read_ubitvar()? as i32 + 2; + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); Ok(()) } fn PushTwoPack5LeftDeltaZero(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); Ok(()) } fn PushTwoPack5LeftDeltaOne(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 1; - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); + *f.last() += 1; + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); Ok(()) } fn PushTwoPack5LeftDeltaN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read_ubitvar()? as i32 + 2; - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); + *f.last() += reader.read_ubitvar()? as i32 + 2; + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); Ok(()) } fn PushThreeLeftDeltaZero(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); Ok(()) } fn PushThreeLeftDeltaOne(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 1; - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); + *f.last() += 1; + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); Ok(()) } fn PushThreeLeftDeltaN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read_ubitvar()? as i32 + 2; - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); - f.data.push(reader.read_fp_bitvar()?); + *f.last() += reader.read_ubitvar()? as i32 + 2; + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); Ok(()) } fn PushThreePack5LeftDeltaZero(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); Ok(()) } fn PushThreePack5LeftDeltaOne(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += 1; - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); + *f.last() += 1; + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); Ok(()) } fn PushThreePack5LeftDeltaN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - *f.data.last_mut().unwrap() += reader.read_ubitvar()? as i32 + 2; - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); - f.data.push(reader.read::(5)?); + *f.last() += reader.read_ubitvar()? as i32 + 2; + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); + f.push(reader.read::(5)?); Ok(()) } fn PushN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { for _ in 0..reader.read_ubitvar()? { - f.data.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); } Ok(()) } fn PushNAndNonTopological(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - for idx in &mut f.data { + for idx in &mut f.data[..f.len as usize] { if reader.read_bit()? { *idx += reader.read_signed_varint32()? + 1; } } for _ in 0..reader.read_ubitvar()? { - f.data.push(reader.read_fp_bitvar()?); + f.push(reader.read_fp_bitvar()?); } Ok(()) } fn PopOnePlusOne(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - f.data.pop(); - *f.data.last_mut().unwrap() += 1; + f.pop(); + *f.last() += 1; Ok(()) } fn PopOnePlusN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - f.data.pop(); - *f.data.last_mut().unwrap() += reader.read_fp_bitvar()? + 1; + f.pop(); + *f.last() += reader.read_fp_bitvar()? + 1; Ok(()) } fn PopAllButOnePlusOne(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - f.data.truncate(1); - *f.data.last_mut().unwrap() += 1; + f.truncate(1); + *f.last() += 1; Ok(()) } fn PopAllButOnePlusN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - f.data.truncate(1); - *f.data.last_mut().unwrap() += reader.read_fp_bitvar()? + 1; + f.truncate(1); + *f.last() += reader.read_fp_bitvar()? + 1; Ok(()) } fn PopAllButOnePlusNPack3Bits(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - f.data.truncate(1); - *f.data.last_mut().unwrap() += reader.read::(3)? + 1; + f.truncate(1); + *f.last() += reader.read::(3)? + 1; Ok(()) } fn PopAllButOnePlusNPack6Bits(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - f.data.truncate(1); - *f.data.last_mut().unwrap() += reader.read::(6)? + 1; + f.truncate(1); + *f.last() += reader.read::(6)? + 1; Ok(()) } fn PopNPlusOne(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - let nsize = f.data.len() - reader.read_fp_bitvar()? as usize; + let nsize = f.len() - reader.read_fp_bitvar()?; assert!(nsize < 7 && nsize > 0, "Invalid fp size for op"); - f.data.truncate(nsize); - *f.data.last_mut().unwrap() += 1; + f.truncate(nsize as usize); + *f.last() += 1; Ok(()) } fn PopNPlusN(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - let nsize = f.data.len() - reader.read_fp_bitvar()? as usize; + let nsize = f.len() - reader.read_fp_bitvar()?; assert!(nsize < 7 && nsize > 0, "Invalid fp size for op"); - f.data.truncate(nsize); - *f.data.last_mut().unwrap() += reader.read_signed_varint32()?; + f.truncate(nsize as usize); + *f.last() += reader.read_signed_varint32()?; Ok(()) } fn PopNAndNonTopographical(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - let nsize = f.data.len() - reader.read_fp_bitvar()? as usize; + let nsize = f.len() - reader.read_fp_bitvar()?; assert!(nsize < 7 && nsize > 0, "Invalid fp size for op"); - f.data.truncate(nsize); - for idx in &mut f.data { + f.truncate(nsize as usize); + for idx in &mut f.data[..f.len as usize] { if reader.read_bit()? { *idx += reader.read_signed_varint32()?; } @@ -368,7 +394,7 @@ fn PopNAndNonTopographical(f: &mut FieldPath, reader: &mut BitReader) -> std::io } fn NonTopoComplex(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - for idx in &mut f.data { + for idx in &mut f.data[..f.len as usize] { if reader.read_bit()? { *idx += reader.read_signed_varint32()?; } @@ -377,14 +403,14 @@ fn NonTopoComplex(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result< } fn NonTopoPenultimatePlusOne(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - assert!(f.data.len() >= 2, "Invalid fp size for op"); - let idx = f.data.len() - 2; - f.data[idx] += 1; + assert!(f.len() >= 2, "Invalid fp size for op"); + let idx = f.len() - 2; + f.data[idx as usize] += 1; Ok(()) } fn NonTopoComplexPack4Bits(f: &mut FieldPath, reader: &mut BitReader) -> std::io::Result<()> { - for idx in &mut f.data { + for idx in &mut f.data[..f.len as usize] { if reader.read_bit()? { *idx += reader.read::(4)? - 7; } @@ -393,7 +419,7 @@ fn NonTopoComplexPack4Bits(f: &mut FieldPath, reader: &mut BitReader) -> std::io } fn FieldPathEncodeFinish(f: &mut FieldPath, _reader: &mut BitReader) -> std::io::Result<()> { - f.finished = true; + f.len = 0; Ok(()) }