taskcluster_upload/
factory.rs1use anyhow::Result;
2use async_trait::async_trait;
3use std::io::{Cursor, SeekFrom};
4use tokio::fs::File;
5use tokio::io::{AsyncRead, AsyncSeekExt};
6
7#[async_trait]
11pub trait AsyncReaderFactory {
12 async fn get_reader<'a>(
14 &'a mut self,
15 ) -> Result<Box<dyn AsyncRead + Sync + Send + Unpin + 'static>>;
16}
17
18pub struct CursorReaderFactory(Vec<u8>);
22
23#[async_trait]
24impl AsyncReaderFactory for CursorReaderFactory {
25 async fn get_reader(&mut self) -> Result<Box<dyn AsyncRead + Sync + Send + Unpin + 'static>> {
26 Ok(Box::new(Cursor::new(self.0.clone())))
27 }
28}
29
30impl CursorReaderFactory {
31 pub fn new(buf: &[u8]) -> Self {
32 Self(buf.to_vec())
33 }
34}
35
36pub struct FileReaderFactory(File);
39
40#[async_trait]
41impl AsyncReaderFactory for FileReaderFactory {
42 async fn get_reader<'a>(
43 &'a mut self,
44 ) -> Result<Box<dyn AsyncRead + Sync + Send + Unpin + 'static>> {
45 let mut file = self.0.try_clone().await?;
46 file.seek(SeekFrom::Start(0)).await?;
47 Ok(Box::new(file))
48 }
49}
50
51impl FileReaderFactory {
52 pub fn new(file: File) -> Self {
53 Self(file)
54 }
55}
56
57#[cfg(test)]
58mod test {
59 use super::*;
60 use anyhow::Result;
61 use tempfile::tempfile;
62 use tokio::io::{copy, AsyncWriteExt};
63
64 const DATA: &[u8] = b"HELLO/WORLD";
65
66 async fn copy_from_factory<F: AsyncReaderFactory>(factory: &mut F) -> std::io::Result<Vec<u8>> {
67 let mut reader = factory.get_reader().await.unwrap();
68 let mut writer = Cursor::new(Vec::new());
69 copy(&mut reader, &mut writer).await?;
70 Ok(writer.into_inner())
71 }
72
73 #[tokio::test]
74 async fn cursor_reader_twice() -> Result<()> {
75 let mut factory = CursorReaderFactory::new(DATA);
76 assert_eq!(©_from_factory(&mut factory).await?, DATA);
77 assert_eq!(©_from_factory(&mut factory).await?, DATA);
78 Ok(())
79 }
80
81 #[tokio::test]
82 async fn file_reader_twice() -> Result<()> {
83 let mut file: File = tempfile()?.into();
84
85 file.write_all(DATA).await?;
86 file.flush().await?;
90
91 let mut factory = FileReaderFactory::new(file);
92 assert_eq!(©_from_factory(&mut factory).await?, DATA);
93 assert_eq!(©_from_factory(&mut factory).await?, DATA);
94 Ok(())
95 }
96}