@@ -310,6 +310,8 @@ pub use self::error::RawOsError;
310
310
pub use self :: error:: SimpleMessage ;
311
311
#[ unstable( feature = "io_const_error" , issue = "133448" ) ]
312
312
pub use self :: error:: const_error;
313
+ #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
314
+ pub use self :: pipe:: { PipeReader , PipeWriter , pipe} ;
313
315
#[ stable( feature = "is_terminal" , since = "1.70.0" ) ]
314
316
pub use self :: stdio:: IsTerminal ;
315
317
pub ( crate ) use self :: stdio:: attempt_print_to_stderr;
@@ -330,14 +332,14 @@ pub use self::{
330
332
} ;
331
333
use crate :: mem:: take;
332
334
use crate :: ops:: { Deref , DerefMut } ;
333
- use crate :: sys:: anonymous_pipe:: { AnonPipe , pipe as pipe_inner} ;
334
335
use crate :: { cmp, fmt, slice, str, sys} ;
335
336
336
337
mod buffered;
337
338
pub ( crate ) mod copy;
338
339
mod cursor;
339
340
mod error;
340
341
mod impls;
342
+ mod pipe;
341
343
pub mod prelude;
342
344
mod stdio;
343
345
mod util;
@@ -3251,257 +3253,3 @@ impl<B: BufRead> Iterator for Lines<B> {
3251
3253
}
3252
3254
}
3253
3255
}
3254
-
3255
- /// Create an anonymous pipe that is close-on-exec and blocking.
3256
- ///
3257
- /// # Behavior
3258
- ///
3259
- /// A pipe is a one-way data channel provided by the OS, which works across processes. A pipe is
3260
- /// typically used to communicate between two or more separate processes, as there are better,
3261
- /// faster ways to communicate within a single process.
3262
- ///
3263
- /// In particular:
3264
- ///
3265
- /// * A read on a [`PipeReader`] blocks until the pipe is non-empty.
3266
- /// * A write on a [`PipeWriter`] blocks when the pipe is full.
3267
- /// * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
3268
- /// returns EOF.
3269
- /// * [`PipeWriter`] can be shared, and multiple processes or threads can write to it at once, but
3270
- /// writes (above a target-specific threshold) may have their data interleaved.
3271
- /// * [`PipeReader`] can be shared, and multiple processes or threads can read it at once. Any
3272
- /// given byte will only get consumed by one reader. There are no guarantees about data
3273
- /// interleaving.
3274
- /// * Portable applications cannot assume any atomicity of messages larger than a single byte.
3275
- ///
3276
- /// # Capacity
3277
- ///
3278
- /// Pipe capacity is platform dependent. To quote the Linux [man page]:
3279
- ///
3280
- /// > Different implementations have different limits for the pipe capacity. Applications should
3281
- /// > not rely on a particular capacity: an application should be designed so that a reading process
3282
- /// > consumes data as soon as it is available, so that a writing process does not remain blocked.
3283
- ///
3284
- /// # Examples
3285
- ///
3286
- /// ```no_run
3287
- /// #![feature(anonymous_pipe)]
3288
- /// # #[cfg(miri)] fn main() {}
3289
- /// # #[cfg(not(miri))]
3290
- /// # fn main() -> std::io::Result<()> {
3291
- /// # use std::process::Command;
3292
- /// # use std::io::{Read, Write};
3293
- /// let (ping_rx, mut ping_tx) = std::io::pipe()?;
3294
- /// let (mut pong_rx, pong_tx) = std::io::pipe()?;
3295
- ///
3296
- /// // Spawn a process that echoes its input.
3297
- /// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
3298
- ///
3299
- /// ping_tx.write_all(b"hello")?;
3300
- /// // Close to unblock echo_server's reader.
3301
- /// drop(ping_tx);
3302
- ///
3303
- /// let mut buf = String::new();
3304
- /// // Block until echo_server's writer is closed.
3305
- /// pong_rx.read_to_string(&mut buf)?;
3306
- /// assert_eq!(&buf, "hello");
3307
- ///
3308
- /// echo_server.wait()?;
3309
- /// # Ok(())
3310
- /// # }
3311
- /// ```
3312
- /// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
3313
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3314
- #[ inline]
3315
- pub fn pipe ( ) -> Result < ( PipeReader , PipeWriter ) > {
3316
- pipe_inner ( ) . map ( |( reader, writer) | ( PipeReader ( reader) , PipeWriter ( writer) ) )
3317
- }
3318
-
3319
- /// Read end of an anonymous pipe.
3320
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3321
- #[ derive( Debug ) ]
3322
- pub struct PipeReader ( pub ( crate ) AnonPipe ) ;
3323
-
3324
- /// Write end of an anonymous pipe.
3325
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3326
- #[ derive( Debug ) ]
3327
- pub struct PipeWriter ( pub ( crate ) AnonPipe ) ;
3328
-
3329
- impl PipeReader {
3330
- /// Create a new [`PipeReader`] instance that shares the same underlying file description.
3331
- ///
3332
- /// # Examples
3333
- ///
3334
- /// ```no_run
3335
- /// #![feature(anonymous_pipe)]
3336
- /// # #[cfg(miri)] fn main() {}
3337
- /// # #[cfg(not(miri))]
3338
- /// # fn main() -> std::io::Result<()> {
3339
- /// # use std::fs;
3340
- /// # use std::io::Write;
3341
- /// # use std::process::Command;
3342
- /// const NUM_SLOT: u8 = 2;
3343
- /// const NUM_PROC: u8 = 5;
3344
- /// const OUTPUT: &str = "work.txt";
3345
- ///
3346
- /// let mut jobs = vec![];
3347
- /// let (reader, mut writer) = std::io::pipe()?;
3348
- ///
3349
- /// // Write NUM_SLOT characters the pipe.
3350
- /// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
3351
- ///
3352
- /// // Spawn several processes that read a character from the pipe, do some work, then
3353
- /// // write back to the pipe. When the pipe is empty, the processes block, so only
3354
- /// // NUM_SLOT processes can be working at any given time.
3355
- /// for _ in 0..NUM_PROC {
3356
- /// jobs.push(
3357
- /// Command::new("bash")
3358
- /// .args(["-c",
3359
- /// &format!(
3360
- /// "read -n 1\n\
3361
- /// echo -n 'x' >> '{OUTPUT}'\n\
3362
- /// echo -n '|'",
3363
- /// ),
3364
- /// ])
3365
- /// .stdin(reader.try_clone()?)
3366
- /// .stdout(writer.try_clone()?)
3367
- /// .spawn()?,
3368
- /// );
3369
- /// }
3370
- ///
3371
- /// // Wait for all jobs to finish.
3372
- /// for mut job in jobs {
3373
- /// job.wait()?;
3374
- /// }
3375
- ///
3376
- /// // Check our work and clean up.
3377
- /// let xs = fs::read_to_string(OUTPUT)?;
3378
- /// fs::remove_file(OUTPUT)?;
3379
- /// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
3380
- /// # Ok(())
3381
- /// # }
3382
- /// ```
3383
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3384
- pub fn try_clone ( & self ) -> Result < Self > {
3385
- self . 0 . try_clone ( ) . map ( Self )
3386
- }
3387
- }
3388
-
3389
- impl PipeWriter {
3390
- /// Create a new [`PipeWriter`] instance that shares the same underlying file description.
3391
- ///
3392
- /// # Examples
3393
- ///
3394
- /// ```no_run
3395
- /// #![feature(anonymous_pipe)]
3396
- /// # #[cfg(miri)] fn main() {}
3397
- /// # #[cfg(not(miri))]
3398
- /// # fn main() -> std::io::Result<()> {
3399
- /// # use std::process::Command;
3400
- /// # use std::io::Read;
3401
- /// let (mut reader, writer) = std::io::pipe()?;
3402
- ///
3403
- /// // Spawn a process that writes to stdout and stderr.
3404
- /// let mut peer = Command::new("bash")
3405
- /// .args([
3406
- /// "-c",
3407
- /// "echo -n foo\n\
3408
- /// echo -n bar >&2"
3409
- /// ])
3410
- /// .stdout(writer.try_clone()?)
3411
- /// .stderr(writer)
3412
- /// .spawn()?;
3413
- ///
3414
- /// // Read and check the result.
3415
- /// let mut msg = String::new();
3416
- /// reader.read_to_string(&mut msg)?;
3417
- /// assert_eq!(&msg, "foobar");
3418
- ///
3419
- /// peer.wait()?;
3420
- /// # Ok(())
3421
- /// # }
3422
- /// ```
3423
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3424
- pub fn try_clone ( & self ) -> Result < Self > {
3425
- self . 0 . try_clone ( ) . map ( Self )
3426
- }
3427
- }
3428
-
3429
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3430
- impl Read for & PipeReader {
3431
- fn read ( & mut self , buf : & mut [ u8 ] ) -> Result < usize > {
3432
- self . 0 . read ( buf)
3433
- }
3434
- fn read_vectored ( & mut self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> Result < usize > {
3435
- self . 0 . read_vectored ( bufs)
3436
- }
3437
- #[ inline]
3438
- fn is_read_vectored ( & self ) -> bool {
3439
- self . 0 . is_read_vectored ( )
3440
- }
3441
- fn read_to_end ( & mut self , buf : & mut Vec < u8 > ) -> Result < usize > {
3442
- self . 0 . read_to_end ( buf)
3443
- }
3444
- fn read_buf ( & mut self , buf : BorrowedCursor < ' _ > ) -> Result < ( ) > {
3445
- self . 0 . read_buf ( buf)
3446
- }
3447
- }
3448
-
3449
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3450
- impl Read for PipeReader {
3451
- fn read ( & mut self , buf : & mut [ u8 ] ) -> Result < usize > {
3452
- self . 0 . read ( buf)
3453
- }
3454
- fn read_vectored ( & mut self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> Result < usize > {
3455
- self . 0 . read_vectored ( bufs)
3456
- }
3457
- #[ inline]
3458
- fn is_read_vectored ( & self ) -> bool {
3459
- self . 0 . is_read_vectored ( )
3460
- }
3461
- fn read_to_end ( & mut self , buf : & mut Vec < u8 > ) -> Result < usize > {
3462
- self . 0 . read_to_end ( buf)
3463
- }
3464
- fn read_buf ( & mut self , buf : BorrowedCursor < ' _ > ) -> Result < ( ) > {
3465
- self . 0 . read_buf ( buf)
3466
- }
3467
- }
3468
-
3469
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3470
- impl Write for & PipeWriter {
3471
- fn write ( & mut self , buf : & [ u8 ] ) -> Result < usize > {
3472
- self . 0 . write ( buf)
3473
- }
3474
- #[ inline]
3475
- fn flush ( & mut self ) -> Result < ( ) > {
3476
- Ok ( ( ) )
3477
- }
3478
-
3479
- fn write_vectored ( & mut self , bufs : & [ IoSlice < ' _ > ] ) -> Result < usize > {
3480
- self . 0 . write_vectored ( bufs)
3481
- }
3482
-
3483
- #[ inline]
3484
- fn is_write_vectored ( & self ) -> bool {
3485
- self . 0 . is_write_vectored ( )
3486
- }
3487
- }
3488
-
3489
- #[ unstable( feature = "anonymous_pipe" , issue = "127154" ) ]
3490
- impl Write for PipeWriter {
3491
- fn write ( & mut self , buf : & [ u8 ] ) -> Result < usize > {
3492
- self . 0 . write ( buf)
3493
- }
3494
- #[ inline]
3495
- fn flush ( & mut self ) -> Result < ( ) > {
3496
- Ok ( ( ) )
3497
- }
3498
-
3499
- fn write_vectored ( & mut self , bufs : & [ IoSlice < ' _ > ] ) -> Result < usize > {
3500
- self . 0 . write_vectored ( bufs)
3501
- }
3502
-
3503
- #[ inline]
3504
- fn is_write_vectored ( & self ) -> bool {
3505
- self . 0 . is_write_vectored ( )
3506
- }
3507
- }
0 commit comments