use crate::{DeviceID, Line};
pub type Drain<'a, T> = std::vec::Drain<'a, T>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum LineOp {
Attach(Line),
Detach(DeviceID),
}
#[derive(Debug)]
pub(crate) struct LineMap {
inner: Inner,
}
#[derive(Debug)]
enum Inner {
Small(Small),
}
#[derive(Debug, Default)]
struct Small {
inner: Vec<(DeviceID, Option<Line>)>,
}
impl LineMap {
pub fn new() -> Self { LineMap{ inner: Inner::Small(Small::default()) } }
pub fn apply(&mut self, op: LineOp) {
match op {
LineOp::Attach(line) => { self.attach(line); }
LineOp::Detach(did) => { self.detach(did); }
}
}
pub fn attach(&mut self, line: Line) -> bool {
match self.inner {
Inner::Small(ref mut small) => small.attach(line),
}
}
pub fn detach(&mut self, did: DeviceID) -> bool {
match self.inner {
Inner::Small(ref mut small) => small.detach(did),
}
}
pub fn drain(&mut self) -> Drain<(DeviceID, Option<Line>)> {
match self.inner {
Inner::Small(ref mut small) => small.inner.drain(..),
}
}
}
impl Small {
fn attach(&mut self, line: Line) -> bool {
let line_did = line.device_id();
let mut last_free: Option<usize> = None;
for (idx, (did, ref mut loon)) in self.inner.iter_mut().enumerate() {
if *did == line_did {
*loon = Some(line);
return true;
} else if loon.is_none() {
last_free = Some(idx);
continue;
}
}
if let Some(free) = last_free {
self.inner[free] = (line_did, Some(line));
} else {
self.inner.push((line_did, Some(line)));
}
false
}
fn detach(&mut self, did: DeviceID) -> bool {
let count = self.inner.len();
for (idx, (did2, ref mut loon)) in self.inner.iter_mut().enumerate() {
if did == *did2 {
if idx == (count - 1) {
self.inner.pop();
} else {
*loon = None;
}
return true;
}
}
false
}
}