use crate::math::{QAngle, Vector};
use sdk_raw::bitbuf::Bits;
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt::{self, Display, Formatter};
const COORD_DENOMINATOR: i32 = 1 << COORD_FRACTIONAL_BITS;
pub const COORD_FRACTIONAL_BITS: u32 = 5;
pub const COORD_INTEGER_BITS: u32 = 14;
const COORD_RESOLUTION: f32 = 1.0 / COORD_DENOMINATOR as f32;
const MAX_VAR_INT32_BYTES: usize = 5;
const NORMAL_DENOMINATOR: i32 = (1 << NORMAL_FRACTIONAL_BITS) - 1;
pub const NORMAL_FRACTIONAL_BITS: u32 = 11;
const NORMAL_RESOLUTION: f64 = 1.0 / NORMAL_DENOMINATOR as f64;
#[doc(alias("bf_read"))]
#[derive(Debug, Clone)]
pub struct BitReader<'a> {
words: &'a [u32],
len: usize,
position: usize,
}
impl<'a> BitReader<'a> {
pub fn new(words: &'a [u32], len: usize) -> Self {
assert!(len <= words.len() * 32, "{len} bits exceed the words given");
Self {
words,
len,
position: 0,
}
}
#[doc(alias("GetNumBitsRead"))]
pub const fn position(&self) -> usize {
self.position
}
#[doc(alias("ReadOneBit"))]
pub fn read_bit(&mut self) -> Result<bool, Overflow> {
Ok(self.read_ubits(1)? != 0)
}
#[doc(alias("ReadBitAngle"))]
pub fn read_bit_angle(&mut self, bits: u32) -> Result<f32, Overflow> {
let turn = (1u64 << bits) as f64;
Ok((f64::from(self.read_ubits(bits)?) * 360.0 / turn) as f32)
}
#[doc(alias("ReadBitCoord"))]
pub fn read_bit_coord(&mut self) -> Result<f32, Overflow> {
let has_integer = self.read_bit()?;
let has_fraction = self.read_bit()?;
if !has_integer && !has_fraction {
return Ok(0.0);
}
let negative = self.read_bit()?;
let integer = match has_integer {
true => self.read_ubits(COORD_INTEGER_BITS)? + 1,
false => 0,
};
let fraction = match has_fraction {
true => self.read_ubits(COORD_FRACTIONAL_BITS)?,
false => 0,
};
let value = integer as f32 + fraction as f32 * COORD_RESOLUTION;
Ok(if negative { -value } else { value })
}
#[doc(alias("ReadBitNormal"))]
pub fn read_bit_normal(&mut self) -> Result<f32, Overflow> {
let negative = self.read_bit()?;
let fraction = f64::from(self.read_ubits(NORMAL_FRACTIONAL_BITS)?);
let value = (fraction / f64::from(NORMAL_DENOMINATOR)) as f32;
Ok(if negative { -value } else { value })
}
#[doc(alias("ReadBitVec3Coord"))]
pub fn read_bit_vec3_coord(&mut self) -> Result<Vector, Overflow> {
let present = [self.read_bit()?, self.read_bit()?, self.read_bit()?];
let mut components = [0.0; 3];
for (component, present) in components.iter_mut().zip(present) {
if present {
*component = self.read_bit_coord()?;
}
}
Ok(Vector::new(components[0], components[1], components[2]))
}
#[doc(alias("ReadBits"))]
pub fn read_bits(&mut self, bits: usize) -> Result<BitWriter, Overflow> {
if self.remaining() < bits {
return Err(Overflow);
}
let mut writer = BitWriter::with_capacity(bits);
for _ in 0..bits / 32 {
writer.push(self.read_ubits(32)?, 32);
}
let rest = (bits % 32) as u32;
writer.push(self.read_ubits(rest)?, rest);
Ok(writer)
}
#[doc(alias("ReadBytes"))]
pub fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, Overflow> {
if self.remaining() / 8 < len {
return Err(Overflow);
}
(0..len).map(|_| self.read_u8()).collect()
}
#[doc(alias("ReadString"))]
pub fn read_cstring(&mut self) -> Result<CString, Overflow> {
let mut bytes = Vec::new();
loop {
match self.read_u8()? {
0 => break,
byte => bytes.push(byte),
}
}
Ok(unsafe { CString::from_vec_unchecked(bytes) })
}
#[doc(alias("ReadFloat", "ReadBitFloat"))]
pub fn read_f32(&mut self) -> Result<f32, Overflow> {
Ok(f32::from_bits(self.read_ubits(32)?))
}
#[doc(alias("ReadChar"))]
pub fn read_i8(&mut self) -> Result<i8, Overflow> {
Ok(self.read_sbits(8)? as i8)
}
#[doc(alias("ReadShort"))]
pub fn read_i16(&mut self) -> Result<i16, Overflow> {
Ok(self.read_sbits(16)? as i16)
}
#[doc(alias("ReadLong"))]
pub fn read_i32(&mut self) -> Result<i32, Overflow> {
Ok(self.read_ubits(32)? as i32)
}
#[doc(alias("ReadSBitLong"))]
pub fn read_sbits(&mut self, bits: u32) -> Result<i32, Overflow> {
assert!((1..=32).contains(&bits), "cannot read {bits} signed bits");
let shift = 32 - bits;
Ok(((self.read_ubits(bits)? << shift) as i32) >> shift)
}
#[doc(alias("ReadByte"))]
pub fn read_u8(&mut self) -> Result<u8, Overflow> {
Ok(self.read_ubits(8)? as u8)
}
#[doc(alias("ReadWord"))]
pub fn read_u16(&mut self) -> Result<u16, Overflow> {
Ok(self.read_ubits(16)? as u16)
}
pub fn read_u32(&mut self) -> Result<u32, Overflow> {
self.read_ubits(32)
}
#[doc(alias("ReadUBitVar"))]
pub fn read_ubit_var(&mut self) -> Result<u32, Overflow> {
let bits = match self.read_ubits(2)? {
0 => 4,
1 => 8,
2 => 12,
_ => 32,
};
self.read_ubits(bits)
}
#[doc(alias("ReadUBitLong"))]
pub fn read_ubits(&mut self, bits: u32) -> Result<u32, Overflow> {
assert!(bits <= 32, "cannot read {bits} bits at once");
if bits == 0 {
return Ok(0);
}
if self.remaining() < bits as usize {
return Err(Overflow);
}
let offset = (self.position % 32) as u32;
let index = self.position / 32;
let mut value = self.words[index] >> offset;
if offset + bits > 32 {
value |= self.words[index + 1] << (32 - offset);
}
self.position += bits as usize;
Ok(value & mask(bits))
}
#[doc(alias("ReadVarInt32"))]
pub fn read_var_u32(&mut self) -> Result<u32, Overflow> {
let mut value = 0u32;
for index in 0..MAX_VAR_INT32_BYTES {
let byte = self.read_u8()?;
value |= u32::from(byte & 0x7f) << (7 * index);
if byte & 0x80 == 0 {
break;
}
}
Ok(value)
}
#[doc(alias("GetNumBitsLeft"))]
pub const fn remaining(&self) -> usize {
self.len - self.position
}
#[doc(alias("SeekRelative"))]
pub fn skip(&mut self, bits: usize) -> Result<(), Overflow> {
if self.remaining() < bits {
return Err(Overflow);
}
self.position += bits;
Ok(())
}
}
#[doc(alias("bf_write"))]
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
pub struct BitWriter {
words: Vec<u32>,
len: usize,
}
impl BitWriter {
pub const fn new() -> Self {
Self {
words: Vec::new(),
len: 0,
}
}
pub fn from_words(words: &[u32], bits: usize) -> Self {
assert!(
bits <= words.len() * 32,
"{bits} bits exceed the words given"
);
let mut writer = Self::with_capacity(bits);
writer.write_words(words, bits);
writer
}
pub fn with_capacity(bits: usize) -> Self {
Self {
words: Vec::with_capacity(bits.div_ceil(32)),
len: 0,
}
}
pub fn as_words(&self) -> &[u32] {
&self.words
}
#[doc(alias("GetNumBytesWritten"))]
pub const fn byte_len(&self) -> usize {
self.len.div_ceil(8)
}
pub fn clear(&mut self) {
self.words.clear();
self.len = 0;
}
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[doc(alias("GetNumBitsWritten"))]
pub const fn len(&self) -> usize {
self.len
}
fn push(&mut self, value: u32, bits: u32) {
if bits == 0 {
return;
}
let offset = (self.len % 32) as u32;
let index = self.len / 32;
self.len += bits as usize;
self.words.resize(self.len.div_ceil(32), 0);
self.words[index] |= value << offset;
if offset + bits > 32 {
self.words[index + 1] |= value >> (32 - offset);
}
}
pub fn reader(&self) -> BitReader<'_> {
BitReader::new(&self.words, self.len)
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes: Vec<u8> = self
.words
.iter()
.flat_map(|word| word.to_le_bytes())
.collect();
bytes.truncate(self.byte_len());
bytes
}
#[doc(alias("WriteOneBit"))]
pub fn write_bit(&mut self, bit: bool) {
self.push(u32::from(bit), 1);
}
#[doc(alias("WriteBitAngle"))]
pub fn write_bit_angle(&mut self, degrees: f32, bits: u32) {
assert!(
(1..=32).contains(&bits),
"cannot write an angle in {bits} bits"
);
let turn = (1u64 << bits) as f64;
let fraction = (f64::from(degrees) / 360.0 * turn) as i64;
self.push((fraction as u32) & mask(bits), bits);
}
#[doc(alias("WriteBitAngles"))]
pub fn write_bit_angles(&mut self, value: QAngle) {
self.write_bit_vec3_coord(Vector::new(value.pitch, value.yaw, value.roll));
}
#[doc(alias("WriteBitCoord"))]
pub fn write_bit_coord(&mut self, value: f32) {
let negative = value <= -COORD_RESOLUTION;
let integer = value.abs() as u32;
let fraction = ((value * COORD_DENOMINATOR as f32) as i32).unsigned_abs()
& (COORD_DENOMINATOR as u32 - 1);
self.write_bit(integer != 0);
self.write_bit(fraction != 0);
if integer != 0 || fraction != 0 {
self.write_bit(negative);
if integer != 0 {
self.push((integer - 1) & mask(COORD_INTEGER_BITS), COORD_INTEGER_BITS);
}
if fraction != 0 {
self.push(fraction, COORD_FRACTIONAL_BITS);
}
}
}
#[doc(alias("WriteBitNormal"))]
pub fn write_bit_normal(&mut self, value: f32) {
let negative = f64::from(value) <= -NORMAL_RESOLUTION;
let fraction = ((value * NORMAL_DENOMINATOR as f32) as i32)
.unsigned_abs()
.min(NORMAL_DENOMINATOR as u32);
self.write_bit(negative);
self.push(fraction, NORMAL_FRACTIONAL_BITS);
}
#[doc(alias("WriteBitVec3Coord"))]
pub fn write_bit_vec3_coord(&mut self, value: Vector) {
let components = [value.x, value.y, value.z];
let present = components.map(|component| component.abs() >= COORD_RESOLUTION);
for flag in present {
self.write_bit(flag);
}
for (component, present) in components.into_iter().zip(present) {
if present {
self.write_bit_coord(component);
}
}
}
#[doc(alias("WriteBitVec3Normal"))]
pub fn write_bit_vec3_normal(&mut self, value: Vector) {
let x = f64::from(value.x.abs()) >= NORMAL_RESOLUTION;
let y = f64::from(value.y.abs()) >= NORMAL_RESOLUTION;
self.write_bit(x);
self.write_bit(y);
if x {
self.write_bit_normal(value.x);
}
if y {
self.write_bit_normal(value.y);
}
self.write_bit(f64::from(value.z) <= -NORMAL_RESOLUTION);
}
#[doc(alias("WriteBits"))]
pub fn write_bits(&mut self, other: &BitWriter) {
self.write_words(&other.words, other.len);
}
#[doc(alias("WriteBytes"))]
pub fn write_bytes(&mut self, bytes: &[u8]) {
for &byte in bytes {
self.push(byte.into(), 8);
}
}
#[doc(alias("WriteString"))]
pub fn write_cstr(&mut self, value: &CStr) {
self.write_bytes(value.to_bytes_with_nul());
}
#[doc(alias("WriteFloat", "WriteBitFloat"))]
pub fn write_f32(&mut self, value: f32) {
self.push(value.to_bits(), 32);
}
#[doc(alias("WriteChar"))]
pub fn write_i8(&mut self, value: i8) {
self.write_sbits(value.into(), 8);
}
#[doc(alias("WriteShort"))]
pub fn write_i16(&mut self, value: i16) {
self.write_sbits(value.into(), 16);
}
#[doc(alias("WriteLong"))]
pub fn write_i32(&mut self, value: i32) {
self.push(value as u32, 32);
}
#[doc(alias("WriteSBitLong"))]
pub fn write_sbits(&mut self, value: i32, bits: u32) {
assert!((1..=32).contains(&bits), "cannot write {bits} signed bits");
let shift = 32 - bits;
assert!(
(value << shift) >> shift == value,
"{value} does not fit in {bits} signed bits"
);
self.push(value as u32 & mask(bits), bits);
}
#[doc(alias("WriteByte"))]
pub fn write_u8(&mut self, value: u8) {
self.push(value.into(), 8);
}
#[doc(alias("WriteWord"))]
pub fn write_u16(&mut self, value: u16) {
self.push(value.into(), 16);
}
pub fn write_u32(&mut self, value: u32) {
self.push(value, 32);
}
#[doc(alias("WriteUBitVar"))]
pub fn write_ubit_var(&mut self, value: u32) {
let (selector, bits) = match value {
0..0x10 => (0, 4),
0x10..0x100 => (1, 8),
0x100..0x1000 => (2, 12),
_ => (3, 32),
};
self.push(selector, 2);
self.push(value, bits);
}
#[doc(alias("WriteUBitLong"))]
pub fn write_ubits(&mut self, value: u32, bits: u32) {
assert!(bits <= 32, "cannot write {bits} bits at once");
assert!(
bits == 32 || value >> bits == 0,
"{value} does not fit in {bits} bits"
);
self.push(value, bits);
}
#[doc(alias("WriteVarInt32"))]
pub fn write_var_u32(&mut self, mut value: u32) {
while value > 0x7f {
self.push((value & 0x7f) | 0x80, 8);
value >>= 7;
}
self.push(value, 8);
}
fn write_words(&mut self, words: &[u32], bits: usize) {
let whole = bits / 32;
for &word in &words[..whole] {
self.push(word, 32);
}
let rest = (bits % 32) as u32;
if rest != 0 {
self.push(words[whole] & mask(rest), rest);
}
}
}
impl From<Bits> for BitWriter {
fn from(bits: Bits) -> Self {
Self::from_words(bits.as_words(), bits.len())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Overflow;
impl Display for Overflow {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("read past the end of the bit buffer")
}
}
impl Error for Overflow {}
const fn mask(bits: u32) -> u32 {
match bits {
32.. => u32::MAX,
_ => (1 << bits) - 1,
}
}