use crate::usm::User;
use rasn::types::ObjectIdentifier;
use rasn_smi::v2::{ApplicationSyntax, ObjectSyntax, SimpleSyntax};
use rasn_snmp::v3::{VarBind, VarBindValue};
use std::hash::Hash;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum OidErr {
OutOfRange,
WrongType,
NoSuchInstance,
NoSuchName,
NoAccess,
NotWritable,
GenErr,
CommitFail,
UndoFail,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Access {
NoAccess,
NotificationOnly,
ReadOnly,
ReadWrite,
ReadCreate,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum OType {
Integer,
RowStatus,
TestAndIncr,
String,
ObjectId,
Address,
Unsigned,
Arbitrary,
Counter,
BigCounter,
Ticks,
}
pub fn check_type(otype: OType, val: &ObjectSyntax) -> bool {
match val {
ObjectSyntax::Simple(SimpleSyntax::Integer(_)) => {
otype == OType::Integer || otype == OType::RowStatus || otype == OType::TestAndIncr
}
ObjectSyntax::Simple(SimpleSyntax::String(_)) => otype == OType::String,
ObjectSyntax::Simple(SimpleSyntax::ObjectId(_)) => otype == OType::ObjectId,
ObjectSyntax::ApplicationWide(ApplicationSyntax::Address(_)) => otype == OType::Address,
ObjectSyntax::ApplicationWide(ApplicationSyntax::Unsigned(_)) => otype == OType::Unsigned,
ObjectSyntax::ApplicationWide(ApplicationSyntax::Arbitrary(_)) => otype == OType::Arbitrary,
ObjectSyntax::ApplicationWide(ApplicationSyntax::Counter(_)) => otype == OType::Counter,
ObjectSyntax::ApplicationWide(ApplicationSyntax::BigCounter(_)) => {
otype == OType::BigCounter
}
ObjectSyntax::ApplicationWide(ApplicationSyntax::Ticks(_)) => otype == OType::Ticks,
}
}
pub trait OidKeeper {
fn is_scalar(&self, oid: ObjectIdentifier) -> bool;
fn get(&self, oid: ObjectIdentifier) -> Result<VarBindValue, OidErr>;
fn get_next(&self, oid: ObjectIdentifier) -> Result<VarBind, OidErr>;
fn access(&self, oid: ObjectIdentifier) -> Access;
fn begin_transaction(&mut self) -> Result<(), OidErr>;
fn set(
&mut self,
oid: ObjectIdentifier,
value: VarBindValue,
user: &User,
) -> Result<VarBindValue, OidErr>;
fn commit(&mut self, user: &User) -> Result<(), OidErr>;
fn rollback(&mut self) -> Result<(), OidErr>;
fn is_empty(&self) -> bool {
false
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::*;
use rasn::types::OctetString;
use rasn_smi::v1::ToOpaque;
use rasn_smi::v2::{ApplicationSyntax, ObjectSyntax};
#[test]
fn test_check_otype_int() {
let val = simple_from_int(21);
assert!(check_type(OType::Integer, &val));
assert!(check_type(OType::TestAndIncr, &val));
assert!(check_type(OType::RowStatus, &val));
assert!(!check_type(OType::String, &val));
assert!(!check_type(OType::ObjectId, &val));
assert!(!check_type(OType::Counter, &val));
assert!(!check_type(OType::BigCounter, &val));
assert!(!check_type(OType::Ticks, &val));
assert!(!check_type(OType::Address, &val));
assert!(!check_type(OType::Unsigned, &val));
assert!(!check_type(OType::Arbitrary, &val));
}
#[test]
fn test_check_otype_str() {
let val = simple_from_str(b"test");
assert!(!check_type(OType::Integer, &val));
assert!(!check_type(OType::TestAndIncr, &val));
assert!(!check_type(OType::RowStatus, &val));
assert!(check_type(OType::String, &val));
assert!(!check_type(OType::ObjectId, &val));
assert!(!check_type(OType::Counter, &val));
assert!(!check_type(OType::BigCounter, &val));
assert!(!check_type(OType::Ticks, &val));
assert!(!check_type(OType::Address, &val));
assert!(!check_type(OType::Unsigned, &val));
assert!(!check_type(OType::Arbitrary, &val));
}
#[test]
fn test_check_otype_objid() {
let val = simple_from_vec(&[0, 1, 2]);
assert!(!check_type(OType::Integer, &val));
assert!(!check_type(OType::TestAndIncr, &val));
assert!(!check_type(OType::RowStatus, &val));
assert!(!check_type(OType::String, &val));
assert!(check_type(OType::ObjectId, &val));
assert!(!check_type(OType::Counter, &val));
assert!(!check_type(OType::BigCounter, &val));
assert!(!check_type(OType::Ticks, &val));
assert!(!check_type(OType::Address, &val));
assert!(!check_type(OType::Unsigned, &val));
assert!(!check_type(OType::Arbitrary, &val));
}
#[test]
fn test_check_otype_counter() {
let val = counter_from_int(42);
assert!(!check_type(OType::Integer, &val));
assert!(!check_type(OType::TestAndIncr, &val));
assert!(!check_type(OType::RowStatus, &val));
assert!(!check_type(OType::String, &val));
assert!(!check_type(OType::ObjectId, &val));
assert!(check_type(OType::Counter, &val));
assert!(!check_type(OType::BigCounter, &val));
assert!(!check_type(OType::Ticks, &val));
assert!(!check_type(OType::Address, &val));
assert!(!check_type(OType::Unsigned, &val));
assert!(!check_type(OType::Arbitrary, &val));
}
#[test]
fn test_check_otype_big() {
let val = big_counter_from_int(42);
assert!(!check_type(OType::Integer, &val));
assert!(!check_type(OType::TestAndIncr, &val));
assert!(!check_type(OType::RowStatus, &val));
assert!(!check_type(OType::String, &val));
assert!(!check_type(OType::ObjectId, &val));
assert!(!check_type(OType::Counter, &val));
assert!(check_type(OType::BigCounter, &val));
assert!(!check_type(OType::Ticks, &val));
assert!(!check_type(OType::Address, &val));
assert!(!check_type(OType::Unsigned, &val));
assert!(!check_type(OType::Arbitrary, &val));
}
#[test]
fn test_check_otype_ticks() {
let val = ticks_from_int(21);
assert!(!check_type(OType::Integer, &val));
assert!(!check_type(OType::TestAndIncr, &val));
assert!(!check_type(OType::RowStatus, &val));
assert!(!check_type(OType::String, &val));
assert!(!check_type(OType::ObjectId, &val));
assert!(!check_type(OType::Counter, &val));
assert!(!check_type(OType::BigCounter, &val));
assert!(check_type(OType::Ticks, &val));
assert!(!check_type(OType::Address, &val));
assert!(!check_type(OType::Unsigned, &val));
assert!(!check_type(OType::Arbitrary, &val));
}
#[test]
fn test_check_otype_addr() {
let val = address_from_vec([0, 0, 0, 0]);
assert!(!check_type(OType::Integer, &val));
assert!(!check_type(OType::TestAndIncr, &val));
assert!(!check_type(OType::RowStatus, &val));
assert!(!check_type(OType::String, &val));
assert!(!check_type(OType::ObjectId, &val));
assert!(!check_type(OType::Counter, &val));
assert!(!check_type(OType::BigCounter, &val));
assert!(!check_type(OType::Ticks, &val));
assert!(check_type(OType::Address, &val));
assert!(!check_type(OType::Unsigned, &val));
assert!(!check_type(OType::Arbitrary, &val));
}
#[test]
fn test_check_otype_unsigned() {
let val = unsigned_from_value(73);
assert!(!check_type(OType::Integer, &val));
assert!(!check_type(OType::TestAndIncr, &val));
assert!(!check_type(OType::RowStatus, &val));
assert!(!check_type(OType::String, &val));
assert!(!check_type(OType::ObjectId, &val));
assert!(!check_type(OType::Counter, &val));
assert!(!check_type(OType::BigCounter, &val));
assert!(!check_type(OType::Ticks, &val));
assert!(!check_type(OType::Arbitrary, &val));
assert!(!check_type(OType::Address, &val));
assert!(check_type(OType::Unsigned, &val));
}
#[test]
fn test_check_otype_arbitrary() {
let val = ObjectSyntax::ApplicationWide(ApplicationSyntax::Arbitrary(
OctetString::from_static(b"test").to_opaque().unwrap(),
));
assert!(check_type(OType::Arbitrary, &val));
assert!(!check_type(OType::Integer, &val));
assert!(!check_type(OType::TestAndIncr, &val));
assert!(!check_type(OType::RowStatus, &val));
assert!(!check_type(OType::String, &val));
assert!(!check_type(OType::ObjectId, &val));
assert!(!check_type(OType::Counter, &val));
assert!(!check_type(OType::BigCounter, &val));
assert!(!check_type(OType::Ticks, &val));
assert!(!check_type(OType::Address, &val));
assert!(!check_type(OType::Unsigned, &val));
}
}