wasmhaiku_glue/
fileparts.rs1#[derive(Debug)]
2pub struct FilePart {
3 pub file_name: String,
4 pub mime_str: String,
5 pub bytes: Vec<u8>,
6}
7
8#[derive(Debug)]
9pub struct FileParts {
10 pub inner: Vec<FilePart>,
11}
12
13impl From<Vec<u8>> for FileParts {
14 fn from(raw: Vec<u8>) -> FileParts {
15 if raw.len() < 16 {
16 return FileParts { inner: vec![] };
17 }
18
19 let total_len = i32::from_le_bytes((&raw[0..4]).try_into().unwrap()) as usize;
20 let mut v = Vec::<FilePart>::with_capacity(total_len);
21 let mut v_offset = (1 + (total_len * 3)) * 4;
22 for i in 0..total_len {
23 let offset = (1 + (i * 3)) * 4;
24 let file_name_len =
25 i32::from_le_bytes((&raw[offset..offset + 4]).try_into().unwrap()) as usize;
26 let file_name = String::from_utf8((&raw[v_offset..v_offset + file_name_len]).to_vec())
27 .unwrap_or_default();
28 v_offset += file_name_len;
29
30 let mime_str_len =
31 i32::from_le_bytes((&raw[offset + 4..offset + 8]).try_into().unwrap()) as usize;
32 let mime_str = String::from_utf8((&raw[v_offset..v_offset + mime_str_len]).to_vec())
33 .unwrap_or_default();
34 v_offset += mime_str_len;
35
36 let bytes_len =
37 i32::from_le_bytes((&raw[offset + 8..offset + 12]).try_into().unwrap()) as usize;
38 let bytes = (&raw[v_offset..v_offset + bytes_len]).to_vec();
39 v_offset += bytes_len;
40
41 v.push(FilePart {
42 file_name,
43 mime_str,
44 bytes,
45 });
46 }
47
48 FileParts { inner: v }
49 }
50}
51
52impl FileParts {
53 pub fn to_vec(&self) -> Vec<u8> {
54 let mut nv = vec![0 as u8; (1 + (3 * self.inner.len())) * 4];
55 nv.splice(0..4, (self.inner.len() as i32).to_le_bytes());
56 self.inner
57 .iter()
58 .enumerate()
59 .fold(nv, |mut accum, (index, item)| {
60 let file_name = item.file_name.as_bytes();
61 accum.extend(file_name);
62 let mime_str = item.mime_str.as_bytes();
63 accum.extend(mime_str);
64 accum.extend(&item.bytes);
65 let offset = (1 + (index * 3)) * 4;
66 accum.splice(offset..offset + 4, (file_name.len() as i32).to_le_bytes());
67 accum.splice(
68 offset + 4..offset + 8,
69 (mime_str.len() as i32).to_le_bytes(),
70 );
71 accum.splice(
72 offset + 8..offset + 12,
73 (item.bytes.len() as i32).to_le_bytes(),
74 );
75 accum
76 })
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn from_into() {
86 let fp = FileParts {
87 inner: vec![
88 FilePart {
89 file_name: String::from("a.txt"),
90 mime_str: String::from("text/plain"),
91 bytes: b"123".to_vec(),
92 },
93 FilePart {
94 file_name: String::from("g.jpg"),
95 mime_str: String::from("image/jpeg"),
96 bytes: b"!@#$%^&*()".to_vec(),
97 },
98 ],
99 };
100
101 let v = fp.to_vec();
102 println!("{:?}", v);
103
104 let fp2: FileParts = v.into();
105 println!("{:?}", fp2);
106
107 assert_eq!(fp.inner[0].file_name, fp2.inner[0].file_name);
108 assert_eq!(fp.inner[1].bytes, fp2.inner[1].bytes);
109 }
110}