Skip to content

Commit

Permalink
Refactor PolicyMappings to keep items in order
Browse files Browse the repository at this point in the history
  • Loading branch information
chifflier committed Jul 27, 2021
1 parent 070b9cf commit c944d21
Showing 1 changed file with 69 additions and 12 deletions.
81 changes: 69 additions & 12 deletions src/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ impl<'a> FromDer<'a> for InhibitAnyPolicy {

#[derive(Clone, Debug, PartialEq)]
pub struct PolicyMappings<'a> {
pub mappings: HashMap<Oid<'a>, Vec<Oid<'a>>>,
pub mappings: Vec<PolicyMapping<'a>>,
}

impl<'a> FromDer<'a> for PolicyMappings<'a> {
Expand All @@ -493,6 +493,64 @@ impl<'a> FromDer<'a> for PolicyMappings<'a> {
}
}

impl<'a> PolicyMappings<'a> {
/// Returns a `HashMap` mapping `Oid` to the list of references to `Oid`
///
/// If several names match the same `Oid`, they are merged in the same entry.
pub fn as_hashmap(&self) -> HashMap<Oid<'a>, Vec<&Oid<'a>>> {
// create the hashmap and merge entries with same OID
let mut m: HashMap<Oid, Vec<&_>> = HashMap::new();
for desc in &self.mappings {
let PolicyMapping {
issuer_domain_policy: left,
subject_domain_policy: right,
} = desc;
if let Some(l) = m.get_mut(&left) {
l.push(right);
} else {
m.insert(left.clone(), vec![right]);
}
}
m
}

/// Returns a `HashMap` mapping `Oid` to the list of `Oid` (consuming the input)
///
/// If several names match the same `Oid`, they are merged in the same entry.
pub fn into_hashmap(self) -> HashMap<Oid<'a>, Vec<Oid<'a>>> {
let mut l = self.mappings;
// create the hashmap and merge entries with same OID
let mut m: HashMap<Oid, Vec<_>> = HashMap::new();
for mapping in l.drain(..) {
let PolicyMapping {
issuer_domain_policy: left,
subject_domain_policy: right,
} = mapping;
if let Some(general_names) = m.get_mut(&left) {
general_names.push(right);
} else {
m.insert(left, vec![right]);
}
}
m
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct PolicyMapping<'a> {
pub issuer_domain_policy: Oid<'a>,
pub subject_domain_policy: Oid<'a>,
}

impl<'a> PolicyMapping<'a> {
pub const fn new(issuer_domain_policy: Oid<'a>, subject_domain_policy: Oid<'a>) -> Self {
PolicyMapping {
issuer_domain_policy,
subject_domain_policy,
}
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct PolicyConstraints {
pub require_explicit_policy: Option<u32>,
Expand Down Expand Up @@ -890,21 +948,20 @@ pub(crate) mod parser {
parse_der_sequence_of_v(parse_der_oid)(i)
}
let (ret, pairs) = parse_der_sequence_of_v(parse_oid_pair)(i)?;
let mut mappings: HashMap<Oid, Vec<Oid>> = HashMap::new();
let mut mappings = Vec::new();
// let mut mappings: HashMap<Oid, Vec<Oid>> = HashMap::new();
for pair in pairs.iter() {
if pair.len() != 2 {
return Err(Err::Failure(BerError::BerValueError));
}
let left = pair[0].as_oid_val().map_err(nom::Err::Failure)?;
let right = pair[1].as_oid_val().map_err(nom::Err::Failure)?;
if left.bytes() == oid!(raw 2.5.29.32.0) || right.bytes() == oid!(raw 2.5.29.32.0) {
// mapping to or from anyPolicy is not allowed
return Err(Err::Failure(BerError::InvalidTag));
}
mappings
.entry(left)
.and_modify(|v| v.push(right.clone()))
.or_insert_with(|| vec![right.clone()]);
// XXX this should go to Validate
// if left.bytes() == oid!(raw 2.5.29.32.0) || right.bytes() == oid!(raw 2.5.29.32.0) {
// // mapping to or from anyPolicy is not allowed
// return Err(Err::Failure(BerError::InvalidTag));
// }
mappings.push(PolicyMapping::new(left, right));
}
Ok((ret, PolicyMappings { mappings }))
}
Expand Down Expand Up @@ -1327,12 +1384,12 @@ mod tests {
}
);
{
let pm = tbs.policy_mappings().unwrap().1;
let pm = tbs.policy_mappings().unwrap().1.clone().into_hashmap();
let mut pm_ref = HashMap::new();
pm_ref.insert(oid!(2.34.23), vec![oid!(2.2)]);
pm_ref.insert(oid!(1.1), vec![oid!(0.0.4)]);
pm_ref.insert(oid!(2.2), vec![oid!(2.2.1), oid!(2.2.3)]);
assert_eq!(pm.mappings, pm_ref);
assert_eq!(pm, pm_ref);
}
}

Expand Down

0 comments on commit c944d21

Please sign in to comment.