conch_runtime_pshaw/
spawn.rs1use crate::ExitStatus;
4use async_trait::async_trait;
5use futures_core::future::BoxFuture;
6
7mod and_or;
8mod case;
9mod for_cmd;
10mod func_exec;
11mod if_cmd;
12mod local_redirections;
13mod loop_cmd;
14mod pipeline;
15mod sequence;
16mod simple;
17mod subshell;
18mod substitution;
19mod swallow_non_fatal;
20
21#[cfg(feature = "conch-parser")]
22pub mod ast_impl;
23pub mod builtin;
24
25pub use self::and_or::{and_or_list, AndOr};
27pub use self::case::{case, PatternBodyPair};
28pub use self::for_cmd::{for_args, for_loop, for_with_args};
29pub use self::func_exec::{function, function_body};
30pub use self::if_cmd::if_cmd;
31pub use self::local_redirections::spawn_with_local_redirections_and_restorer;
32pub use self::loop_cmd::loop_cmd;
33pub use self::pipeline::pipeline;
34pub use self::sequence::{sequence, sequence_exact, sequence_slice, SequenceSlice};
35pub use self::simple::{simple_command, simple_command_with_restorer};
36pub use self::subshell::subshell;
37pub use self::substitution::substitution;
38pub use self::swallow_non_fatal::swallow_non_fatal_errors;
39
40#[async_trait]
52pub trait Spawn<E: ?Sized> {
53 type Error;
55
56 async fn spawn(&self, env: &mut E) -> Result<BoxFuture<'static, ExitStatus>, Self::Error>;
75}
76
77impl<'a, T, E> Spawn<E> for &'a T
78where
79 T: ?Sized + Spawn<E>,
80 E: ?Sized,
81{
82 type Error = T::Error;
83
84 fn spawn<'life0, 'life1, 'async_trait>(
85 &'life0 self,
86 env: &'life1 mut E,
87 ) -> BoxFuture<'async_trait, Result<BoxFuture<'static, ExitStatus>, Self::Error>>
88 where
89 'life0: 'async_trait,
90 'life1: 'async_trait,
91 Self: 'async_trait,
92 {
93 (**self).spawn(env)
94 }
95}
96
97impl<T, E> Spawn<E> for Box<T>
98where
99 T: ?Sized + Spawn<E>,
100 E: ?Sized,
101{
102 type Error = T::Error;
103
104 fn spawn<'life0, 'life1, 'async_trait>(
105 &'life0 self,
106 env: &'life1 mut E,
107 ) -> BoxFuture<'async_trait, Result<BoxFuture<'static, ExitStatus>, Self::Error>>
108 where
109 'life0: 'async_trait,
110 'life1: 'async_trait,
111 Self: 'async_trait,
112 {
113 (**self).spawn(env)
114 }
115}
116
117impl<T, E> Spawn<E> for std::sync::Arc<T>
118where
119 T: ?Sized + Spawn<E>,
120 E: ?Sized,
121{
122 type Error = T::Error;
123
124 fn spawn<'life0, 'life1, 'async_trait>(
125 &'life0 self,
126 env: &'life1 mut E,
127 ) -> BoxFuture<'async_trait, Result<BoxFuture<'static, ExitStatus>, Self::Error>>
128 where
129 'life0: 'async_trait,
130 'life1: 'async_trait,
131 Self: 'async_trait,
132 {
133 (**self).spawn(env)
134 }
135}
136
137#[derive(Debug, PartialEq, Eq, Clone)]
139pub struct GuardBodyPair<T> {
140 pub guard: T,
143 pub body: T,
145}
146
147#[cfg(test)]
148mod test {
149 use super::Spawn;
150 use crate::{ExitStatus, EXIT_SUCCESS};
151 use futures_core::future::BoxFuture;
152 use std::sync::Arc;
153
154 #[test]
155 fn check_spawn_impls() {
156 struct Dummy;
157
158 #[async_trait::async_trait]
159 impl<E> Spawn<E> for Dummy
160 where
161 E: ?Sized + Send,
162 {
163 type Error = ();
164
165 async fn spawn(
166 &self,
167 _: &mut E,
168 ) -> Result<BoxFuture<'static, ExitStatus>, Self::Error> {
169 Ok(Box::pin(async { EXIT_SUCCESS }))
170 }
171 }
172
173 fn assert_spawn<T: Spawn<()>>() {}
174
175 assert_spawn::<Dummy>();
176 assert_spawn::<&Dummy>();
177 assert_spawn::<&&Dummy>();
178
179 assert_spawn::<Box<Dummy>>();
180 assert_spawn::<Box<&Dummy>>();
181 assert_spawn::<Box<dyn Spawn<(), Error = ()>>>();
182
183 assert_spawn::<Arc<Dummy>>();
184 assert_spawn::<&Arc<Dummy>>();
185 assert_spawn::<Arc<dyn Spawn<(), Error = ()>>>();
186 }
187}