dodecet_encoder/
string.rs1use crate::{Dodecet, DodecetError, Result};
6use std::ops::{Deref, DerefMut};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct DodecetString {
22 data: Vec<Dodecet>,
23}
24
25impl DodecetString {
26 pub fn new() -> Self {
37 DodecetString { data: Vec::new() }
38 }
39
40 pub fn with_capacity(capacity: usize) -> Self {
51 DodecetString {
52 data: Vec::with_capacity(capacity),
53 }
54 }
55
56 pub fn capacity(&self) -> usize {
58 self.data.capacity()
59 }
60
61 pub fn from_slice(values: &[u16]) -> Self {
72 DodecetString {
73 data: values.iter().map(|&v| Dodecet::from_hex(v)).collect(),
74 }
75 }
76
77 pub fn from_dodecets(dodecets: Vec<Dodecet>) -> Self {
90 DodecetString { data: dodecets }
91 }
92
93 pub fn push(&mut self, value: u16) {
105 self.data.push(Dodecet::from_hex(value));
106 }
107
108 pub fn push_dodecet(&mut self, dodecet: Dodecet) {
110 self.data.push(dodecet);
111 }
112
113 pub fn pop(&mut self) -> Option<Dodecet> {
126 self.data.pop()
127 }
128
129 pub fn to_hex_string(&self) -> String {
140 self.data
141 .iter()
142 .map(|d| d.to_hex_string())
143 .collect::<Vec<_>>()
144 .join("")
145 }
146
147 pub fn from_hex_str(s: &str) -> Result<Self> {
159 if !s.len().is_multiple_of(3) {
160 return Err(DodecetError::InvalidHex);
161 }
162
163 let mut data = Vec::with_capacity(s.len() / 3);
164
165 for chunk in s.as_bytes().chunks(3) {
166 let chunk_str = std::str::from_utf8(chunk).unwrap();
167 data.push(Dodecet::from_hex_str(chunk_str)?);
168 }
169
170 Ok(DodecetString { data })
171 }
172
173 pub fn to_bytes(&self) -> Vec<u8> {
187 let mut bytes = Vec::with_capacity((self.data.len() * 3).div_ceil(2));
188
189 for chunk in self.data.chunks(2) {
190 if chunk.len() == 2 {
191 let d0 = chunk[0].value() as u32;
192 let d1 = chunk[1].value() as u32;
193
194 bytes.push(((d0 >> 4) & 0xFF) as u8);
196 bytes.push((((d0 & 0x0F) << 4) | ((d1 >> 8) & 0x0F)) as u8);
197 bytes.push((d1 & 0xFF) as u8);
198 } else if chunk.len() == 1 {
199 let d0 = chunk[0].value() as u32;
201 bytes.push(((d0 >> 4) & 0xFF) as u8);
202 bytes.push(((d0 & 0x0F) << 4) as u8);
203 }
204 }
205
206 bytes
207 }
208
209 pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
221 let mut data = Vec::new();
222
223 let mut i = 0;
224 while i + 2 < bytes.len() {
225 let d0 = ((bytes[i] as u32) << 4) | ((bytes[i + 1] as u32) >> 4);
226 let d1 = (((bytes[i + 1] as u32) & 0x0F) << 8) | (bytes[i + 2] as u32);
227
228 data.push(Dodecet::from_hex(d0 as u16));
229 data.push(Dodecet::from_hex(d1 as u16));
230
231 i += 3;
232 }
233
234 if i + 1 < bytes.len() {
236 let d0 = ((bytes[i] as u32) << 4) | ((bytes[i + 1] as u32) >> 4);
237 data.push(Dodecet::from_hex(d0 as u16));
238 } else if i < bytes.len() {
239 let d0 = (bytes[i] as u32) << 4;
240 data.push(Dodecet::from_hex(d0 as u16));
241 }
242
243 Ok(DodecetString { data })
244 }
245
246 pub fn iter(&self) -> impl Iterator<Item = &Dodecet> {
248 self.data.iter()
249 }
250
251 pub fn as_inner(&self) -> &Vec<Dodecet> {
253 &self.data
254 }
255
256 pub fn as_inner_mut(&mut self) -> &mut Vec<Dodecet> {
258 &mut self.data
259 }
260}
261
262impl Default for DodecetString {
263 fn default() -> Self {
264 Self::new()
265 }
266}
267
268impl Deref for DodecetString {
269 type Target = [Dodecet];
270
271 fn deref(&self) -> &Self::Target {
272 &self.data
273 }
274}
275
276impl DerefMut for DodecetString {
277 fn deref_mut(&mut self) -> &mut Self::Target {
278 &mut self.data
279 }
280}
281
282impl From<Vec<u16>> for DodecetString {
283 fn from(values: Vec<u16>) -> Self {
284 DodecetString::from_slice(&values)
285 }
286}
287
288impl From<Vec<Dodecet>> for DodecetString {
289 fn from(data: Vec<Dodecet>) -> Self {
290 DodecetString { data }
291 }
292}
293
294impl std::fmt::Display for DodecetString {
295 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
296 write!(f, "[")?;
297 for (i, d) in self.data.iter().enumerate() {
298 if i > 0 {
299 write!(f, ", ")?;
300 }
301 write!(f, "{}", d)?;
302 }
303 write!(f, "]")
304 }
305}
306
307#[cfg(test)]
308mod tests {
309 use super::*;
310
311 #[test]
312 fn test_creation() {
313 let s = DodecetString::new();
314 assert!(s.is_empty());
315
316 let s = DodecetString::with_capacity(10);
317 assert!(s.as_inner().capacity() >= 10);
318 }
319
320 #[test]
321 fn test_push_pop() {
322 let mut s = DodecetString::new();
323 s.push(0x123);
324 s.push(0x456);
325
326 assert_eq!(s.len(), 2);
327 assert_eq!(s[0].value(), 0x123);
328 assert_eq!(s[1].value(), 0x456);
329
330 let d = s.pop().unwrap();
331 assert_eq!(d.value(), 0x456);
332 assert_eq!(s.len(), 1);
333 }
334
335 #[test]
336 fn test_from_slice() {
337 let s = DodecetString::from_slice(&[0x123, 0x456, 0x789]);
338 assert_eq!(s.len(), 3);
339 assert_eq!(s[0].value(), 0x123);
340 assert_eq!(s[1].value(), 0x456);
341 assert_eq!(s[2].value(), 0x789);
342 }
343
344 #[test]
345 fn test_hex_string() {
346 let s = DodecetString::from_slice(&[0x123, 0x456, 0x789]);
347 assert_eq!(s.to_hex_string(), "123456789");
348
349 let s2 = DodecetString::from_hex_str("123456789").unwrap();
350 assert_eq!(s2.len(), 3);
351 assert_eq!(s2[0].value(), 0x123);
352 }
353
354 #[test]
355 fn test_bytes_conversion() {
356 let s = DodecetString::from_slice(&[0x123, 0x456]);
357 let bytes = s.to_bytes();
358
359 assert_eq!(bytes.len(), 3);
361
362 let s2 = DodecetString::from_bytes(&bytes).unwrap();
363 assert_eq!(s2.len(), 2);
364 assert_eq!(s2[0].value(), 0x123);
365 assert_eq!(s2[1].value(), 0x456);
366 }
367
368 #[test]
369 fn test_bytes_odd_length() {
370 let s = DodecetString::from_slice(&[0x123, 0x456, 0x789]);
371 let bytes = s.to_bytes();
372
373 assert!(bytes.len() <= 5);
375
376 let s2 = DodecetString::from_bytes(&bytes).unwrap();
377 assert_eq!(s2.len(), 3);
378 }
379
380 #[test]
381 fn test_display() {
382 let s = DodecetString::from_slice(&[0x123, 0x456]);
383 assert_eq!(format!("{}", s), "[0x123, 0x456]");
384 }
385}