Skip to main content

tf_demo_parser/demo/
sendprop.rs

1use super::packet::datatable::ParseSendTable;
2use super::vector::{Vector, VectorXY};
3use crate::consthash::ConstFnvHash;
4use crate::demo::message::stringtable::log_base2;
5use crate::demo::packet::datatable::SendTableName;
6use crate::demo::parser::MalformedSendPropDefinitionError;
7use crate::demo::sendprop_gen::get_prop_names;
8use crate::{ParseError, ReadResult, Result, Stream};
9use bitbuffer::{BitRead, BitReadStream, Endianness, LittleEndian};
10#[cfg(feature = "write")]
11use bitbuffer::{BitWrite, BitWriteSized, BitWriteStream};
12use enumflags2::{bitflags, BitFlags};
13#[cfg(feature = "write")]
14use num_traits::Signed;
15use parse_display::Display;
16use serde::de::Error;
17use serde::{Deserialize, Deserializer, Serialize, Serializer};
18use std::borrow::Cow;
19use std::cmp::min;
20use std::convert::{TryFrom, TryInto};
21use std::fmt::{self, Debug, Display, Formatter};
22use std::hash::Hash;
23use std::ops::{BitOr, Deref};
24
25#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
26#[derive(PartialEq, Eq, Hash, Debug, Display, Clone, Serialize, Deserialize, Ord, PartialOrd)]
27#[cfg_attr(feature = "write", derive(BitWrite))]
28pub struct SendPropName(Cow<'static, str>);
29
30impl SendPropName {
31    pub fn as_str(&self) -> &str {
32        self.0.as_ref()
33    }
34}
35
36impl<E: Endianness> BitRead<'_, E> for SendPropName {
37    fn read(stream: &mut BitReadStream<'_, E>) -> bitbuffer::Result<Self> {
38        String::read(stream).map(SendPropName::from)
39    }
40}
41
42impl PartialEq<&str> for SendPropName {
43    fn eq(&self, other: &&str) -> bool {
44        self.as_str() == *other
45    }
46}
47
48impl From<String> for SendPropName {
49    fn from(value: String) -> Self {
50        Self(Cow::Owned(value))
51    }
52}
53
54impl From<&'static str> for SendPropName {
55    fn from(value: &'static str) -> Self {
56        SendPropName(Cow::Borrowed(value))
57    }
58}
59
60impl AsRef<str> for SendPropName {
61    fn as_ref(&self) -> &str {
62        self.0.as_ref()
63    }
64}
65
66impl Deref for SendPropName {
67    type Target = str;
68
69    fn deref(&self) -> &Self::Target {
70        self.0.deref()
71    }
72}
73
74#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct RawSendPropDefinition {
77    pub prop_type: SendPropType,
78    pub name: SendPropName,
79    pub identifier: SendPropIdentifier,
80    pub flags: SendPropFlags,
81    pub table_name: Option<SendTableName>,
82    pub low_value: Option<f32>,
83    pub high_value: Option<f32>,
84    pub bit_count: Option<u32>,
85    pub element_count: Option<u16>,
86    pub array_property: Option<Box<RawSendPropDefinition>>,
87    pub original_bit_count: Option<u32>,
88}
89
90impl PartialEq for RawSendPropDefinition {
91    fn eq(&self, other: &Self) -> bool {
92        self.identifier() == other.identifier()
93    }
94}
95
96impl fmt::Display for RawSendPropDefinition {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        match self.prop_type {
99            SendPropType::Vector | SendPropType::VectorXY => write!(
100                f,
101                "{}({})(flags: {}, low: {}, high: {}, bits: {})",
102                self.name,
103                self.prop_type,
104                self.flags,
105                self.low_value.unwrap_or_default(),
106                self.high_value.unwrap_or_default(),
107                self.bit_count.unwrap_or(96) / 3
108            ),
109            SendPropType::Float => write!(
110                f,
111                "{}({})(flags: {}, low: {}, high: {}, bits: {})",
112                self.name,
113                self.prop_type,
114                self.flags,
115                self.low_value.unwrap_or_default(),
116                self.high_value.unwrap_or_default(),
117                self.bit_count.unwrap_or(32)
118            ),
119            SendPropType::Int => write!(
120                f,
121                "{}({})(flags: {}, bits: {})",
122                self.name,
123                self.prop_type,
124                self.flags,
125                self.bit_count.unwrap_or(32)
126            ),
127            SendPropType::String => {
128                write!(f, "{}({})", self.name, self.prop_type)
129            }
130            SendPropType::Array => match &self.array_property {
131                Some(array_prop) => write!(
132                    f,
133                    "{}([{}({})] * {})",
134                    self.name,
135                    array_prop.prop_type,
136                    array_prop.flags,
137                    self.element_count.unwrap_or_default(),
138                ),
139                None => write!(f, "{}(Malformed array)", self.name),
140            },
141            SendPropType::DataTable => match &self.table_name {
142                Some(sub_table) => write!(f, "{}(DataTable = {})", self.name, sub_table),
143                None => write!(f, "{}(Malformed DataTable)", self.name),
144            },
145            SendPropType::NumSendPropTypes => {
146                write!(f, "{}(NumSendPropTypes)", self.name)
147            }
148        }
149    }
150}
151
152impl RawSendPropDefinition {
153    pub fn identifier(&self) -> SendPropIdentifier {
154        self.identifier
155    }
156
157    pub fn with_array_property(self, array_property: Self) -> Self {
158        RawSendPropDefinition {
159            prop_type: self.prop_type,
160            identifier: self.identifier,
161            name: self.name,
162            flags: self.flags,
163            table_name: self.table_name,
164            low_value: self.low_value,
165            high_value: self.high_value,
166            bit_count: self.bit_count,
167            element_count: self.element_count,
168            array_property: Some(Box::new(array_property)),
169            original_bit_count: self.original_bit_count,
170        }
171    }
172
173    /// Get the referred data table
174    ///
175    /// Note that this is not the owner table
176    pub fn get_data_table<'a>(&self, tables: &'a [ParseSendTable]) -> Option<&'a ParseSendTable> {
177        if self.prop_type == SendPropType::DataTable {
178            self.table_name
179                .as_ref()
180                .and_then(|name| tables.iter().find(|table| table.name == *name))
181        } else {
182            None
183        }
184    }
185
186    pub fn read(stream: &mut Stream, owner_table: &SendTableName) -> ReadResult<Self> {
187        let prop_type = SendPropType::read(stream)?;
188        let name: SendPropName = stream.read()?;
189        let identifier = SendPropIdentifier::new(owner_table.as_str(), name.as_str());
190        let flags = SendPropFlags::read(stream)?;
191        let mut table_name = None;
192        let mut element_count = None;
193        let mut low_value = None;
194        let mut high_value = None;
195        let mut bit_count = None;
196        if flags.contains(SendPropFlag::Exclude) || prop_type == SendPropType::DataTable {
197            table_name = Some(stream.read()?);
198        } else if prop_type == SendPropType::Array {
199            element_count = Some(stream.read_int(10)?);
200        } else {
201            low_value = Some(stream.read()?);
202            high_value = Some(stream.read()?);
203            bit_count = Some(stream.read_int(7)?);
204        }
205        let original_bit_count = bit_count;
206
207        if flags.contains(SendPropFlag::NoScale) {
208            if prop_type == SendPropType::Float {
209                bit_count = Some(32);
210            } else if prop_type == SendPropType::Vector
211                && !flags.contains(SendPropFlag::NormalVarInt)
212            {
213                bit_count = Some(32 * 3);
214            }
215        }
216
217        Ok(RawSendPropDefinition {
218            prop_type,
219            name,
220            identifier,
221            flags,
222            table_name,
223            low_value,
224            high_value,
225            bit_count,
226            element_count,
227            original_bit_count,
228            array_property: None,
229        })
230    }
231
232    pub fn is_exclude(&self) -> bool {
233        self.flags.contains(SendPropFlag::Exclude)
234    }
235
236    pub fn get_exclude_table(&self) -> Option<&SendTableName> {
237        if self.is_exclude() {
238            self.table_name.as_ref()
239        } else {
240            None
241        }
242    }
243}
244
245#[cfg(feature = "write")]
246impl BitWrite<LittleEndian> for RawSendPropDefinition {
247    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
248        self.prop_type.write(stream)?;
249        self.name.write(stream)?;
250        self.flags.write(stream)?;
251
252        if let Some(table_name) = self.table_name.as_ref() {
253            table_name.write(stream)?;
254        }
255        if let Some(element_count) = self.element_count {
256            element_count.write_sized(stream, 10)?;
257        }
258        if let (Some(low_value), Some(high_value), Some(bit_count)) =
259            (self.low_value, self.high_value, self.original_bit_count)
260        {
261            low_value.write(stream)?;
262            high_value.write(stream)?;
263            bit_count.write_sized(stream, 7)?;
264        }
265
266        Ok(())
267    }
268}
269
270#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
271#[derive(BitRead, Copy, Clone, PartialEq, Debug, Display, Serialize, Deserialize)]
272#[cfg_attr(feature = "write", derive(BitWrite))]
273#[discriminant_bits = 5]
274pub enum SendPropType {
275    Int = 0,
276    Float = 1,
277    Vector = 2,
278    VectorXY = 3,
279    String = 4,
280    Array = 5,
281    DataTable = 6,
282    NumSendPropTypes = 7,
283}
284
285#[bitflags]
286#[derive(Copy, Clone, PartialEq, Debug)]
287#[repr(u16)]
288pub enum SendPropFlag {
289    // Unsigned integer data.
290    Unsigned = 1,
291    // If this is set, the float/vector is treated like a world coordinate.
292    // Note that the bit count is ignored in this case.
293    Coord = 2,
294    // For floating point, don't scale into range, just take value as is.
295    NoScale = 4,
296    // For floating point, limit high value to range minus one bit unit
297    RoundDown = 8,
298    // For floating point, limit low value to range minus one bit unit
299    RoundUp = 16,
300    // This is an exclude prop (not excluded, but it points at another prop to be excluded).
301    Exclude = 64,
302    // Use XYZ/Exponent encoding for vectors.
303    XYZE = 128,
304    // This tells us that the property is inside an array, so it shouldn't be put into the
305    // flattened property list. Its array will point at it when it needs to.
306    InsideArray = 256,
307    // Set for datatable props using one of the default datatable proxies like
308    // SendProxy_DataTableToDataTable that always send the data to all clients.
309    ProxyAlwaysYes = 512,
310    // this is an often changed field, moved to head of sendtable so it gets a small index
311    ChangesOften = 1024,
312    // Set automatically if SPROP_VECTORELEM is used.
313    IsVectorElement = 2048,
314    // Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer
315    // (ie: for all automatically-chained base classes).
316    // In this case, it can get rid of this SendPropDataTable altogether and spare the
317    // trouble of walking the hierarchy more than necessary.
318    Collapsible = 4096,
319    // Like SPROP_COORD, but special handling for multiplayer games
320    CoordMP = 8192,
321    // Like SPROP_COORD, but special handling for multiplayer games
322    // where the fractional component only gets a 3 bits instead of 5
323    CoordMPLowPrecision = 16384,
324    // SPROP_COORD_MP, but coordinates are rounded to integral boundaries
325    // overloaded as both "Normal" and "VarInt"
326    CoordMPIntegral = 32768,
327    NormalVarInt = 32,
328}
329
330#[derive(Debug, Copy, Clone, PartialEq, Default, Serialize, Deserialize)]
331pub struct SendPropFlags(BitFlags<SendPropFlag>);
332
333#[cfg(feature = "schemars")]
334impl schemars::JsonSchema for SendPropFlags {
335    fn schema_name() -> std::borrow::Cow<'static, str> {
336        "SendPropFlags".into()
337    }
338
339    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
340        u16::json_schema(generator)
341    }
342}
343
344impl BitOr<SendPropFlag> for SendPropFlags {
345    type Output = SendPropFlags;
346
347    fn bitor(self, rhs: SendPropFlag) -> Self::Output {
348        Self(self.0 | rhs)
349    }
350}
351
352impl fmt::Display for SendPropFlags {
353    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354        let debug = format!("{:?}", self.0);
355        let flags: String = debug
356            .chars()
357            .skip_while(|c| *c != '[')
358            .take_while(|c| *c != ')')
359            .collect();
360        write!(f, "{flags}")
361    }
362}
363
364impl SendPropFlags {
365    pub fn contains(self, other: SendPropFlag) -> bool {
366        self.0.contains(other)
367    }
368}
369
370impl BitRead<'_, LittleEndian> for SendPropFlags {
371    fn read(stream: &mut Stream) -> ReadResult<Self> {
372        // since all 16 bits worth of flags are used there are no invalid flags
373        Ok(SendPropFlags(BitFlags::from_bits_truncate(stream.read()?)))
374    }
375
376    fn bit_size() -> Option<usize> {
377        Some(16)
378    }
379}
380
381#[cfg(feature = "write")]
382impl BitWrite<LittleEndian> for SendPropFlags {
383    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
384        self.0.bits().write(stream)
385    }
386}
387
388#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
389#[derive(Debug, Clone, Serialize, Deserialize)]
390pub enum FloatDefinition {
391    Coord,
392    CoordMP,
393    CoordMPLowPrecision,
394    CoordMPIntegral,
395    FloatNoScale,
396    NormalVarFloat,
397    Scaled { bit_count: u8, high: f32, low: f32 },
398}
399
400impl FloatDefinition {
401    pub fn new(
402        flags: SendPropFlags,
403        bit_count: Option<u32>,
404        high: Option<f32>,
405        low: Option<f32>,
406    ) -> std::result::Result<Self, MalformedSendPropDefinitionError> {
407        if flags.contains(SendPropFlag::Coord) {
408            Ok(FloatDefinition::Coord)
409        } else if flags.contains(SendPropFlag::CoordMP) {
410            Ok(FloatDefinition::CoordMP)
411        } else if flags.contains(SendPropFlag::CoordMPLowPrecision) {
412            Ok(FloatDefinition::CoordMPLowPrecision)
413        } else if flags.contains(SendPropFlag::CoordMPIntegral) {
414            Ok(FloatDefinition::CoordMPIntegral)
415        } else if flags.contains(SendPropFlag::NoScale) {
416            Ok(FloatDefinition::FloatNoScale)
417        } else if flags.contains(SendPropFlag::NormalVarInt) {
418            Ok(FloatDefinition::NormalVarFloat)
419        } else if let (Some(bit_count), Some(high), Some(low)) = (bit_count, high, low) {
420            Ok(FloatDefinition::Scaled {
421                bit_count: bit_count as u8,
422                high,
423                low,
424            })
425        } else {
426            Err(MalformedSendPropDefinitionError::UnsizedFloat)
427        }
428    }
429}
430
431#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
432#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct SendPropDefinition {
434    pub identifier: SendPropIdentifier,
435    pub parse_definition: SendPropParseDefinition,
436}
437
438impl TryFrom<&RawSendPropDefinition> for SendPropDefinition {
439    type Error = MalformedSendPropDefinitionError;
440
441    fn try_from(definition: &RawSendPropDefinition) -> std::result::Result<Self, Self::Error> {
442        let parse_definition = definition.try_into()?;
443        Ok(SendPropDefinition {
444            parse_definition,
445            identifier: definition.identifier(),
446        })
447    }
448}
449
450#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
451#[derive(Debug, Clone, Serialize, Deserialize)]
452pub enum SendPropParseDefinition {
453    NormalVarInt {
454        changes_often: bool,
455        unsigned: bool,
456    },
457    UnsignedInt {
458        changes_often: bool,
459        bit_count: u8,
460    },
461    Int {
462        changes_often: bool,
463        bit_count: u8,
464    },
465    Float {
466        changes_often: bool,
467        definition: FloatDefinition,
468    },
469    String {
470        changes_often: bool,
471    },
472    Vector {
473        changes_often: bool,
474        definition: FloatDefinition,
475    },
476    VectorXY {
477        changes_often: bool,
478        definition: FloatDefinition,
479    },
480    Array {
481        changes_often: bool,
482        inner_definition: Box<SendPropParseDefinition>,
483        count_bit_count: u16,
484    },
485}
486
487impl SendPropParseDefinition {
488    pub fn changes_often(&self) -> bool {
489        match self {
490            SendPropParseDefinition::NormalVarInt { changes_often, .. } => *changes_often,
491            SendPropParseDefinition::UnsignedInt { changes_often, .. } => *changes_often,
492            SendPropParseDefinition::Int { changes_often, .. } => *changes_often,
493            SendPropParseDefinition::Float { changes_often, .. } => *changes_often,
494            SendPropParseDefinition::String { changes_often, .. } => *changes_often,
495            SendPropParseDefinition::Vector { changes_often, .. } => *changes_often,
496            SendPropParseDefinition::VectorXY { changes_often, .. } => *changes_often,
497            SendPropParseDefinition::Array { changes_often, .. } => *changes_often,
498        }
499    }
500}
501
502impl TryFrom<&RawSendPropDefinition> for SendPropParseDefinition {
503    type Error = MalformedSendPropDefinitionError;
504
505    fn try_from(definition: &RawSendPropDefinition) -> std::result::Result<Self, Self::Error> {
506        let changes_often = definition.flags.contains(SendPropFlag::ChangesOften);
507        match definition.prop_type {
508            SendPropType::Int => {
509                if definition.flags.contains(SendPropFlag::NormalVarInt) {
510                    Ok(SendPropParseDefinition::NormalVarInt {
511                        changes_often,
512                        unsigned: definition.flags.contains(SendPropFlag::Unsigned),
513                    })
514                } else if definition.flags.contains(SendPropFlag::Unsigned) {
515                    Ok(SendPropParseDefinition::UnsignedInt {
516                        changes_often,
517                        bit_count: definition.bit_count.unwrap_or(32) as u8,
518                    })
519                } else {
520                    Ok(SendPropParseDefinition::Int {
521                        changes_often,
522                        bit_count: definition.bit_count.unwrap_or(32) as u8,
523                    })
524                }
525            }
526            SendPropType::Float => Ok(SendPropParseDefinition::Float {
527                changes_often,
528                definition: FloatDefinition::new(
529                    definition.flags,
530                    definition.bit_count,
531                    definition.high_value,
532                    definition.low_value,
533                )?,
534            }),
535            SendPropType::String => Ok(SendPropParseDefinition::String { changes_often }),
536            SendPropType::Vector => Ok(SendPropParseDefinition::Vector {
537                changes_often,
538                definition: FloatDefinition::new(
539                    definition.flags,
540                    definition.bit_count,
541                    definition.high_value,
542                    definition.low_value,
543                )?,
544            }),
545            SendPropType::VectorXY => Ok(SendPropParseDefinition::VectorXY {
546                changes_often,
547                definition: FloatDefinition::new(
548                    definition.flags,
549                    definition.bit_count,
550                    definition.high_value,
551                    definition.low_value,
552                )?,
553            }),
554            SendPropType::Array => {
555                let element_count = definition
556                    .element_count
557                    .ok_or(MalformedSendPropDefinitionError::UnsizedArray)?;
558                let count_bit_count = log_base2(element_count) as u16 + 1;
559                let child_definition = definition
560                    .array_property
561                    .as_deref()
562                    .ok_or(MalformedSendPropDefinitionError::UntypedArray)?;
563                Ok(SendPropParseDefinition::Array {
564                    changes_often,
565                    inner_definition: Box::new(SendPropParseDefinition::try_from(
566                        child_definition,
567                    )?),
568                    count_bit_count,
569                })
570            }
571            _ => Err(MalformedSendPropDefinitionError::InvalidPropType),
572        }
573    }
574}
575
576#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
577#[derive(Debug, Clone, Serialize, Deserialize)]
578#[serde(untagged)]
579pub enum SendPropValue {
580    Vector(Vector),
581    VectorXY(VectorXY),
582    Integer(i64),
583    Float(f32),
584    String(String),
585    Array(Vec<SendPropValue>),
586}
587
588impl PartialEq for SendPropValue {
589    fn eq(&self, other: &Self) -> bool {
590        // allow comparing some "compatible" types
591        match (self, other) {
592            (SendPropValue::Vector(value1), SendPropValue::Vector(value2)) => value1 == value2,
593            (SendPropValue::VectorXY(value1), SendPropValue::VectorXY(value2)) => value1 == value2,
594            (SendPropValue::Integer(value1), SendPropValue::Integer(value2)) => value1 == value2,
595            (SendPropValue::Float(value1), SendPropValue::Float(value2)) => value1 - value2 < 0.001,
596            (SendPropValue::String(value1), SendPropValue::String(value2)) => value1 == value2,
597            (SendPropValue::Array(value1), SendPropValue::Array(value2)) => value1 == value2,
598            (SendPropValue::Integer(value1), SendPropValue::Float(value2)) => {
599                *value1 as f64 == *value2 as f64
600            }
601            (SendPropValue::Float(value1), SendPropValue::Integer(value2)) => {
602                *value1 as f64 == *value2 as f64
603            }
604            (SendPropValue::Vector(value1), SendPropValue::VectorXY(value2)) => {
605                value1.x == value2.x && value1.y == value2.y && value1.z == 0.0
606            }
607            (SendPropValue::VectorXY(value1), SendPropValue::Vector(value2)) => {
608                value1.x == value2.x && value1.y == value2.y && value2.z == 0.0
609            }
610            (SendPropValue::Vector(value1), SendPropValue::Array(value2)) => {
611                value1 == value2.as_slice()
612            }
613            (SendPropValue::Array(value1), SendPropValue::Vector(value2)) => {
614                value2 == value1.as_slice()
615            }
616            (SendPropValue::VectorXY(value1), SendPropValue::Array(value2)) => {
617                value1 == value2.as_slice()
618            }
619            (SendPropValue::Array(value1), SendPropValue::VectorXY(value2)) => {
620                value2 == value1.as_slice()
621            }
622            _ => false,
623        }
624    }
625}
626
627impl fmt::Display for SendPropValue {
628    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
629        match self {
630            SendPropValue::Vector(vector) => Display::fmt(vector, f),
631            SendPropValue::VectorXY(vector) => Display::fmt(vector, f),
632            SendPropValue::Integer(int) => Display::fmt(int, f),
633            SendPropValue::Float(float) => Display::fmt(float, f),
634            SendPropValue::String(string) => Display::fmt(string, f),
635            SendPropValue::Array(array) => {
636                write!(f, "[")?;
637                for child in array {
638                    write!(f, "{child}")?;
639                }
640                write!(f, "]")
641            }
642        }
643    }
644}
645
646fn float_scale(bit_count: u8) -> f32 {
647    // is this -1 correct?, it is consistent with the js version but seems weird
648    (1i32.wrapping_shl(bit_count as u32)) as f32 - 1.0
649}
650
651impl SendPropValue {
652    pub fn parse(stream: &mut Stream, definition: &SendPropParseDefinition) -> Result<Self> {
653        match definition {
654            SendPropParseDefinition::NormalVarInt { unsigned, .. } => {
655                read_var_int(stream, !*unsigned)
656                    .map_err(ParseError::from)
657                    .map(|int| {
658                        if *unsigned {
659                            int as u32 as i64
660                        } else {
661                            int as i64
662                        }
663                    })
664                    .map(SendPropValue::from)
665            }
666            SendPropParseDefinition::UnsignedInt { bit_count, .. } => {
667                Ok((stream.read_sized::<u32>(*bit_count as usize)? as i64).into())
668            }
669            SendPropParseDefinition::Int { bit_count, .. } => stream
670                .read_int::<i32>((*bit_count) as usize)
671                .map_err(ParseError::from)
672                .map(SendPropValue::from),
673            SendPropParseDefinition::Float {
674                definition: float_definition,
675                ..
676            } => Self::read_float(stream, float_definition).map(SendPropValue::from),
677            SendPropParseDefinition::String { .. } => {
678                let length = stream.read_int(9)?;
679                stream
680                    .read_sized::<String>(length)
681                    .map_err(ParseError::from)
682                    .map(SendPropValue::from)
683            }
684            SendPropParseDefinition::Vector {
685                definition: float_definition,
686                ..
687            } => {
688                let x = Self::read_float(stream, float_definition)?;
689                let y = Self::read_float(stream, float_definition)?;
690                let z = match float_definition {
691                    FloatDefinition::NormalVarFloat => {
692                        let is_negative = stream.read()?;
693                        let x2y2 = x * x + y * y;
694                        let z = if x2y2 < 1.0f32 {
695                            f32::sqrt(1.0f32 - x2y2)
696                        } else {
697                            0.0f32
698                        };
699
700                        if is_negative {
701                            -z
702                        } else {
703                            z
704                        }
705                    }
706                    _ => Self::read_float(stream, float_definition)?,
707                };
708
709                Ok(Vector { x, y, z }.into())
710            }
711            SendPropParseDefinition::VectorXY {
712                definition: float_definition,
713                ..
714            } => Ok(VectorXY {
715                x: Self::read_float(stream, float_definition)?,
716                y: Self::read_float(stream, float_definition)?,
717            }
718            .into()),
719            SendPropParseDefinition::Array {
720                count_bit_count,
721                inner_definition,
722                ..
723            } => {
724                let count = stream.read_int(*count_bit_count as usize)?;
725                let mut values = Vec::with_capacity(min(count, 128));
726
727                for _ in 0..count {
728                    values.push(Self::parse(stream, inner_definition)?);
729                }
730
731                Ok(values.into())
732            }
733        }
734    }
735
736    #[cfg(feature = "write")]
737    pub fn encode(
738        &self,
739        stream: &mut BitWriteStream<LittleEndian>,
740        definition: &SendPropParseDefinition,
741    ) -> Result<()> {
742        match definition {
743            SendPropParseDefinition::NormalVarInt { unsigned, .. } => {
744                let val: i64 = self.try_into()?;
745                write_var_int(val as i32, stream, !*unsigned)?;
746                Ok(())
747            }
748            SendPropParseDefinition::UnsignedInt { bit_count, .. } => {
749                let val: i64 = self.try_into()?;
750                (val as u32).write_sized(stream, *bit_count as usize)?;
751                Ok(())
752            }
753            SendPropParseDefinition::Int { bit_count, .. } => {
754                let val: i64 = self.try_into()?;
755                (val as i32).write_sized(stream, *bit_count as usize)?;
756                Ok(())
757            }
758            SendPropParseDefinition::Float {
759                definition: float_definition,
760                ..
761            } => {
762                let val: f32 = self.try_into()?;
763                Self::write_float(val, stream, float_definition)
764            }
765            SendPropParseDefinition::String { .. } => {
766                let val: &str = self.try_into()?;
767                (val.len() as u16).write_sized(stream, 9)?;
768                val.write_sized(stream, val.len())?;
769                Ok(())
770            }
771            SendPropParseDefinition::Vector {
772                definition: float_definition,
773                ..
774            } => {
775                let val: Vector = self.try_into()?;
776                Self::write_float(val.x, stream, float_definition)?;
777                Self::write_float(val.y, stream, float_definition)?;
778                match float_definition {
779                    FloatDefinition::NormalVarFloat => stream.write_bool(val.z.is_negative())?,
780                    _ => Self::write_float(val.z, stream, float_definition)?,
781                }
782                Ok(())
783            }
784            SendPropParseDefinition::VectorXY {
785                definition: float_definition,
786                ..
787            } => {
788                let val: VectorXY = self.try_into()?;
789                Self::write_float(val.x, stream, float_definition)?;
790                Self::write_float(val.y, stream, float_definition)?;
791                Ok(())
792            }
793            SendPropParseDefinition::Array {
794                count_bit_count,
795                inner_definition,
796                ..
797            } => {
798                let array: &[SendPropValue] = self.try_into()?;
799                (array.len() as u16).write_sized(stream, *count_bit_count as usize)?;
800
801                for inner in array {
802                    inner.encode(stream, inner_definition)?
803                }
804
805                Ok(())
806            }
807        }
808    }
809
810    fn read_float(stream: &mut Stream, definition: &FloatDefinition) -> Result<f32> {
811        match definition {
812            FloatDefinition::Coord => read_bit_coord(stream).map_err(ParseError::from),
813            FloatDefinition::CoordMP => {
814                read_bit_coord_mp(stream, false, false).map_err(ParseError::from)
815            }
816            FloatDefinition::CoordMPLowPrecision => {
817                read_bit_coord_mp(stream, false, true).map_err(ParseError::from)
818            }
819            FloatDefinition::CoordMPIntegral => {
820                read_bit_coord_mp(stream, true, false).map_err(ParseError::from)
821            }
822            FloatDefinition::FloatNoScale => stream.read().map_err(ParseError::from),
823            FloatDefinition::NormalVarFloat => read_bit_normal(stream).map_err(ParseError::from),
824            FloatDefinition::Scaled {
825                bit_count,
826                low,
827                high,
828            } => {
829                let raw: u32 = stream.read_int(*bit_count as usize)?;
830                let scale = float_scale(*bit_count);
831                let percentage = (raw as f32) / scale;
832                Ok(low + ((high - low) * percentage))
833            }
834        }
835    }
836
837    #[cfg(feature = "write")]
838    fn write_float(
839        val: f32,
840        stream: &mut BitWriteStream<LittleEndian>,
841        definition: &FloatDefinition,
842    ) -> Result<()> {
843        match definition {
844            FloatDefinition::Coord => write_bit_coord(val, stream).map_err(ParseError::from),
845            FloatDefinition::CoordMP => {
846                write_bit_coord_mp(val, stream, false, false).map_err(ParseError::from)
847            }
848            FloatDefinition::CoordMPLowPrecision => {
849                write_bit_coord_mp(val, stream, false, true).map_err(ParseError::from)
850            }
851            FloatDefinition::CoordMPIntegral => {
852                write_bit_coord_mp(val, stream, true, false).map_err(ParseError::from)
853            }
854            FloatDefinition::FloatNoScale => val.write(stream).map_err(ParseError::from),
855            FloatDefinition::NormalVarFloat => {
856                write_bit_normal(val, stream).map_err(ParseError::from)
857            }
858            FloatDefinition::Scaled {
859                bit_count,
860                low,
861                high,
862            } => {
863                let percentage = (val - low) / (high - low);
864                let scale = float_scale(*bit_count);
865                let raw = (percentage * scale).round() as u32;
866                raw.write_sized(stream, *bit_count as usize)?;
867
868                Ok(())
869            }
870        }
871    }
872}
873
874#[test]
875#[cfg(feature = "write")]
876fn test_send_prop_value_roundtrip() {
877    use bitbuffer::{BitReadBuffer, BitReadStream};
878
879    fn send_prop_value_roundtrip(val: SendPropValue, def: SendPropParseDefinition) {
880        let mut data = Vec::new();
881        let pos = {
882            let mut write = BitWriteStream::new(&mut data, LittleEndian);
883            val.encode(&mut write, &def).unwrap();
884            write.bit_len()
885        };
886        let mut read = BitReadStream::new(BitReadBuffer::new(&data, LittleEndian));
887        assert_eq!(val, SendPropValue::parse(&mut read, &def).unwrap());
888        assert_eq!(pos, read.pos());
889    }
890    send_prop_value_roundtrip(
891        SendPropValue::Integer(0),
892        SendPropParseDefinition::UnsignedInt {
893            changes_often: false,
894            bit_count: 5,
895        },
896    );
897    send_prop_value_roundtrip(
898        SendPropValue::Integer(12),
899        SendPropParseDefinition::NormalVarInt {
900            changes_often: false,
901            unsigned: false,
902        },
903    );
904    send_prop_value_roundtrip(
905        SendPropValue::Integer(12),
906        SendPropParseDefinition::NormalVarInt {
907            changes_often: false,
908            unsigned: false,
909        },
910    );
911    send_prop_value_roundtrip(
912        SendPropValue::Integer(-12),
913        SendPropParseDefinition::NormalVarInt {
914            changes_often: false,
915            unsigned: false,
916        },
917    );
918    send_prop_value_roundtrip(
919        SendPropValue::String("foobar".into()),
920        SendPropParseDefinition::String {
921            changes_often: false,
922        },
923    );
924    send_prop_value_roundtrip(
925        SendPropValue::Vector(Vector {
926            x: 1.0,
927            y: 0.0,
928            z: 1.125,
929        }),
930        SendPropParseDefinition::Vector {
931            changes_often: false,
932            definition: FloatDefinition::Coord,
933        },
934    );
935    send_prop_value_roundtrip(
936        SendPropValue::Vector(Vector {
937            x: 0.0,
938            y: 0.0,
939            z: -1.0,
940        }),
941        SendPropParseDefinition::Vector {
942            changes_often: false,
943            definition: FloatDefinition::NormalVarFloat,
944        },
945    );
946    send_prop_value_roundtrip(
947        SendPropValue::VectorXY(VectorXY { x: 1.0, y: 0.0 }),
948        SendPropParseDefinition::VectorXY {
949            changes_often: false,
950            definition: FloatDefinition::FloatNoScale,
951        },
952    );
953    send_prop_value_roundtrip(
954        SendPropValue::Float(12.5),
955        SendPropParseDefinition::Float {
956            changes_often: false,
957            definition: FloatDefinition::CoordMP,
958        },
959    );
960    send_prop_value_roundtrip(
961        SendPropValue::Float(12.0),
962        SendPropParseDefinition::Float {
963            changes_often: false,
964            definition: FloatDefinition::CoordMPIntegral,
965        },
966    );
967    send_prop_value_roundtrip(
968        SendPropValue::Float(12.5),
969        SendPropParseDefinition::Float {
970            changes_often: false,
971            definition: FloatDefinition::CoordMPLowPrecision,
972        },
973    );
974    send_prop_value_roundtrip(
975        SendPropValue::Float(12.498169),
976        SendPropParseDefinition::Float {
977            changes_often: false,
978            definition: FloatDefinition::Scaled {
979                bit_count: 12,
980                high: 25.0,
981                low: 10.0,
982            },
983        },
984    );
985    send_prop_value_roundtrip(
986        SendPropValue::Array(vec![
987            SendPropValue::Integer(0),
988            SendPropValue::Integer(1),
989            SendPropValue::Integer(2),
990        ]),
991        SendPropParseDefinition::Array {
992            changes_often: false,
993            inner_definition: Box::new(SendPropParseDefinition::UnsignedInt {
994                changes_often: false,
995                bit_count: 3,
996            }),
997            count_bit_count: 5,
998        },
999    );
1000
1001    send_prop_value_roundtrip(
1002        SendPropValue::Float(76.22549),
1003        SendPropParseDefinition::Float {
1004            changes_often: false,
1005            definition: FloatDefinition::Scaled {
1006                bit_count: 10,
1007                high: 102.3,
1008                low: 0.09990235,
1009            },
1010        },
1011    );
1012    send_prop_value_roundtrip(
1013        SendPropValue::Vector(Vector {
1014            x: 1.0,
1015            y: -25.96875,
1016            z: 0.1875,
1017        }),
1018        SendPropParseDefinition::Vector {
1019            changes_often: false,
1020            definition: FloatDefinition::CoordMP,
1021        },
1022    );
1023    send_prop_value_roundtrip(
1024        SendPropValue::Integer(-1),
1025        SendPropParseDefinition::NormalVarInt {
1026            changes_often: false,
1027            unsigned: false,
1028        },
1029    );
1030}
1031
1032#[test]
1033#[cfg(feature = "write")]
1034fn test_encode_vector_normal_var_float() {
1035    use bitbuffer::BitWriteStream;
1036
1037    let vector = SendPropValue::Vector(Vector {
1038        x: 0.0f32,
1039        y: 0.0f32,
1040        z: -1.0f32,
1041    });
1042    let def = SendPropParseDefinition::Vector {
1043        changes_often: false,
1044        definition: FloatDefinition::NormalVarFloat,
1045    };
1046
1047    let mut data = Vec::new();
1048    let pos = {
1049        let mut write = BitWriteStream::new(&mut data, LittleEndian);
1050        vector.encode(&mut write, &def).unwrap();
1051        write.bit_len()
1052    };
1053
1054    assert_eq!(pos, 25);
1055    assert_eq!(data, vec![0, 0, 0, 1]);
1056}
1057
1058impl From<i32> for SendPropValue {
1059    fn from(value: i32) -> Self {
1060        SendPropValue::Integer(value as i64)
1061    }
1062}
1063
1064impl From<i64> for SendPropValue {
1065    fn from(value: i64) -> Self {
1066        SendPropValue::Integer(value)
1067    }
1068}
1069
1070impl From<Vector> for SendPropValue {
1071    fn from(value: Vector) -> Self {
1072        SendPropValue::Vector(value)
1073    }
1074}
1075
1076impl From<VectorXY> for SendPropValue {
1077    fn from(value: VectorXY) -> Self {
1078        SendPropValue::VectorXY(value)
1079    }
1080}
1081
1082impl From<f32> for SendPropValue {
1083    fn from(value: f32) -> Self {
1084        SendPropValue::Float(value)
1085    }
1086}
1087
1088impl From<String> for SendPropValue {
1089    fn from(value: String) -> Self {
1090        SendPropValue::String(value)
1091    }
1092}
1093
1094impl From<Vec<SendPropValue>> for SendPropValue {
1095    fn from(value: Vec<SendPropValue>) -> Self {
1096        SendPropValue::Array(value)
1097    }
1098}
1099
1100impl TryFrom<&SendPropValue> for i64 {
1101    type Error = MalformedSendPropDefinitionError;
1102    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1103        match value {
1104            SendPropValue::Integer(val) => Ok(*val),
1105            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1106                expected: "integer",
1107                value: value.clone(),
1108            }),
1109        }
1110    }
1111}
1112
1113impl TryFrom<&SendPropValue> for bool {
1114    type Error = MalformedSendPropDefinitionError;
1115    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1116        match value {
1117            SendPropValue::Integer(val) => Ok(*val > 0),
1118            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1119                expected: "boolean",
1120                value: value.clone(),
1121            }),
1122        }
1123    }
1124}
1125
1126impl TryFrom<&SendPropValue> for Vector {
1127    type Error = MalformedSendPropDefinitionError;
1128    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1129        match value {
1130            SendPropValue::Vector(val) => Ok(*val),
1131            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1132                expected: "vector",
1133                value: value.clone(),
1134            }),
1135        }
1136    }
1137}
1138
1139impl TryFrom<&SendPropValue> for VectorXY {
1140    type Error = MalformedSendPropDefinitionError;
1141    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1142        match value {
1143            SendPropValue::VectorXY(val) => Ok(*val),
1144            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1145                expected: "vectorxy",
1146                value: value.clone(),
1147            }),
1148        }
1149    }
1150}
1151
1152impl TryFrom<&SendPropValue> for f32 {
1153    type Error = MalformedSendPropDefinitionError;
1154    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1155        match value {
1156            SendPropValue::Float(val) => Ok(*val),
1157            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1158                expected: "float",
1159                value: value.clone(),
1160            }),
1161        }
1162    }
1163}
1164
1165impl<'a> TryFrom<&'a SendPropValue> for &'a str {
1166    type Error = MalformedSendPropDefinitionError;
1167    fn try_from(value: &'a SendPropValue) -> std::result::Result<Self, Self::Error> {
1168        match value {
1169            SendPropValue::String(val) => Ok(val.as_str()),
1170            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1171                expected: "string",
1172                value: value.clone(),
1173            }),
1174        }
1175    }
1176}
1177
1178impl<'a> TryFrom<&'a SendPropValue> for &'a [SendPropValue] {
1179    type Error = MalformedSendPropDefinitionError;
1180    fn try_from(value: &'a SendPropValue) -> std::result::Result<Self, Self::Error> {
1181        match value {
1182            SendPropValue::Array(val) => Ok(val.as_slice()),
1183            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1184                expected: "array",
1185                value: value.clone(),
1186            }),
1187        }
1188    }
1189}
1190
1191#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
1192pub struct SendPropIdentifier(u64);
1193
1194impl SendPropIdentifier {
1195    pub const fn new(table: &str, prop: &str) -> Self {
1196        let hasher = ConstFnvHash::new().push_string(table).push_string(prop);
1197        SendPropIdentifier(hasher.finish())
1198    }
1199
1200    /// Construct a SendPropIdentifier from a u64; like std::convert::From<u64> but marked as
1201    /// const.
1202    pub const fn from_const(raw: u64) -> Self {
1203        SendPropIdentifier(raw)
1204    }
1205
1206    /// This returns an option because only props known at compile time will return a name here
1207    ///
1208    /// If you need to know the name of every property you need to keep a map yourself
1209    pub fn table_name(&self) -> Option<SendTableName> {
1210        get_prop_names(*self).map(|(table, _)| table.into())
1211    }
1212
1213    /// This returns an option because only props known at compile time will return a name here
1214    ///
1215    /// If you need to know the name of every property you need to keep a map yourself
1216    pub fn prop_name(&self) -> Option<SendPropName> {
1217        get_prop_names(*self).map(|(_, prop)| prop.into())
1218    }
1219
1220    /// This returns an option because only props known at compile time will return a name here
1221    ///
1222    /// If you need to know the name of every property you need to keep a map yourself
1223    pub fn names(&self) -> Option<(SendTableName, SendPropName)> {
1224        get_prop_names(*self).map(|(table, prop)| (table.into(), prop.into()))
1225    }
1226}
1227
1228impl From<u64> for SendPropIdentifier {
1229    fn from(raw: u64) -> Self {
1230        SendPropIdentifier(raw)
1231    }
1232}
1233
1234impl From<SendPropIdentifier> for u64 {
1235    fn from(identifier: SendPropIdentifier) -> Self {
1236        identifier.0
1237    }
1238}
1239
1240impl Display for SendPropIdentifier {
1241    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1242        match get_prop_names(*self) {
1243            Some((table, prop)) => write!(f, "{table}.{prop}"),
1244            None => write!(f, "Prop name {} not known", self.0),
1245        }
1246    }
1247}
1248
1249impl<'de> Deserialize<'de> for SendPropIdentifier {
1250    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
1251    where
1252        D: Deserializer<'de>,
1253    {
1254        #[derive(Deserialize)]
1255        #[serde(untagged)]
1256        enum Options<'a> {
1257            Num(u64),
1258            Str(Cow<'a, str>),
1259        }
1260
1261        let raw = Options::deserialize(deserializer)?;
1262        Ok(match raw {
1263            Options::Num(num) => SendPropIdentifier(num),
1264            Options::Str(s) => {
1265                let num: u64 = s.parse().map_err(D::Error::custom)?;
1266                SendPropIdentifier(num)
1267            }
1268        })
1269    }
1270}
1271
1272impl Serialize for SendPropIdentifier {
1273    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1274    where
1275        S: Serializer,
1276    {
1277        self.0.to_string().serialize(serializer)
1278    }
1279}
1280
1281#[cfg(feature = "schema")]
1282impl schemars::JsonSchema for SendPropIdentifier {
1283    fn schema_name() -> std::borrow::Cow<'static, str> {
1284        "SendPropIdentifier".into()
1285    }
1286
1287    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
1288        <String as schemars::JsonSchema>::json_schema(generator)
1289    }
1290}
1291
1292#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
1293#[derive(Clone, Display, PartialEq, Serialize, Deserialize)]
1294#[display("{index} = {value}")]
1295pub struct SendProp {
1296    pub index: u32,
1297    pub identifier: SendPropIdentifier,
1298    pub value: SendPropValue,
1299}
1300
1301impl Debug for SendProp {
1302    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1303        write!(f, "{} = {}", self.identifier, self.value)
1304    }
1305}
1306
1307pub fn read_var_int(stream: &mut Stream, signed: bool) -> ReadResult<i32> {
1308    let abs_int = crate::demo::message::stringtable::read_var_int(stream)? as i32;
1309
1310    if signed {
1311        Ok((abs_int >> 1) ^ -(abs_int & 1))
1312    } else {
1313        Ok(abs_int)
1314    }
1315}
1316
1317#[cfg(feature = "write")]
1318pub fn write_var_int(
1319    int: i32,
1320    stream: &mut BitWriteStream<LittleEndian>,
1321    signed: bool,
1322) -> ReadResult<()> {
1323    let abs = if signed {
1324        let int = (int << 1) ^ (int >> 31);
1325        u32::from_le_bytes(int.to_le_bytes())
1326    } else {
1327        int as u32
1328    };
1329
1330    crate::demo::message::stringtable::write_var_int(abs, stream)
1331}
1332
1333#[test]
1334#[cfg(feature = "write")]
1335fn test_var_int_roundtrip() {
1336    use bitbuffer::{BitReadBuffer, BitReadStream};
1337
1338    fn var_int_roundtrip(int: i32, signed: bool) {
1339        let mut data = Vec::new();
1340        let pos = {
1341            let mut write = BitWriteStream::new(&mut data, LittleEndian);
1342            write_var_int(int, &mut write, signed).unwrap();
1343            write.bit_len()
1344        };
1345        let mut read = BitReadStream::new(BitReadBuffer::new(&data, LittleEndian));
1346        assert_eq!(int, read_var_int(&mut read, signed).unwrap());
1347        assert_eq!(pos, read.pos());
1348    }
1349    var_int_roundtrip(0, false);
1350    var_int_roundtrip(1, false);
1351    var_int_roundtrip(10, false);
1352    var_int_roundtrip(55, false);
1353    var_int_roundtrip(355, false);
1354    var_int_roundtrip(12354, false);
1355    var_int_roundtrip(123125412, false);
1356
1357    var_int_roundtrip(0, true);
1358    var_int_roundtrip(1, true);
1359    var_int_roundtrip(10, true);
1360    var_int_roundtrip(55, true);
1361    var_int_roundtrip(355, true);
1362    var_int_roundtrip(12354, true);
1363    var_int_roundtrip(123125412, true);
1364    var_int_roundtrip(-0, true);
1365    var_int_roundtrip(-1, true);
1366    var_int_roundtrip(-10, true);
1367    var_int_roundtrip(-55, true);
1368    var_int_roundtrip(-355, true);
1369    var_int_roundtrip(-12354, true);
1370    var_int_roundtrip(-123125412, true);
1371}
1372
1373pub fn read_bit_coord(stream: &mut Stream) -> ReadResult<f32> {
1374    let has_int = stream.read()?;
1375    let has_frac = stream.read()?;
1376
1377    Ok(if has_int || has_frac {
1378        let sign = if stream.read()? { -1f32 } else { 1f32 };
1379        let int_val: u16 = if has_int {
1380            stream.read_sized::<u16>(14)? + 1
1381        } else {
1382            0
1383        };
1384        let frac_val: u8 = if has_frac { stream.read_sized(5)? } else { 0 };
1385        let value = int_val as f32 + (frac_val as f32 * get_frac_factor(5));
1386        value * sign
1387    } else {
1388        0f32
1389    })
1390}
1391
1392#[cfg(feature = "write")]
1393pub fn write_bit_coord(val: f32, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
1394    let has_int = val.abs() >= 1.0;
1395    has_int.write(stream)?;
1396    let has_frac = val.fract() != 0.0;
1397    has_frac.write(stream)?;
1398
1399    if has_frac || has_int {
1400        let sign = val.is_negative();
1401        sign.write(stream)?;
1402    }
1403    let abs = val.abs();
1404    if has_int {
1405        (abs as u16 - 1).write_sized(stream, 14)?;
1406    }
1407    if has_frac {
1408        let frac_val = (abs.fract() / get_frac_factor(5)) as u8;
1409        frac_val.write_sized(stream, 5)?;
1410    }
1411    Ok(())
1412}
1413
1414#[test]
1415#[cfg(feature = "write")]
1416fn bit_coord_roundtrip() {
1417    use bitbuffer::BitReadBuffer;
1418
1419    let mut data = Vec::with_capacity(16);
1420    let (pos1, pos2, pos3, pos4) = {
1421        let mut write = BitWriteStream::new(&mut data, LittleEndian);
1422        write_bit_coord(0.0, &mut write).unwrap();
1423        let pos1 = write.bit_len();
1424        write_bit_coord(123.0, &mut write).unwrap();
1425        let pos2 = write.bit_len();
1426        write_bit_coord(123.4375, &mut write).unwrap();
1427        let pos3 = write.bit_len();
1428        write_bit_coord(-0.4375, &mut write).unwrap();
1429        let pos4 = write.bit_len();
1430        (pos1, pos2, pos3, pos4)
1431    };
1432
1433    let mut read = Stream::from(BitReadBuffer::new(&data, LittleEndian));
1434    assert_eq!(0.0, read_bit_coord(&mut read).unwrap());
1435    assert_eq!(pos1, read.pos());
1436    assert_eq!(123.0, read_bit_coord(&mut read).unwrap());
1437    assert_eq!(pos2, read.pos());
1438    assert_eq!(123.4375, read_bit_coord(&mut read).unwrap());
1439    assert_eq!(pos3, read.pos());
1440    assert_eq!(-0.4375, read_bit_coord(&mut read).unwrap());
1441    assert_eq!(pos4, read.pos());
1442}
1443
1444fn get_frac_factor(bits: usize) -> f32 {
1445    1.0 / ((1 << bits) as f32)
1446}
1447
1448pub fn read_bit_coord_mp(
1449    stream: &mut Stream,
1450    is_integral: bool,
1451    low_precision: bool,
1452) -> ReadResult<f32> {
1453    let mut value = 0.0;
1454    let mut is_negative = false;
1455
1456    let in_bounds = stream.read()?;
1457    let has_int_val = stream.read()?;
1458
1459    if is_integral {
1460        if has_int_val {
1461            is_negative = stream.read()?;
1462
1463            let int_val = stream.read_sized::<u32>(if in_bounds { 11 } else { 14 })? + 1;
1464            value = int_val as f32;
1465        }
1466    } else {
1467        is_negative = stream.read()?;
1468        if has_int_val {
1469            let int_val = stream.read_sized::<u32>(if in_bounds { 11 } else { 14 })? + 1;
1470            value = int_val as f32;
1471        }
1472        let frac_bits = if low_precision { 3 } else { 5 };
1473        let frac_val: u32 = stream.read_sized(frac_bits)?;
1474        value += (frac_val as f32) * get_frac_factor(frac_bits);
1475    }
1476
1477    if is_negative {
1478        value = -value;
1479    }
1480
1481    Ok(value)
1482}
1483
1484#[cfg(feature = "write")]
1485pub fn write_bit_coord_mp(
1486    val: f32,
1487    stream: &mut BitWriteStream<LittleEndian>,
1488    is_integral: bool,
1489    low_precision: bool,
1490) -> ReadResult<()> {
1491    let abs = val.abs();
1492    let in_bounds = (abs as u32) < (1 << 11);
1493    let has_int_val = abs >= 1.0;
1494    in_bounds.write(stream)?;
1495    has_int_val.write(stream)?;
1496
1497    if is_integral {
1498        if has_int_val {
1499            val.is_sign_negative().write(stream)?;
1500            ((abs - 1.0) as u32).write_sized(stream, if in_bounds { 11 } else { 14 })?;
1501        }
1502    } else {
1503        val.is_sign_negative().write(stream)?;
1504        if has_int_val {
1505            ((abs - 1.0) as u32).write_sized(stream, if in_bounds { 11 } else { 14 })?;
1506        }
1507        let frac_bits = if low_precision { 3 } else { 5 };
1508        let frac_val = (abs.fract() / get_frac_factor(frac_bits)) as u32;
1509        frac_val.write_sized(stream, frac_bits)?;
1510    }
1511
1512    Ok(())
1513}
1514
1515#[test]
1516#[cfg(feature = "write")]
1517fn test_bit_coord_mp_roundtrip() {
1518    use bitbuffer::{BitReadBuffer, BitReadStream};
1519
1520    fn bit_coord_mp_normal(val: f32, is_integral: bool, low_precision: bool) {
1521        let mut data = Vec::with_capacity(16);
1522        let pos = {
1523            let mut write = BitWriteStream::new(&mut data, LittleEndian);
1524            write_bit_coord_mp(val, &mut write, is_integral, low_precision).unwrap();
1525            write.bit_len()
1526        };
1527        let mut read = BitReadStream::new(BitReadBuffer::new(&data, LittleEndian));
1528        assert_eq!(
1529            val,
1530            read_bit_coord_mp(&mut read, is_integral, low_precision).unwrap()
1531        );
1532        assert_eq!(pos, read.pos());
1533    }
1534
1535    bit_coord_mp_normal(1.0, false, false);
1536
1537    bit_coord_mp_normal(0.0, false, false);
1538    bit_coord_mp_normal(0.5, false, false);
1539    bit_coord_mp_normal(-0.5, false, false);
1540    bit_coord_mp_normal(1234.5, false, false);
1541    bit_coord_mp_normal(-1234.5, false, false);
1542    bit_coord_mp_normal(2.0f32.powf(12.0) + 0.125, false, false);
1543
1544    bit_coord_mp_normal(0.0, false, true);
1545    bit_coord_mp_normal(0.5, false, true);
1546    bit_coord_mp_normal(-0.5, false, true);
1547    bit_coord_mp_normal(1234.5, false, true);
1548    bit_coord_mp_normal(-1234.5, false, true);
1549    bit_coord_mp_normal(2.0f32.powf(12.0) + 0.125, false, true);
1550
1551    bit_coord_mp_normal(0.0, true, false);
1552    bit_coord_mp_normal(1234.0, true, false);
1553    bit_coord_mp_normal(-1234.0, true, false);
1554    bit_coord_mp_normal(2.0f32.powf(12.0), true, false);
1555}
1556
1557pub fn read_bit_normal(stream: &mut Stream) -> ReadResult<f32> {
1558    let is_negative = stream.read()?;
1559    let frac_val: u16 = stream.read_sized(11)?;
1560    let value = (frac_val as f32) * get_frac_factor(11);
1561    if is_negative {
1562        Ok(-value)
1563    } else {
1564        Ok(value)
1565    }
1566}
1567
1568#[cfg(feature = "write")]
1569pub fn write_bit_normal(val: f32, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
1570    val.is_sign_negative().write(stream)?;
1571    let frac_val = (val.abs().fract() / get_frac_factor(11)) as u16;
1572    frac_val.write_sized(stream, 11)
1573}
1574
1575#[test]
1576#[cfg(feature = "write")]
1577fn test_bit_normal_roundtrip() {
1578    use bitbuffer::{BitReadBuffer, BitReadStream};
1579
1580    fn roundtrip_normal(val: f32) {
1581        let mut data = Vec::with_capacity(16);
1582        let pos = {
1583            let mut write = BitWriteStream::new(&mut data, LittleEndian);
1584            write_bit_normal(val, &mut write).unwrap();
1585            write.bit_len()
1586        };
1587        let mut read = BitReadStream::new(BitReadBuffer::new(&data, LittleEndian));
1588        assert_eq!(val, read_bit_normal(&mut read).unwrap());
1589        assert_eq!(pos, read.pos());
1590    }
1591    roundtrip_normal(0.0);
1592    roundtrip_normal(-0.0);
1593    roundtrip_normal(0.5);
1594    roundtrip_normal(-0.5);
1595}
1596
1597#[test]
1598fn test_vector_normal_var_float() {
1599    use bitbuffer::BitReadBuffer;
1600
1601    let data: Vec<u8> = vec![0, 0, 0, 0];
1602    let mut buffer = BitReadBuffer::new(&data, LittleEndian);
1603    // (1 (sign bit) + 11 (frac val)) * 2 (NormalVarFloat) + 1 (z sign bit)
1604    buffer.truncate(25).unwrap();
1605    let mut read = BitReadStream::new(buffer);
1606
1607    let vector = SendPropValue::parse(
1608        &mut read,
1609        &SendPropParseDefinition::Vector {
1610            changes_often: false,
1611            definition: FloatDefinition::NormalVarFloat,
1612        },
1613    )
1614    .unwrap();
1615
1616    assert_eq!(
1617        SendPropValue::Vector(Vector {
1618            x: 0.0f32,
1619            y: 0.0f32,
1620            z: 1.0f32
1621        }),
1622        vector
1623    );
1624}