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
189pub trait AsAlgorithmIdentifierRef {
191 fn as_algo_ref<'a>(&'a self) -> AlgorithmIdentifierRef<'a>;
193}
194
195impl<'a> AsAlgorithmIdentifierRef for AlgorithmIdentifierRef<'a> {
196 fn as_algo_ref(&self) -> AlgorithmIdentifierRef<'a> {
197 *self
198 }
199}
200
201#[cfg(feature = "alloc")]
202mod allocating {
203 use super::*;
204 use der::referenced::*;
205
206 impl<'a> RefToOwned<'a> for AlgorithmIdentifierRef<'a> {
207 type Owned = AlgorithmIdentifierOwned;
208 fn ref_to_owned(&self) -> Self::Owned {
209 AlgorithmIdentifier {
210 oid: self.oid,
211 parameters: self.parameters.ref_to_owned(),
212 }
213 }
214 }
215
216 impl OwnedToRef for AlgorithmIdentifierOwned {
217 type Borrowed<'a> = AlgorithmIdentifierRef<'a>;
218 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
219 AlgorithmIdentifier {
220 oid: self.oid,
221 parameters: self.parameters.owned_to_ref(),
222 }
223 }
224 }
225
226 impl AsAlgorithmIdentifierRef for AlgorithmIdentifierOwned {
227 fn as_algo_ref<'a>(&'a self) -> AlgorithmIdentifierRef<'a> {
228 AlgorithmIdentifier {
229 oid: self.oid,
230 parameters: self.parameters.owned_to_ref(),
231 }
232 }
233 }
234
235 impl<'a> From<AlgorithmIdentifierRef<'a>> for AlgorithmIdentifierOwned {
236 fn from(value: AlgorithmIdentifierRef) -> Self {
237 Self {
238 oid: value.oid,
239 parameters: value.parameters.map(Into::into),
240 }
241 }
242 }
243
244 impl<'a> From<&'a AlgorithmIdentifierOwned> for AlgorithmIdentifierRef<'a> {
245 fn from(value: &'a AlgorithmIdentifierOwned) -> Self {
246 Self {
247 oid: value.oid,
248 parameters: value.parameters.as_ref().map(|p| p.to_ref()),
249 }
250 }
251 }
252}