conch_runtime_pshaw/env/
fd_manager.rs

1use crate::env::{AsyncIoEnvironment, FileDescEnvironment, FileDescOpener, Pipe, SubEnvironment};
2use crate::io::Permissions;
3use crate::Fd;
4use futures_core::future::BoxFuture;
5use std::borrow::Cow;
6use std::fs::OpenOptions;
7use std::io;
8use std::path::Path;
9
10mod tokio;
11pub use self::tokio::TokioFileDescManagerEnv;
12
13/// A marker trait for implementations which can open, store, and perform
14/// async I/O operations on file handles.
15pub trait FileDescManagerEnvironment:
16    FileDescOpener
17    + FileDescEnvironment<FileHandle = <Self as FileDescOpener>::OpenedFileHandle>
18    + AsyncIoEnvironment<IoHandle = <Self as FileDescOpener>::OpenedFileHandle>
19{
20}
21
22impl<T> FileDescManagerEnvironment for T
23where
24    T: FileDescOpener,
25    T: FileDescEnvironment<FileHandle = <T as FileDescOpener>::OpenedFileHandle>,
26    T: AsyncIoEnvironment<IoHandle = <T as FileDescOpener>::OpenedFileHandle>,
27{
28}
29
30/// An environment implementation which manages opening, storing, and performing
31/// async I/O operations on file descriptor handles.
32#[derive(Default, Debug, Clone, PartialEq, Eq)]
33pub struct FileDescManagerEnv<O, S, A> {
34    opener: O,
35    storer: S,
36    async_env: A,
37}
38
39impl<O, S, A> FileDescManagerEnv<O, S, A> {
40    /// Create a new environment using specific opener/storer/async implementations.
41    pub fn new(opener: O, storer: S, async_env: A) -> Self {
42        Self {
43            opener,
44            storer,
45            async_env,
46        }
47    }
48}
49
50impl<O, S, A> SubEnvironment for FileDescManagerEnv<O, S, A>
51where
52    O: SubEnvironment,
53    S: SubEnvironment,
54    A: SubEnvironment,
55{
56    fn sub_env(&self) -> Self {
57        Self {
58            opener: self.opener.sub_env(),
59            storer: self.storer.sub_env(),
60            async_env: self.async_env.sub_env(),
61        }
62    }
63}
64
65impl<O, S, A> FileDescOpener for FileDescManagerEnv<O, S, A>
66where
67    O: FileDescOpener,
68    A: AsyncIoEnvironment,
69    A::IoHandle: From<O::OpenedFileHandle>,
70{
71    type OpenedFileHandle = A::IoHandle;
72
73    fn open_path(&mut self, path: &Path, opts: &OpenOptions) -> io::Result<Self::OpenedFileHandle> {
74        self.opener
75            .open_path(path, opts)
76            .map(Self::OpenedFileHandle::from)
77    }
78
79    fn open_pipe(&mut self) -> io::Result<Pipe<Self::OpenedFileHandle>> {
80        self.opener.open_pipe().map(|pipe| Pipe {
81            reader: pipe.reader.into(),
82            writer: pipe.writer.into(),
83        })
84    }
85}
86
87impl<O, S, A> FileDescEnvironment for FileDescManagerEnv<O, S, A>
88where
89    S: FileDescEnvironment,
90{
91    type FileHandle = S::FileHandle;
92
93    fn file_desc(&self, fd: Fd) -> Option<(&Self::FileHandle, Permissions)> {
94        self.storer.file_desc(fd)
95    }
96
97    fn set_file_desc(&mut self, fd: Fd, handle: Self::FileHandle, perms: Permissions) {
98        self.storer.set_file_desc(fd, handle, perms)
99    }
100
101    fn close_file_desc(&mut self, fd: Fd) {
102        self.storer.close_file_desc(fd)
103    }
104}
105
106impl<O, S, A> AsyncIoEnvironment for FileDescManagerEnv<O, S, A>
107where
108    A: AsyncIoEnvironment,
109{
110    type IoHandle = A::IoHandle;
111
112    fn read_all(&mut self, fd: Self::IoHandle) -> BoxFuture<'static, io::Result<Vec<u8>>> {
113        self.async_env.read_all(fd)
114    }
115
116    fn write_all<'a>(
117        &mut self,
118        fd: Self::IoHandle,
119        data: Cow<'a, [u8]>,
120    ) -> BoxFuture<'a, io::Result<()>> {
121        self.async_env.write_all(fd, data)
122    }
123
124    fn write_all_best_effort(&mut self, fd: Self::IoHandle, data: Vec<u8>) {
125        self.async_env.write_all_best_effort(fd, data);
126    }
127}