Skip to content

Commit

Permalink
Break: use toml to serialize raw output
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel Perestoronin committed Dec 6, 2022
1 parent 3e586fb commit d931db3
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 166 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ default = []
[dependencies]
anyhow = "1.0.66"
clap = { version = "4.0.29", features = ["derive"] }
hex = { version = "0.4.3", features = ["serde"] }
prost = { version = "0.11.3", default-features = false }
serde = { version = "1.0.149", default-features = false, features = ["derive"] }
serde_json = "1.0.89"
toml = "0.5.9"
wotbreplay-parser = "0.2.0-alpha.5"
53 changes: 31 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ World of Tanks Blitz replay inspector in Rust. Uses [`eigenein/wotbreplay-parser

### Convert known fields into JSON

```shell
wotbreplay-inspector 20221205_1409__zeekrab_A140_ASTRON_REX_105_2308651318200102307.wotbreplay battle-results
```
❯ wotbreplay-inspector 20221205_1409__zeekrab_A140_ASTRON_REX_105_2308651318200102307.wotbreplay battle-results

```json5
{
"timestamp": 1670245795,
"players": [
Expand All @@ -22,8 +25,8 @@ World of Tanks Blitz replay inspector in Rust. Uses [`eigenein/wotbreplay-parser
"nickname": "Roberto_Cadenas_Diaz",
"platoon_id": null,
"team_number": 2,
"clan_tag": "ORUGA"
"clan_tag": "ORUGA",
// ...
```
Note: this ignores any unknown fields.
Expand All @@ -32,24 +35,30 @@ Note: this ignores any unknown fields.
Useful for manual inspection:
```shell
wotbreplay-inspector 20221205_1409__zeekrab_A140_ASTRON_REX_105_2308651318200102307.wotbreplay battle-results --raw
```
❯ wotbreplay-inspector 20221205_1409__zeekrab_A140_ASTRON_REX_105_2308651318200102307.wotbreplay battle-results --raw
# 1: varint
1 = { u64 = 65543, i64 = -32772 }
# 2: varint
2 = { u64 = 1670282196, i64 = 835141098 }
# 3: varint
3 = { u64 = 1, i64 = -1 }
# 4: varint
4 = { u64 = 1, i64 = -1 }
# 5: varint
5 = { u64 = 345, i64 = -173 }
# start message #8
[8]
# 2: varint
2 = { u64 = 32250, i64 = 16125 }
```
Tip: it's supposed to be `diff`-friendly to compare fields between different replays.
```toml
[[1]]
type = "VarInt"
unsigned = 65543
signed = -32772

[[2]]
type = "VarInt"
unsigned = 1670282196
signed = 835141098

[[3]]
type = "VarInt"
unsigned = 1
signed = -1

[[4]]
type = "VarInt"
unsigned = 1
signed = -1

# ...
```
63 changes: 28 additions & 35 deletions src/inspect.rs
Original file line number Diff line number Diff line change
@@ -1,70 +1,63 @@
//! Protocol Buffers inspection.

mod inspector;
mod models;
mod visit;

use std::collections::BTreeMap;

use anyhow::{ensure, Context};
use prost::bytes::Buf;
use prost::encoding::{decode_key, decode_varint, WireType};

pub use self::inspector::*;
use self::visit::Visit;
pub use self::models::*;
use crate::prelude::*;

/// Inspects the message in the buffer.
///
/// Because `prost` nor `prost-reflect` don't provide this kind of functionality,
/// I've implemented it manually based on the low-level `prost` functions.
pub fn inspect(buffer: &[u8], visit: &mut impl Visit) -> Result {
pub fn inspect(buffer: &[u8]) -> Result<Message> {
let mut fields: BTreeMap<Tag, Vec<Value>> = BTreeMap::new();
let mut buffer = buffer;

while buffer.remaining() != 0 {
let (tag, wire_type) = decode_key(&mut buffer).context("failed to decode the field key")?;
match wire_type {
let tag = Tag(tag);
let value = match wire_type {
WireType::ThirtyTwoBit => Some(Value::fixed32(buffer.get_u32_le())),
WireType::SixtyFourBit => Some(Value::fixed64(buffer.get_u64_le())),
WireType::Varint => {
let value = decode_varint(&mut buffer).with_context(|| {
format!("failed to decode the varint value for tag {}", tag)
format!("failed to decode the varint value for tag {}", tag.0)
})?;
visit.varint(tag, value);
}
WireType::ThirtyTwoBit => {
visit.fixed32(tag, buffer.get_u32_le());
}
WireType::SixtyFourBit => {
visit.fixed64(tag, buffer.get_u64_le());
}
WireType::StartGroup => {
visit.start_group(tag);
}
WireType::EndGroup => {
visit.end_group(tag);
Some(Value::varint(value))
}
WireType::LengthDelimited => {
let length = decode_varint(&mut buffer)
.with_context(|| format!("failed to decode the length for tag {}", tag))?
.with_context(|| format!("failed to decode the length for tag {}", tag.0))?
as usize;
let inner_buffer = &buffer[..length];
match validate_message(inner_buffer) {
let value = match validate_message(inner_buffer) {
Ok(_) => {
visit.start_message(tag);
inspect(inner_buffer, visit).with_context(|| {
format!("failed to inspect the message for tag {}", tag)
let message = inspect(inner_buffer).with_context(|| {
format!("failed to inspect the message for tag {}", tag.0)
})?;
visit.end_message(tag);
Some(Value::Message(Box::new(message)))
}
Err(_) => match std::str::from_utf8(inner_buffer) {
Ok(value) => {
visit.string(tag, value)?;
}
Err(_) => {
visit.bytes(tag, inner_buffer)?;
}
},
}
Err(_) => Some(Value::bytes(inner_buffer)),
};
buffer.advance(length);
value
}
WireType::StartGroup => None,
WireType::EndGroup => None,
};
if let Some(value) = value {
fields.entry(tag).or_default().push(value);
}
}
Ok(())

Ok(Message(fields))
}

/// Validates correctness of the buffer prior to calling the visitor.
Expand Down
107 changes: 0 additions & 107 deletions src/inspect/inspector.rs

This file was deleted.

Loading

0 comments on commit d931db3

Please sign in to comment.