aoe2_probe/utils/
string.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    io::Source,
7    parse::{Decode, Encode},
8};
9
10#[derive(Clone, Debug, Serialize, Deserialize)]
11pub struct DynString<T: Numeric> {
12    capacity: T,
13    raw: String,
14}
15
16impl<T> DynString<T>
17where
18    T: Numeric,
19{
20    pub fn new(raw: &str) -> Self {
21        DynString {
22            capacity: T::from_usize(raw.len()),
23            raw: raw.to_string(),
24        }
25    }
26
27    pub fn with_capacity(capacity: T, raw: &str) -> Self {
28        if capacity.to_usize() < raw.len() {
29            panic!("Content is over capacity!")
30        }
31        DynString {
32            capacity,
33            raw: raw.to_string(),
34        }
35    }
36
37    pub fn capacity(&self) -> T {
38        self.capacity
39    }
40
41    pub fn content(&self) -> &String {
42        &self.raw
43    }
44
45    pub fn content_mut(&mut self) -> &mut String {
46        &mut self.raw
47    }
48
49    pub fn set_content(&mut self, content: &str) {
50        if self.capacity.to_usize() < content.len() {
51            self.capacity = T::from_usize(content.len());
52        }
53
54        self.raw = content.to_string();
55    }
56}
57
58impl<T> Encode for DynString<T>
59where
60    T: Numeric,
61{
62    fn to_le_vec(&self) -> Vec<u8> {
63        let container_len: usize = if self.capacity.to_usize() < self.raw.len() {
64            self.capacity.to_usize()
65        } else {
66            self.raw.len()
67        };
68
69        let mut vec = Vec::<u8>::new();
70        let mut prefix = self.capacity.to_le_vec();
71        let content = self.raw.clone().into_bytes();
72        let mut container = vec![0; container_len];
73        for (index, _) in content.iter().enumerate() {
74            container[index] = content[index];
75        }
76        vec.append(&mut prefix);
77        vec.append(&mut container);
78        vec
79    }
80}
81
82impl Decode for DynString<u16> {
83    fn from_le_vec(source: &mut Source) -> Result<Self, String> {
84        let capacity = u16::from_le_vec(source)?;
85        let raw = String::from_utf8_lossy(&source.get_vec(capacity as usize)?[..]).to_string();
86
87        Ok(DynString::with_capacity(capacity, &raw))
88    }
89}
90
91impl Decode for DynString<u32> {
92    fn from_le_vec(source: &mut Source) -> Result<Self, String> {
93        let capacity = u32::from_le_vec(source)?;
94        let raw = String::from_utf8_lossy(&source.get_vec(capacity as usize)?[..]).to_string();
95
96        Ok(DynString::with_capacity(capacity, &raw))
97    }
98}
99
100pub trait Numeric: Copy + Encode {
101    fn to_usize(&self) -> usize;
102    fn from_usize(num: usize) -> Self;
103}
104
105impl Numeric for u16 {
106    fn to_usize(&self) -> usize {
107        *self as usize
108    }
109
110    fn from_usize(num: usize) -> Self {
111        num as u16
112    }
113}
114impl Numeric for u32 {
115    fn to_usize(&self) -> usize {
116        *self as usize
117    }
118
119    fn from_usize(num: usize) -> Self {
120        num as u32
121    }
122}
123
124#[derive(Clone, Debug, Serialize, Deserialize)]
125pub struct C4 {
126    raw: String,
127}
128
129impl C4 {
130    pub fn new(content: &str) -> Self {
131        if content.len() > 4 {
132            panic!("Out of the fixed capacity!")
133        }
134
135        C4 {
136            raw: content.to_string(),
137        }
138    }
139
140    pub fn content(&self) -> &String {
141        &self.raw
142    }
143
144    pub fn set_content(&mut self, content: &str) {
145        if content.len() > 4 {
146            panic!("Out of the fixed capacity!")
147        }
148        self.raw = content.to_string();
149    }
150}
151
152impl Decode for C4 {
153    fn from_le_vec(source: &mut Source) -> Result<Self, String> {
154        let raw = String::from_utf8_lossy(&source.get_vec(4_usize)?[..]).to_string();
155
156        Ok(C4::new(&raw))
157    }
158}
159
160impl Encode for C4 {
161    fn to_le_vec(&self) -> Vec<u8> {
162        let content = self.raw.clone().into_bytes();
163        let mut container = vec![0; 4];
164        for (index, _) in content.iter().enumerate() {
165            container[index] = content[index];
166        }
167        container
168    }
169}
170
171#[derive(Clone, Serialize, Deserialize)]
172pub struct C256 {
173    raw: String,
174}
175
176impl C256 {
177    pub fn new(content: &str) -> Self {
178        if content.len() > 256 {
179            panic!("Out of the fixed capacity!")
180        }
181
182        C256 {
183            raw: content.to_string(),
184        }
185    }
186
187    pub fn content(&self) -> &String {
188        &self.raw
189    }
190
191    pub fn set_content(&mut self, content: &str) {
192        if content.len() > 256 {
193            panic!("Out of the fixed capacity!")
194        }
195        self.raw = content.to_string();
196    }
197}
198
199impl Decode for C256 {
200    fn from_le_vec(source: &mut Source) -> Result<Self, String> {
201        let raw = String::from_utf8_lossy(&source.get_vec(256_usize)?[..]).to_string();
202        Ok(C256::new(&raw))
203    }
204}
205
206impl Encode for C256 {
207    fn to_le_vec(&self) -> Vec<u8> {
208        let content = self.raw.clone().into_bytes();
209        let mut container = vec![0; 256];
210        for (index, _) in content.iter().enumerate() {
211            container[index] = content[index];
212        }
213        container
214    }
215}
216
217impl fmt::Debug for C256 {
218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219        write!(f, "{}", self.raw.trim_matches(char::from(0)))
220    }
221}