use crate::attr::AttributeTypeAndValue;
use alloc::vec::Vec;
use core::{fmt, str::FromStr};
use der::{asn1::SetOfVec, Encode};
pub type Name = RdnSequence;
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct RdnSequence(pub Vec<RelativeDistinguishedName>);
impl RdnSequence {
#[deprecated(since = "0.2.1", note = "use RdnSequence::from_str(...)?.to_der()")]
pub fn encode_from_string(s: &str) -> Result<Vec<u8>, der::Error> {
Self::from_str(s)?.to_der()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl FromStr for RdnSequence {
type Err = der::Error;
fn from_str(s: &str) -> der::Result<Self> {
split(s, b',')
.map(RelativeDistinguishedName::from_str)
.collect::<der::Result<Vec<_>>>()
.map(Self)
}
}
impl fmt::Display for RdnSequence {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, atv) in self.0.iter().enumerate() {
match i {
0 => write!(f, "{}", atv)?,
_ => write!(f, ",{}", atv)?,
}
}
Ok(())
}
}
impl_newtype!(RdnSequence, Vec<RelativeDistinguishedName>);
fn find(s: &str, b: u8) -> impl '_ + Iterator<Item = usize> {
(0..s.len())
.filter(move |i| s.as_bytes()[*i] == b)
.filter(|i| {
let x = i
.checked_sub(2)
.map(|i| s.as_bytes()[i])
.unwrap_or_default();
let y = i
.checked_sub(1)
.map(|i| s.as_bytes()[i])
.unwrap_or_default();
y != b'\\' || x == b'\\'
})
}
fn split(s: &str, b: u8) -> impl '_ + Iterator<Item = &'_ str> {
let mut prev = 0;
find(s, b).chain([s.len()].into_iter()).map(move |i| {
let x = &s[prev..i];
prev = i + 1;
x
})
}
pub type DistinguishedName = RdnSequence;
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct RelativeDistinguishedName(pub SetOfVec<AttributeTypeAndValue>);
impl RelativeDistinguishedName {
#[deprecated(
since = "0.2.1",
note = "use RelativeDistinguishedName::from_str(...)?.to_der()"
)]
pub fn encode_from_string(s: &str) -> Result<Vec<u8>, der::Error> {
Self::from_str(s)?.to_der()
}
}
impl FromStr for RelativeDistinguishedName {
type Err = der::Error;
fn from_str(s: &str) -> der::Result<Self> {
split(s, b'+')
.map(AttributeTypeAndValue::from_str)
.collect::<der::Result<Vec<_>>>()?
.try_into()
.map(Self)
}
}
impl fmt::Display for RelativeDistinguishedName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, atv) in self.0.iter().enumerate() {
match i {
0 => write!(f, "{}", atv)?,
_ => write!(f, "+{}", atv)?,
}
}
Ok(())
}
}
impl_newtype!(RelativeDistinguishedName, SetOfVec<AttributeTypeAndValue>);