wot_battle_results_parser_utils/
lib.rs

1use std::{
2    fs::{self, DirEntry},
3    path::Path,
4};
5
6use anyhow::{Context, Result};
7use miniz_oxide::inflate::DecompressError;
8use serde::Deserializer;
9use serde_pickle::Value as PickleValue;
10mod pickle;
11pub use pickle::IntoSubValue;
12
13// Get files in directory, given directory path (only direct childs of the directory)
14#[cfg(not(target_arch = "wasm32"))]
15pub fn parse_dir<P: AsRef<Path>>(path: P) -> Result<Vec<DirEntry>> {
16    let file_paths = fs::read_dir(path).with_context(|| "failed to read dir")?;
17
18    Ok(file_paths
19        .filter_map(|entry| entry.ok().filter(|entry| entry.path().is_file()))
20        .collect())
21}
22
23#[derive(serde::Deserialize)]
24#[serde(untagged)]
25enum BoolableValue {
26    Bool(bool),
27    Int(i32),
28}
29
30/// WoT sometimes uses int and boolean interchangeably for the same field and we can't have that
31pub fn bool_to_int<'de, D>(de: D) -> Result<i32, D::Error>
32where
33    D: Deserializer<'de>,
34{
35    let val: BoolableValue = serde::de::Deserialize::deserialize(de)?;
36
37    match val {
38        BoolableValue::Bool(val) => Ok(val as i32),
39        BoolableValue::Int(val) => Ok(val),
40    }
41}
42
43pub fn load_pickle(input: &[u8]) -> Result<PickleValue, DataError> {
44    let result = serde_pickle::value_from_slice(input, Default::default())?;
45
46    Ok(result)
47}
48
49pub fn decompress_vec<E>(compressed: &[u8], f: fn(DecompressError) -> E) -> Result<Vec<u8>, E> {
50    miniz_oxide::inflate::decompress_to_vec_zlib(compressed).map_err(|err| f(err))
51}
52
53#[derive(thiserror::Error, Debug)]
54pub enum DataError {
55    #[error("Decompressed failed: {0}")]
56    DecompressionFaliure(String),
57
58    #[error("{0}")]
59    PickleParseError(#[from] serde_pickle::Error),
60
61    #[error("{0}")]
62    Other(String),
63}
64
65
66/// `[0, 9, 15, 0]` => `"0_9_15_0"`
67pub fn version_as_string(version: [u16; 4]) -> String {
68    version.map(|x| x.to_string()).join("_")
69}
70
71/// `"0_9_15_0"` => `[0, 9, 15, 0]`  
72pub fn version_string_as_arr(version: String) -> Option<[u16; 4]> {
73    let vec: Option<Vec<u16>> = version.split('_').map(|v| v.parse().ok()).collect();
74
75    if let Some(vec) = vec {
76        if vec.len() == 4 {
77            Some([vec[0], vec[1], vec[2], vec[3]])
78        } else {
79            None
80        }
81    } else {
82        None
83    }
84}