eitherq 0.1.2

Queue which support two different types.
Documentation
//! `EitherQueue` is queue that supports two different queues as one.

use std::collections::VecDeque;
use std::time::Instant;

/// Representation of two queues in one.
pub struct EitherQueue<L, R> {
  left: VecDeque<(Instant, L)>,
  right: VecDeque<(Instant, R)>
}


pub enum Either<L, R> {
  Left(L),
  Right(R)
}

impl<L, R> EitherQueue<L, R> {
  /// Allocate and return a new, empty, `EitherQueue` object.
  #[inline(always)]
  pub fn new() -> Self {
    Self::default()
  }


  /// Returns the number of nodes in both left and right queues combined.
  ///
  /// ```
  /// let mut q = eitherq::EitherQueue::<&str, u32>::new();
  /// q.push_left("elena");
  /// q.push_left("chloe");
  /// q.push_right(42);
  /// assert_eq!(q.len(), 3);
  /// ```
  #[inline(always)]
  pub fn len(&self) -> usize {
    self.left.len() + self.right.len()
  }


  #[inline(always)]
  pub fn left_len(&self) -> usize {
    self.left.len()
  }


  #[inline(always)]
  pub fn right_len(&self) -> usize {
    self.right.len()
  }


  /// Returns `true` if both internal queues are empty.
  ///
  /// ```
  /// let mut q = eitherq::EitherQueue::<&str, u32>::new();
  /// assert_eq!(q.is_empty(), true);
  /// q.push_left("charlie");
  /// assert_eq!(q.is_empty(), false);
  /// q.clear();
  /// q.push_right(17);
  /// assert_eq!(q.is_empty(), false);
  /// ```
  #[inline(always)]
  pub fn is_empty(&self) -> bool {
    self.left.is_empty() && self.right.is_empty()
  }


  /// Returns `true` if the left queue is empty.  Returns `false` otherwise.
  #[inline(always)]
  pub fn is_left_empty(&self) -> bool {
    self.left.is_empty()
  }


  /// Returns `true` if the right queue is empty.  Returns `false` otherwise.
  #[inline(always)]
  pub fn is_right_empty(&self) -> bool {
    self.right.is_empty()
  }


  /// Clears all elements from both queues.
  ///
  /// ```
  /// let mut q = eitherq::EitherQueue::<&str, u32>::new();
  /// q.push_left("sully");
  /// q.push_right(11);
  /// q.clear();
  /// assert_eq!(q.len(), 0);
  /// ```
  #[inline(always)]
  pub fn clear(&mut self) {
    self.left.clear();
    self.right.clear();
  }


  #[inline(always)]
  pub fn push(&mut self, n: Either<L, R>) {
    match n {
      Either::Left(n) => self.push_left(n),
      Either::Right(n) => self.push_right(n)
    }
  }


  #[inline(always)]
  pub fn push_left(&mut self, n: L) {
    self.left.push_back((Instant::now(), n));
  }


  #[inline(always)]
  pub fn push_right(&mut self, n: R) {
    self.right.push_back((Instant::now(), n));
  }


  /// Take the "oldest" node off the queue.
  pub fn pop(&mut self) -> Option<Either<L, R>> {
    if self.left.is_empty() {
      // The "left" queue is empty, so try the "right" one
      if let Some((_, n)) = self.right.pop_front() {
        Some(Either::Right(n))
      } else {
        // Both queues are empty
        None
      }
    } else if self.right.is_empty() {
      // The "left" has nodes, but the "right" does not
      if let Some((_, n)) = self.left.pop_front() {
        Some(Either::Left(n))
      } else {
        // Should never happen
        unreachable!("Could not get node that is known to exist");
      }
    } else {
      // There are nodes in both queues.
      // Find out which of the queues has the oldest node.
      // If they are equal, the left queue will take predence.
      let next_left = {
        let (li, _) = self
          .left
          .front()
          .expect("Unable to get reference to expected front left node");
        let (ri, _) = self
          .right
          .front()
          .expect("Unable to get reference to expected front right node");
        li <= ri
      };

      if next_left {
        let (_, n) = self
          .left
          .pop_front()
          .expect("Unexpectededly unable to get next left node");
        Some(Either::Left(n))
      } else {
        let (_, n) = self
          .right
          .pop_front()
          .expect("Unexpectededly unable to get next put node");
        Some(Either::Right(n))
      }
    }
  }


  /// Take the oldest node off the left queue.
  #[inline(always)]
  pub fn pop_left(&mut self) -> Option<L> {
    if let Some((_, n)) = self.left.pop_front() {
      Some(n)
    } else {
      None
    }
  }


  /// Take the oldest node off the right queue.
  #[inline(always)]
  pub fn pop_right(&mut self) -> Option<R> {
    if let Some((_, n)) = self.right.pop_front() {
      Some(n)
    } else {
      None
    }
  }
}

impl<L, R> Default for EitherQueue<L, R> {
  fn default() -> Self {
    Self {
      left: VecDeque::new(),
      right: VecDeque::new()
    }
  }
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :