conch_runtime_pshaw/env/fd_manager/
tokio.rs

1use crate::env::{
2    ArcFileDescOpenerEnv, ArcUnwrappingAsyncIoEnv, AsyncIoEnvironment, FileDescEnv,
3    FileDescEnvironment, FileDescManagerEnv, FileDescOpener, FileDescOpenerEnv, Pipe,
4    SubEnvironment, TokioAsyncIoEnv,
5};
6use crate::io::{FileDesc, Permissions};
7use crate::Fd;
8use futures_core::future::BoxFuture;
9use std::borrow::Cow;
10use std::fs::OpenOptions;
11use std::io;
12use std::path::Path;
13use std::sync::Arc;
14
15/// An environment implementation which manages opening, storing, and performing
16/// async I/O operations on file descriptor handles via `tokio`.
17#[derive(Default, Debug, Clone)]
18pub struct TokioFileDescManagerEnv {
19    inner: FileDescManagerEnv<
20        ArcFileDescOpenerEnv<FileDescOpenerEnv>,
21        FileDescEnv<Arc<FileDesc>>,
22        ArcUnwrappingAsyncIoEnv<TokioAsyncIoEnv>,
23    >,
24}
25
26impl TokioFileDescManagerEnv {
27    fn with_fd_env(env: FileDescEnv<Arc<FileDesc>>) -> Self {
28        Self {
29            inner: FileDescManagerEnv::new(
30                ArcFileDescOpenerEnv::new(FileDescOpenerEnv::new()),
31                env,
32                ArcUnwrappingAsyncIoEnv::new(TokioAsyncIoEnv::new()),
33            ),
34        }
35    }
36
37    /// Create a new environment using specific opener/storer/async implementations.
38    pub fn new() -> Self {
39        Self::with_fd_env(FileDescEnv::new())
40    }
41
42    /// Constructs a new environment with no open file descriptors,
43    /// but with a specified capacity for storing open file descriptors.
44    pub fn with_capacity(capacity: usize) -> Self {
45        Self::with_fd_env(FileDescEnv::with_capacity(capacity))
46    }
47
48    /// Constructs a new environment and initializes it with duplicated
49    /// stdio file descriptors or handles of the current process.
50    pub fn with_process_stdio() -> io::Result<Self> {
51        Ok(Self::with_fd_env(FileDescEnv::with_process_stdio()?))
52    }
53}
54
55impl SubEnvironment for TokioFileDescManagerEnv {
56    fn sub_env(&self) -> Self {
57        Self {
58            inner: self.inner.sub_env(),
59        }
60    }
61}
62
63impl FileDescOpener for TokioFileDescManagerEnv {
64    type OpenedFileHandle = Arc<FileDesc>;
65
66    fn open_path(&mut self, path: &Path, opts: &OpenOptions) -> io::Result<Self::OpenedFileHandle> {
67        self.inner.open_path(path, opts)
68    }
69
70    fn open_pipe(&mut self) -> io::Result<Pipe<Self::OpenedFileHandle>> {
71        self.inner.open_pipe()
72    }
73}
74
75impl FileDescEnvironment for TokioFileDescManagerEnv {
76    type FileHandle = Arc<FileDesc>;
77
78    fn file_desc(&self, fd: Fd) -> Option<(&Self::FileHandle, Permissions)> {
79        self.inner.file_desc(fd)
80    }
81
82    fn set_file_desc(&mut self, fd: Fd, handle: Self::FileHandle, perms: Permissions) {
83        self.inner.set_file_desc(fd, handle, perms)
84    }
85
86    fn close_file_desc(&mut self, fd: Fd) {
87        self.inner.close_file_desc(fd);
88    }
89}
90
91impl AsyncIoEnvironment for TokioFileDescManagerEnv {
92    type IoHandle = Arc<FileDesc>;
93
94    fn read_all(&mut self, fd: Self::IoHandle) -> BoxFuture<'static, io::Result<Vec<u8>>> {
95        self.inner.read_all(fd)
96    }
97
98    fn write_all<'a>(
99        &mut self,
100        fd: Self::IoHandle,
101        data: Cow<'a, [u8]>,
102    ) -> BoxFuture<'a, io::Result<()>> {
103        self.inner.write_all(fd, data)
104    }
105
106    fn write_all_best_effort(&mut self, fd: Self::IoHandle, data: Vec<u8>) {
107        self.inner.write_all_best_effort(fd, data)
108    }
109}