use std::fmt::Debug;
use std::{borrow::Borrow, mem::MaybeUninit};
use core::cmp::Ordering;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use fastrand;
use crate::core::pair::Pair;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Default, Clone, Hash)]
pub struct MultiPair<K, V> {
pub key: K,
pub value: V,
pub discriminator: u64,
}
impl<K: Ord, V: PartialEq> MultiPair<K, V> {
pub fn new(key: K, value: V) -> Self {
Self { key, value, discriminator: fastrand::u64(..) }
}
pub fn with_infimum(key: K) -> Self {
Self { key, value: unsafe { MaybeUninit::uninit().assume_init() }, discriminator: INFIMUM }
}
pub fn with_supremum(key: K) -> Self {
Self { key, value: unsafe { MaybeUninit::uninit().assume_init() }, discriminator: SUPREMUM }
}
}
impl<K: Ord, V: PartialEq> Eq for MultiPair<K, V> {}
impl<K: Ord, V: PartialEq> PartialEq<Self> for MultiPair<K, V> {
fn eq(&self, other: &Self) -> bool {
self.key.eq(&other.key) && self.value.eq(&other.value)
}
}
const INFIMUM: u64 = 0;
const SUPREMUM: u64 = u64::MAX;
impl<K: Ord, V: PartialEq> Ord for MultiPair<K, V> {
fn cmp(&self, other: &Self) -> Ordering {
match self.key.cmp(&other.key) {
Ordering::Equal => {
if (self.discriminator == INFIMUM || other.discriminator == INFIMUM) || (self.discriminator == SUPREMUM || other.discriminator == SUPREMUM) {
return self.discriminator.cmp(&other.discriminator);
}
if self.value.eq(&other.value) {
return Ordering::Equal;
}
self.discriminator.cmp(&other.discriminator)
},
ord => ord,
}
}
}
impl<K: Ord, V: PartialEq> PartialOrd for MultiPair<K, V> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<K: Ord, V: PartialEq> Borrow<K> for MultiPair<K, V> {
fn borrow(&self) -> &K {
&self.key
}
}
impl<K: Ord, V: PartialEq> From<Pair<K, V>> for MultiPair<K, V> {
fn from(pair: Pair<K, V>) -> Self {
MultiPair {
key: pair.key,
value: pair.value,
discriminator: fastrand::u64(..),
}
}
}
impl<K: Ord, V: PartialEq> From<MultiPair<K, V>> for Pair<K, V> {
fn from(pair: MultiPair<K, V>) -> Self {
Pair {
key: pair.key,
value: pair.value,
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::core::node::NodeLike;
use std::ops::Bound::*;
#[test]
fn borrow_test() {
let pair = MultiPair::new(1usize, 2usize);
assert_eq!(<MultiPair<usize, usize> as Borrow<usize>>::borrow(&pair), &1usize);
}
#[test]
fn eq_test() {
let pair_one = MultiPair::new(1usize, 2usize);
let pair_two = MultiPair::new(1usize, 3usize);
assert_ne!(pair_one, pair_two);
}
#[test]
fn node_like() {
let mut vec = Vec::new();
let p1 = MultiPair::new(1, "a");
let p2 = MultiPair::new(1, "b");
let p3 = MultiPair::new(2, "c");
NodeLike::insert(&mut vec, p1.clone());
NodeLike::insert(&mut vec, p2.clone());
assert_eq!(vec.len(), 2);
NodeLike::insert(&mut vec, p1.clone());
assert_eq!(vec.len(), 2);
NodeLike::insert(&mut vec, p3.clone());
assert_eq!(vec.len(), 3);
}
#[test]
fn range_bounds() {
let mut vec = Vec::new();
let p1a = MultiPair::new(1, "a");
let p1b = MultiPair::new(1, "b");
let p1c = MultiPair::new(1, "c");
let p2a = MultiPair::new(2, "a");
let p2b = MultiPair::new(2, "b");
let p3a = MultiPair::new(3, "a");
let p3b = MultiPair::new(3, "b");
let p3c = MultiPair::new(3, "c");
let p3d = MultiPair::new(3, "d");
let p4a = MultiPair::new(4, "a");
NodeLike::insert(&mut vec, p4a.clone());
NodeLike::insert(&mut vec, p1a.clone());
NodeLike::insert(&mut vec, p1c.clone());
NodeLike::insert(&mut vec, p1b.clone());
NodeLike::insert(&mut vec, p2b.clone());
NodeLike::insert(&mut vec, p2a.clone());
NodeLike::insert(&mut vec, p3a.clone());
NodeLike::insert(&mut vec, p3b.clone());
NodeLike::insert(&mut vec, p3d.clone());
NodeLike::insert(&mut vec, p3c.clone());
assert_eq!(vec.len(), 10);
let start_1 = vec.rank(Included(&MultiPair::with_infimum(1)), true).or_else(|| Some(0)).unwrap();
let end_1 = vec.rank(Excluded(&MultiPair::with_supremum(1)), true).unwrap();
let range_1 = &vec[start_1..=end_1];
assert_eq!(range_1.len(), 3);
assert!(range_1.contains(&p1a));
assert!(range_1.contains(&p1b));
assert!(range_1.contains(&p1c));
let end_2 = vec.rank(Excluded(&MultiPair::with_supremum(2)), true).unwrap();
let range_2 = &vec[start_1..=end_2];
assert_eq!(range_2.len(), 5);
assert!(range_2.contains(&p1a));
assert!(range_2.contains(&p1b));
assert!(range_2.contains(&p1c));
assert!(range_2.contains(&p2a));
assert!(range_2.contains(&p2b));
assert_ne!(range_2.contains(&p3a), true);
let start_3 = vec.rank(Included(&MultiPair::with_infimum(3)), true).unwrap() + 1;
let end_3 = vec.rank(Excluded(&MultiPair::with_supremum(3)), true).unwrap();
let range_3 = &vec[start_3..=end_3];
assert_eq!(range_3.len(), 4);
assert!(range_3.contains(&p3a));
assert!(range_3.contains(&p3b));
assert!(range_3.contains(&p3c));
assert!(range_3.contains(&p3d));
let start_4 = vec.rank(Included(&MultiPair::with_infimum(4)), true).unwrap() + 1;
let end_4 = vec.rank(Excluded(&MultiPair::with_supremum(4)), true).unwrap();
let range_4 = &vec[start_4..=end_4];
assert_eq!(range_4.len(), 1);
assert!(range_4.contains(&p4a));
}
}