wolfrpg_map_parser/command/
string_condition_command.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
pub mod operator;
pub mod compare_operator;
pub mod condition;

use crate::byte_utils::{as_u32_vec, parse_string_vec};
use crate::command::common::case::Case;
use crate::command::common::u32_or_string::U32OrString;
use crate::command::common::CASES_END_SIGNATURE;
use crate::command::string_condition_command::condition::Condition;
use crate::command::string_condition_command::operator::Operator;
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq)]
pub struct StringConditionCommand {
    else_case: bool,
    conditions: Vec<Condition>,
    cases: Vec<Case>
}

impl StringConditionCommand {
    pub(crate) fn parse(bytes: &[u8], signature: u32) -> (usize, u32, Self) {
        let mut offset: usize = 0;

        let (case_count, else_case): (u8,bool) = Self::parse_case_count(bytes[offset]);
        offset += 1;

        offset += 3; // Padding

        let variables: Vec<u32> = as_u32_vec(&bytes[offset..offset + (4 * case_count) as usize]);
        offset += 4 * case_count as usize;

        let value_count:usize = Self::value_count(signature, case_count as u32);
        let values: Vec<u32> = as_u32_vec(&bytes[offset..offset + (4 * value_count)]);
        offset += 4 * value_count;

        offset += 1; // Padding;

        let condition_count: usize = bytes[offset] as usize;
        offset += 1;

        let (bytes_read, conditions): (usize, Vec<String>)
            = parse_string_vec(&bytes[offset..], condition_count);
        offset += bytes_read;

        offset += 1; // Conditions end

        let conditions: Vec<Condition> = Self::make_conditions(variables, values, conditions);

        let case_count: usize = case_count as usize + else_case as usize;
        let (bytes_read, mut commands_read, cases): (usize, u32, Vec<Case>)
            = Case::parse_multiple(&bytes[offset..], case_count);
        offset += bytes_read;

        let cases_end: &[u8] = &bytes[offset..offset+8];
        offset += 8;
        commands_read += 1;

        if cases_end != CASES_END_SIGNATURE {
            panic!("Invalid cases end.");
        }

        (offset, commands_read, Self {
            else_case,
            conditions,
            cases
        })
    }

    fn parse_case_count(cases: u8) -> (u8, bool) {
        (cases & 0x0f, cases & 0b00010000 != 0)
    }

    fn value_count(signature: u32, case_count: u32) -> usize {
        ((signature >> 24) - 2 - case_count) as usize
    }

    fn make_conditions(variables: Vec<u32>, values: Vec<u32>,
                       conditions: Vec<String>) -> Vec<Condition> {
        let mut ret_conditions: Vec<Condition> = Vec::with_capacity(variables.len());

        for i in 0..variables.len() {
            let operator: u8 = (variables[i] >> 24) as u8;
            let operator: Operator = Operator::new(operator);
            let variable: u32 = variables[i] & 0x00ffffff;

            let value: U32OrString = if operator.value_is_variable() {
                U32OrString::U32(values[i])
            } else {
              U32OrString::String(conditions[i].clone())
            };

            ret_conditions.push(Condition::new(variable, operator, value));
        }

        ret_conditions
    }

    pub fn else_case(&self) -> bool {
        self.else_case
    }
    
    pub fn else_case_mut(&mut self) -> &mut bool {
        &mut self.else_case
    }

    pub fn conditions(&self) -> &Vec<Condition> {
        &self.conditions
    }
    
    pub fn conditions_mut(&mut self) -> &mut Vec<Condition> {
        &mut self.conditions
    }

    pub fn cases(&self) -> &Vec<Case> {
        &self.cases
    }
    
    pub fn cases_mut(&mut self) -> &mut Vec<Case> {
        &mut self.cases
    }
}