mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
ParseSendTable write
This commit is contained in:
parent
35b0bb15ee
commit
26e57ca59b
2 changed files with 176 additions and 17 deletions
|
|
@ -1,16 +1,14 @@
|
||||||
use bitbuffer::{BitRead, BitWrite};
|
|
||||||
|
|
||||||
use crate::demo::parser::MalformedSendPropDefinitionError;
|
use crate::demo::parser::MalformedSendPropDefinitionError;
|
||||||
use crate::demo::sendprop::{
|
use crate::demo::sendprop::{
|
||||||
RawSendPropDefinition, SendPropDefinition, SendPropFlag, SendPropIdentifier, SendPropType,
|
RawSendPropDefinition, SendPropDefinition, SendPropFlag, SendPropIdentifier, SendPropType,
|
||||||
};
|
};
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
|
use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::iter::once;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Display, FromStr,
|
BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Display, FromStr,
|
||||||
|
|
@ -80,18 +78,23 @@ impl From<String> for SendTableName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
impl From<&str> for SendTableName {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ParseSendTable {
|
pub struct ParseSendTable {
|
||||||
pub name: SendTableName,
|
pub name: SendTableName,
|
||||||
pub props: Vec<RawSendPropDefinition>,
|
pub props: Vec<RawSendPropDefinition>,
|
||||||
pub needs_decoder: bool,
|
pub needs_decoder: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseSendTable {
|
impl Parse<'_> for ParseSendTable {
|
||||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||||
let needs_decoder = stream.read()?;
|
let needs_decoder = stream.read()?;
|
||||||
let raw_name: String = stream.read()?;
|
let name: SendTableName = stream.read()?;
|
||||||
let name: SendTableName = raw_name.into();
|
|
||||||
let prop_count = stream.read_int(10)?;
|
let prop_count = stream.read_int(10)?;
|
||||||
|
|
||||||
let mut array_element_prop = None;
|
let mut array_element_prop = None;
|
||||||
|
|
@ -123,6 +126,106 @@ impl ParseSendTable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitWrite<LittleEndian> for ParseSendTable {
|
||||||
|
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> bitbuffer::Result<()> {
|
||||||
|
self.needs_decoder.write(stream)?;
|
||||||
|
self.name.write(stream)?;
|
||||||
|
|
||||||
|
let prop_count: u16 = self
|
||||||
|
.props
|
||||||
|
.iter()
|
||||||
|
.map(|prop| match prop.array_property {
|
||||||
|
Some(_) => 2,
|
||||||
|
None => 1,
|
||||||
|
})
|
||||||
|
.sum();
|
||||||
|
prop_count.write_sized(stream, 10)?;
|
||||||
|
|
||||||
|
for prop in self
|
||||||
|
.props
|
||||||
|
.iter()
|
||||||
|
.flat_map(|prop| prop.array_property.as_deref().into_iter().chain(once(prop)))
|
||||||
|
{
|
||||||
|
prop.write(stream)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_send_table_roundtrip() {
|
||||||
|
use crate::demo::sendprop::SendPropFlags;
|
||||||
|
|
||||||
|
let state = ParserState::new(|_| false, false);
|
||||||
|
crate::test_roundtrip_encode(
|
||||||
|
ParseSendTable {
|
||||||
|
name: "foo".into(),
|
||||||
|
props: vec![],
|
||||||
|
needs_decoder: true,
|
||||||
|
},
|
||||||
|
&state,
|
||||||
|
);
|
||||||
|
crate::test_roundtrip_encode(
|
||||||
|
ParseSendTable {
|
||||||
|
name: "table1".into(),
|
||||||
|
props: vec![
|
||||||
|
RawSendPropDefinition {
|
||||||
|
prop_type: SendPropType::Float,
|
||||||
|
name: "prop1".into(),
|
||||||
|
owner_table: "table1".into(),
|
||||||
|
flags: SendPropFlags::default() | SendPropFlag::ChangesOften,
|
||||||
|
table_name: None,
|
||||||
|
low_value: Some(0.0),
|
||||||
|
high_value: Some(128.0),
|
||||||
|
bit_count: Some(10),
|
||||||
|
element_count: None,
|
||||||
|
array_property: None,
|
||||||
|
},
|
||||||
|
RawSendPropDefinition {
|
||||||
|
prop_type: SendPropType::Array,
|
||||||
|
name: "prop2".into(),
|
||||||
|
owner_table: "table1".into(),
|
||||||
|
flags: SendPropFlags::default(),
|
||||||
|
table_name: None,
|
||||||
|
low_value: None,
|
||||||
|
high_value: None,
|
||||||
|
bit_count: None,
|
||||||
|
element_count: Some(10),
|
||||||
|
array_property: Some(Box::new(RawSendPropDefinition {
|
||||||
|
prop_type: SendPropType::Int,
|
||||||
|
name: "prop3".into(),
|
||||||
|
owner_table: "table1".into(),
|
||||||
|
flags: SendPropFlags::default()
|
||||||
|
| SendPropFlag::InsideArray
|
||||||
|
| SendPropFlag::NoScale,
|
||||||
|
table_name: None,
|
||||||
|
low_value: Some(i32::MIN as f32),
|
||||||
|
high_value: Some(i32::MAX as f32),
|
||||||
|
bit_count: Some(32),
|
||||||
|
element_count: None,
|
||||||
|
array_property: None,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
RawSendPropDefinition {
|
||||||
|
prop_type: SendPropType::DataTable,
|
||||||
|
name: "prop1".into(),
|
||||||
|
owner_table: "table1".into(),
|
||||||
|
flags: SendPropFlags::default() | SendPropFlag::Exclude,
|
||||||
|
table_name: Some("table2".into()),
|
||||||
|
low_value: None,
|
||||||
|
high_value: None,
|
||||||
|
bit_count: None,
|
||||||
|
element_count: None,
|
||||||
|
array_property: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
needs_decoder: true,
|
||||||
|
},
|
||||||
|
&state,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
impl ParseSendTable {
|
impl ParseSendTable {
|
||||||
pub fn flatten_props(&self, tables: &[ParseSendTable]) -> Result<Vec<SendPropDefinition>> {
|
pub fn flatten_props(&self, tables: &[ParseSendTable]) -> Result<Vec<SendPropDefinition>> {
|
||||||
let mut flat = Vec::with_capacity(32);
|
let mut flat = Vec::with_capacity(32);
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,22 @@ use std::cmp::min;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::ops::BitOr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
BitRead, PartialEq, Eq, Hash, Debug, Display, Clone, Serialize, Deserialize, Ord, PartialOrd,
|
BitRead,
|
||||||
|
BitWrite,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
Debug,
|
||||||
|
Display,
|
||||||
|
Clone,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
Ord,
|
||||||
|
PartialOrd,
|
||||||
)]
|
)]
|
||||||
pub struct SendPropName(Rc<String>);
|
pub struct SendPropName(Rc<String>);
|
||||||
|
|
||||||
|
|
@ -41,7 +53,13 @@ impl From<String> for SendPropName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
impl From<&str> for SendPropName {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
value.to_string().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct RawSendPropDefinition {
|
pub struct RawSendPropDefinition {
|
||||||
pub prop_type: SendPropType,
|
pub prop_type: SendPropType,
|
||||||
pub name: SendPropName,
|
pub name: SendPropName,
|
||||||
|
|
@ -55,11 +73,11 @@ pub struct RawSendPropDefinition {
|
||||||
pub array_property: Option<Box<RawSendPropDefinition>>,
|
pub array_property: Option<Box<RawSendPropDefinition>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for RawSendPropDefinition {
|
// impl PartialEq for RawSendPropDefinition {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
// fn eq(&self, other: &Self) -> bool {
|
||||||
self.identifier() == other.identifier()
|
// self.identifier() == other.identifier()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl fmt::Display for RawSendPropDefinition {
|
impl fmt::Display for RawSendPropDefinition {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
|
@ -214,7 +232,31 @@ impl RawSendPropDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Copy, Clone, PartialEq, Debug, Display)]
|
impl BitWrite<LittleEndian> for RawSendPropDefinition {
|
||||||
|
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
||||||
|
self.prop_type.write(stream)?;
|
||||||
|
self.name.write(stream)?;
|
||||||
|
self.flags.write(stream)?;
|
||||||
|
|
||||||
|
if let Some(table_name) = self.table_name.as_ref() {
|
||||||
|
table_name.write(stream)?;
|
||||||
|
}
|
||||||
|
if let Some(element_count) = self.element_count {
|
||||||
|
element_count.write_sized(stream, 10)?;
|
||||||
|
}
|
||||||
|
if let (Some(low_value), Some(high_value), Some(bit_count)) =
|
||||||
|
(self.low_value, self.high_value, self.bit_count)
|
||||||
|
{
|
||||||
|
low_value.write(stream)?;
|
||||||
|
high_value.write(stream)?;
|
||||||
|
bit_count.write_sized(stream, 7)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BitRead, BitWrite, Copy, Clone, PartialEq, Debug, Display)]
|
||||||
#[discriminant_bits = 5]
|
#[discriminant_bits = 5]
|
||||||
pub enum SendPropType {
|
pub enum SendPropType {
|
||||||
Int = 0,
|
Int = 0,
|
||||||
|
|
@ -272,9 +314,17 @@ pub enum SendPropFlag {
|
||||||
NormalVarInt = 32,
|
NormalVarInt = 32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Default)]
|
||||||
pub struct SendPropFlags(BitFlags<SendPropFlag>);
|
pub struct SendPropFlags(BitFlags<SendPropFlag>);
|
||||||
|
|
||||||
|
impl BitOr<SendPropFlag> for SendPropFlags {
|
||||||
|
type Output = SendPropFlags;
|
||||||
|
|
||||||
|
fn bitor(self, rhs: SendPropFlag) -> Self::Output {
|
||||||
|
Self(self.0 | rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for SendPropFlags {
|
impl fmt::Display for SendPropFlags {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let debug = format!("{:?}", self.0);
|
let debug = format!("{:?}", self.0);
|
||||||
|
|
@ -304,6 +354,12 @@ impl BitRead<'_, LittleEndian> for SendPropFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitWrite<LittleEndian> for SendPropFlags {
|
||||||
|
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
||||||
|
self.0.bits().write(stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum FloatDefinition {
|
pub enum FloatDefinition {
|
||||||
Coord,
|
Coord,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue