1pub mod helpers;
2pub mod notifications;
3pub mod readwrite;
4pub mod streamreadwrite;
5pub mod transformer;
6pub mod transformers;
7
8#[cfg(test)]
9mod tests {
10 use crate::helpers::footer_parser::{FooterParser, Range};
11 use crate::readwrite::ArunaReadWriter;
12 use crate::streamreadwrite::ArunaStreamReadWriter;
13 use crate::transformer::{FileContext, ReadWriter};
14 use crate::transformers::decrypt::ChaCha20Dec;
15 use crate::transformers::encrypt::ChaCha20Enc;
16 use crate::transformers::filter::Filter;
17 use crate::transformers::footer::FooterGenerator;
18 use crate::transformers::gzip_comp::GzipEnc;
19 use crate::transformers::size_probe::SizeProbe;
20 use crate::transformers::tar::TarEnc;
21 use crate::transformers::zstd_comp::ZstdEnc;
23 use crate::transformers::zstd_decomp::ZstdDec;
24 use bytes::Bytes;
25 use digest::Digest;
26 use futures::{StreamExt, TryStreamExt};
27 use md5::Md5;
28 use tokio::fs::File;
29 use tokio::io::{AsyncReadExt, AsyncSeekExt};
30
31 #[tokio::test]
32 async fn e2e_compressor_test_with_file() {
33 let file = File::open("test.txt").await.unwrap();
34 let file2 = File::create("test.txt.out.1").await.unwrap();
35
36 ArunaReadWriter::new_with_writer(file, file2)
38 .add_transformer(ZstdEnc::new(false))
39 .add_transformer(ZstdDec::new())
40 .process()
41 .await
42 .unwrap();
43
44 let mut file = File::open("test.txt").await.unwrap();
45 let mut file2 = File::open("test.txt.out.1").await.unwrap();
46 let mut buf1 = String::new();
47 let mut buf2 = String::new();
48 file.read_to_string(&mut buf1).await.unwrap();
49 file2.read_to_string(&mut buf2).await.unwrap();
50 assert!(buf1 == buf2)
51 }
52
53 #[tokio::test]
54 async fn e2e_encrypt_test_with_vec_no_pad() {
55 let file = b"This is a very very important test".to_vec();
56 let mut file2 = Vec::new();
57
58 ArunaReadWriter::new_with_writer(file.as_ref(), &mut file2)
60 .add_transformer(
61 ChaCha20Enc::new(false, b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
62 )
63 .add_transformer(
64 ChaCha20Dec::new(Some(b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
65 )
66 .process()
67 .await
68 .unwrap();
69
70 assert_eq!(file, file2);
71 }
72
73 #[tokio::test]
74 async fn e2e_encrypt_test_with_vec_with_pad() {
75 let file = b"This is a very very important test".to_vec();
76 let mut file2 = Vec::new();
77
78 ArunaReadWriter::new_with_writer(file.as_ref(), &mut file2)
80 .add_transformer(
81 ChaCha20Enc::new(true, b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
82 )
83 .add_transformer(
84 ChaCha20Dec::new(Some(b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
85 )
86 .process()
87 .await
88 .unwrap();
89
90 assert_eq!(file, file2);
91 }
92
93 #[tokio::test]
94 async fn e2e_encrypt_test_with_file_no_pad() {
95 let file = File::open("test.txt").await.unwrap();
96 let file2 = File::create("test.txt.out.2").await.unwrap();
97
98 ArunaReadWriter::new_with_writer(file, file2)
100 .add_transformer(
101 ChaCha20Enc::new(false, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
102 )
103 .add_transformer(
104 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
105 )
106 .process()
107 .await
108 .unwrap();
109
110 let mut file = File::open("test.txt").await.unwrap();
111 let mut file2 = File::open("test.txt.out.2").await.unwrap();
112 let mut buf1 = String::new();
113 let mut buf2 = String::new();
114 file.read_to_string(&mut buf1).await.unwrap();
115 file2.read_to_string(&mut buf2).await.unwrap();
116 assert!(buf1 == buf2)
117 }
118
119 #[tokio::test]
120 async fn e2e_encrypt_test_with_file_with_pad() {
121 let file = File::open("test.txt").await.unwrap();
122 let file2 = File::create("test.txt.out.3").await.unwrap();
123
124 ArunaReadWriter::new_with_writer(file, file2)
126 .add_transformer(
127 ChaCha20Enc::new(true, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
128 )
129 .add_transformer(
130 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
131 )
132 .process()
133 .await
134 .unwrap();
135
136 let mut file = File::open("test.txt").await.unwrap();
137 let mut file2 = File::open("test.txt.out.3").await.unwrap();
138 let mut buf1 = String::new();
139 let mut buf2 = String::new();
140 file.read_to_string(&mut buf1).await.unwrap();
141 file2.read_to_string(&mut buf2).await.unwrap();
142 assert!(buf1 == buf2)
143 }
144
145 #[tokio::test]
146 async fn e2e_test_roundtrip_with_file() {
147 let file = File::open("test.txt").await.unwrap();
148 let file2 = File::create("test.txt.out.4").await.unwrap();
149
150 ArunaReadWriter::new_with_writer(file, file2)
152 .add_transformer(ZstdEnc::new(false))
153 .add_transformer(ZstdEnc::new(false))
154 .add_transformer(
155 ChaCha20Enc::new(true, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
156 )
157 .add_transformer(
158 ChaCha20Enc::new(false, b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
159 )
160 .add_transformer(
161 ChaCha20Dec::new(Some(b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
162 )
163 .add_transformer(
164 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
165 )
166 .add_transformer(ZstdDec::new())
167 .add_transformer(ZstdDec::new())
168 .process()
169 .await
170 .unwrap();
171
172 let mut file = File::open("test.txt").await.unwrap();
173 let mut file2 = File::open("test.txt.out.4").await.unwrap();
174 let mut buf1 = String::new();
175 let mut buf2 = String::new();
176 file.read_to_string(&mut buf1).await.unwrap();
177 file2.read_to_string(&mut buf2).await.unwrap();
178 assert!(buf1 == buf2)
179 }
180
181 #[tokio::test]
182 async fn test_with_vec() {
183 let file = b"This is a very very important test".to_vec();
184 let mut file2 = Vec::new();
185
186 ArunaReadWriter::new_with_writer(file.as_ref(), &mut file2)
188 .add_transformer(ZstdEnc::new(false))
189 .add_transformer(ZstdEnc::new(false)) .add_transformer(
191 ChaCha20Enc::new(false, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
192 )
193 .add_transformer(
194 ChaCha20Enc::new(false, b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
195 )
196 .add_transformer(
197 ChaCha20Dec::new(Some(b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
198 )
199 .add_transformer(
200 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
201 )
202 .add_transformer(ZstdDec::new())
203 .add_transformer(ZstdDec::new()) .process()
205 .await
206 .unwrap();
207 assert!(file == file2)
208 }
209
210 #[tokio::test]
211 async fn test_with_file_footer() {
212 let file = File::open("test.txt").await.unwrap();
213 let file2 = File::create("test.txt.out.5").await.unwrap();
214 ArunaReadWriter::new_with_writer(file, file2)
215 .add_transformer(ZstdEnc::new(false))
216 .add_transformer(
217 ChaCha20Enc::new(false, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
218 )
219 .add_transformer(
220 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
221 )
222 .add_transformer(FooterGenerator::new(None))
223 .add_transformer(ZstdDec::new())
224 .process()
225 .await
226 .unwrap();
227
228 let mut file = File::open("test.txt").await.unwrap();
229 let mut file2 = File::open("test.txt.out.5").await.unwrap();
230 let mut buf1 = String::new();
231 let mut buf2 = String::new();
232 file.read_to_string(&mut buf1).await.unwrap();
233 file2.read_to_string(&mut buf2).await.unwrap();
234 assert!(buf1 == buf2)
235 }
236
237 #[tokio::test]
238 async fn test_footer_parsing() {
239 let file = File::open("test.txt").await.unwrap();
240 let file2 = File::create("test.txt.out.6").await.unwrap();
241 ArunaReadWriter::new_with_writer(file, file2)
242 .add_transformer(ZstdEnc::new(false))
243 .add_transformer(FooterGenerator::new(None))
244 .add_transformer(
245 ChaCha20Enc::new(false, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
246 )
247 .add_transformer(
248 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
249 )
250 .process()
251 .await
252 .unwrap();
253
254 let mut file2 = File::open("test.txt.out.6").await.unwrap();
255
256 file2
257 .seek(std::io::SeekFrom::End(-65536 * 2))
258 .await
259 .unwrap();
260
261 let buf: &mut [u8; 65536 * 2] = &mut [0; 65536 * 2];
262 file2.read_exact(buf).await.unwrap();
263
264 let mut fp = FooterParser::new(buf);
265
266 fp.parse().unwrap();
267
268 let (a, b) = fp
269 .get_offsets_by_range(Range { from: 0, to: 1000 })
270 .unwrap();
271
272 assert!(a.to % (65536) == 0);
273
274 assert_eq!(
275 a,
276 Range {
277 from: 0,
278 to: 25 * 65536
279 }
280 );
281 assert!(b == Range { from: 0, to: 1000 })
282 }
283
284 #[tokio::test]
285 async fn test_footer_parsing_encrypted() {
286 let file = File::open("test.txt").await.unwrap();
287 let file2 = File::create("test.txt.out.7").await.unwrap();
288 ArunaReadWriter::new_with_writer(file, file2)
289 .add_transformer(ZstdEnc::new(false))
290 .add_transformer(FooterGenerator::new(None))
291 .add_transformer(
292 ChaCha20Enc::new(false, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
293 )
294 .process()
295 .await
296 .unwrap();
297
298 let mut file2 = File::open("test.txt.out.7").await.unwrap();
299 file2
300 .seek(std::io::SeekFrom::End((-65536 - 28) * 2))
301 .await
302 .unwrap();
303
304 let buf: &mut [u8; (65536 + 28) * 2] = &mut [0; (65536 + 28) * 2];
305 file2.read_exact(buf).await.unwrap();
306
307 let mut fp =
308 FooterParser::from_encrypted(buf, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea").unwrap();
309 fp.parse().unwrap();
310
311 let (a, b) = fp
312 .get_offsets_by_range(Range { from: 0, to: 1000 })
313 .unwrap();
314
315 assert!(a.to % (65536 + 28) == 0);
316
317 assert!(
318 a == Range {
319 from: 0,
320 to: 25 * (65536 + 28)
321 }
322 );
323 assert!(b == Range { from: 0, to: 1000 })
324 }
325
326 #[tokio::test]
327 async fn test_with_filter() {
328 let file = b"This is a very very important test".to_vec();
329 let mut file2 = Vec::new();
330
331 ArunaReadWriter::new_with_writer(file.as_ref(), &mut file2)
333 .add_transformer(ZstdEnc::new(false))
334 .add_transformer(ZstdEnc::new(false)) .add_transformer(
336 ChaCha20Enc::new(false, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
337 )
338 .add_transformer(
339 ChaCha20Enc::new(false, b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
340 )
341 .add_transformer(
342 ChaCha20Dec::new(Some(b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
343 )
344 .add_transformer(
345 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
346 )
347 .add_transformer(ZstdDec::new())
348 .add_transformer(ZstdDec::new())
349 .add_transformer(Filter::new(Range { from: 0, to: 3 }))
350 .process()
351 .await
352 .unwrap();
353
354 println!("{:?}", file2);
355 assert_eq!(file2, b"Thi".to_vec());
356 }
357
358 #[tokio::test]
359 async fn test_read_write_multifile() {
360 let file1 = b"This is a very very important test".to_vec();
361 let file2 = b"This is a very very important test".to_vec();
362 let mut file3: Vec<u8> = Vec::new();
363
364 let combined = Vec::from_iter(file1.clone().into_iter().chain(file2.clone()));
365
366 let (sx, rx) = async_channel::bounded(10);
367 sx.send((
368 FileContext {
369 file_name: "file1.txt".to_string(),
370 input_size: file1.len() as u64,
371 file_size: file1.len() as u64,
372 ..Default::default()
373 },
374 false,
375 ))
376 .await
377 .unwrap();
378
379 sx.send((
380 FileContext {
381 file_name: "file2.txt".to_string(),
382 input_size: file2.len() as u64,
383 file_size: file2.len() as u64,
384 ..Default::default()
385 },
386 true,
387 ))
388 .await
389 .unwrap();
390
391 let mut aswr = ArunaReadWriter::new_with_writer(combined.as_ref(), &mut file3)
393 .add_transformer(ZstdEnc::new(false))
394 .add_transformer(ZstdEnc::new(false)) .add_transformer(
396 ChaCha20Enc::new(false, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
397 )
398 .add_transformer(
399 ChaCha20Enc::new(false, b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
400 )
401 .add_transformer(
402 ChaCha20Dec::new(Some(b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
403 )
404 .add_transformer(
405 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
406 )
407 .add_transformer(ZstdDec::new())
408 .add_transformer(ZstdDec::new())
409 .add_transformer(Filter::new(Range { from: 0, to: 3 }));
410 aswr.add_file_context_receiver(rx).await.unwrap();
411 aswr.process().await.unwrap();
412 drop(aswr);
413
414 println!("{:?}", file3);
415 assert_eq!(file3, b"Thi".to_vec());
416 }
417
418 #[tokio::test]
419 async fn stream_test() {
420 let mut file2 = Vec::new();
421
422 use futures::stream;
423
424 let stream = stream::iter(vec![
425 Ok(Bytes::from_iter(
426 b"This is a very very important test".to_vec(),
427 )),
428 Ok(Bytes::from(b"This is a very very important test".to_vec())),
429 ]);
430
431 ArunaStreamReadWriter::new_with_writer(stream, &mut file2)
433 .add_transformer(ZstdEnc::new(false))
434 .add_transformer(ZstdEnc::new(false)) .add_transformer(
436 ChaCha20Enc::new(true, b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
437 )
438 .add_transformer(
439 ChaCha20Enc::new(true, b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec()).unwrap(),
440 )
441 .add_transformer(
442 ChaCha20Dec::new(Some(b"99wj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
443 )
444 .add_transformer(
445 ChaCha20Dec::new(Some(b"wvwj3485nxgyq5ub9zd3e7jsrq7a92ea".to_vec())).unwrap(),
446 )
447 .add_transformer(ZstdDec::new())
448 .add_transformer(ZstdDec::new())
449 .add_transformer(Filter::new(Range { from: 0, to: 3 }))
450 .process()
451 .await
452 .unwrap();
453
454 println!("{:?}", file2);
455 assert_eq!(file2, b"Thi".to_vec());
456 }
457
458 #[tokio::test]
459 async fn e2e_test_read_write_multifile_tar_small() {
460 let file1 = b"This is a very very important test".to_vec();
461 let file2 = b"Another brilliant This is a very very important test1337".to_vec();
462 let mut file3 = File::create("test.txt.out.8").await.unwrap();
463
464 let combined = Vec::from_iter(file1.clone().into_iter().chain(file2.clone()));
465
466 let (sx, rx) = async_channel::bounded(10);
467 sx.send((
468 FileContext {
469 file_name: "file1.txt".to_string(),
470 input_size: file2.len() as u64,
471 file_size: file1.len() as u64,
472 ..Default::default()
473 },
474 false,
475 ))
476 .await
477 .unwrap();
478
479 sx.send((
480 FileContext {
481 file_name: "file2.txt".to_string(),
482 input_size: file2.len() as u64,
483 file_size: file2.len() as u64,
484 ..Default::default()
485 },
486 true,
487 ))
488 .await
489 .unwrap();
490
491 let mut aswr = ArunaReadWriter::new_with_writer(combined.as_ref(), &mut file3)
493 .add_transformer(TarEnc::new());
494 aswr.add_file_context_receiver(rx).await.unwrap();
495 aswr.process().await.unwrap();
496 }
497
498 #[tokio::test]
499 async fn e2e_test_read_write_multifile_tar_real() {
500 let mut file1 = File::open("test.txt").await.unwrap();
501 let mut file2 = File::open("test.txt").await.unwrap();
502 let mut file3 = File::create("test.txt.out.9").await.unwrap();
503
504 let mut combined = Vec::new();
505 file1.read_to_end(&mut combined).await.unwrap();
506 file2.read_to_end(&mut combined).await.unwrap();
507
508 let (sx, rx) = async_channel::bounded(10);
509 sx.send((
510 FileContext {
511 file_name: "file1.txt".to_string(),
512 input_size: file1.metadata().await.unwrap().len(),
513 file_size: file1.metadata().await.unwrap().len(),
514 ..Default::default()
515 },
516 false,
517 ))
518 .await
519 .unwrap();
520
521 sx.send((
522 FileContext {
523 file_name: "file2.txt".to_string(),
524 input_size: file2.metadata().await.unwrap().len(),
525 file_size: file2.metadata().await.unwrap().len(),
526 ..Default::default()
527 },
528 true,
529 ))
530 .await
531 .unwrap();
532
533 let mut aswr = ArunaReadWriter::new_with_writer(combined.as_ref(), &mut file3)
535 .add_transformer(TarEnc::new());
536 aswr.add_file_context_receiver(rx).await.unwrap();
537 aswr.process().await.unwrap();
538 }
539
540 #[tokio::test]
541 async fn e2e_test_stream_write_multifile_tar_real() {
542 let file1 = File::open("test.txt").await.unwrap();
543 let file2 = File::open("test.txt").await.unwrap();
544
545 let file1_size = file1.metadata().await.unwrap().len();
546 let file2_size = file2.metadata().await.unwrap().len();
547
548 let stream1 = tokio_util::io::ReaderStream::new(file1);
549 let stream2 = tokio_util::io::ReaderStream::new(file2);
550
551 let chained = stream1.chain(stream2);
552 let mapped = chained.map_err(|_| {
553 Box::<(dyn std::error::Error + Send + Sync + 'static)>::from("a_str_error")
554 });
555 let mut file3 = File::create("test.txt.out.10").await.unwrap();
556
557 let (sx, rx) = async_channel::bounded(10);
558 sx.send((
559 FileContext {
560 file_name: "file1.txt".to_string(),
561 input_size: file1_size,
562 file_size: file1_size,
563 ..Default::default()
564 },
565 false,
566 ))
567 .await
568 .unwrap();
569
570 sx.send((
571 FileContext {
572 file_name: "file2.txt".to_string(),
573 input_size: file2_size,
574 file_size: file2_size,
575 ..Default::default()
576 },
577 true,
578 ))
579 .await
580 .unwrap();
581
582 let mut aswr = ArunaStreamReadWriter::new_with_writer(mapped, &mut file3)
584 .add_transformer(TarEnc::new());
585 aswr.add_file_context_receiver(rx).await.unwrap();
586 aswr.process().await.unwrap();
587 }
588
589 #[tokio::test]
590 async fn e2e_test_stream_tar_gz() {
591 let file1 = File::open("test.txt").await.unwrap();
592 let file2 = File::open("test.txt").await.unwrap();
593
594 let file1_size = file1.metadata().await.unwrap().len();
595 let file2_size = file2.metadata().await.unwrap().len();
596
597 let stream1 = tokio_util::io::ReaderStream::new(file1);
598 let stream2 = tokio_util::io::ReaderStream::new(file2);
599
600 let chained = stream1.chain(stream2);
601 let mapped = chained.map_err(|_| {
602 Box::<(dyn std::error::Error + Send + Sync + 'static)>::from("a_str_error")
603 });
604 let mut file3 = File::create("test.txt.out.11").await.unwrap();
605
606 let (sx, rx) = async_channel::bounded(10);
607 sx.send((
608 FileContext {
609 file_name: "file1.txt".to_string(),
610 input_size: file1_size,
611 file_size: file1_size,
612 ..Default::default()
613 },
614 false,
615 ))
616 .await
617 .unwrap();
618
619 sx.send((
620 FileContext {
621 file_name: "file2.txt".to_string(),
622 input_size: file2_size,
623 file_size: file2_size,
624 ..Default::default()
625 },
626 true,
627 ))
628 .await
629 .unwrap();
630
631 let mut aswr = ArunaStreamReadWriter::new_with_writer(mapped, &mut file3)
633 .add_transformer(TarEnc::new())
634 .add_transformer(GzipEnc::new());
635 aswr.add_file_context_receiver(rx).await.unwrap();
636 aswr.process().await.unwrap();
637 }
638
639 #[tokio::test]
640 async fn hashing_transformer_test() {
641 let file = b"This is a very very important test".to_vec();
642 let mut file2 = Vec::new();
643
644 let (probe, rx) = SizeProbe::new();
645 let (md5_trans, rx2) =
646 crate::transformers::hashing_transformer::HashingTransformer::new(Md5::new());
647
648 ArunaReadWriter::new_with_writer(file.as_ref(), &mut file2)
650 .add_transformer(md5_trans)
651 .add_transformer(probe)
652 .process()
653 .await
654 .unwrap();
655
656 let size = rx.try_recv().unwrap();
657 let md5 = rx2.try_recv().unwrap();
658
659 assert_eq!(size, 34);
660 assert_eq!(md5, "4f276870b4b5f84c0b2bbfce30757176".to_string());
661 }
662
663 #[tokio::test]
664 async fn e2e_test_stream_tar_folder() {
665 let file1 = File::open("test.txt").await.unwrap();
666 let file2 = File::open("test.txt").await.unwrap();
667
668 let file1_size = file1.metadata().await.unwrap().len();
669 let file2_size = file2.metadata().await.unwrap().len();
670
671 let stream1 = tokio_util::io::ReaderStream::new(file1);
672 let stream2 = tokio_util::io::ReaderStream::new(file2);
673
674 let chained = stream1.chain(stream2);
675 let mapped = chained.map_err(|_| {
676 Box::<(dyn std::error::Error + Send + Sync + 'static)>::from("a_str_error")
677 });
678 let mut file3 = File::create("test.txt.out.tar").await.unwrap();
679
680 let (sx, rx) = async_channel::bounded(10);
681
682 sx.send((
683 FileContext {
684 file_name: "blup/".to_string(),
685 input_size: 0,
686 file_size: 0,
687 is_dir: true,
688 ..Default::default()
689 },
690 false,
691 ))
692 .await
693 .unwrap();
694
695 sx.send((
696 FileContext {
697 file_name: "blup/file1.txt".to_string(),
698 input_size: file1_size,
699 file_size: file1_size,
700 ..Default::default()
701 },
702 false,
703 ))
704 .await
705 .unwrap();
706
707 sx.send((
708 FileContext {
709 file_name: "blip/".to_string(),
710 input_size: 0,
711 file_size: 0,
712 is_dir: true,
713 ..Default::default()
714 },
715 false,
716 ))
717 .await
718 .unwrap();
719
720 sx.send((
721 FileContext {
722 file_name: "blip/file2.txt".to_string(),
723 input_size: file2_size,
724 file_size: file2_size,
725 ..Default::default()
726 },
727 true,
728 ))
729 .await
730 .unwrap();
731
732 let mut aswr = ArunaStreamReadWriter::new_with_writer(mapped, &mut file3)
734 .add_transformer(TarEnc::new());
735 aswr.add_file_context_receiver(rx).await.unwrap();
737 aswr.process().await.unwrap();
738 }
739
740 }