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