mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 10:14:06 +02:00
game event writing
This commit is contained in:
parent
5573ec5db2
commit
a55217cc55
11 changed files with 1021 additions and 844 deletions
804
codegen/out.rs
804
codegen/out.rs
File diff suppressed because it is too large
Load diff
|
|
@ -239,7 +239,7 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
||||||
quote!(pub #name: #ty,)
|
quote!(pub #name: #ty,)
|
||||||
});
|
});
|
||||||
|
|
||||||
let name = Ident::new(&format!("{}Event", get_event_name(&event.name)), span);
|
let name = Ident::new(&format!("{}Event", get_event_name(event.event_type.as_str())), span);
|
||||||
|
|
||||||
let entry_readers = event.entries.iter().map(|entry| {
|
let entry_readers = event.entries.iter().map(|entry| {
|
||||||
let name_str = get_entry_name(&entry.name);
|
let name_str = get_entry_name(&entry.name);
|
||||||
|
|
@ -260,7 +260,7 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
#[derive(Debug, BitWrite)]
|
#[derive(Debug, BitWrite, PartialEq)]
|
||||||
pub struct #name {
|
pub struct #name {
|
||||||
#(#fields)*
|
#(#fields)*
|
||||||
}
|
}
|
||||||
|
|
@ -279,7 +279,7 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
let event_variants = events.iter().map(|event| {
|
let event_variants = events.iter().map(|event| {
|
||||||
let name_str = get_event_name(&event.name);
|
let name_str = get_event_name(event.event_type.as_str());
|
||||||
let name = Ident::new(&name_str, span);
|
let name = Ident::new(&name_str, span);
|
||||||
let struct_name = Ident::new(&format!("{}Event", name_str), span);
|
let struct_name = Ident::new(&format!("{}Event", name_str), span);
|
||||||
|
|
||||||
|
|
@ -291,7 +291,7 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
let event_types = events.iter().map(|event| {
|
let event_types = events.iter().map(|event| {
|
||||||
let name_str = get_event_name(&event.name);
|
let name_str = get_event_name(event.event_type.as_str());
|
||||||
let name = Ident::new(&name_str, span);
|
let name = Ident::new(&name_str, span);
|
||||||
let id = Literal::u16_unsuffixed(event.id.into());
|
let id = Literal::u16_unsuffixed(event.id.into());
|
||||||
|
|
||||||
|
|
@ -299,21 +299,21 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
let type_from_names = events.iter().map(|event| {
|
let type_from_names = events.iter().map(|event| {
|
||||||
let name_str = &event.name;
|
let name_str = event.event_type.as_str();
|
||||||
let variant_name = Ident::new(&get_event_name(&name_str), span);
|
let variant_name = Ident::new(&get_event_name(&name_str), span);
|
||||||
|
|
||||||
quote!(#name_str => GameEventType::#variant_name,)
|
quote!(#name_str => GameEventType::#variant_name,)
|
||||||
});
|
});
|
||||||
|
|
||||||
let type_to_names = events.iter().map(|event| {
|
let type_to_names = events.iter().map(|event| {
|
||||||
let name_str = &event.name;
|
let name_str = event.event_type.as_str();
|
||||||
let variant_name = Ident::new(&get_event_name(&name_str), span);
|
let variant_name = Ident::new(&get_event_name(&name_str), span);
|
||||||
|
|
||||||
quote!(GameEventType::#variant_name => #name_str,)
|
quote!(GameEventType::#variant_name => #name_str,)
|
||||||
});
|
});
|
||||||
|
|
||||||
let read_events = events.iter().map(|event| {
|
let read_events = events.iter().map(|event| {
|
||||||
let name = get_event_name(&event.name);
|
let name = get_event_name(event.event_type.as_str());
|
||||||
let variant_name = Ident::new(&name, span);
|
let variant_name = Ident::new(&name, span);
|
||||||
let struct_name = Ident::new(&format!("{}Event", name), span);
|
let struct_name = Ident::new(&format!("{}Event", name), span);
|
||||||
|
|
||||||
|
|
@ -333,7 +333,7 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
let write_events = events.iter().map(|event| {
|
let write_events = events.iter().map(|event| {
|
||||||
let name = get_event_name(&event.name);
|
let name = get_event_name(event.event_type.as_str());
|
||||||
let variant_name = Ident::new(&name, span);
|
let variant_name = Ident::new(&name, span);
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
|
|
@ -342,7 +342,7 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
let sizes = events.iter().map(|event| {
|
let sizes = events.iter().map(|event| {
|
||||||
let name = get_event_name(&event.name);
|
let name = get_event_name(event.event_type.as_str());
|
||||||
let struct_name = Ident::new(&format!("{}Event", name), span);
|
let struct_name = Ident::new(&format!("{}Event", name), span);
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
|
|
@ -376,7 +376,7 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
||||||
|
|
||||||
#(#event_definitions)*
|
#(#event_definitions)*
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum GameEvent {
|
pub enum GameEvent {
|
||||||
#(#event_variants)*
|
#(#event_variants)*
|
||||||
Unknown(RawGameEvent),
|
Unknown(RawGameEvent),
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -12,7 +12,6 @@ use std::cmp::Ordering;
|
||||||
pub struct GameEventDefinition {
|
pub struct GameEventDefinition {
|
||||||
pub id: GameEventTypeId,
|
pub id: GameEventTypeId,
|
||||||
pub event_type: GameEventType,
|
pub event_type: GameEventType,
|
||||||
pub name: String,
|
|
||||||
pub entries: Vec<GameEventEntry>,
|
pub entries: Vec<GameEventEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,7 +35,7 @@ impl Ord for GameEventDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct GameEventEntry {
|
pub struct GameEventEntry {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub kind: GameEventValueType,
|
pub kind: GameEventValueType,
|
||||||
|
|
@ -55,7 +54,7 @@ pub enum GameEventValueType {
|
||||||
Local = 7,
|
Local = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum GameEventValue {
|
pub enum GameEventValue {
|
||||||
String(String),
|
String(String),
|
||||||
Float(f32),
|
Float(f32),
|
||||||
|
|
@ -155,7 +154,7 @@ impl EventValue for () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct RawGameEvent {
|
pub struct RawGameEvent {
|
||||||
pub event_type: GameEventType,
|
pub event_type: GameEventType,
|
||||||
pub values: Vec<GameEventValue>,
|
pub values: Vec<GameEventValue>,
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,14 @@ impl BitWrite<LittleEndian> for BSPDecalMessage {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decal_roundtrip() {
|
fn test_decal_roundtrip() {
|
||||||
crate::test_roundtrip_encode(BSPDecalMessage {
|
crate::test_roundtrip_write(BSPDecalMessage {
|
||||||
position: Vector::default(),
|
position: Vector::default(),
|
||||||
texture_index: 0,
|
texture_index: 0,
|
||||||
ent_index: 0,
|
ent_index: 0,
|
||||||
model_index: 0,
|
model_index: 0,
|
||||||
low_priority: false,
|
low_priority: false,
|
||||||
});
|
});
|
||||||
crate::test_roundtrip_encode(BSPDecalMessage {
|
crate::test_roundtrip_write(BSPDecalMessage {
|
||||||
position: Vector {
|
position: Vector {
|
||||||
x: 1.0,
|
x: 1.0,
|
||||||
y: 0.5,
|
y: 0.5,
|
||||||
|
|
|
||||||
|
|
@ -59,12 +59,12 @@ impl BitWrite<LittleEndian> for ClassInfoMessage {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_say_text2_roundtrip() {
|
fn test_say_text2_roundtrip() {
|
||||||
crate::test_roundtrip_encode(ClassInfoMessage {
|
crate::test_roundtrip_write(ClassInfoMessage {
|
||||||
count: 8,
|
count: 8,
|
||||||
create: true,
|
create: true,
|
||||||
entries: Vec::new(),
|
entries: Vec::new(),
|
||||||
});
|
});
|
||||||
crate::test_roundtrip_encode(ClassInfoMessage {
|
crate::test_roundtrip_write(ClassInfoMessage {
|
||||||
count: 3,
|
count: 3,
|
||||||
create: false,
|
create: false,
|
||||||
entries: vec![
|
entries: vec![
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
|
||||||
use parse_display::Display;
|
use parse_display::Display;
|
||||||
|
|
||||||
use crate::demo::gameevent_gen::GameEventType;
|
use crate::demo::gameevent_gen::GameEventType;
|
||||||
|
|
@ -8,8 +8,9 @@ use crate::demo::gamevent::{
|
||||||
use crate::demo::parser::{Encode, ParseBitSkip};
|
use crate::demo::parser::{Encode, ParseBitSkip};
|
||||||
use crate::{GameEventError, Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{GameEventError, Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct GameEventMessage {
|
pub struct GameEventMessage {
|
||||||
|
pub event_type_id: GameEventTypeId,
|
||||||
pub event: GameEvent,
|
pub event: GameEvent,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17,11 +18,12 @@ impl Parse<'_> for GameEventMessage {
|
||||||
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
|
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
|
||||||
let length: u16 = stream.read_sized(11)?;
|
let length: u16 = stream.read_sized(11)?;
|
||||||
let mut data = stream.read_bits(length as usize)?;
|
let mut data = stream.read_bits(length as usize)?;
|
||||||
let event_type: GameEventTypeId = data.read()?;
|
let event_type_id: GameEventTypeId = data.read()?;
|
||||||
|
|
||||||
// game event definitions haven't been sent yet, ignore
|
// game event definitions haven't been sent yet, ignore
|
||||||
if state.event_definitions.is_empty() {
|
if state.event_definitions.is_empty() {
|
||||||
return Ok(GameEventMessage {
|
return Ok(GameEventMessage {
|
||||||
|
event_type_id,
|
||||||
event: GameEvent::Unknown(RawGameEvent {
|
event: GameEvent::Unknown(RawGameEvent {
|
||||||
event_type: GameEventType::Unknown,
|
event_type: GameEventType::Unknown,
|
||||||
values: Vec::new(),
|
values: Vec::new(),
|
||||||
|
|
@ -29,15 +31,18 @@ impl Parse<'_> for GameEventMessage {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let event = match state.event_definitions.get(usize::from(event_type)) {
|
let event = match state.event_definitions.get(usize::from(event_type_id)) {
|
||||||
Some(definition) => GameEvent::read(&mut data, definition)?,
|
Some(definition) => GameEvent::read(&mut data, definition)?,
|
||||||
None => {
|
None => {
|
||||||
return Err(ParseError::MalformedGameEvent(GameEventError::UnknownType(
|
return Err(ParseError::MalformedGameEvent(GameEventError::UnknownType(
|
||||||
event_type,
|
event_type_id,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(GameEventMessage { event })
|
Ok(GameEventMessage {
|
||||||
|
event_type_id,
|
||||||
|
event,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,10 +52,61 @@ impl Encode for GameEventMessage {
|
||||||
stream: &mut BitWriteStream<LittleEndian>,
|
stream: &mut BitWriteStream<LittleEndian>,
|
||||||
_state: &ParserState,
|
_state: &ParserState,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Ok(stream.reserve_length(11, |_stream| Ok(()))?)
|
Ok(stream.reserve_length(11, |stream| {
|
||||||
|
self.event_type_id.write(stream)?;
|
||||||
|
self.event.write(stream)
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_game_event_roundtrip() {
|
||||||
|
use crate::demo::gameevent_gen::{GameInitEvent, ServerShutdownEvent};
|
||||||
|
|
||||||
|
let definitions = vec![
|
||||||
|
GameEventDefinition {
|
||||||
|
id: GameEventTypeId(0),
|
||||||
|
event_type: GameEventType::ServerShutdown,
|
||||||
|
entries: vec![GameEventEntry {
|
||||||
|
name: "reason".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
GameEventDefinition {
|
||||||
|
id: GameEventTypeId(1),
|
||||||
|
event_type: GameEventType::ServerChangeLevelFailed,
|
||||||
|
entries: vec![GameEventEntry {
|
||||||
|
name: "level_name".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
GameEventDefinition {
|
||||||
|
id: GameEventTypeId(2),
|
||||||
|
event_type: GameEventType::GameInit,
|
||||||
|
entries: vec![],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let mut state = ParserState::new(|_| false, false);
|
||||||
|
state.event_definitions = definitions;
|
||||||
|
|
||||||
|
crate::test_roundtrip_encode(
|
||||||
|
GameEventMessage {
|
||||||
|
event_type_id: GameEventTypeId(0),
|
||||||
|
event: GameEvent::ServerShutdown(ServerShutdownEvent {
|
||||||
|
reason: "asd".into(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
&state,
|
||||||
|
);
|
||||||
|
crate::test_roundtrip_encode(
|
||||||
|
GameEventMessage {
|
||||||
|
event_type_id: GameEventTypeId(2),
|
||||||
|
event: GameEvent::GameInit(GameInitEvent {}),
|
||||||
|
},
|
||||||
|
&state,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
impl ParseBitSkip<'_> for GameEventMessage {
|
impl ParseBitSkip<'_> for GameEventMessage {
|
||||||
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
||||||
let length: u16 = stream.read_sized(11)?;
|
let length: u16 = stream.read_sized(11)?;
|
||||||
|
|
@ -73,7 +129,7 @@ impl From<GameEventTypeId> for u16 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct GameEventListMessage {
|
pub struct GameEventListMessage {
|
||||||
pub event_list: Vec<GameEventDefinition>,
|
pub event_list: Vec<GameEventDefinition>,
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +153,6 @@ impl BitRead<'_, LittleEndian> for GameEventDefinition {
|
||||||
Ok(GameEventDefinition {
|
Ok(GameEventDefinition {
|
||||||
id: event_type,
|
id: event_type,
|
||||||
event_type: GameEventType::from_type_name(name.as_str()),
|
event_type: GameEventType::from_type_name(name.as_str()),
|
||||||
name,
|
|
||||||
entries,
|
entries,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +162,6 @@ impl BitWrite<LittleEndian> for GameEventDefinition {
|
||||||
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
||||||
self.id.write(stream)?;
|
self.id.write(stream)?;
|
||||||
self.event_type.as_str().write(stream)?;
|
self.event_type.as_str().write(stream)?;
|
||||||
self.name.write(stream)?;
|
|
||||||
|
|
||||||
for entry in self.entries.iter() {
|
for entry in self.entries.iter() {
|
||||||
entry.kind.write(stream)?;
|
entry.kind.write(stream)?;
|
||||||
|
|
@ -119,6 +173,18 @@ impl BitWrite<LittleEndian> for GameEventDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_event_definition_roundtrip() {
|
||||||
|
crate::test_roundtrip_write(GameEventDefinition {
|
||||||
|
id: GameEventTypeId(0),
|
||||||
|
event_type: GameEventType::ServerChangeLevelFailed,
|
||||||
|
entries: vec![GameEventEntry {
|
||||||
|
name: "level_name".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
impl BitRead<'_, LittleEndian> for GameEventListMessage {
|
impl BitRead<'_, LittleEndian> for GameEventListMessage {
|
||||||
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
||||||
let count: u16 = stream.read_sized(9)?;
|
let count: u16 = stream.read_sized(9)?;
|
||||||
|
|
@ -132,7 +198,7 @@ impl BitRead<'_, LittleEndian> for GameEventListMessage {
|
||||||
|
|
||||||
impl BitWrite<LittleEndian> for GameEventListMessage {
|
impl BitWrite<LittleEndian> for GameEventListMessage {
|
||||||
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
|
||||||
(self.event_list.len() as u16).write(stream)?;
|
(self.event_list.len() as u16).write_sized(stream, 9)?;
|
||||||
stream.reserve_length(20, |stream| {
|
stream.reserve_length(20, |stream| {
|
||||||
for event in self.event_list.iter() {
|
for event in self.event_list.iter() {
|
||||||
event.write(stream)?;
|
event.write(stream)?;
|
||||||
|
|
@ -143,3 +209,81 @@ impl BitWrite<LittleEndian> for GameEventListMessage {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_event_list_roundtrip() {
|
||||||
|
crate::test_roundtrip_write(GameEventListMessage { event_list: vec![] });
|
||||||
|
crate::test_roundtrip_write(GameEventListMessage {
|
||||||
|
event_list: vec![GameEventDefinition {
|
||||||
|
id: GameEventTypeId(0),
|
||||||
|
event_type: GameEventType::ServerChangeLevelFailed,
|
||||||
|
entries: vec![GameEventEntry {
|
||||||
|
name: "level_name".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
crate::test_roundtrip_write(GameEventListMessage {
|
||||||
|
event_list: vec![
|
||||||
|
GameEventDefinition {
|
||||||
|
id: GameEventTypeId(0),
|
||||||
|
event_type: GameEventType::ServerSpawn,
|
||||||
|
entries: vec![
|
||||||
|
GameEventEntry {
|
||||||
|
name: "hostname".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "address".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "ip".to_string(),
|
||||||
|
kind: GameEventValueType::Long,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "port".to_string(),
|
||||||
|
kind: GameEventValueType::Short,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "game".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "map_name".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "max_players".to_string(),
|
||||||
|
kind: GameEventValueType::Long,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "os".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "dedicated".to_string(),
|
||||||
|
kind: GameEventValueType::Boolean,
|
||||||
|
},
|
||||||
|
GameEventEntry {
|
||||||
|
name: "password".to_string(),
|
||||||
|
kind: GameEventValueType::Boolean,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
GameEventDefinition {
|
||||||
|
id: GameEventTypeId(1),
|
||||||
|
event_type: GameEventType::ServerChangeLevelFailed,
|
||||||
|
entries: vec![GameEventEntry {
|
||||||
|
name: "level_name".to_string(),
|
||||||
|
kind: GameEventValueType::String,
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
GameEventDefinition {
|
||||||
|
id: GameEventTypeId(2),
|
||||||
|
event_type: GameEventType::GameInit,
|
||||||
|
entries: vec![],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,8 @@ impl<'a> BitWrite<LittleEndian> for UserMessage<'a> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_user_message_roundtrip() {
|
fn test_user_message_roundtrip() {
|
||||||
crate::test_roundtrip_encode(UserMessage::Train(TrainMessage { data: 12 }));
|
crate::test_roundtrip_write(UserMessage::Train(TrainMessage { data: 12 }));
|
||||||
crate::test_roundtrip_encode(UserMessage::SayText2(Box::new(SayText2Message {
|
crate::test_roundtrip_write(UserMessage::SayText2(Box::new(SayText2Message {
|
||||||
client: 3,
|
client: 3,
|
||||||
raw: 1,
|
raw: 1,
|
||||||
kind: ChatMessageKind::ChatTeamDead,
|
kind: ChatMessageKind::ChatTeamDead,
|
||||||
|
|
@ -297,7 +297,7 @@ impl BitWrite<LittleEndian> for SayText2Message {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_say_text2_roundtrip() {
|
fn test_say_text2_roundtrip() {
|
||||||
crate::test_roundtrip_encode(SayText2Message {
|
crate::test_roundtrip_write(SayText2Message {
|
||||||
client: 3,
|
client: 3,
|
||||||
raw: 1,
|
raw: 1,
|
||||||
kind: ChatMessageKind::ChatTeamDead,
|
kind: ChatMessageKind::ChatTeamDead,
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,12 @@ impl BitWrite<LittleEndian> for VoiceInitMessage {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_voice_init_roundtrip() {
|
fn test_voice_init_roundtrip() {
|
||||||
crate::test_roundtrip_encode(VoiceInitMessage {
|
crate::test_roundtrip_write(VoiceInitMessage {
|
||||||
codec: "foo".into(),
|
codec: "foo".into(),
|
||||||
quality: 0,
|
quality: 0,
|
||||||
sampling_rate: 0,
|
sampling_rate: 0,
|
||||||
});
|
});
|
||||||
crate::test_roundtrip_encode(VoiceInitMessage {
|
crate::test_roundtrip_write(VoiceInitMessage {
|
||||||
codec: "foo".into(),
|
codec: "foo".into(),
|
||||||
quality: 255,
|
quality: 255,
|
||||||
sampling_rate: 12,
|
sampling_rate: 12,
|
||||||
|
|
@ -119,13 +119,13 @@ fn test_parse_sounds_roundtrip() {
|
||||||
use bitbuffer::BitReadBuffer;
|
use bitbuffer::BitReadBuffer;
|
||||||
let inner = BitReadBuffer::new(&[1, 2, 3, 4, 5, 6], LittleEndian);
|
let inner = BitReadBuffer::new(&[1, 2, 3, 4, 5, 6], LittleEndian);
|
||||||
|
|
||||||
crate::test_roundtrip_encode(ParseSoundsMessage {
|
crate::test_roundtrip_write(ParseSoundsMessage {
|
||||||
reliable: false,
|
reliable: false,
|
||||||
num: 0,
|
num: 0,
|
||||||
length: inner.bit_len() as u16,
|
length: inner.bit_len() as u16,
|
||||||
data: inner.clone().into(),
|
data: inner.clone().into(),
|
||||||
});
|
});
|
||||||
crate::test_roundtrip_encode(ParseSoundsMessage {
|
crate::test_roundtrip_write(ParseSoundsMessage {
|
||||||
reliable: true,
|
reliable: true,
|
||||||
num: 1,
|
num: 1,
|
||||||
length: inner.bit_len() as u16,
|
length: inner.bit_len() as u16,
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,12 @@ impl<E: Endianness> BitWrite<E> for ViewAngles {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_view_angles_roundtrip() {
|
fn test_view_angles_roundtrip() {
|
||||||
crate::test_roundtrip_encode(ViewAngles {
|
crate::test_roundtrip_write(ViewAngles {
|
||||||
origin: (Vector::default(), Vector::default()),
|
origin: (Vector::default(), Vector::default()),
|
||||||
angles: (Vector::default(), Vector::default()),
|
angles: (Vector::default(), Vector::default()),
|
||||||
local_angles: (Vector::default(), Vector::default()),
|
local_angles: (Vector::default(), Vector::default()),
|
||||||
});
|
});
|
||||||
crate::test_roundtrip_encode(ViewAngles {
|
crate::test_roundtrip_write(ViewAngles {
|
||||||
origin: (
|
origin: (
|
||||||
Vector {
|
Vector {
|
||||||
x: 1.0,
|
x: 1.0,
|
||||||
|
|
|
||||||
38
src/lib.rs
38
src/lib.rs
|
|
@ -15,7 +15,7 @@ mod nullhasher;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn test_roundtrip_encode<
|
fn test_roundtrip_write<
|
||||||
'a,
|
'a,
|
||||||
T: bitbuffer::BitRead<'a, bitbuffer::LittleEndian>
|
T: bitbuffer::BitRead<'a, bitbuffer::LittleEndian>
|
||||||
+ bitbuffer::BitWrite<bitbuffer::LittleEndian>
|
+ bitbuffer::BitWrite<bitbuffer::LittleEndian>
|
||||||
|
|
@ -41,6 +41,40 @@ fn test_roundtrip_encode<
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pos,
|
pos,
|
||||||
read.pos(),
|
read.pos(),
|
||||||
"Failed to assert that all encoded bytes are used for decoding"
|
"Failed to assert that all encoded bits ({}) are used for decoding ({})",
|
||||||
|
pos,
|
||||||
|
read.pos()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[track_caller]
|
||||||
|
fn test_roundtrip_encode<
|
||||||
|
'a,
|
||||||
|
T: Parse<'a> + crate::demo::parser::Encode + std::fmt::Debug + std::cmp::PartialEq,
|
||||||
|
>(
|
||||||
|
val: T,
|
||||||
|
state: &ParserState,
|
||||||
|
) {
|
||||||
|
let mut data = Vec::with_capacity(128);
|
||||||
|
use bitbuffer::{BitReadBuffer, BitReadStream, BitWriteStream, LittleEndian};
|
||||||
|
let pos = {
|
||||||
|
let mut stream = BitWriteStream::new(&mut data, LittleEndian);
|
||||||
|
val.encode(&mut stream, state).unwrap();
|
||||||
|
stream.bit_len()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut read = BitReadStream::new(BitReadBuffer::new_owned(data, LittleEndian));
|
||||||
|
assert_eq!(
|
||||||
|
val,
|
||||||
|
T::parse(&mut read, state).unwrap(),
|
||||||
|
"Failed to assert the parsed message is equal to the original"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
pos,
|
||||||
|
read.pos(),
|
||||||
|
"Failed to assert that all encoded bits ({}) are used for decoding ({})",
|
||||||
|
pos,
|
||||||
|
read.pos()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue