hff_core/utilities/
string_vec.rs1use crate::{
2 byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt},
3 Ecc, Endian, Error, Result, BE, LE, NE,
4};
5use std::{
6 io::{Read, Write},
7 ops::{Deref, DerefMut},
8};
9
10#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
13pub struct StringVec {
14 strings: Vec<String>,
16}
17
18impl StringVec {
19 const ID: Ecc = Ecc::new("STR_VEC");
21
22 pub fn new() -> Self {
24 Self { strings: vec![] }
25 }
26
27 pub fn to_bytes<E: ByteOrder>(self) -> Result<Vec<u8>> {
30 let mut bytes = vec![];
31 let writer: &mut dyn Write = &mut bytes;
32
33 Self::ID.write::<E>(writer)?;
34 writer.write_u64::<E>(self.strings.len() as u64)?;
35
36 for s in self.strings {
37 let b = s.as_bytes();
38 writer.write_u64::<E>(b.len() as u64)?;
39 writer.write_all(b)?;
40 }
41
42 Ok(bytes)
43 }
44
45 pub fn from_bytes(mut bytes: &[u8]) -> Result<Self> {
47 let reader: &mut dyn Read = &mut bytes;
49 let id = Ecc::from(reader.read_u64::<NE>()?);
55 match id.endian(Self::ID) {
56 Some(endian) => match endian {
57 Endian::Big => Self::from_bytes_endian::<BE>(reader),
58 Endian::Little => Self::from_bytes_endian::<LE>(reader),
59 },
60 None => Err(Error::Invalid("Not a string vector.".into())),
61 }
62 }
63
64 fn from_bytes_endian<E: ByteOrder>(reader: &mut dyn Read) -> Result<Self> {
66 let count = reader.read_u64::<E>()?;
67
68 let mut strings = StringVec::new();
69 for _ in 0..count {
70 let len = reader.read_u64::<E>()?;
71 let mut s = vec![0; len as usize];
72 reader.read_exact(&mut s)?;
73 strings.push(std::str::from_utf8(&s)?.to_string());
74 }
75
76 Ok(strings)
77 }
78}
79
80impl<I, V> From<I> for StringVec
81where
82 I: Iterator<Item = V>,
83 V: AsRef<str>,
84{
85 fn from(value: I) -> Self {
86 Self {
87 strings: value.map(|s| s.as_ref().to_owned()).collect(),
88 }
89 }
90}
91
92impl Deref for StringVec {
93 type Target = Vec<String>;
94
95 fn deref(&self) -> &Self::Target {
96 &self.strings
97 }
98}
99
100impl DerefMut for StringVec {
101 fn deref_mut(&mut self) -> &mut Self::Target {
102 &mut self.strings
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn simple() {
112 let test_data = ["This", "is", "some", "test", "data."];
113 let strings: StringVec = test_data.clone().iter().into();
114 let bytes = strings.to_bytes::<LE>().unwrap();
115
116 let result = StringVec::from_bytes(&bytes).unwrap();
117 assert!(
118 test_data
119 .iter()
120 .zip(result.iter())
121 .map(|(l, r)| if l == r { 0 } else { 1 })
122 .sum::<usize>()
123 == 0
124 );
125 }
126}