use std::collections::BTreeMap;
use std::iter::{repeat, Enumerate};
use std::mem::size_of;
use std::slice;
use num_integer::Integer;
use num_traits::{cast, Bounded, Num, NumCast};
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub struct SmallInts<F: Integer + Bounded + NumCast + Copy, B: Integer + NumCast + Copy> {
smallints: Vec<F>,
bigints: BTreeMap<usize, B>,
}
impl<S: Integer + Bounded + NumCast + Copy, B: Integer + NumCast + Copy> Default
for SmallInts<S, B>
{
fn default() -> Self {
assert!(
size_of::<S>() < size_of::<B>(),
"S has to be smaller than B"
);
SmallInts {
smallints: Vec::new(),
bigints: BTreeMap::new(),
}
}
}
impl<S: Integer + Bounded + NumCast + Copy, B: Integer + NumCast + Copy> SmallInts<S, B> {
pub fn new() -> Self {
Default::default()
}
pub fn with_capacity(n: usize) -> Self {
assert!(
size_of::<S>() < size_of::<B>(),
"S has to be smaller than B"
);
SmallInts {
smallints: Vec::with_capacity(n),
bigints: BTreeMap::new(),
}
}
pub fn from_elem(v: S, n: usize) -> Self {
assert!(
size_of::<S>() < size_of::<B>(),
"S has to be smaller than B"
);
if v > cast(0).unwrap() {
assert!(v < S::max_value(), "v has to be smaller than maximum value");
}
SmallInts {
smallints: repeat(v).take(n).collect(),
bigints: BTreeMap::new(),
}
}
pub fn get(&self, i: usize) -> Option<B> {
if i < self.smallints.len() {
self.real_value(i, self.smallints[i])
} else {
None
}
}
pub fn push(&mut self, v: B) {
let maxv: S = S::max_value();
match cast(v) {
Some(v) if v < maxv => self.smallints.push(v),
_ => {
let i = self.smallints.len();
self.smallints.push(maxv);
self.bigints.insert(i, v);
}
}
}
pub fn set(&mut self, i: usize, v: B) {
let maxv: S = S::max_value();
match cast(v) {
Some(v) if v < maxv => self.smallints[i] = v,
_ => {
self.smallints[i] = maxv;
self.bigints.insert(i, v);
}
}
}
pub fn iter(&self) -> Iter<'_, S, B> {
Iter {
smallints: self,
items: self.smallints.iter().enumerate(),
}
}
pub fn decompress(&self) -> Vec<B> {
self.iter().collect()
}
pub fn len(&self) -> usize {
self.smallints.len()
}
pub fn is_empty(&self) -> bool {
self.smallints.is_empty()
}
fn real_value(&self, i: usize, v: S) -> Option<B> {
if v < S::max_value() {
cast(v)
} else {
self.bigints.get(&i).cloned()
}
}
}
#[derive(Clone, Debug)]
pub struct Iter<'a, S, B>
where
S: Integer + Bounded + NumCast + Copy,
B: Integer + NumCast + Copy,
<S as Num>::FromStrRadixErr: 'a,
<B as Num>::FromStrRadixErr: 'a,
{
smallints: &'a SmallInts<S, B>,
items: Enumerate<slice::Iter<'a, S>>,
}
impl<'a, S, B> Iterator for Iter<'a, S, B>
where
S: 'a + Integer + Bounded + NumCast + Copy,
B: 'a + Integer + NumCast + Copy,
<S as Num>::FromStrRadixErr: 'a,
<B as Num>::FromStrRadixErr: 'a,
{
type Item = B;
fn next(&mut self) -> Option<B> {
match self.items.next() {
Some((i, &v)) => self.smallints.real_value(i, v),
None => None,
}
}
}
#[cfg(tests)]
mod tests {
#[test]
fn test_serde() {
use serde::{Deserialize, Serialize};
fn impls_serde_traits<S: Serialize + Deserialize>() {}
impls_serde_traits::<SmallInts<i8, isize>>();
}
}