use core::convert::TryFrom;
use der::{
Any, Decodable, Encodable, Encoder, Error, Length, Message, Null, ObjectIdentifier, Result, Tag,
};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AlgorithmIdentifier<'a> {
pub oid: ObjectIdentifier,
pub parameters: Option<AlgorithmParameters<'a>>,
}
impl<'a> AlgorithmIdentifier<'a> {
pub fn parameters_any(&self) -> Result<Any<'a>> {
let params = self.parameters.ok_or(der::ErrorKind::Truncated)?;
params.any().ok_or_else(|| {
der::ErrorKind::UnexpectedTag {
expected: Some(der::Tag::Sequence),
actual: params.tag(),
}
.into()
})
}
pub fn parameters_oid(&self) -> Result<ObjectIdentifier> {
let params = self.parameters.ok_or(der::ErrorKind::Truncated)?;
params.oid().ok_or_else(|| {
der::ErrorKind::UnexpectedTag {
expected: Some(der::Tag::Sequence),
actual: params.tag(),
}
.into()
})
}
}
impl<'a> TryFrom<&'a [u8]> for AlgorithmIdentifier<'a> {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<Self> {
Self::from_bytes(bytes)
}
}
impl<'a> TryFrom<Any<'a>> for AlgorithmIdentifier<'a> {
type Error = Error;
fn try_from(any: Any<'a>) -> Result<AlgorithmIdentifier<'a>> {
any.sequence(|decoder| {
let oid = decoder.decode()?;
let parameters = decoder.decode()?;
Ok(Self { oid, parameters })
})
}
}
impl<'a> Message<'a> for AlgorithmIdentifier<'a> {
fn fields<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce(&[&dyn Encodable]) -> Result<T>,
{
f(&[&self.oid, &self.parameters])
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AlgorithmParameters<'a> {
Any(Any<'a>),
Null,
Oid(ObjectIdentifier),
}
impl<'a> AlgorithmParameters<'a> {
pub fn any(self) -> Option<Any<'a>> {
match self {
Self::Any(any) => Some(any),
_ => None,
}
}
pub fn is_null(self) -> bool {
self == AlgorithmParameters::Null
}
pub fn is_oid(self) -> bool {
self.oid().is_some()
}
pub fn oid(self) -> Option<ObjectIdentifier> {
match self {
Self::Oid(oid) => Some(oid),
_ => None,
}
}
pub fn tag(self) -> Tag {
match self {
Self::Any(any) => any.tag(),
Self::Null => Tag::Null,
Self::Oid(_) => Tag::ObjectIdentifier,
}
}
}
impl<'a> From<Null> for AlgorithmParameters<'a> {
fn from(_: Null) -> AlgorithmParameters<'a> {
Self::Null
}
}
impl<'a> From<ObjectIdentifier> for AlgorithmParameters<'a> {
fn from(oid: ObjectIdentifier) -> AlgorithmParameters<'a> {
Self::Oid(oid)
}
}
impl<'a> TryFrom<Any<'a>> for AlgorithmParameters<'a> {
type Error = Error;
fn try_from(any: Any<'a>) -> Result<AlgorithmParameters<'a>> {
match any.tag() {
Tag::Null => Null::try_from(any).map(Into::into),
Tag::ObjectIdentifier => any.oid().map(Into::into),
_ => Ok(Self::Any(any)),
}
}
}
impl<'a> Encodable for AlgorithmParameters<'a> {
fn encoded_len(&self) -> Result<Length> {
match self {
Self::Any(any) => any.encoded_len(),
Self::Null => Null.encoded_len(),
Self::Oid(oid) => oid.encoded_len(),
}
}
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
match self {
Self::Any(any) => any.encode(encoder),
Self::Null => encoder.null(),
Self::Oid(oid) => encoder.oid(*oid),
}
}
}