use std::io;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Key {
Up,
Down,
Left,
Right,
Esc,
Char(u8),
}
#[derive(Debug)]
pub struct Keys<'a> {
buffer: &'a [u8],
offset: usize,
}
impl<'a> Keys<'a> {
#[inline]
pub fn new<R>(reader: &mut R, buffer: &'a mut [u8]) -> io::Result<Self>
where
R: io::Read,
{
reader.read_keys(buffer)
}
#[inline]
pub fn with_filled_buffer(buffer: &'a [u8]) -> Self {
Self { buffer, offset: 0 }
}
#[inline]
pub fn bytes(&self) -> &[u8] {
self.buffer
}
#[inline]
fn consume(&mut self, advance: usize, key: Key) -> Option<Key> {
self.offset += advance;
Some(key)
}
}
impl<'a> Iterator for Keys<'a> {
type Item = Key;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match &self.buffer[self.offset..] {
[] => None,
[b'\x1b', rest @ ..] => match rest {
[b'[', b'A', ..] => self.consume(3, Key::Up),
[b'[', b'B', ..] => self.consume(3, Key::Down),
[b'[', b'C', ..] => self.consume(3, Key::Right),
[b'[', b'D', ..] => self.consume(3, Key::Left),
_ => self.consume(1, Key::Esc),
},
[ch, ..] => self.consume(1, Key::Char(*ch)),
}
}
}
pub trait ReadKeys {
fn read_keys<'a>(&mut self, buffer: &'a mut [u8]) -> io::Result<Keys<'a>>;
}
impl<R> ReadKeys for R
where
R: io::Read,
{
#[inline]
fn read_keys<'a>(&mut self, buffer: &'a mut [u8]) -> io::Result<Keys<'a>> {
let count = self.read(buffer)?;
Ok(Keys::with_filled_buffer(&buffer[..count]))
}
}