primitive_archiver/
lib.rs1use std::io::Result;
2use async_compression::tokio::write::{DeflateDecoder, DeflateEncoder};
3use bytes::{BufMut, BytesMut};
4use tokio::io::AsyncWriteExt;
5
6async fn compress(data: &[u8]) -> Result<Vec<u8>> {
7 let mut encoder = DeflateEncoder::new(Vec::new());
8
9 encoder.write_all(data).await?;
10 encoder.shutdown().await?;
11
12 Ok(encoder.into_inner())
13}
14
15async fn decompress(data: &[u8]) -> Result<Vec<u8>> {
16 let mut decoder = DeflateDecoder::new(Vec::new());
17
18 decoder.write_all(data).await?;
19 decoder.shutdown().await?;
20
21 Ok(decoder.into_inner())
22}
23
24#[derive(Debug)]
25pub struct File {
26 pub name: String,
27 pub content: Vec<u8>
28}
29
30impl File {
31 pub fn new(name: &str, content: Vec<u8>) -> File {
32 File {
33 name: name.to_owned(),
34 content
35 }
36 }
37}
38
39pub struct Archiver {
40 pub stack: Vec<File>,
41 pub bytes: BytesMut
42}
43
44impl Archiver {
45 pub fn new() -> Archiver {
46 Archiver {
47 stack: Vec::new(),
48 bytes: BytesMut::new()
49 }
50 }
51
52 pub fn put(&mut self, name: &str, content: Vec<u8>) {
53 self.stack.push(File::new(name, content));
54 }
55
56 async fn write(&mut self, name: &str, content: &[u8]) -> Result<()> {
57 let filename_len = name.len() as u16;
58 let filename_size = filename_len.to_le_bytes();
59 let filename_content = name.as_bytes();
60
61 let content_compressed = compress(&content).await?;
62 let content_len = content_compressed.len() as u32;
63 let content_size = content_len.to_le_bytes();
64
65 self.bytes.put(&filename_size[..]);
66 self.bytes.put(filename_content);
67
68 self.bytes.put(&content_size[..]);
69 self.bytes.put(&content_compressed[..]);
70
71 Ok(())
72 }
73
74 pub async fn end(&mut self) {
75 let files: Vec<File> = self.stack.drain(..).collect();
76
77 for file in files {
78 let _ = self.write(&file.name, &file.content).await;
79 }
80 }
81}
82
83pub struct Unarchiver {
84 pub files: Vec<File>
85}
86
87impl Unarchiver {
88 pub fn new() -> Unarchiver {
89 Unarchiver {
90 files: Vec::new()
91 }
92 }
93
94 pub async fn read(&mut self, bytes: &mut BytesMut) {
95 let size = bytes.len();
96 let mut remained = size;
97
98 while remained > 0 {
99 if remained < 2 {
100 return
101 }
102
103 let le_len = bytes.split_to(2);
104 let len: usize = u16::from_le_bytes(le_len.as_ref().try_into().unwrap()).into();
105
106 remained -= 2;
107
108 if remained < len {
109 return
110 }
111
112 let str = bytes.split_to(len);
113 let name = String::from_utf8(str.to_vec()).unwrap();
114
115 remained -= len;
116
117 if remained < 4 {
118 return
119 }
120
121 let le_len = bytes.split_to(4);
122 let len = u32::from_le_bytes(le_len.as_ref().try_into().unwrap()) as usize;
123
124 remained -= 4;
125
126 let compressed = bytes.split_to(len);
127
128 if let Ok(content) = decompress(&compressed).await {
129 remained -= len;
130
131 self.files.push(File {
132 name,
133 content
134 });
135 } else {
136 return
137 }
138 }
139 }
140}