use crate::oid::Oid;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OidTable<V> {
entries: Vec<(Oid, V)>,
}
impl<V> OidTable<V> {
pub fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
entries: Vec::with_capacity(capacity),
}
}
pub fn insert(&mut self, oid: Oid, value: V) {
match self.entries.binary_search_by(|(o, _)| o.cmp(&oid)) {
Ok(idx) => self.entries[idx].1 = value,
Err(idx) => self.entries.insert(idx, (oid, value)),
}
}
pub fn remove(&mut self, oid: &Oid) -> Option<V> {
match self.entries.binary_search_by(|(o, _)| o.cmp(oid)) {
Ok(idx) => Some(self.entries.remove(idx).1),
Err(_) => None,
}
}
pub fn get(&self, oid: &Oid) -> Option<&V> {
match self.entries.binary_search_by(|(o, _)| o.cmp(oid)) {
Ok(idx) => Some(&self.entries[idx].1),
Err(_) => None,
}
}
pub fn get_next(&self, oid: &Oid) -> Option<(&Oid, &V)> {
match self.entries.binary_search_by(|(o, _)| o.cmp(oid)) {
Ok(idx) => {
self.entries.get(idx + 1).map(|(o, v)| (o, v))
}
Err(idx) => {
self.entries.get(idx).map(|(o, v)| (o, v))
}
}
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn clear(&mut self) {
self.entries.clear();
}
pub fn iter(&self) -> impl Iterator<Item = (&Oid, &V)> {
self.entries.iter().map(|(o, v)| (o, v))
}
}
impl<V> Default for OidTable<V> {
fn default() -> Self {
Self::new()
}
}
impl<'a, V> IntoIterator for &'a OidTable<V> {
type Item = (&'a Oid, &'a V);
type IntoIter =
std::iter::Map<std::slice::Iter<'a, (Oid, V)>, fn(&'a (Oid, V)) -> (&'a Oid, &'a V)>;
fn into_iter(self) -> Self::IntoIter {
self.entries.iter().map(|(o, v)| (o, v))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::oid;
#[test]
fn test_oid_table_insert_and_get() {
let mut table: OidTable<i32> = OidTable::new();
table.insert(oid!(1, 3, 6, 1, 2), 100);
table.insert(oid!(1, 3, 6, 1, 1), 50);
table.insert(oid!(1, 3, 6, 1, 3), 150);
assert_eq!(table.get(&oid!(1, 3, 6, 1, 1)), Some(&50));
assert_eq!(table.get(&oid!(1, 3, 6, 1, 2)), Some(&100));
assert_eq!(table.get(&oid!(1, 3, 6, 1, 3)), Some(&150));
assert_eq!(table.get(&oid!(1, 3, 6, 1, 4)), None);
}
#[test]
fn test_oid_table_update_existing() {
let mut table: OidTable<i32> = OidTable::new();
table.insert(oid!(1, 3, 6, 1, 1), 50);
table.insert(oid!(1, 3, 6, 1, 1), 100);
assert_eq!(table.get(&oid!(1, 3, 6, 1, 1)), Some(&100));
assert_eq!(table.len(), 1);
}
#[test]
fn test_oid_table_get_next() {
let mut table: OidTable<i32> = OidTable::new();
table.insert(oid!(1, 3, 6, 1, 1), 50);
table.insert(oid!(1, 3, 6, 1, 2), 100);
table.insert(oid!(1, 3, 6, 1, 3), 150);
let next = table.get_next(&oid!(1, 3, 6, 1, 0));
assert!(next.is_some());
assert_eq!(next.unwrap().0, &oid!(1, 3, 6, 1, 1));
let next = table.get_next(&oid!(1, 3, 6, 1, 1));
assert!(next.is_some());
assert_eq!(next.unwrap().0, &oid!(1, 3, 6, 1, 2));
let next = table.get_next(&oid!(1, 3, 6, 1, 1, 5));
assert!(next.is_some());
assert_eq!(next.unwrap().0, &oid!(1, 3, 6, 1, 2));
let next = table.get_next(&oid!(1, 3, 6, 1, 3));
assert!(next.is_none());
let next = table.get_next(&oid!(1, 3, 6, 1, 4));
assert!(next.is_none());
}
#[test]
fn test_oid_table_remove() {
let mut table: OidTable<i32> = OidTable::new();
table.insert(oid!(1, 3, 6, 1, 1), 50);
table.insert(oid!(1, 3, 6, 1, 2), 100);
assert_eq!(table.remove(&oid!(1, 3, 6, 1, 1)), Some(50));
assert_eq!(table.remove(&oid!(1, 3, 6, 1, 1)), None);
assert_eq!(table.len(), 1);
}
#[test]
fn test_oid_table_iter() {
let mut table: OidTable<i32> = OidTable::new();
table.insert(oid!(1, 3, 6, 1, 3), 150);
table.insert(oid!(1, 3, 6, 1, 1), 50);
table.insert(oid!(1, 3, 6, 1, 2), 100);
let entries: Vec<_> = table.iter().collect();
assert_eq!(entries.len(), 3);
assert_eq!(entries[0].0, &oid!(1, 3, 6, 1, 1));
assert_eq!(entries[1].0, &oid!(1, 3, 6, 1, 2));
assert_eq!(entries[2].0, &oid!(1, 3, 6, 1, 3));
}
#[test]
fn test_oid_table_empty() {
let table: OidTable<i32> = OidTable::new();
assert!(table.is_empty());
assert_eq!(table.len(), 0);
assert!(table.get_next(&oid!(1, 3, 6, 1)).is_none());
}
}