Skip to main content

virtual_file_transfer/
factory_source.rs

1use crate::{FileSource, SourceReader};
2use std::io;
3
4/// Adapts a reader-producing closure into a [`FileSource`].
5///
6/// The closure is called whenever the receiving application requests a new
7/// stream. It must create an independent reader on every invocation.
8///
9/// Use a closure that implements `Fn() -> io::Result<SourceReader>` and is
10/// `Send + Sync`.
11pub struct FactorySource<F> {
12    open: F,
13}
14
15impl<F> FactorySource<F>
16where
17    F: Fn() -> io::Result<SourceReader> + Send + Sync,
18{
19    /// Creates a file source using the supplied reader factory.
20    ///
21    /// The factory is evaluated lazily when [`FileSource::open`] is called,
22    /// rather than when this value is constructed.
23    pub fn new(open: F) -> Self {
24        Self { open }
25    }
26}
27
28impl<F> FileSource for FactorySource<F>
29where
30    F: Fn() -> io::Result<SourceReader> + Send + Sync,
31{
32    fn open(&self) -> io::Result<SourceReader> {
33        (self.open)()
34    }
35}
36
37#[cfg(test)]
38mod tests {
39
40    use super::*;
41    use std::io::Read;
42
43    #[test]
44    fn factory_source_opens_reader() {
45        let source = FactorySource::new(|| {
46            Ok(SourceReader::seekable(std::io::Cursor::new(
47                b"hello".to_vec(),
48            )))
49        });
50
51        let mut reader = source.open().unwrap();
52
53        let mut buffer = Vec::new();
54        reader.read_to_end(&mut buffer).unwrap();
55
56        assert_eq!(buffer, b"hello");
57    }
58
59    #[test]
60    fn factory_source_creates_independent_readers() {
61        let source = FactorySource::new(|| {
62            Ok(SourceReader::seekable(std::io::Cursor::new(
63                b"hello".to_vec(),
64            )))
65        });
66
67        let mut first = source.open().unwrap();
68        let mut second = source.open().unwrap();
69
70        let mut buffer = [0u8; 1];
71
72        first.read_exact(&mut buffer).unwrap();
73        assert_eq!(&buffer, b"h");
74
75        second.read_exact(&mut buffer).unwrap();
76        assert_eq!(&buffer, b"h");
77    }
78}