1
1
use std:: {
2
+ any:: Any ,
2
3
io:: { Read , Result } ,
3
4
process:: { Child , ChildStderr , ChildStdin , ChildStdout , Command , ExitStatus , Output } ,
4
5
} ;
@@ -15,22 +16,21 @@ crate::generic_wrap::Wrap!(
15
16
StdCommandWrapper ,
16
17
Child ,
17
18
StdChildWrapper ,
18
- StdChild // |child| StdChild( child)
19
+ |child| child
19
20
) ;
20
21
21
- crate :: generic_wrap:: MaybeAnyTrait ! {
22
22
/// Wrapper for `std::process::Child`.
23
23
///
24
24
/// This trait exposes most of the functionality of the underlying [`Child`]. It is implemented for
25
- /// [`StdChild`] (a thin wrapper around [`Child`]) (because implementing directly on [`Child`] would
26
- /// loop) and by wrappers.
25
+ /// [`Child`] and by wrappers.
27
26
///
28
27
/// The required methods are `inner`, `inner_mut`, and `into_inner`. That provides access to the
29
- /// underlying `Child` and allows the wrapper to be dropped and the `Child` to be used directly if
30
- /// necessary.
28
+ /// lower layer and ultimately allows the wrappers to be unwrap and the `Child` to be used directly
29
+ /// if necessary. There are convenience `inner_child`, `inner_child_mut` and `into_inner_child`
30
+ /// methods on the trait object.
31
31
///
32
32
/// It also makes it possible for all the other methods to have default implementations. Some are
33
- /// direct passthroughs to the underlying `Child` , while others are more complex.
33
+ /// direct passthroughs to the lower layers , while others are more complex.
34
34
///
35
35
/// Here's a simple example of a wrapper:
36
36
///
@@ -42,32 +42,32 @@ crate::generic_wrap::MaybeAnyTrait! {
42
42
/// pub struct YourChildWrapper(Child);
43
43
///
44
44
/// impl StdChildWrapper for YourChildWrapper {
45
- /// fn inner(&self) -> &Child {
45
+ /// fn inner(&self) -> &dyn StdChildWrapper {
46
46
/// &self.0
47
47
/// }
48
48
///
49
- /// fn inner_mut(&mut self) -> &mut Child {
49
+ /// fn inner_mut(&mut self) -> &mut dyn StdChildWrapper {
50
50
/// &mut self.0
51
51
/// }
52
52
///
53
- /// fn into_inner(self: Box<Self>) -> Child {
54
- /// ( *self).0
53
+ /// fn into_inner(self: Box<Self>) -> Box<dyn StdChildWrapper> {
54
+ /// Box::new(( *self).0)
55
55
/// }
56
56
/// }
57
57
/// ```
58
- pub trait StdChildWrapper {
59
- /// Obtain a reference to the underlying `Child` .
60
- fn inner( & self ) -> & Child ;
58
+ pub trait StdChildWrapper : Any + std :: fmt :: Debug + Send {
59
+ /// Obtain a reference to the wrapped child .
60
+ fn inner ( & self ) -> & dyn StdChildWrapper ;
61
61
62
- /// Obtain a mutable reference to the underlying `Child` .
63
- fn inner_mut( & mut self ) -> & mut Child ;
62
+ /// Obtain a mutable reference to the wrapped child .
63
+ fn inner_mut ( & mut self ) -> & mut dyn StdChildWrapper ;
64
64
65
- /// Consume the wrapper and return the underlying `Child` .
65
+ /// Consume the current wrapper and return the wrapped child .
66
66
///
67
- /// Note that this may disrupt whatever the wrappers were doing. However, wrappers must ensure
68
- /// that the `Child` is in a consistent state when this is called or they are dropped, so that
69
- /// this is always safe.
70
- fn into_inner( self : Box <Self >) -> Child ;
67
+ /// Note that this may disrupt whatever the current wrapper was doing. However, wrappers must
68
+ /// ensure that the wrapped child is in a consistent state when this is called or they are
69
+ /// dropped, so that this is always safe.
70
+ fn into_inner ( self : Box < Self > ) -> Box < dyn StdChildWrapper > ;
71
71
72
72
/// Obtain a clone if possible.
73
73
///
@@ -79,23 +79,23 @@ pub trait StdChildWrapper {
79
79
80
80
/// Obtain the `Child`'s stdin.
81
81
///
82
- /// By default this is a passthrough to the underlying `Child` .
82
+ /// By default this is a passthrough to the wrapped child .
83
83
fn stdin ( & mut self ) -> & mut Option < ChildStdin > {
84
- & mut self . inner_mut( ) . stdin
84
+ self . inner_mut ( ) . stdin ( )
85
85
}
86
86
87
87
/// Obtain the `Child`'s stdout.
88
88
///
89
- /// By default this is a passthrough to the underlying `Child` .
89
+ /// By default this is a passthrough to the wrapped child .
90
90
fn stdout ( & mut self ) -> & mut Option < ChildStdout > {
91
- & mut self . inner_mut( ) . stdout
91
+ self . inner_mut ( ) . stdout ( )
92
92
}
93
93
94
94
/// Obtain the `Child`'s stderr.
95
95
///
96
- /// By default this is a passthrough to the underlying `Child` .
96
+ /// By default this is a passthrough to the wrapped child .
97
97
fn stderr ( & mut self ) -> & mut Option < ChildStderr > {
98
- & mut self . inner_mut( ) . stderr
98
+ self . inner_mut ( ) . stderr ( )
99
99
}
100
100
101
101
/// Obtain the `Child`'s process ID.
@@ -127,15 +127,7 @@ pub trait StdChildWrapper {
127
127
/// library uses it to provide a consistent API across both std and Tokio (and because it's a
128
128
/// generally useful API).
129
129
fn start_kill ( & mut self ) -> Result < ( ) > {
130
- #[ cfg( unix) ]
131
- {
132
- self . signal( Signal :: SIGKILL as _)
133
- }
134
-
135
- #[ cfg( not( unix) ) ]
136
- {
137
- self . inner_mut( ) . kill( )
138
- }
130
+ self . inner_mut ( ) . start_kill ( )
139
131
}
140
132
141
133
/// Check if the `Child` has exited without blocking, and if so, return its exit status.
@@ -204,6 +196,51 @@ pub trait StdChildWrapper {
204
196
/// was introduced by command-group to abstract over the signal behaviour between process groups
205
197
/// and unwrapped processes.
206
198
#[ cfg( unix) ]
199
+ fn signal ( & self , sig : i32 ) -> Result < ( ) > {
200
+ self . inner ( ) . signal ( sig)
201
+ }
202
+ }
203
+
204
+ impl StdChildWrapper for Child {
205
+ fn inner ( & self ) -> & dyn StdChildWrapper {
206
+ self
207
+ }
208
+ fn inner_mut ( & mut self ) -> & mut dyn StdChildWrapper {
209
+ self
210
+ }
211
+ fn into_inner ( self : Box < Self > ) -> Box < dyn StdChildWrapper > {
212
+ self
213
+ }
214
+ fn stdin ( & mut self ) -> & mut Option < ChildStdin > {
215
+ & mut self . stdin
216
+ }
217
+ fn stdout ( & mut self ) -> & mut Option < ChildStdout > {
218
+ & mut self . stdout
219
+ }
220
+ fn stderr ( & mut self ) -> & mut Option < ChildStderr > {
221
+ & mut self . stderr
222
+ }
223
+ fn id ( & self ) -> u32 {
224
+ Child :: id ( self )
225
+ }
226
+ fn start_kill ( & mut self ) -> Result < ( ) > {
227
+ #[ cfg( unix) ]
228
+ {
229
+ self . signal ( Signal :: SIGKILL as _ )
230
+ }
231
+
232
+ #[ cfg( not( unix) ) ]
233
+ {
234
+ Child :: kill ( self )
235
+ }
236
+ }
237
+ fn try_wait ( & mut self ) -> Result < Option < ExitStatus > > {
238
+ Child :: try_wait ( self )
239
+ }
240
+ fn wait ( & mut self ) -> Result < ExitStatus > {
241
+ Child :: wait ( self )
242
+ }
243
+ #[ cfg( unix) ]
207
244
fn signal ( & self , sig : i32 ) -> Result < ( ) > {
208
245
kill (
209
246
Pid :: from_raw ( i32:: try_from ( self . id ( ) ) . map_err ( std:: io:: Error :: other) ?) ,
@@ -212,25 +249,51 @@ pub trait StdChildWrapper {
212
249
. map_err ( std:: io:: Error :: from)
213
250
}
214
251
}
215
- }
216
252
217
- /// A thin wrapper around [`Child`].
218
- ///
219
- /// This is used only because implementing [`StdChildWrapper`] directly on std's [`Child`] creates
220
- /// loops in the type system. It is not intended to be used directly, but only to be used internally
221
- /// by the library.
222
- #[ derive( Debug ) ]
223
- pub struct StdChild ( pub Child ) ;
224
-
225
- impl StdChildWrapper for StdChild {
226
- fn inner ( & self ) -> & Child {
227
- & self . 0
253
+ impl dyn StdChildWrapper {
254
+ fn downcast_ref < T : ' static > ( & self ) -> Option < & T > {
255
+ ( self as & dyn Any ) . downcast_ref ( )
228
256
}
229
- fn inner_mut ( & mut self ) -> & mut Child {
230
- & mut self . 0
257
+
258
+ fn is_raw_child ( & self ) -> bool {
259
+ self . downcast_ref :: < Child > ( ) . is_some ( )
260
+ }
261
+
262
+ /// Obtain a reference to the underlying [`Child`].
263
+ pub fn inner_child ( & self ) -> & Child {
264
+ let mut inner = self ;
265
+ while !inner. is_raw_child ( ) {
266
+ inner = inner. inner ( ) ;
267
+ }
268
+
269
+ // UNWRAP: we've just checked that it's Some with is_raw_child()
270
+ inner. downcast_ref ( ) . unwrap ( )
271
+ }
272
+
273
+ /// Obtain a mutable reference to the underlying [`Child`].
274
+ ///
275
+ /// Modifying the raw child may be unsound depending on the layering of wrappers.
276
+ pub unsafe fn inner_child_mut ( & mut self ) -> & mut Child {
277
+ let mut inner = self ;
278
+ while !inner. is_raw_child ( ) {
279
+ inner = inner. inner_mut ( ) ;
280
+ }
281
+
282
+ // UNWRAP: we've just checked that with is_raw_child()
283
+ ( inner as & mut dyn Any ) . downcast_mut ( ) . unwrap ( )
231
284
}
232
- fn into_inner ( self : Box < Self > ) -> Child {
233
- ( * self ) . 0
285
+
286
+ /// Obtain the underlying [`Child`].
287
+ ///
288
+ /// Unwrapping everything may be unsound depending on the state of the wrappers.
289
+ pub unsafe fn into_inner_child ( self : Box < Self > ) -> Child {
290
+ let mut inner = self ;
291
+ while !inner. is_raw_child ( ) {
292
+ inner = inner. into_inner ( ) ;
293
+ }
294
+
295
+ // UNWRAP: we've just checked that with is_raw_child()
296
+ * ( inner as Box < dyn Any > ) . downcast ( ) . unwrap ( )
234
297
}
235
298
}
236
299
0 commit comments