use crate::keeper::OidKeeper;
use log::info;
use rasn::types::ObjectIdentifier;
pub struct OidMap {
store: Vec<(ObjectIdentifier, Box<dyn OidKeeper>)>,
}
impl OidMap {
pub fn new() -> Self {
let store: Vec<(ObjectIdentifier, Box<dyn OidKeeper>)> = vec![];
OidMap { store }
}
pub fn push(&mut self, oid: ObjectIdentifier, arg: Box<dyn OidKeeper>) {
self.store.push((oid, arg));
}
pub fn sort(&mut self) {
self.store.sort_by(|a, b| a.0.cmp(&b.0));
info!("Sorted");
}
pub fn search(&self, oid: &ObjectIdentifier) -> Result<usize, usize> {
self.store.binary_search_by(|a| {
let al = a.0.len();
let b = if oid.len() > al {
oid.get(0..al).unwrap() } else {
oid
};
a.0.to_vec().cmp(&b.to_vec())
})
}
pub fn search_next(&mut self, oid: &ObjectIdentifier) -> Option<&mut Box<dyn OidKeeper>> {
let bin_res = self.store.binary_search_by(|a| {
let al = a.0.len();
let b = if oid.len() > al {
oid.get(0..al).unwrap() } else {
oid
};
a.0.to_vec().cmp(&b.to_vec())
});
match bin_res {
Ok(which) => {
if which < self.store.len() - 1 {
Some(&mut self.store[which + 1].1)
} else {
None
}
}
Err(insert_point) => {
if insert_point < self.store.len() {
Some(&mut self.store[insert_point].1)
} else {
None
}
}
}
}
pub fn idx(&mut self, i: usize) -> &mut Box<dyn OidKeeper> {
&mut self.store[i].1
}
pub fn oid(&self, i: usize) -> &ObjectIdentifier {
&self.store[i].0
}
pub fn len(&self) -> usize {
self.store.len()
}
pub fn is_empty(&self) -> bool {
self.store.is_empty()
}
}
impl Default for OidMap {
fn default() -> Self {
Self::new()
}
}
pub struct ContextMap<'a> {
cmap: Vec<(&'a [u8], &'a mut OidMap)>,
}
impl<'a> ContextMap<'a> {
pub fn new() -> Self {
ContextMap { cmap: vec![] }
}
pub fn insert(&mut self, context_name: &'a [u8], oid_map: &'a mut OidMap) {
self.cmap.push((context_name, oid_map));
}
pub fn lookup(&mut self, context_name: &[u8]) -> Option<&mut OidMap> {
for (name, oid_map) in &mut self.cmap {
if *name == context_name {
return Some(oid_map);
}
}
None
}
pub fn sort(&mut self) {
for (_, omap) in &mut self.cmap {
omap.sort();
}
self.cmap.sort_by(|a, b| a.0.cmp(b.0));
}
}
impl Default for ContextMap<'_> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::keeper;
use crate::scalar::ScalarMemOid;
use crate::utils::*;
use rasn::types::ObjectIdentifier;
use rasn_snmp::v3::VarBindValue;
const ARC: [u32; 1] = [1];
const ARC_LONG: [u32; 3] = [1, 0, 0];
const ARC0: [u32; 1] = [0];
const ARC2: [u32; 2] = [2, 2];
const ARC3: [u32; 2] = [1, 3];
#[test]
fn test_load1() {
let value = simple_from_int(42);
let s: Box<dyn OidKeeper> = Box::new(ScalarMemOid::new(
value.clone(),
keeper::OType::Integer,
keeper::Access::ReadWrite,
));
let t: Box<dyn OidKeeper> = Box::new(ScalarMemOid::new(
value.clone(),
keeper::OType::Integer,
keeper::Access::ReadWrite,
));
let o0 = ObjectIdentifier::new(&ARC0).unwrap(); let o1 = ObjectIdentifier::new(&ARC).unwrap(); let o1_l = ObjectIdentifier::new(&ARC_LONG).unwrap(); let o2 = ObjectIdentifier::new(&ARC2).unwrap(); let o3 = ObjectIdentifier::new(&ARC3).unwrap(); let mut om = OidMap::default();
assert!(om.is_empty());
om.push(o1.clone(), s);
om.push(o3.clone(), t);
om.sort();
assert!(!om.is_empty());
assert_eq!(om.len(), 2);
let res = om.search(&o1);
assert!(res.is_ok());
let res = om.search(&o2);
assert!(res.is_err());
assert_eq!(*om.oid(0), o1);
let resn = om.search_next(&o3);
assert!(resn.is_none());
let resn = om.search_next(&o2);
assert!(resn.is_none());
let resn = om.search_next(&o1);
assert!(resn.is_some());
let resn = om.search_next(&o1_l);
assert!(resn.is_some());
let resn = om.search_next(&o0);
assert!(resn.is_some());
assert_eq!(resn.unwrap().get(o1).unwrap(), VarBindValue::Value(value));
}
#[test]
fn test_context_map() {
let value = simple_from_int(42);
let s: Box<dyn OidKeeper> = Box::new(ScalarMemOid::new(
value,
keeper::OType::Integer,
keeper::Access::ReadWrite,
));
let o1 = ObjectIdentifier::new(&ARC).unwrap(); let mut om = OidMap::default();
assert!(om.is_empty());
om.push(o1.clone(), s);
om.sort();
assert!(!om.is_empty());
let mut om2 = OidMap::default();
{
let mut cm = ContextMap::default();
cm.insert(b"test", &mut om);
cm.insert(b"aardvark", &mut om2);
cm.sort();
assert!(cm.lookup(b"other").is_none());
assert!(cm.lookup(b"test").is_some());
}
}
}