primitive_archiver/
lib.rs

1use 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}