pub trait KeyPosition {
type Pos;
fn from_pos(pos: Self::Pos) -> Self;
fn add_pos(&mut self, pos: Self::Pos);
fn remove_pos(&mut self, pos: &Self::Pos) -> bool;
}
pub trait KeyPositionAsSlice {
type Pos;
fn as_position_slice(&self) -> &[Self::Pos];
}
impl<K> KeyPositionAsSlice for &K
where
K: KeyPositionAsSlice,
{
type Pos = K::Pos;
fn as_position_slice(&self) -> &[Self::Pos] {
(*self).as_position_slice()
}
}
pub type UniqueKeyPosition<P> = Option<P>;
impl<P> KeyPosition for UniqueKeyPosition<P>
where
P: PartialEq,
{
type Pos = P;
fn from_pos(pos: P) -> Self {
Some(pos)
}
fn add_pos(&mut self, _pos: P) {
panic!("unique UniqueKeyPositon can not add a new position")
}
fn remove_pos(&mut self, pos: &P) -> bool {
match self.as_ref() {
Some(p) if p == pos => {
*self = None;
true
}
Some(_) => false,
None => true,
}
}
}
impl<P> KeyPositionAsSlice for UniqueKeyPosition<P> {
type Pos = P;
fn as_position_slice(&self) -> &[Self::Pos] {
self.as_slice()
}
}
pub type MultiKeyPosition<P> = Vec<P>;
impl<P> KeyPosition for MultiKeyPosition<P>
where
P: Ord + PartialEq,
{
type Pos = P;
fn from_pos(pos: P) -> Self {
vec![pos]
}
fn add_pos(&mut self, pos: P) {
if let Err(idx) = self.binary_search(&pos) {
self.insert(idx, pos);
}
}
fn remove_pos(&mut self, pos: &P) -> bool {
self.retain(|v| v != pos);
self.is_empty()
}
}
impl<P> KeyPositionAsSlice for MultiKeyPosition<P> {
type Pos = P;
fn as_position_slice(&self) -> &[Self::Pos] {
self.as_slice()
}
}
#[cfg(test)]
mod tests {
mod unique_key_position {
use super::super::*;
#[test]
fn unique_new() {
assert_eq!(UniqueKeyPosition::from_pos(7), Some(7));
assert_eq!(UniqueKeyPosition::from_pos(7).as_position_slice(), &[7]);
}
#[test]
#[should_panic]
fn add_pos_with_panic() {
UniqueKeyPosition::from_pos(1).add_pos(2);
}
#[test]
fn as_position() {
let mut x = UniqueKeyPosition::from_pos(1);
assert_eq!(x.as_position_slice(), &[1; 1]);
assert!(x.remove_pos(&1));
assert_eq!(x.as_position_slice(), &[]);
}
#[test]
fn remove_pos() {
let mut x = UniqueKeyPosition::from_pos(1);
assert!(!x.remove_pos(&2));
assert!(x.remove_pos(&1));
assert!(x.remove_pos(&1));
assert!(x.remove_pos(&2));
}
}
mod multi_key_indices {
use super::super::*;
#[test]
fn multi_new() {
assert_eq!(MultiKeyPosition::from_pos(7), vec![7]);
assert_eq!(MultiKeyPosition::from_pos(7).as_slice(), &[7]);
}
#[test]
fn multi_position_and_are_ordered() {
let mut m = MultiKeyPosition::from_pos(2);
assert_eq!(&[2], m.as_slice());
m.add_pos(1);
assert_eq!(&[1, 2], m.as_slice());
m.add_pos(0);
assert_eq!(&[0, 1, 2], m.as_slice());
}
#[test]
fn multi_duplicate() {
let mut m = MultiKeyPosition::from_pos(1);
assert_eq!(&[1], m.as_slice());
m.add_pos(1);
assert_eq!(&[1], m.as_slice());
}
#[test]
fn multi_ordered() {
let mut m = MultiKeyPosition::from_pos(5);
assert_eq!(&[5], m.as_slice());
m.add_pos(3);
m.add_pos(1);
m.add_pos(4);
assert_eq!(&[1, 3, 4, 5], m.as_slice());
}
#[test]
fn remove() {
let mut m = MultiKeyPosition::from_pos(5);
m.add_pos(3);
m.add_pos(2);
assert_eq!(&[2, 3, 5], m.as_slice());
assert!(!m.remove_pos(&3));
assert!(!m.remove_pos(&3));
assert!(!m.remove_pos(&2));
assert!(m.remove_pos(&5));
assert!(m.remove_pos(&3));
}
}
}