pub struct Input<'a> {
pub scanner: MutexGuard<'a, Scanner<Box<dyn Read + Send>>>,
}
Expand description
A terminal Connection
’s input.
In addition to Read
and BufRead
, terminal input also implements
Scan
for ingesting text and ANSI escape sequences. The implementation of
all three traits uses the same, shared buffer. At the same time, it does not
share any state (nor implementation) with standard I/O in Rust’s standard
library.
Reads from the terminal connection time out after a duration configurable in
0.1s increments. In that case, Read::read
returns a count of 0,
BufRead::fill_buf
an empty slice, and Scan::read_token
an error with
kind ErrorKind::TimedOut
. On Unix, the
timeout is implemented with the terminal’s MIN
and TIME
parameters
On Windows, the timeout is implemented with
WaitForSingleObject
.
§Scanning Tokens vs Reading Bytes
Despite requiring a fairly elaborate state machine, the implementation of
read_token()
has been carefully engineered to
return to the start state whenever possible. However, that is not possible
when reading from the terminal connection results in an error or when a
Token::Control
appears in the middle of a
Token::Sequence
. In these cases,
in_flight()
returns true
.
It is possible to interleave reading bytes through Read
and BufRead
as well as tokens through Scan
, as long as byte-reads consume data at
token granularity as well. For that reason,
fill_buf()
and consume()
are
much preferred over read()
because the former two methods
provide exact control over consumed bytes, whereas the latter method does
not. For the same reason, byte-reads fail with
ErrorKind::InFlight
, if the state
machine currently is in-flight.
§Error Recovery
Unless the terminal connection keeps erroring, a viable error recovery strategy is to keep reading tokens. The state machine usually returns to the start state after the first error. Doing so requires reading at most 3 bytes for UTF-8 characters and, in theory, an unlimited number of bytes for pathological ANSI escape sequences.
§Pathological Input
To protect against such pathological inputs, the implementation gracefully
handles out-of-memory conditions, i.e., when a sequence is longer than the
internal buffer size. It does not dynamically grow the buffer size, but
instead keeps processing bytes until the sequence is complete and then
returns ErrorKind::OutOfMemory
.
However, if a sequence is much longer than the buffer size, continuing to
scan it makes little sense. Hence, upon reaching a configurable limit, the
state machine forcibly resets and discards any unread bytes before returning
ErrorKind::PathologicalSequence
.
In that case, it probably is advisable to terminate the terminal connection,
since a denial-of-service attack appears to be under way.
Fields§
§scanner: MutexGuard<'a, Scanner<Box<dyn Read + Send>>>
Implementations§
Trait Implementations§
Source§impl BufRead for Input<'_>
impl BufRead for Input<'_>
Source§fn fill_buf(&mut self) -> Result<&[u8]>
fn fill_buf(&mut self) -> Result<&[u8]>
Source§fn consume(&mut self, amt: usize)
fn consume(&mut self, amt: usize)
amt
bytes have been consumed from the buffer,
so they should no longer be returned in calls to read
. Read moreSource§fn has_data_left(&mut self) -> Result<bool, Error>
fn has_data_left(&mut self) -> Result<bool, Error>
buf_read_has_data_left
)Read
has any data left to be read. Read more1.83.0 · Source§fn skip_until(&mut self, byte: u8) -> Result<usize, Error>
fn skip_until(&mut self, byte: u8) -> Result<usize, Error>
byte
or EOF is reached. Read more1.0.0 · Source§fn read_line(&mut self, buf: &mut String) -> Result<usize, Error>
fn read_line(&mut self, buf: &mut String) -> Result<usize, Error>
0xA
byte) is reached, and append
them to the provided String
buffer. Read moreSource§impl Read for Input<'_>
impl Read for Input<'_>
Source§fn read(&mut self, buf: &mut [u8]) -> Result<usize>
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
1.36.0 · Source§fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>
read
, except that it reads into a slice of buffers. Read moreSource§fn is_read_vectored(&self) -> bool
fn is_read_vectored(&self) -> bool
can_vector
)1.0.0 · Source§fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
buf
. Read more1.0.0 · Source§fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
buf
. Read more1.6.0 · Source§fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>
buf
. Read moreSource§fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
read_buf
)Source§fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
read_buf
)cursor
. Read more1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Read
. Read more