Starting input system
This commit is contained in:
parent
61a7ce3904
commit
70319a98cb
|
@ -1,3 +1,4 @@
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
|
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
|
||||||
|
|
||||||
pub struct KvmKeyboardEvent {
|
pub struct KvmKeyboardEvent {
|
||||||
|
@ -10,3 +11,12 @@ impl KvmEventTrait for KvmKeyboardEvent {
|
||||||
KvmEvent::Keyboard(self)
|
KvmEvent::Keyboard(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for KvmKeyboardEvent {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self.state {
|
||||||
|
KvmButtonState::Pressed => write!(f, "Press {}", self.key_code),
|
||||||
|
KvmButtonState::Released => write!(f, "Press {}", self.key_code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,17 +22,8 @@ pub trait KvmEventTrait {
|
||||||
impl Display for KvmEvent {
|
impl Display for KvmEvent {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
KvmEvent::Pointer(_) => write!(f, "Pointer"),
|
KvmEvent::Pointer(e) => write!(f, "Pointer({e})"),
|
||||||
KvmEvent::Keyboard(_) => write!(f, "Keyboard")
|
KvmEvent::Keyboard(e) => write!(f, "Keyboard({e})")
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for KvmButtonState {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
KvmButtonState::Pressed => write!(f, "Pressed"),
|
|
||||||
KvmButtonState::Released => write!(f, "Released")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
|
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
|
||||||
|
|
||||||
pub enum KvmPointerEvent {
|
pub enum KvmPointerEvent {
|
||||||
Motion(KvmPointerMotionEvent),
|
MotionRelative(KvmPointerMotionRelativeEvent),
|
||||||
|
MotionAbsolute(KvmPointerMotionAbsoluteEvent),
|
||||||
Button(KvmPointerButtonEvent),
|
Button(KvmPointerButtonEvent),
|
||||||
Scroll(KvmPointerScrollEvent),
|
Scroll(KvmPointerScrollEvent),
|
||||||
}
|
}
|
||||||
|
@ -11,13 +13,20 @@ pub struct KvmPointerButtonEvent {
|
||||||
pub state: KvmButtonState,
|
pub state: KvmButtonState,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct KvmPointerMotionEvent {
|
pub struct KvmPointerMotionRelativeEvent {
|
||||||
pub dx: f64,
|
pub dx: f64,
|
||||||
pub dx_unaccelerated: f64,
|
pub dx_unaccelerated: f64,
|
||||||
pub dy: f64,
|
pub dy: f64,
|
||||||
pub dy_unaccelerated: f64,
|
pub dy_unaccelerated: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct KvmPointerMotionAbsoluteEvent {
|
||||||
|
pub x: f64,
|
||||||
|
pub x_mm: f64,
|
||||||
|
pub y: f64,
|
||||||
|
pub y_mm: f64,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct KvmPointerScrollEvent {
|
pub struct KvmPointerScrollEvent {
|
||||||
pub horizontal_scroll_value: f64,
|
pub horizontal_scroll_value: f64,
|
||||||
pub vertical_scroll_value: f64,
|
pub vertical_scroll_value: f64,
|
||||||
|
@ -49,6 +58,45 @@ macro_rules! kvm_event_traits {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kvm_event_traits!(Motion, KvmPointerMotionEvent);
|
kvm_event_traits!(MotionRelative, KvmPointerMotionRelativeEvent);
|
||||||
|
kvm_event_traits!(MotionAbsolute, KvmPointerMotionAbsoluteEvent);
|
||||||
kvm_event_traits!(Button, KvmPointerButtonEvent);
|
kvm_event_traits!(Button, KvmPointerButtonEvent);
|
||||||
kvm_event_traits!(Scroll, KvmPointerScrollEvent);
|
kvm_event_traits!(Scroll, KvmPointerScrollEvent);
|
||||||
|
|
||||||
|
impl Display for KvmPointerEvent {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
KvmPointerEvent::Button(e) => write!(f, "Button({e})"),
|
||||||
|
KvmPointerEvent::MotionRelative(e) => write!(f, "MotionRelative({e})"),
|
||||||
|
KvmPointerEvent::MotionAbsolute(e) => write!(f, "MotionAbsolute({e})"),
|
||||||
|
KvmPointerEvent::Scroll(e) => write!(f, "Scroll({e})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for KvmPointerButtonEvent {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self.state {
|
||||||
|
KvmButtonState::Pressed => write!(f, "Press {}", self.button),
|
||||||
|
KvmButtonState::Released => write!(f, "Release {}", self.button)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for KvmPointerMotionRelativeEvent {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "x: {} ({}), y: {} ({})", self.dx, self.dx_unaccelerated, self.dy, self.dy_unaccelerated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for KvmPointerMotionAbsoluteEvent {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "x: {} ({}), y: {} ({})", self.x, self.x_mm, self.y, self.y_mm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for KvmPointerScrollEvent {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "h: {}, v: {}", self.horizontal_scroll_value, self.vertical_scroll_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use input::event::pointer::{Axis, ButtonState, PointerButtonEvent, PointerMotion
|
||||||
|
|
||||||
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
|
use crate::input::events::{KvmButtonState, KvmEvent, KvmEventTrait};
|
||||||
use crate::input::events::keyboard::KvmKeyboardEvent;
|
use crate::input::events::keyboard::KvmKeyboardEvent;
|
||||||
use crate::input::events::pointer::{KvmPointerButtonEvent, KvmPointerEvent, KvmPointerEventTrait, KvmPointerMotionEvent, KvmPointerScrollEvent};
|
use crate::input::events::pointer::{KvmPointerButtonEvent, KvmPointerEvent, KvmPointerEventTrait, KvmPointerMotionAbsoluteEvent, KvmPointerMotionRelativeEvent, KvmPointerScrollEvent};
|
||||||
use crate::input::mappings::MappingError::{UnknownEvent, UnsupportedEvent};
|
use crate::input::mappings::MappingError::{UnknownEvent, UnsupportedEvent};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -47,8 +47,8 @@ impl FromLibinputEvent<PointerEvent> for KvmPointerEvent {
|
||||||
fn from_libinput(event: PointerEvent) -> Result<Self, MappingError> {
|
fn from_libinput(event: PointerEvent) -> Result<Self, MappingError> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
match event {
|
match event {
|
||||||
PointerEvent::Motion(event) => get_pointer_event::<PointerMotionEvent, KvmPointerMotionEvent>(event),
|
PointerEvent::Motion(event) => get_pointer_event::<PointerMotionEvent, KvmPointerMotionRelativeEvent>(event),
|
||||||
PointerEvent::MotionAbsolute(event) => get_pointer_event::<PointerMotionAbsoluteEvent, KvmPointerMotionEvent>(event),
|
PointerEvent::MotionAbsolute(event) => get_pointer_event::<PointerMotionAbsoluteEvent, KvmPointerMotionAbsoluteEvent>(event),
|
||||||
PointerEvent::Button(event) => get_pointer_event::<PointerButtonEvent, KvmPointerButtonEvent>(event),
|
PointerEvent::Button(event) => get_pointer_event::<PointerButtonEvent, KvmPointerButtonEvent>(event),
|
||||||
PointerEvent::ScrollWheel(event) => get_pointer_event::<PointerScrollWheelEvent, KvmPointerScrollEvent>(event),
|
PointerEvent::ScrollWheel(event) => get_pointer_event::<PointerScrollWheelEvent, KvmPointerScrollEvent>(event),
|
||||||
PointerEvent::ScrollFinger(event) => get_pointer_event::<PointerScrollFingerEvent, KvmPointerScrollEvent>(event),
|
PointerEvent::ScrollFinger(event) => get_pointer_event::<PointerScrollFingerEvent, KvmPointerScrollEvent>(event),
|
||||||
|
@ -64,9 +64,9 @@ fn get_pointer_event<T, U>(event: T) -> Result<KvmPointerEvent, MappingError>
|
||||||
Ok(U::from_libinput(event)?.into_kvm_pointer_event())
|
Ok(U::from_libinput(event)?.into_kvm_pointer_event())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromLibinputEvent<PointerMotionEvent> for KvmPointerMotionEvent {
|
impl FromLibinputEvent<PointerMotionEvent> for KvmPointerMotionRelativeEvent {
|
||||||
fn from_libinput(event: PointerMotionEvent) -> Result<Self, MappingError> {
|
fn from_libinput(event: PointerMotionEvent) -> Result<Self, MappingError> {
|
||||||
Ok(KvmPointerMotionEvent {
|
Ok(KvmPointerMotionRelativeEvent {
|
||||||
dx: event.dx(),
|
dx: event.dx(),
|
||||||
dx_unaccelerated: event.dx_unaccelerated(),
|
dx_unaccelerated: event.dx_unaccelerated(),
|
||||||
dy: event.dy(),
|
dy: event.dy(),
|
||||||
|
@ -75,9 +75,14 @@ impl FromLibinputEvent<PointerMotionEvent> for KvmPointerMotionEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromLibinputEvent<PointerMotionAbsoluteEvent> for KvmPointerMotionEvent {
|
impl FromLibinputEvent<PointerMotionAbsoluteEvent> for KvmPointerMotionAbsoluteEvent {
|
||||||
fn from_libinput(event: PointerMotionAbsoluteEvent) -> Result<Self, MappingError> {
|
fn from_libinput(event: PointerMotionAbsoluteEvent) -> Result<Self, MappingError> {
|
||||||
Err(UnsupportedEvent(event.into_event())) // TODO
|
Ok(KvmPointerMotionAbsoluteEvent {
|
||||||
|
x: event.absolute_x_transformed(1920),
|
||||||
|
x_mm: event.absolute_x(),
|
||||||
|
y: event.absolute_y_transformed(1080),
|
||||||
|
y_mm: event.absolute_y(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io;
|
use std::os::fd::{AsRawFd, OwnedFd};
|
||||||
use std::os::fd::OwnedFd;
|
|
||||||
use std::os::unix::fs::OpenOptionsExt;
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use input::{Libinput, LibinputInterface};
|
use input::{Libinput, LibinputInterface};
|
||||||
use input::Event;
|
use input::Event;
|
||||||
use input::Event::{Keyboard, Pointer};
|
|
||||||
use input::event::keyboard::{KeyboardEventTrait, KeyState};
|
|
||||||
use input::event::{KeyboardEvent, PointerEvent};
|
|
||||||
use input::event::PointerEvent::{Button, Motion};
|
|
||||||
use libc::{O_RDONLY, O_RDWR, O_WRONLY};
|
use libc::{O_RDONLY, O_RDWR, O_WRONLY};
|
||||||
use crate::input::events::keyboard::KvmKeyboardEvent;
|
use linux::epoll::{Epoll, EpollFlags};
|
||||||
use crate::input::events::KvmEvent;
|
|
||||||
use crate::input::events::pointer::{KvmPointerButtonEvent, KvmPointerMotionEvent};
|
|
||||||
use crate::input::mappings::FromLibinputEvent;
|
|
||||||
|
|
||||||
mod events;
|
use crate::input::events::KvmEvent;
|
||||||
|
use crate::input::mappings::{FromLibinputEvent, MappingError};
|
||||||
|
|
||||||
|
pub mod events;
|
||||||
mod mappings;
|
mod mappings;
|
||||||
|
|
||||||
const UDEV_SEAT: &str = "seat0";
|
const UDEV_SEAT: &str = "seat0";
|
||||||
|
const CLIENT_SWITCH_KEY_CODE: u32 = 100; // Alt Right
|
||||||
|
|
||||||
|
pub struct InputSystem<S> {
|
||||||
|
sub_system: S,
|
||||||
|
epoll: Epoll,
|
||||||
|
}
|
||||||
|
|
||||||
struct Interface;
|
struct Interface;
|
||||||
|
|
||||||
|
@ -39,31 +40,108 @@ impl LibinputInterface for Interface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen_inputs() -> io::Result<()> {
|
impl InputSystem<Libinput> {
|
||||||
let input = prepare_libinput();
|
pub fn new() -> Result<Self, LibinputSubsystemError> {
|
||||||
read_inputs(input)
|
let mut libinput = prepare_libinput()?;
|
||||||
|
let epoll = create_epoll(&libinput)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
sub_system: libinput,
|
||||||
|
epoll,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait_for_events(&mut self) -> Result<(), LibinputSubsystemError> {
|
||||||
|
match self.epoll.wait() {
|
||||||
|
Ok(e) => self.dispatch(),
|
||||||
|
Err(e) => Err(LibinputSubsystemError::Polling(format!("Failed to wait for epoll: {}", e)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch(&mut self) -> Result<(), LibinputSubsystemError> {
|
||||||
|
let dispatch_result = self.sub_system.dispatch();
|
||||||
|
if dispatch_result.is_err() {
|
||||||
|
return Err(LibinputSubsystemError::Polling("Failed to dispatch libinput events".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_libinput() -> Libinput {
|
impl Iterator for InputSystem<Libinput> {
|
||||||
|
type Item = KvmEvent;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut next = self.sub_system.next();
|
||||||
|
if next.is_none() {
|
||||||
|
// Try to get more events
|
||||||
|
match self.wait_for_events() {
|
||||||
|
Ok(_) => {
|
||||||
|
next = self.sub_system.next();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failed to wait for events: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match next {
|
||||||
|
Some(e) => {
|
||||||
|
match map_libinput_event(e) {
|
||||||
|
Ok(e) => Some(e),
|
||||||
|
Err(e) => {
|
||||||
|
println!("Event failed: {:?}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LibinputSubsystemError {
|
||||||
|
Initialization(String),
|
||||||
|
Polling(String),
|
||||||
|
Mapping(MappingError),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_libinput() -> Result<Libinput, LibinputSubsystemError> {
|
||||||
let mut input = Libinput::new_with_udev(Interface);
|
let mut input = Libinput::new_with_udev(Interface);
|
||||||
input.udev_assign_seat(UDEV_SEAT).unwrap();
|
match input.udev_assign_seat(UDEV_SEAT) {
|
||||||
input
|
Ok(_) => Ok(input),
|
||||||
|
Err(_) => Err(LibinputSubsystemError::Initialization("Failed to assign a seat to the libinput context".to_string()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_inputs(mut input: Libinput) -> io::Result<()> {
|
fn create_epoll(input: &Libinput) -> Result<Epoll, LibinputSubsystemError> {
|
||||||
loop {
|
match Epoll::with_flags(&[EpollFlags::In]) {
|
||||||
input.dispatch().unwrap();
|
Ok(epoll) => {
|
||||||
for event in &mut input {
|
let interest = epoll.add_interest(input.as_raw_fd(), 0u64, &[]);
|
||||||
let mapping_result = KvmEvent::from_libinput(event);
|
match interest {
|
||||||
if mapping_result.is_err() {
|
Ok(_) => Ok(epoll),
|
||||||
println!("Error: {:?}", &mapping_result.err());
|
Err(e) => Err(LibinputSubsystemError::Initialization(format!("Failed to add epoll interest: {}", e)))
|
||||||
} else {
|
|
||||||
let kvm_event = mapping_result.unwrap();
|
|
||||||
match kvm_event {
|
|
||||||
KvmEvent::Keyboard(event) => println!("Key event: {} ({})", event.key_code, event.state),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) => Err(LibinputSubsystemError::Initialization(format!("Failed to create poll context: {}", e)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_libinput_event(event: Event) -> Result<KvmEvent, LibinputSubsystemError> {
|
||||||
|
match KvmEvent::from_libinput(event) {
|
||||||
|
Err(error) => Err(LibinputSubsystemError::Mapping(error)),
|
||||||
|
Ok(mapped_event) => Ok(mapped_event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intercept_client_switch_event(event: &KvmEvent) -> bool {
|
||||||
|
match event {
|
||||||
|
KvmEvent::Keyboard(event) if event.key_code == CLIENT_SWITCH_KEY_CODE => {
|
||||||
|
// Do stuff
|
||||||
|
println!("Right Alt key event");
|
||||||
|
false
|
||||||
|
}
|
||||||
|
_ => true
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,24 +1,46 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::io;
|
use std::fmt::Error;
|
||||||
|
use std::{io, thread};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use messages::client_registration::ClientRegistration;
|
use messages::client_registration::ClientRegistration;
|
||||||
use messages::serialization::{DeserializeMessage, read_message_data, SerializeMessage};
|
use messages::serialization::{DeserializeMessage, read_message_data, SerializeMessage};
|
||||||
|
|
||||||
use crate::input::{listen_inputs};
|
use crate::input::{InputSystem, LibinputSubsystemError};
|
||||||
|
use crate::input::events::KvmEvent;
|
||||||
|
use crate::multi_index_queue::MultiIndexQueue;
|
||||||
use crate::net::tcp_server::{NextIntent, TcpClient, TcpServer};
|
use crate::net::tcp_server::{NextIntent, TcpClient, TcpServer};
|
||||||
|
|
||||||
mod net;
|
mod net;
|
||||||
mod input;
|
mod input;
|
||||||
mod client;
|
mod client;
|
||||||
|
|
||||||
|
mod multi_index_queue;
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
// let addr = SocketAddr::from(([127, 0, 0, 1], 4433));
|
// let addr = SocketAddr::from(([127, 0, 0, 1], 4433));
|
||||||
// let mut server: TcpServer<KvmClient> = TcpServer::new(addr)?;
|
// let mut server: TcpServer<KvmClient> = TcpServer::new(addr)?;
|
||||||
//
|
//
|
||||||
// server.listen()?;
|
// server.listen()?;
|
||||||
|
|
||||||
listen_inputs()?;
|
let mut input_system = InputSystem::new().expect("Failed to initialize input system");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
for event in &mut input_system {
|
||||||
|
println!("Received event: {}", event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// let mut queue = MultiIndexQueue::new(Box::new(input_system));
|
||||||
|
// let mut index = queue.create_index();
|
||||||
|
//
|
||||||
|
// loop {
|
||||||
|
// let next: Option<&KvmEvent> = queue.next(&mut index);
|
||||||
|
// if next.is_some() {
|
||||||
|
// println!("Received event: {}", next.unwrap());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
const QUEUE_CAPACITY: usize = 1000;
|
||||||
|
|
||||||
|
pub struct MultiIndexQueue<T> {
|
||||||
|
iterator: Box<dyn Iterator<Item=T>>,
|
||||||
|
items: VecDeque<T>,
|
||||||
|
offset: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq)]
|
||||||
|
pub struct QueueIndex {
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MultiIndexQueue<T> {
|
||||||
|
pub fn new(iterator: Box<dyn Iterator<Item=T>>) -> Self {
|
||||||
|
Self {
|
||||||
|
iterator,
|
||||||
|
items: VecDeque::with_capacity(QUEUE_CAPACITY),
|
||||||
|
offset: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_index(&self) -> QueueIndex {
|
||||||
|
QueueIndex { index: self.offset }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&mut self, index: &mut QueueIndex) -> Option<&T> {
|
||||||
|
if self.items.is_empty() {
|
||||||
|
self.fill_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
let real_index = index.index - self.offset;
|
||||||
|
if real_index > QUEUE_CAPACITY {
|
||||||
|
let next = self.fill_next();
|
||||||
|
index.index += 1;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
let real_index = index.index - self.offset;
|
||||||
|
let item = self.items.get(real_index);
|
||||||
|
index.index += 1;
|
||||||
|
|
||||||
|
item
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_queue(&mut self) {
|
||||||
|
let mut index = 0usize;
|
||||||
|
let initial_queue_len = self.items.len();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if initial_queue_len + index >= QUEUE_CAPACITY {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.fill_next().is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_next(&mut self) -> Option<&T> {
|
||||||
|
let next = self.iterator.next();
|
||||||
|
match next {
|
||||||
|
Some(next) => {
|
||||||
|
self.items.pop_front();
|
||||||
|
self.items.push_back(next);
|
||||||
|
self.offset += 1;
|
||||||
|
self.items.get(QUEUE_CAPACITY)
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd<Self> for QueueIndex {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for QueueIndex {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
self.index.cmp(&other.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<Self> for QueueIndex {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.index == other.index
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue