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)) => {
608                value1 == value2.as_slice()
609            }
610            (SendPropValue::Array(value1), SendPropValue::Vector(value2)) => {
611                value2 == value1.as_slice()
612            }
613            (SendPropValue::VectorXY(value1), SendPropValue::Array(value2)) => {
614                value1 == value2.as_slice()
615            }
616            (SendPropValue::Array(value1), SendPropValue::VectorXY(value2)) => {
617                value2 == value1.as_slice()
618            }
619            _ => false,
620        }
621    }
622}
623
624impl fmt::Display for SendPropValue {
625    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
626        match self {
627            SendPropValue::Vector(vector) => Display::fmt(vector, f),
628            SendPropValue::VectorXY(vector) => Display::fmt(vector, f),
629            SendPropValue::Integer(int) => Display::fmt(int, f),
630            SendPropValue::Float(float) => Display::fmt(float, f),
631            SendPropValue::String(string) => Display::fmt(string, f),
632            SendPropValue::Array(array) => {
633                write!(f, "[")?;
634                for child in array {
635                    write!(f, "{}", child)?;
636                }
637                write!(f, "]")
638            }
639        }
640    }
641}
642
643fn float_scale(bit_count: u8) -> f32 {
644    // is this -1 correct?, it is consistent with the js version but seems weird
645    (1i32.wrapping_shl(bit_count as u32)) as f32 - 1.0
646}
647
648impl SendPropValue {
649    pub fn parse(stream: &mut Stream, definition: &SendPropParseDefinition) -> Result<Self> {
650        match definition {
651            SendPropParseDefinition::NormalVarInt { unsigned, .. } => {
652                read_var_int(stream, !*unsigned)
653                    .map_err(ParseError::from)
654                    .map(|int| int as i64)
655                    .map(SendPropValue::from)
656            }
657            SendPropParseDefinition::UnsignedInt { bit_count, .. } => {
658                Ok((stream.read_sized::<u32>(*bit_count as usize)? as i64).into())
659            }
660            SendPropParseDefinition::Int { bit_count, .. } => stream
661                .read_int::<i32>((*bit_count) as usize)
662                .map_err(ParseError::from)
663                .map(SendPropValue::from),
664            SendPropParseDefinition::Float {
665                definition: float_definition,
666                ..
667            } => Self::read_float(stream, float_definition).map(SendPropValue::from),
668            SendPropParseDefinition::String { .. } => {
669                let length = stream.read_int(9)?;
670                stream
671                    .read_sized::<String>(length)
672                    .map_err(ParseError::from)
673                    .map(SendPropValue::from)
674            }
675            SendPropParseDefinition::Vector {
676                definition: float_definition,
677                ..
678            } => Ok(Vector {
679                x: Self::read_float(stream, float_definition)?,
680                y: Self::read_float(stream, float_definition)?,
681                z: Self::read_float(stream, float_definition)?,
682            }
683            .into()),
684            SendPropParseDefinition::VectorXY {
685                definition: float_definition,
686                ..
687            } => Ok(VectorXY {
688                x: Self::read_float(stream, float_definition)?,
689                y: Self::read_float(stream, float_definition)?,
690            }
691            .into()),
692            SendPropParseDefinition::Array {
693                count_bit_count,
694                inner_definition,
695                ..
696            } => {
697                let count = stream.read_int(*count_bit_count as usize)?;
698                let mut values = Vec::with_capacity(min(count, 128));
699
700                for _ in 0..count {
701                    values.push(Self::parse(stream, inner_definition)?);
702                }
703
704                Ok(values.into())
705            }
706        }
707    }
708    pub fn encode(
709        &self,
710        stream: &mut BitWriteStream<LittleEndian>,
711        definition: &SendPropParseDefinition,
712    ) -> Result<()> {
713        match definition {
714            SendPropParseDefinition::NormalVarInt { unsigned, .. } => {
715                let val: i64 = self.try_into()?;
716                write_var_int(val as i32, stream, !*unsigned)?;
717                Ok(())
718            }
719            SendPropParseDefinition::UnsignedInt { bit_count, .. } => {
720                let val: i64 = self.try_into()?;
721                (val as u32).write_sized(stream, *bit_count as usize)?;
722                Ok(())
723            }
724            SendPropParseDefinition::Int { bit_count, .. } => {
725                let val: i64 = self.try_into()?;
726                (val as i32).write_sized(stream, *bit_count as usize)?;
727                Ok(())
728            }
729            SendPropParseDefinition::Float {
730                definition: float_definition,
731                ..
732            } => {
733                let val: f32 = self.try_into()?;
734                Self::write_float(val, stream, float_definition)
735            }
736            SendPropParseDefinition::String { .. } => {
737                let val: &str = self.try_into()?;
738                (val.len() as u16).write_sized(stream, 9)?;
739                val.write_sized(stream, val.len())?;
740                Ok(())
741            }
742            SendPropParseDefinition::Vector {
743                definition: float_definition,
744                ..
745            } => {
746                let val: Vector = self.try_into()?;
747                Self::write_float(val.x, stream, float_definition)?;
748                Self::write_float(val.y, stream, float_definition)?;
749                Self::write_float(val.z, stream, float_definition)?;
750                Ok(())
751            }
752            SendPropParseDefinition::VectorXY {
753                definition: float_definition,
754                ..
755            } => {
756                let val: VectorXY = self.try_into()?;
757                Self::write_float(val.x, stream, float_definition)?;
758                Self::write_float(val.y, stream, float_definition)?;
759                Ok(())
760            }
761            SendPropParseDefinition::Array {
762                count_bit_count,
763                inner_definition,
764                ..
765            } => {
766                let array: &[SendPropValue] = self.try_into()?;
767                (array.len() as u16).write_sized(stream, *count_bit_count as usize)?;
768
769                for inner in array {
770                    inner.encode(stream, inner_definition)?
771                }
772
773                Ok(())
774            }
775        }
776    }
777
778    fn read_float(stream: &mut Stream, definition: &FloatDefinition) -> Result<f32> {
779        match definition {
780            FloatDefinition::Coord => read_bit_coord(stream).map_err(ParseError::from),
781            FloatDefinition::CoordMP => {
782                read_bit_coord_mp(stream, false, false).map_err(ParseError::from)
783            }
784            FloatDefinition::CoordMPLowPrecision => {
785                read_bit_coord_mp(stream, false, true).map_err(ParseError::from)
786            }
787            FloatDefinition::CoordMPIntegral => {
788                read_bit_coord_mp(stream, true, false).map_err(ParseError::from)
789            }
790            FloatDefinition::FloatNoScale => stream.read().map_err(ParseError::from),
791            FloatDefinition::NormalVarFloat => read_bit_normal(stream).map_err(ParseError::from),
792            FloatDefinition::Scaled {
793                bit_count,
794                low,
795                high,
796            } => {
797                let raw: u32 = stream.read_int(*bit_count as usize)?;
798                let scale = float_scale(*bit_count);
799                let percentage = (raw as f32) / scale;
800                Ok(low + ((high - low) * percentage))
801            }
802        }
803    }
804
805    fn write_float(
806        val: f32,
807        stream: &mut BitWriteStream<LittleEndian>,
808        definition: &FloatDefinition,
809    ) -> Result<()> {
810        match definition {
811            FloatDefinition::Coord => write_bit_coord(val, stream).map_err(ParseError::from),
812            FloatDefinition::CoordMP => {
813                write_bit_coord_mp(val, stream, false, false).map_err(ParseError::from)
814            }
815            FloatDefinition::CoordMPLowPrecision => {
816                write_bit_coord_mp(val, stream, false, true).map_err(ParseError::from)
817            }
818            FloatDefinition::CoordMPIntegral => {
819                write_bit_coord_mp(val, stream, true, false).map_err(ParseError::from)
820            }
821            FloatDefinition::FloatNoScale => val.write(stream).map_err(ParseError::from),
822            FloatDefinition::NormalVarFloat => {
823                write_bit_normal(val, stream).map_err(ParseError::from)
824            }
825            FloatDefinition::Scaled {
826                bit_count,
827                low,
828                high,
829            } => {
830                let percentage = (val - low) / (high - low);
831                let scale = float_scale(*bit_count);
832                let raw = (percentage * scale).round() as u32;
833                raw.write_sized(stream, *bit_count as usize)?;
834
835                Ok(())
836            }
837        }
838    }
839}
840
841#[test]
842fn test_send_prop_value_roundtrip() {
843    use bitbuffer::{BitReadBuffer, BitReadStream};
844
845    fn send_prop_value_roundtrip(val: SendPropValue, def: SendPropParseDefinition) {
846        let mut data = Vec::new();
847        let pos = {
848            let mut write = BitWriteStream::new(&mut data, LittleEndian);
849            val.encode(&mut write, &def).unwrap();
850            write.bit_len()
851        };
852        let mut read = BitReadStream::new(BitReadBuffer::new(&data, LittleEndian));
853        assert_eq!(val, SendPropValue::parse(&mut read, &def).unwrap());
854        assert_eq!(pos, read.pos());
855    }
856    send_prop_value_roundtrip(
857        SendPropValue::Integer(0),
858        SendPropParseDefinition::UnsignedInt {
859            changes_often: false,
860            bit_count: 5,
861        },
862    );
863    send_prop_value_roundtrip(
864        SendPropValue::Integer(12),
865        SendPropParseDefinition::NormalVarInt {
866            changes_often: false,
867            unsigned: false,
868        },
869    );
870    send_prop_value_roundtrip(
871        SendPropValue::Integer(12),
872        SendPropParseDefinition::NormalVarInt {
873            changes_often: false,
874            unsigned: false,
875        },
876    );
877    send_prop_value_roundtrip(
878        SendPropValue::Integer(-12),
879        SendPropParseDefinition::NormalVarInt {
880            changes_often: false,
881            unsigned: true,
882        },
883    );
884    send_prop_value_roundtrip(
885        SendPropValue::String("foobar".into()),
886        SendPropParseDefinition::String {
887            changes_often: false,
888        },
889    );
890    send_prop_value_roundtrip(
891        SendPropValue::Vector(Vector {
892            x: 1.0,
893            y: 0.0,
894            z: 1.125,
895        }),
896        SendPropParseDefinition::Vector {
897            changes_often: false,
898            definition: FloatDefinition::Coord,
899        },
900    );
901    send_prop_value_roundtrip(
902        SendPropValue::VectorXY(VectorXY { x: 1.0, y: 0.0 }),
903        SendPropParseDefinition::VectorXY {
904            changes_often: false,
905            definition: FloatDefinition::FloatNoScale,
906        },
907    );
908    send_prop_value_roundtrip(
909        SendPropValue::Float(12.5),
910        SendPropParseDefinition::Float {
911            changes_often: false,
912            definition: FloatDefinition::CoordMP,
913        },
914    );
915    send_prop_value_roundtrip(
916        SendPropValue::Float(12.0),
917        SendPropParseDefinition::Float {
918            changes_often: false,
919            definition: FloatDefinition::CoordMPIntegral,
920        },
921    );
922    send_prop_value_roundtrip(
923        SendPropValue::Float(12.5),
924        SendPropParseDefinition::Float {
925            changes_often: false,
926            definition: FloatDefinition::CoordMPLowPrecision,
927        },
928    );
929    send_prop_value_roundtrip(
930        SendPropValue::Float(12.498169),
931        SendPropParseDefinition::Float {
932            changes_often: false,
933            definition: FloatDefinition::Scaled {
934                bit_count: 12,
935                high: 25.0,
936                low: 10.0,
937            },
938        },
939    );
940    send_prop_value_roundtrip(
941        SendPropValue::Array(vec![
942            SendPropValue::Integer(0),
943            SendPropValue::Integer(1),
944            SendPropValue::Integer(2),
945        ]),
946        SendPropParseDefinition::Array {
947            changes_often: false,
948            inner_definition: Box::new(SendPropParseDefinition::UnsignedInt {
949                changes_often: false,
950                bit_count: 3,
951            }),
952            count_bit_count: 5,
953        },
954    );
955
956    send_prop_value_roundtrip(
957        SendPropValue::Float(76.22549),
958        SendPropParseDefinition::Float {
959            changes_often: false,
960            definition: FloatDefinition::Scaled {
961                bit_count: 10,
962                high: 102.3,
963                low: 0.09990235,
964            },
965        },
966    );
967    send_prop_value_roundtrip(
968        SendPropValue::Vector(Vector {
969            x: 1.0,
970            y: -25.96875,
971            z: 0.1875,
972        }),
973        SendPropParseDefinition::Vector {
974            changes_often: false,
975            definition: FloatDefinition::CoordMP,
976        },
977    );
978    send_prop_value_roundtrip(
979        SendPropValue::Integer(-1),
980        SendPropParseDefinition::NormalVarInt {
981            changes_often: false,
982            unsigned: false,
983        },
984    );
985}
986
987impl From<i32> for SendPropValue {
988    fn from(value: i32) -> Self {
989        SendPropValue::Integer(value as i64)
990    }
991}
992
993impl From<i64> for SendPropValue {
994    fn from(value: i64) -> Self {
995        SendPropValue::Integer(value)
996    }
997}
998
999impl From<Vector> for SendPropValue {
1000    fn from(value: Vector) -> Self {
1001        SendPropValue::Vector(value)
1002    }
1003}
1004
1005impl From<VectorXY> for SendPropValue {
1006    fn from(value: VectorXY) -> Self {
1007        SendPropValue::VectorXY(value)
1008    }
1009}
1010
1011impl From<f32> for SendPropValue {
1012    fn from(value: f32) -> Self {
1013        SendPropValue::Float(value)
1014    }
1015}
1016
1017impl From<String> for SendPropValue {
1018    fn from(value: String) -> Self {
1019        SendPropValue::String(value)
1020    }
1021}
1022
1023impl From<Vec<SendPropValue>> for SendPropValue {
1024    fn from(value: Vec<SendPropValue>) -> Self {
1025        SendPropValue::Array(value)
1026    }
1027}
1028
1029impl TryFrom<&SendPropValue> for i64 {
1030    type Error = MalformedSendPropDefinitionError;
1031    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1032        match value {
1033            SendPropValue::Integer(val) => Ok(*val),
1034            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1035                expected: "integer",
1036                value: value.clone(),
1037            }),
1038        }
1039    }
1040}
1041
1042impl TryFrom<&SendPropValue> for bool {
1043    type Error = MalformedSendPropDefinitionError;
1044    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1045        match value {
1046            SendPropValue::Integer(val) => Ok(*val > 0),
1047            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1048                expected: "boolean",
1049                value: value.clone(),
1050            }),
1051        }
1052    }
1053}
1054
1055impl TryFrom<&SendPropValue> for Vector {
1056    type Error = MalformedSendPropDefinitionError;
1057    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1058        match value {
1059            SendPropValue::Vector(val) => Ok(*val),
1060            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1061                expected: "vector",
1062                value: value.clone(),
1063            }),
1064        }
1065    }
1066}
1067
1068impl TryFrom<&SendPropValue> for VectorXY {
1069    type Error = MalformedSendPropDefinitionError;
1070    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1071        match value {
1072            SendPropValue::VectorXY(val) => Ok(*val),
1073            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1074                expected: "vectorxy",
1075                value: value.clone(),
1076            }),
1077        }
1078    }
1079}
1080
1081impl TryFrom<&SendPropValue> for f32 {
1082    type Error = MalformedSendPropDefinitionError;
1083    fn try_from(value: &SendPropValue) -> std::result::Result<Self, Self::Error> {
1084        match value {
1085            SendPropValue::Float(val) => Ok(*val),
1086            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1087                expected: "float",
1088                value: value.clone(),
1089            }),
1090        }
1091    }
1092}
1093
1094impl<'a> TryFrom<&'a SendPropValue> for &'a str {
1095    type Error = MalformedSendPropDefinitionError;
1096    fn try_from(value: &'a SendPropValue) -> std::result::Result<Self, Self::Error> {
1097        match value {
1098            SendPropValue::String(val) => Ok(val.as_str()),
1099            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1100                expected: "string",
1101                value: value.clone(),
1102            }),
1103        }
1104    }
1105}
1106
1107impl<'a> TryFrom<&'a SendPropValue> for &'a [SendPropValue] {
1108    type Error = MalformedSendPropDefinitionError;
1109    fn try_from(value: &'a SendPropValue) -> std::result::Result<Self, Self::Error> {
1110        match value {
1111            SendPropValue::Array(val) => Ok(val.as_slice()),
1112            _ => Err(MalformedSendPropDefinitionError::WrongPropType {
1113                expected: "array",
1114                value: value.clone(),
1115            }),
1116        }
1117    }
1118}
1119
1120#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
1121pub struct SendPropIdentifier(u64);
1122
1123impl SendPropIdentifier {
1124    pub const fn new(table: &str, prop: &str) -> Self {
1125        let hasher = ConstFnvHash::new().push_string(table).push_string(prop);
1126        SendPropIdentifier(hasher.finish())
1127    }
1128
1129    /// Construct a SendPropIdentifier from a u64; like std::convert::From<u64> but marked as
1130    /// const.
1131    pub const fn from_const(raw: u64) -> Self {
1132        SendPropIdentifier(raw)
1133    }
1134
1135    /// This returns an option because only props known at compile time will return a name here
1136    ///
1137    /// If you need to know the name of every property you need to keep a map yourself
1138    pub fn table_name(&self) -> Option<SendTableName> {
1139        get_prop_names(*self).map(|(table, _)| table.into())
1140    }
1141
1142    /// This returns an option because only props known at compile time will return a name here
1143    ///
1144    /// If you need to know the name of every property you need to keep a map yourself
1145    pub fn prop_name(&self) -> Option<SendPropName> {
1146        get_prop_names(*self).map(|(_, prop)| prop.into())
1147    }
1148
1149    /// This returns an option because only props known at compile time will return a name here
1150    ///
1151    /// If you need to know the name of every property you need to keep a map yourself
1152    pub fn names(&self) -> Option<(SendTableName, SendPropName)> {
1153        get_prop_names(*self).map(|(table, prop)| (table.into(), prop.into()))
1154    }
1155}
1156
1157impl From<u64> for SendPropIdentifier {
1158    fn from(raw: u64) -> Self {
1159        SendPropIdentifier(raw)
1160    }
1161}
1162
1163impl From<SendPropIdentifier> for u64 {
1164    fn from(identifier: SendPropIdentifier) -> Self {
1165        identifier.0
1166    }
1167}
1168
1169impl Display for SendPropIdentifier {
1170    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1171        match get_prop_names(*self) {
1172            Some((table, prop)) => write!(f, "{}.{}", table, prop),
1173            None => write!(f, "Prop name {} not known", self.0),
1174        }
1175    }
1176}
1177
1178impl<'de> Deserialize<'de> for SendPropIdentifier {
1179    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
1180    where
1181        D: Deserializer<'de>,
1182    {
1183        #[derive(Deserialize)]
1184        #[serde(untagged)]
1185        enum Options<'a> {
1186            Num(u64),
1187            Str(Cow<'a, str>),
1188        }
1189
1190        let raw = Options::deserialize(deserializer)?;
1191        Ok(match raw {
1192            Options::Num(num) => SendPropIdentifier(num),
1193            Options::Str(s) => {
1194                let num: u64 = s.parse().map_err(D::Error::custom)?;
1195                SendPropIdentifier(num)
1196            }
1197        })
1198    }
1199}
1200
1201impl Serialize for SendPropIdentifier {
1202    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1203    where
1204        S: Serializer,
1205    {
1206        self.0.to_string().serialize(serializer)
1207    }
1208}
1209
1210#[cfg(feature = "schema")]
1211impl schemars::JsonSchema for SendPropIdentifier {
1212    fn schema_name() -> String {
1213        "SendPropIdentifier".into()
1214    }
1215
1216    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1217        <String as schemars::JsonSchema>::json_schema(gen)
1218    }
1219}
1220
1221#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
1222#[derive(Clone, Display, PartialEq, Serialize, Deserialize)]
1223#[display("{index} = {value}")]
1224pub struct SendProp {
1225    pub index: u32,
1226    pub identifier: SendPropIdentifier,
1227    pub value: SendPropValue,
1228}
1229
1230impl Debug for SendProp {
1231    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1232        write!(f, "{} = {}", self.identifier, self.value)
1233    }
1234}
1235
1236pub fn read_var_int(stream: &mut Stream, signed: bool) -> ReadResult<i32> {
1237    let abs_int = crate::demo::message::stringtable::read_var_int(stream)? as i32;
1238
1239    if signed {
1240        Ok((abs_int >> 1) ^ -(abs_int & 1))
1241    } else {
1242        Ok(abs_int)
1243    }
1244}
1245
1246pub fn write_var_int(
1247    int: i32,
1248    stream: &mut BitWriteStream<LittleEndian>,
1249    signed: bool,
1250) -> ReadResult<()> {
1251    let abs = if signed {
1252        let int = (int << 1) ^ (int >> 31);
1253        u32::from_le_bytes(int.to_le_bytes())
1254    } else {
1255        int as u32
1256    };
1257
1258    crate::demo::message::stringtable::write_var_int(abs, stream)
1259}
1260
1261#[test]
1262fn test_var_int_roundtrip() {
1263    use bitbuffer::{BitReadBuffer, BitReadStream};
1264
1265    fn var_int_roundtrip(int: i32, signed: bool) {
1266        let mut data = Vec::new();
1267        let pos = {
1268            let mut write = BitWriteStream::new(&mut data, LittleEndian);
1269            write_var_int(int, &mut write, signed).unwrap();
1270            write.bit_len()
1271        };
1272        let mut read = BitReadStream::new(BitReadBuffer::new(&data, LittleEndian));
1273        assert_eq!(int, read_var_int(&mut read, signed).unwrap());
1274        assert_eq!(pos, read.pos());
1275    }
1276    var_int_roundtrip(0, false);
1277    var_int_roundtrip(1, false);
1278    var_int_roundtrip(10, false);
1279    var_int_roundtrip(55, false);
1280    var_int_roundtrip(355, false);
1281    var_int_roundtrip(12354, false);
1282    var_int_roundtrip(123125412, false);
1283
1284    var_int_roundtrip(0, true);
1285    var_int_roundtrip(1, true);
1286    var_int_roundtrip(10, true);
1287    var_int_roundtrip(55, true);
1288    var_int_roundtrip(355, true);
1289    var_int_roundtrip(12354, true);
1290    var_int_roundtrip(123125412, true);
1291    var_int_roundtrip(-0, true);
1292    var_int_roundtrip(-1, true);
1293    var_int_roundtrip(-10, true);
1294    var_int_roundtrip(-55, true);
1295    var_int_roundtrip(-355, true);
1296    var_int_roundtrip(-12354, true);
1297    var_int_roundtrip(-123125412, true);
1298}
1299
1300pub fn read_bit_coord(stream: &mut Stream) -> ReadResult<f32> {
1301    let has_int = stream.read()?;
1302    let has_frac = stream.read()?;
1303
1304    Ok(if has_int || has_frac {
1305        let sign = if stream.read()? { -1f32 } else { 1f32 };
1306        let int_val: u16 = if has_int {
1307            stream.read_sized::<u16>(14)? + 1
1308        } else {
1309            0
1310        };
1311        let frac_val: u8 = if has_frac { stream.read_sized(5)? } else { 0 };
1312        let value = int_val as f32 + (frac_val as f32 * get_frac_factor(5));
1313        value * sign
1314    } else {
1315        0f32
1316    })
1317}
1318
1319pub fn write_bit_coord(val: f32, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
1320    let has_int = val.abs() >= 1.0;
1321    has_int.write(stream)?;
1322    let has_frac = val.fract() != 0.0;
1323    has_frac.write(stream)?;
1324
1325    if has_frac || has_int {
1326        let sign = val.is_negative();
1327        sign.write(stream)?;
1328    }
1329    let abs = val.abs();
1330    if has_int {
1331        (abs as u16 - 1).write_sized(stream, 14)?;
1332    }
1333    if has_frac {
1334        let frac_val = (abs.fract() / get_frac_factor(5)) as u8;
1335        frac_val.write_sized(stream, 5)?;
1336    }
1337    Ok(())
1338}
1339
1340#[test]
1341fn bit_coord_roundtrip() {
1342    use bitbuffer::BitReadBuffer;
1343
1344    let mut data = Vec::with_capacity(16);
1345    let (pos1, pos2, pos3, pos4) = {
1346        let mut write = BitWriteStream::new(&mut data, LittleEndian);
1347        write_bit_coord(0.0, &mut write).unwrap();
1348        let pos1 = write.bit_len();
1349        write_bit_coord(123.0, &mut write).unwrap();
1350        let pos2 = write.bit_len();
1351        write_bit_coord(123.4375, &mut write).unwrap();
1352        let pos3 = write.bit_len();
1353        write_bit_coord(-0.4375, &mut write).unwrap();
1354        let pos4 = write.bit_len();
1355        (pos1, pos2, pos3, pos4)
1356    };
1357
1358    let mut read = Stream::from(BitReadBuffer::new(&data, LittleEndian));
1359    assert_eq!(0.0, read_bit_coord(&mut read).unwrap());
1360    assert_eq!(pos1, read.pos());
1361    assert_eq!(123.0, read_bit_coord(&mut read).unwrap());
1362    assert_eq!(pos2, read.pos());
1363    assert_eq!(123.4375, read_bit_coord(&mut read).unwrap());
1364    assert_eq!(pos3, read.pos());
1365    assert_eq!(-0.4375, read_bit_coord(&mut read).unwrap());
1366    assert_eq!(pos4, read.pos());
1367}
1368
1369fn get_frac_factor(bits: usize) -> f32 {
1370    1.0 / ((1 << bits) as f32)
1371}
1372
1373pub fn read_bit_coord_mp(
1374    stream: &mut Stream,
1375    is_integral: bool,
1376    low_precision: bool,
1377) -> ReadResult<f32> {
1378    let mut value = 0.0;
1379    let mut is_negative = false;
1380
1381    let in_bounds = stream.read()?;
1382    let has_int_val = stream.read()?;
1383
1384    if is_integral {
1385        if has_int_val {
1386            is_negative = stream.read()?;
1387
1388            let int_val = stream.read_sized::<u32>(if in_bounds { 11 } else { 14 })? + 1;
1389            value = int_val as f32;
1390        }
1391    } else {
1392        is_negative = stream.read()?;
1393        if has_int_val {
1394            let int_val = stream.read_sized::<u32>(if in_bounds { 11 } else { 14 })? + 1;
1395            value = int_val as f32;
1396        }
1397        let frac_bits = if low_precision { 3 } else { 5 };
1398        let frac_val: u32 = stream.read_sized(frac_bits)?;
1399        value += (frac_val as f32) * get_frac_factor(frac_bits);
1400    }
1401
1402    if is_negative {
1403        value = -value;
1404    }
1405
1406    Ok(value)
1407}
1408
1409pub fn write_bit_coord_mp(
1410    val: f32,
1411    stream: &mut BitWriteStream<LittleEndian>,
1412    is_integral: bool,
1413    low_precision: bool,
1414) -> ReadResult<()> {
1415    let abs = val.abs();
1416    let in_bounds = (abs as u32) < (1 << 11);
1417    let has_int_val = abs >= 1.0;
1418    in_bounds.write(stream)?;
1419    has_int_val.write(stream)?;
1420
1421    if is_integral {
1422        if has_int_val {
1423            val.is_sign_negative().write(stream)?;
1424            ((abs - 1.0) as u32).write_sized(stream, if in_bounds { 11 } else { 14 })?;
1425        }
1426    } else {
1427        val.is_sign_negative().write(stream)?;
1428        if has_int_val {
1429            ((abs - 1.0) as u32).write_sized(stream, if in_bounds { 11 } else { 14 })?;
1430        }
1431        let frac_bits = if low_precision { 3 } else { 5 };
1432        let frac_val = (abs.fract() / get_frac_factor(frac_bits)) as u32;
1433        frac_val.write_sized(stream, frac_bits)?;
1434    }
1435
1436    Ok(())
1437}
1438
1439#[test]
1440fn test_bit_coord_mp_roundtrip() {
1441    use bitbuffer::{BitReadBuffer, BitReadStream};
1442
1443    fn bit_coord_mp_normal(val: f32, is_integral: bool, low_precision: bool) {
1444        let mut data = Vec::with_capacity(16);
1445        let pos = {
1446            let mut write = BitWriteStream::new(&mut data, LittleEndian);
1447            write_bit_coord_mp(val, &mut write, is_integral, low_precision).unwrap();
1448            write.bit_len()
1449        };
1450        let mut read = BitReadStream::new(BitReadBuffer::new(&data, LittleEndian));
1451        assert_eq!(
1452            val,
1453            read_bit_coord_mp(&mut read, is_integral, low_precision).unwrap()
1454        );
1455        assert_eq!(pos, read.pos());
1456    }
1457
1458    bit_coord_mp_normal(1.0, false, false);
1459
1460    bit_coord_mp_normal(0.0, false, false);
1461    bit_coord_mp_normal(0.5, false, false);
1462    bit_coord_mp_normal(-0.5, false, false);
1463    bit_coord_mp_normal(1234.5, false, false);
1464    bit_coord_mp_normal(-1234.5, false, false);
1465    bit_coord_mp_normal(2.0f32.powf(12.0) + 0.125, false, false);
1466
1467    bit_coord_mp_normal(0.0, false, true);
1468    bit_coord_mp_normal(0.5, false, true);
1469    bit_coord_mp_normal(-0.5, false, true);
1470    bit_coord_mp_normal(1234.5, false, true);
1471    bit_coord_mp_normal(-1234.5, false, true);
1472    bit_coord_mp_normal(2.0f32.powf(12.0) + 0.125, false, true);
1473
1474    bit_coord_mp_normal(0.0, true, false);
1475    bit_coord_mp_normal(1234.0, true, false);
1476    bit_coord_mp_normal(-1234.0, true, false);
1477    bit_coord_mp_normal(2.0f32.powf(12.0), true, false);
1478}
1479
1480pub fn read_bit_normal(stream: &mut Stream) -> ReadResult<f32> {
1481    let is_negative = stream.read()?;
1482    let frac_val: u16 = stream.read_sized(11)?;
1483    let value = (frac_val as f32) * get_frac_factor(11);
1484    if is_negative {
1485        Ok(-value)
1486    } else {
1487        Ok(value)
1488    }
1489}
1490
1491pub fn write_bit_normal(val: f32, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
1492    val.is_sign_negative().write(stream)?;
1493    let frac_val = (val.abs().fract() / get_frac_factor(11)) as u16;
1494    frac_val.write_sized(stream, 11)
1495}
1496
1497#[test]
1498fn test_bit_normal_roundtrip() {
1499    use bitbuffer::{BitReadBuffer, BitReadStream};
1500
1501    fn roundtrip_normal(val: f32) {
1502        let mut data = Vec::with_capacity(16);
1503        let pos = {
1504            let mut write = BitWriteStream::new(&mut data, LittleEndian);
1505            write_bit_normal(val, &mut write).unwrap();
1506            write.bit_len()
1507        };
1508        let mut read = BitReadStream::new(BitReadBuffer::new(&data, LittleEndian));
1509        assert_eq!(val, read_bit_normal(&mut read).unwrap());
1510        assert_eq!(pos, read.pos());
1511    }
1512    roundtrip_normal(0.0);
1513    roundtrip_normal(-0.0);
1514    roundtrip_normal(0.5);
1515    roundtrip_normal(-0.5);
1516}