use super::{end, names, sequence, tag};
use crate::attribute::Attribute;
use crate::signer::required;
use crate::{Error, ErrorCode, Result};
use structured_asn1::memory::{OwnedVec, Work};
use structured_asn1::{Element, Encoding, Oid, ScopedReader, Tag};
use structured_pkix::general_name::{self, GeneralName};
const FIELD: &str = "attributeCertificate.role";
pub const IDENTIFIER: Oid<'static> = Oid::from_bytes(&[0x55, 4, 72]);
#[derive(Debug)]
pub struct RoleSyntax<'a> {
element: Element<'a>,
authority_element: Option<Element<'a>>,
authority: Option<OwnedVec<GeneralName<'a>>>,
name_wrapper: Element<'a>,
name_element: Element<'a>,
name: &'a str,
}
impl<'a> RoleSyntax<'a> {
pub fn read(parent: &mut ScopedReader<'a, '_>) -> Result<Self> {
let element = required(parent, FIELD)?;
let reading = Self::read_element(parent, &element)?;
end(parent, FIELD)?;
Ok(reading)
}
pub fn read_element(parent: &ScopedReader<'a, '_>, element: &Element<'a>) -> Result<Self> {
let mut der = parent
.reread(element, Encoding::Der)
.map_err(|e| Error::encoding(e, FIELD))?;
let element = required(&mut der, FIELD)?;
tag(&element, sequence(), FIELD)?;
end(&der, FIELD)?;
let mut inside = der.enter(&element).map_err(|e| Error::encoding(e, FIELD))?;
let mut next = required(&mut inside, FIELD)?;
let (authority_element, authority) = if next.tag() == Tag::context(true, 0) {
let authority = names(&inside, &next, FIELD)?;
let original = next;
next = required(&mut inside, FIELD)?;
(Some(original), Some(authority))
} else {
(None, None)
};
tag(&next, Tag::context(true, 1), FIELD)?;
end(&inside, FIELD)?;
let mut wrapped = inside.enter(&next).map_err(|e| Error::encoding(e, FIELD))?;
let name_element = required(&mut wrapped, FIELD)?;
tag(&name_element, Tag::context(false, 6), FIELD)?;
end(&wrapped, FIELD)?;
let GeneralName::Uri(name) =
general_name::read(&wrapped, &name_element, FIELD).map_err(Error::pkix)?
else {
unreachable!("URI tag preflight")
};
Ok(Self {
element,
authority_element,
authority,
name_wrapper: next,
name_element,
name,
})
}
pub fn read_attribute<W: Work>(attribute: &Attribute<'a>, work: &W) -> Result<OwnedVec<Self>> {
let execution = attribute.query_in(work);
execution
.charge_work(4)
.map_err(|e| Error::resource(e, FIELD, attribute.span().start))?;
if attribute.kind() != IDENTIFIER {
return Err(Error::schema(
ErrorCode::UnexpectedContentType,
FIELD,
attribute.span().start,
));
}
if attribute.values().is_empty() {
return Err(Error::schema(
ErrorCode::AttributeCardinality,
FIELD,
attribute.span().start,
));
}
let mut values = execution.vector();
values
.try_reserve_exact(attribute.values().len())
.map_err(|e| Error::resource(e, FIELD, attribute.span().start))?;
for index in 0..attribute.values().len() {
let mut reader = attribute
.value_reader_scoped(index, &execution, FIELD)?
.ok_or_else(|| {
Error::schema(
ErrorCode::AttributeCardinality,
FIELD,
attribute.span().start,
)
})?;
let at = reader.offset();
let value = Self::read(&mut reader)?;
values
.try_push(value)
.map_err(|e| Error::resource(e, FIELD, at))?;
}
Ok(values.into_owned())
}
#[must_use]
pub fn element(&self) -> Element<'a> {
self.element
}
#[must_use]
pub fn authority(&self) -> Option<&[GeneralName<'a>]> {
self.authority.as_deref()
}
#[must_use]
pub fn authority_element(&self) -> Option<Element<'a>> {
self.authority_element
}
#[must_use]
pub fn name_wrapper(&self) -> Element<'a> {
self.name_wrapper
}
#[must_use]
pub fn name_element(&self) -> Element<'a> {
self.name_element
}
#[must_use]
pub fn name(&self) -> &'a str {
self.name
}
}