1use crate::{Error, Result};
4use core::cmp::Ordering;
5use der::{
6 Decode, DecodeValue, DerOrd, Encode, EncodeValue, Header, Length, Reader, Sequence, ValueOrd,
7 Writer,
8 asn1::{AnyRef, Choice, ObjectIdentifier},
9};
10
11#[cfg(feature = "alloc")]
12use der::asn1::Any;
13
14#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
24#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
25pub struct AlgorithmIdentifier<Params> {
26 pub oid: ObjectIdentifier,
29
30 pub parameters: Option<Params>,
32}
33
34impl<'a, Params> DecodeValue<'a> for AlgorithmIdentifier<Params>
35where
36 Params: Choice<'a, Error = der::Error>,
37{
38 type Error = der::Error;
39
40 fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
41 Ok(Self {
42 oid: reader.decode()?,
43 parameters: reader.decode()?,
44 })
45 }
46}
47
48impl<Params> EncodeValue for AlgorithmIdentifier<Params>
49where
50 Params: Encode,
51{
52 fn value_len(&self) -> der::Result<Length> {
53 self.oid.encoded_len()? + self.parameters.encoded_len()?
54 }
55
56 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
57 self.oid.encode(writer)?;
58 self.parameters.encode(writer)?;
59 Ok(())
60 }
61}
62
63impl<'a, Params> Sequence<'a> for AlgorithmIdentifier<Params> where
64 Params: Choice<'a, Error = der::Error> + Encode
65{
66}
67
68impl<'a, Params> TryFrom<&'a [u8]> for AlgorithmIdentifier<Params>
69where
70 Params: Choice<'a, Error = der::Error> + Encode,
71{
72 type Error = Error;
73
74 fn try_from(bytes: &'a [u8]) -> Result<Self> {
75 Ok(Self::from_der(bytes)?)
76 }
77}
78
79impl<Params> ValueOrd for AlgorithmIdentifier<Params>
80where
81 Params: DerOrd,
82{
83 fn value_cmp(&self, other: &Self) -> der::Result<Ordering> {
84 match self.oid.der_cmp(&other.oid)? {
85 Ordering::Equal => self.parameters.der_cmp(&other.parameters),
86 other => Ok(other),
87 }
88 }
89}
90
91pub type AlgorithmIdentifierRef<'a> = AlgorithmIdentifier<AnyRef<'a>>;
93
94pub type AlgorithmIdentifierWithOid = AlgorithmIdentifier<ObjectIdentifier>;
96
97#[cfg(feature = "alloc")]
99pub type AlgorithmIdentifierOwned = AlgorithmIdentifier<Any>;
100
101impl<Params> AlgorithmIdentifier<Params> {
102 pub fn assert_algorithm_oid(&self, expected_oid: ObjectIdentifier) -> Result<ObjectIdentifier> {
107 if self.oid == expected_oid {
108 Ok(expected_oid)
109 } else {
110 Err(Error::OidUnknown { oid: self.oid })
111 }
112 }
113}
114
115impl<'a> AlgorithmIdentifierRef<'a> {
116 pub fn assert_parameters_oid(
121 &self,
122 expected_oid: ObjectIdentifier,
123 ) -> Result<ObjectIdentifier> {
124 let actual_oid = self.parameters_oid()?;
125
126 if actual_oid == expected_oid {
127 Ok(actual_oid)
128 } else {
129 Err(Error::OidUnknown { oid: actual_oid })
130 }
131 }
132
133 pub fn assert_oids(
138 &self,
139 algorithm: ObjectIdentifier,
140 parameters: ObjectIdentifier,
141 ) -> Result<()> {
142 self.assert_algorithm_oid(algorithm)?;
143 self.assert_parameters_oid(parameters)?;
144 Ok(())
145 }
146
147 pub fn parameters_any(&self) -> Result<AnyRef<'a>> {
152 self.parameters.ok_or(Error::AlgorithmParametersMissing)
153 }
154
155 pub fn parameters_oid(&self) -> Result<ObjectIdentifier> {
161 Ok(ObjectIdentifier::try_from(self.parameters_any()?)?)
162 }
163
164 pub fn oids(&self) -> der::Result<(ObjectIdentifier, Option<ObjectIdentifier>)> {
173 Ok((
174 self.oid,
175 match self.parameters {
176 None => None,
177 Some(p) => {
178 if p.is_null() {
179 None
180 } else {
181 Some(p.decode_as::<ObjectIdentifier>()?)
182 }
183 }
184 },
185 ))
186 }
187}
188
189#[cfg(feature = "alloc")]
190mod allocating {
191 use super::*;
192 use der::referenced::*;
193
194 impl<'a> RefToOwned<'a> for AlgorithmIdentifierRef<'a> {
195 type Owned = AlgorithmIdentifierOwned;
196 fn ref_to_owned(&self) -> Self::Owned {
197 AlgorithmIdentifier {
198 oid: self.oid,
199 parameters: self.parameters.ref_to_owned(),
200 }
201 }
202 }
203
204 impl OwnedToRef for AlgorithmIdentifierOwned {
205 type Borrowed<'a> = AlgorithmIdentifierRef<'a>;
206 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
207 AlgorithmIdentifier {
208 oid: self.oid,
209 parameters: self.parameters.owned_to_ref(),
210 }
211 }
212 }
213}