@@ -7,7 +7,7 @@ use crate::io::prelude::*;
7
7
8
8
use crate :: cell:: { Cell , RefCell } ;
9
9
use crate :: fmt;
10
- use crate :: io:: { self , BufReader , Initializer , IoSlice , IoSliceMut , LineWriter } ;
10
+ use crate :: io:: { self , BufReader , Initializer , IoSlice , IoSliceMut , LineWriter , Lines , Split } ;
11
11
use crate :: lazy:: SyncOnceCell ;
12
12
use crate :: pin:: Pin ;
13
13
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
@@ -195,17 +195,17 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
195
195
196
196
/// A handle to the standard input stream of a process.
197
197
///
198
- /// Each handle is a shared reference to a global buffer of input data to this
199
- /// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
200
- /// (e.g., `.lines()`). Reads to this handle are otherwise locked with respect
201
- /// to other reads.
198
+ /// Each handle is a shared reference to a global buffer of input data to
199
+ /// this process. Access is also synchronized via a lock, and explicit
200
+ /// control over locking is available via the [`lock`] method.
202
201
///
203
202
/// This handle implements the `Read` trait, but beware that concurrent reads
204
203
/// of `Stdin` must be executed with care.
205
204
///
206
205
/// Created by the [`io::stdin`] method.
207
206
///
208
207
/// [`io::stdin`]: stdin
208
+ /// [`lock`]: Stdin::lock
209
209
///
210
210
/// ### Note: Windows Portability Consideration
211
211
///
@@ -263,9 +263,16 @@ pub struct StdinLock<'a> {
263
263
264
264
/// Constructs a new handle to the standard input of the current process.
265
265
///
266
- /// Each handle returned is a reference to a shared global buffer whose access
267
- /// is synchronized via a mutex. If you need more explicit control over
268
- /// locking, see the [`Stdin::lock`] method.
266
+ /// Each handle returned is a reference to a shared global buffer whose
267
+ /// access is synchronized via a mutex. The [`lines`], [`read_line`], and
268
+ /// [`split`] methods, as well as all of the [`Read`] methods, implicitly
269
+ /// lock the handle. If you need more explicit control over locking, or
270
+ /// need to access the underlying [`BufRead`] implementation, see the
271
+ /// [`Stdin::lock`] method.
272
+ ///
273
+ /// [`lines`]: Stdin::lines
274
+ /// [`read_line`]: Stdin::read_line
275
+ /// [`split`]: Stdin::split
269
276
///
270
277
/// ### Note: Windows Portability Consideration
271
278
/// When operating in a console, the Windows implementation of this stream does not support
@@ -367,6 +374,66 @@ impl Stdin {
367
374
pub fn read_line ( & self , buf : & mut String ) -> io:: Result < usize > {
368
375
self . lock ( ) . read_line ( buf)
369
376
}
377
+
378
+ // Consumes a `Stdin` and returns a static `StdinLock`. This relies on
379
+ // internal knowledge that the `Mutex` reference inside `Stdin` is
380
+ // static.
381
+ fn into_lock ( self ) -> StdinLock < ' static > {
382
+ StdinLock { inner : self . inner . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) }
383
+ }
384
+
385
+ /// Consumes this handle and returns an iterator over the input lines.
386
+ ///
387
+ /// For detailed semantics of this method, see the documentation on
388
+ /// [`BufRead::lines`].
389
+ ///
390
+ /// # Examples
391
+ ///
392
+ /// ```no_run
393
+ /// #![feature(stdin_forwarders)]
394
+ /// use std::io;
395
+ ///
396
+ /// let lines = io::stdin().lines();
397
+ /// for line in lines {
398
+ /// println!("got a line: {}", line.unwrap());
399
+ /// }
400
+ /// ```
401
+ #[ unstable(
402
+ feature = "stdin_forwarders" ,
403
+ reason = "it can be useful to get a `Lines` iterator without having \
404
+ to explicitly deal with locks and lifetimes",
405
+ issue = "none"
406
+ ) ]
407
+ pub fn lines ( self ) -> Lines < StdinLock < ' static > > {
408
+ self . into_lock ( ) . lines ( )
409
+ }
410
+
411
+ /// Consumes this handle and returns an iterator over input bytes,
412
+ /// split at the specified byte value.
413
+ ///
414
+ /// For detailed semantics of this method, see the documentation on
415
+ /// [`BufRead::split`].
416
+ ///
417
+ /// # Examples
418
+ ///
419
+ /// ```no_run
420
+ /// #![feature(stdin_forwarders)]
421
+ /// use std::io;
422
+ ///
423
+ /// let splits = io::stdin().split(b'-');
424
+ /// for split in splits {
425
+ /// println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap()));
426
+ /// }
427
+ /// ```
428
+ #[ unstable(
429
+ feature = "stdin_forwarders" ,
430
+ reason = "it can be useful to get a `Split` iterator without having \
431
+ to explicitly deal with locks and lifetimes",
432
+ issue = "none"
433
+ ) ]
434
+ pub fn split ( self , byte : u8 ) -> Split < StdinLock < ' static > > {
435
+ self . into_lock ( ) . split ( byte)
436
+ }
370
437
}
371
438
372
439
#[ stable( feature = "std_debug" , since = "1.16.0" ) ]
0 commit comments