use super::Result;
use const_oid::ObjectIdentifier;
use der::Tag;
use der::asn1::{Any, SetOfVec};
use x509_cert::attr::AttributeTypeAndValue;
use x509_cert::name::{RdnSequence, RelativeDistinguishedName};
pub(super) const OID_CN: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.5.4.3");
const OID_O: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.5.4.10");
const OID_C: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.5.4.6");
const OID_ST: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.5.4.8");
const OID_L: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.5.4.7");
const OID_STREET: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.5.4.9");
const OID_POSTAL_CODE: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.5.4.17");
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NameAttribute {
pub oid: ObjectIdentifier,
pub value: String,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Name {
pub attrs: Vec<NameAttribute>,
}
impl Name {
pub fn new() -> Self {
Self { attrs: Vec::new() }
}
pub fn cn(mut self, value: impl Into<String>) -> Self {
self.attrs.push(NameAttribute {
oid: OID_CN,
value: value.into(),
});
self
}
pub fn org(mut self, value: impl Into<String>) -> Self {
self.attrs.push(NameAttribute {
oid: OID_O,
value: value.into(),
});
self
}
pub fn country(mut self, value: impl Into<String>) -> Self {
self.attrs.push(NameAttribute {
oid: OID_C,
value: value.into(),
});
self
}
pub fn province(mut self, value: impl Into<String>) -> Self {
self.attrs.push(NameAttribute {
oid: OID_ST,
value: value.into(),
});
self
}
pub fn locality(mut self, value: impl Into<String>) -> Self {
self.attrs.push(NameAttribute {
oid: OID_L,
value: value.into(),
});
self
}
pub fn street(mut self, value: impl Into<String>) -> Self {
self.attrs.push(NameAttribute {
oid: OID_STREET,
value: value.into(),
});
self
}
pub fn postal_code(mut self, value: impl Into<String>) -> Self {
self.attrs.push(NameAttribute {
oid: OID_POSTAL_CODE,
value: value.into(),
});
self
}
pub fn push(mut self, oid: ObjectIdentifier, value: impl Into<String>) -> Self {
self.attrs.push(NameAttribute {
oid,
value: value.into(),
});
self
}
pub(super) fn to_x509_name(&self) -> Result<x509_cert::name::Name> {
let mut rdns = Vec::with_capacity(self.attrs.len());
for attr in &self.attrs {
let mut set = SetOfVec::new();
set.insert(AttributeTypeAndValue {
oid: attr.oid,
value: Any::new(Tag::Utf8String, attr.value.as_bytes())?,
})
.expect("single ATAV per RDN must be unique");
rdns.push(RelativeDistinguishedName::from(set));
}
Ok(RdnSequence(rdns))
}
}