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
#[cfg(test)]
#[path = "./expansion_test.rs"]
mod expansion_test;
use crate::parser;
use crate::types::instruction::InstructionMetaInfo;
use std::collections::HashMap;
pub(crate) enum ExpandedValue {
Single(String),
Multi(Vec<String>),
None,
}
fn should_break_key(value: char) -> bool {
value == ' ' || value == '\n' || value == '\t' || value == '\r' || value == '='
}
fn push_prefix(buffer: &mut String, single_type: bool, found_prefix_fully: bool) {
if single_type {
buffer.push('$');
} else {
buffer.push('%');
}
if found_prefix_fully {
buffer.push('{');
}
}
pub(crate) fn expand_by_wrapper(
value: &str,
meta_info: &InstructionMetaInfo,
variables: &HashMap<String, String>,
) -> ExpandedValue {
let mut value_string = String::new();
let mut prefix_index = 0;
let mut found_prefix = false;
let mut key = String::new();
let mut force_push = false;
let mut single_type = true;
for next_char in value.chars() {
if !found_prefix {
if next_char == '\\' && prefix_index == 0 {
force_push = true
} else if force_push {
if next_char != '$' {
value_string.push('\\');
}
value_string.push(next_char);
force_push = false;
} else if prefix_index == 0 && (next_char == '$' || next_char == '%') {
prefix_index = 1;
single_type = if next_char == '$' { true } else { false };
} else if prefix_index == 1 && next_char == '{' {
found_prefix = true;
prefix_index = 0;
key.clear();
} else {
if prefix_index > 0 || found_prefix {
push_prefix(&mut value_string, single_type, found_prefix);
prefix_index = 0;
}
value_string.push(next_char);
}
} else if next_char == '}' {
match variables.get(&key) {
Some(variable_value) => value_string.push_str(&variable_value),
_ => (),
};
key.clear();
found_prefix = false;
} else if should_break_key(next_char) {
if prefix_index > 0 || found_prefix {
push_prefix(&mut value_string, single_type, found_prefix);
prefix_index = 0;
}
value_string.push_str(&key);
value_string.push(next_char);
key.clear();
found_prefix = false;
} else {
key.push(next_char);
}
}
if force_push {
value_string.push('\\');
} else if key.len() > 0 {
if prefix_index > 0 || found_prefix {
push_prefix(&mut value_string, single_type, found_prefix);
}
value_string.push_str(&key);
}
if value_string.is_empty() {
ExpandedValue::None
} else if single_type {
ExpandedValue::Single(value_string.to_string())
} else {
let chars = value_string.to_string().chars().collect();
match parser::reparse_arguments(meta_info, &chars, 0) {
Ok(values_option) => match values_option {
Some(values) => ExpandedValue::Multi(values),
None => ExpandedValue::None,
},
Err(_) => ExpandedValue::None,
}
}
}