prettytty

Struct Input

Source
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§

Source§

impl<'a> Input<'a>

Source

pub fn is_readable(&self) -> bool

Determine whether the input has bytes buffered.

Trait Implementations§

Source§

impl BufRead for Input<'_>

Source§

fn fill_buf(&mut self) -> Result<&[u8]>

Returns the contents of the internal buffer, filling it with more data from the inner reader if it is empty. Read more
Source§

fn consume(&mut self, amt: usize)

Tells this buffer that amt bytes have been consumed from the buffer, so they should no longer be returned in calls to read. Read more
Source§

fn has_data_left(&mut self) -> Result<bool, Error>

🔬This is a nightly-only experimental API. (buf_read_has_data_left)
Checks if the underlying Read has any data left to be read. Read more
1.0.0 · Source§

fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize, Error>

Reads all bytes into buf until the delimiter byte or EOF is reached. Read more
1.83.0 · Source§

fn skip_until(&mut self, byte: u8) -> Result<usize, Error>

Skips all bytes until the delimiter byte or EOF is reached. Read more
1.0.0 · Source§

fn read_line(&mut self, buf: &mut String) -> Result<usize, Error>

Reads all bytes until a newline (the 0xA byte) is reached, and append them to the provided String buffer. Read more
1.0.0 · Source§

fn split(self, byte: u8) -> Split<Self>
where Self: Sized,

Returns an iterator over the contents of this reader split on the byte byte. Read more
1.0.0 · Source§

fn lines(self) -> Lines<Self>
where Self: Sized,

Returns an iterator over the lines of this reader. Read more
Source§

impl<'a> Debug for Input<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Read for Input<'_>

Source§

fn read(&mut self, buf: &mut [u8]) -> Result<usize>

Pull some bytes from this source into the specified buffer, returning how many bytes were read. Read more
1.36.0 · Source§

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>

Like read, except that it reads into a slice of buffers. Read more
Source§

fn is_read_vectored(&self) -> bool

🔬This is a nightly-only experimental API. (can_vector)
Determines if this Reader has an efficient read_vectored implementation. Read more
1.0.0 · Source§

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>

Reads all bytes until EOF in this source, placing them into buf. Read more
1.0.0 · Source§

fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>

Reads all bytes until EOF in this source, appending them to buf. Read more
1.6.0 · Source§

fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>

Reads the exact number of bytes required to fill buf. Read more
Source§

fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>

🔬This is a nightly-only experimental API. (read_buf)
Pull some bytes from this source into the specified buffer. Read more
Source§

fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>

🔬This is a nightly-only experimental API. (read_buf)
Reads the exact number of bytes required to fill cursor. Read more
1.0.0 · Source§

fn by_ref(&mut self) -> &mut Self
where Self: Sized,

Creates a “by reference” adaptor for this instance of Read. Read more
1.0.0 · Source§

fn bytes(self) -> Bytes<Self>
where Self: Sized,

Transforms this Read instance to an Iterator over its bytes. Read more
1.0.0 · Source§

fn chain<R>(self, next: R) -> Chain<Self, R>
where R: Read, Self: Sized,

Creates an adapter which will chain this stream with another. Read more
1.0.0 · Source§

fn take(self, limit: u64) -> Take<Self>
where Self: Sized,

Creates an adapter which will read at most limit bytes from it. Read more
Source§

impl Scan for Input<'_>

Source§

fn in_flight(&self) -> bool

Determine if the state machine currently is in-flight. Read more
Source§

fn read_token(&mut self) -> Result<Token<'_>>

Read the next token. Read more
Source§

fn read_sequence(&mut self, control: Control) -> Result<&[u8]>

Read the next token as a control sequence. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Input<'a>

§

impl<'a> RefUnwindSafe for Input<'a>

§

impl<'a> !Send for Input<'a>

§

impl<'a> !Sync for Input<'a>

§

impl<'a> Unpin for Input<'a>

§

impl<'a> UnwindSafe for Input<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.