use std::collections::HashMap;
use lber::structure::{PL, StructureTag};
use lber::structures::{ASNTag, Boolean, OctetString, Sequence, Tag};
use lber::universal::Types;
pub mod types {
pub use self::inner::_ControlType::{PagedResults, PostReadResp, PreReadResp};
pub type ControlType = self::inner::_ControlType;
mod inner {
#[derive(Clone, Copy, Debug)]
pub enum _ControlType {
PagedResults,
PostReadResp,
PreReadResp,
#[doc(hidden)]
_Nonexhaustive,
}
}
}
use self::types::ControlType;
mod assertion;
pub use self::assertion::Assertion;
mod paged_results;
pub use self::paged_results::PagedResults;
mod proxy_auth;
pub use self::proxy_auth::ProxyAuth;
mod read_entry;
pub use self::read_entry::{PostRead, PostReadResp, PreRead, PreReadResp, ReadEntryResp};
mod relax_rules;
pub use self::relax_rules::RelaxRules;
lazy_static! {
static ref CONTROLS: HashMap<&'static str, ControlType> = {
let mut map = HashMap::new();
map.insert(self::paged_results::PAGED_RESULTS_OID, types::PagedResults);
map.insert(self::read_entry::POST_READ_OID, types::PostReadResp);
map.insert(self::read_entry::PRE_READ_OID, types::PreReadResp);
map
};
}
pub trait IntoRawControlVec {
fn into(self) -> Vec<RawControl>;
}
impl IntoRawControlVec for RawControl {
fn into(self) -> Vec<RawControl> {
vec![self]
}
}
impl IntoRawControlVec for Vec<RawControl> {
fn into(self) -> Vec<RawControl> {
self
}
}
pub trait MakeCritical {
fn critical(self) -> CriticalControl<Self> where Self: Sized {
CriticalControl {
control: self,
}
}
}
pub struct CriticalControl<T> {
control: T
}
impl<T> From<CriticalControl<T>> for RawControl
where T: Into<RawControl>
{
fn from(cc: CriticalControl<T>) -> RawControl {
let mut rc = cc.control.into();
rc.crit = true;
rc
}
}
pub trait ControlParser {
fn parse(val: &[u8]) -> Self;
}
#[derive(Clone, Debug)]
pub struct Control(pub Option<ControlType>, pub RawControl);
#[derive(Clone, Debug)]
pub struct RawControl {
pub ctype: String,
pub crit: bool,
pub val: Option<Vec<u8>>,
}
impl RawControl {
pub fn parse<T: ControlParser>(&self) -> T {
T::parse(self.val.as_ref().expect("value"))
}
}
pub fn build_tag(rc: RawControl)-> StructureTag {
let mut seq = vec![
Tag::OctetString(OctetString {
inner: Vec::from(rc.ctype.as_bytes()),
.. Default::default()
})
];
if rc.crit {
seq.push(Tag::Boolean(Boolean {
inner: true,
.. Default::default()
}));
}
if let Some(val) = rc.val {
seq.push(Tag::OctetString(OctetString {
inner: val,
.. Default::default()
}));
}
Tag::Sequence(Sequence {
inner: seq,
.. Default::default()
}).into_structure()
}
pub fn parse_controls(t: StructureTag) -> Vec<Control> {
let tags = t.expect_constructed().expect("result sequence").into_iter();
let mut ctrls = Vec::new();
for ctrl in tags {
let mut components = ctrl.expect_constructed().expect("components").into_iter();
let ctype = String::from_utf8(components.next().expect("element").expect_primitive().expect("octet string")).expect("control type");
let next = components.next();
let (crit, maybe_val) = match next {
None => (false, None),
Some(c) => match c {
StructureTag { id, ref payload, .. } if id == Types::Boolean as u64 => match *payload {
PL::P(ref v) => (v[0] != 0, components.next()),
PL::C(_) => panic!("decoding error"),
},
StructureTag { id, .. } if id == Types::OctetString as u64 => (false, Some(c.clone())),
_ => panic!("decoding error"),
},
};
let val = match maybe_val {
None => None,
Some(v) => Some(Vec::from(v.expect_primitive().expect("octet string"))),
};
let known_type = match CONTROLS.get(&*ctype) {
Some(val) => Some(*val),
None => None,
};
ctrls.push(Control(known_type, RawControl { ctype: ctype, crit: crit, val: val }));
}
ctrls
}