1#![cfg(feature = "std")]
2
3use std::io::Write;
4
5use crate::to_ber::*;
6use crate::{Class, Header, Length, SerializeResult, Tag};
7
8pub trait ToDer {
40 type Encoder: BerEncoder;
41
42 fn der_content_len(&self) -> Length;
46
47 fn der_total_len(&self) -> Length {
49 let (_, _, tag) = self.der_tag_info();
50 let content_length = self.der_content_len();
51 ber_total_length(tag, content_length)
52 }
53
54 fn der_tag_info(&self) -> (Class, bool, Tag);
56
57 fn der_write_content<W: Write>(&self, target: &mut W) -> SerializeResult<usize>;
61
62 fn der_write_header<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
66 let mut encoder = Self::Encoder::new();
67
68 let mut sz = 0;
69 let (class, constructed, tag) = self.der_tag_info();
70 sz += encoder.write_tag_info(class, constructed, tag, target)?;
71
72 let length = self.der_content_len();
74 sz += encoder.write_length(length, target)?;
75
76 Ok(sz)
77 }
78
79 fn der_encode<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
83 let sz = self.der_write_header(target)? + self.der_write_content(target)?;
84
85 Ok(sz)
86 }
87
88 fn der_encode_tagged_explicit<W: Write>(
94 &self,
95 class: Class,
96 tag_number: u32,
97 target: &mut W,
98 ) -> SerializeResult<usize> {
99 let length = self.der_total_len();
100 let tagged_header = Header::new(class, true, Tag(tag_number), length);
101 let sz = tagged_header.der_write_header(target)?
102 + self.der_write_header(target)?
103 + self.der_write_content(target)?;
104
105 Ok(sz)
106 }
107
108 fn der_encode_tagged_implicit<W: Write>(
114 &self,
115 class: Class,
116 tag_number: u32,
117 target: &mut W,
118 ) -> SerializeResult<usize> {
119 let length = self.der_content_len();
120 let (_, constructed, _) = self.der_tag_info();
121 let tagged_header = Header::new(class, constructed, Tag(tag_number), length);
122 let sz = tagged_header.der_write_header(target)? + self.der_write_content(target)?;
123
124 Ok(sz)
125 }
126
127 fn to_der_vec(&self) -> SerializeResult<Vec<u8>> {
129 let mut v = Vec::new();
130 self.der_encode(&mut v)?;
131 Ok(v)
132 }
133
134 fn write_der<W: Write>(&self, writer: &mut W) -> SerializeResult<usize> {
138 self.der_encode(writer)
139 }
140
141 #[deprecated(since = "0.8.0", note = "Use `der_total_len()` instead.")]
147 fn to_der_len(&self) -> crate::Result<usize> {
148 match self.der_content_len() {
149 Length::Definite(sz) => Ok(sz),
150 Length::Indefinite => Err(crate::Error::IndefiniteLengthUnexpected),
151 }
152 }
153
154 #[deprecated(since = "0.8.0", note = "Use `to_der_vec()` instead.")]
155 fn to_der_vec_raw(&self) -> SerializeResult<Vec<u8>> {
156 self.to_der_vec()
157 }
158}
159
160impl<E, T: ToDer> ToDer for &'_ T
163where
164 T: ToDer<Encoder = E>,
165 E: BerEncoder,
166{
167 type Encoder = <T as ToDer>::Encoder;
168
169 fn der_content_len(&self) -> Length {
170 (*self).der_content_len()
171 }
172
173 fn der_tag_info(&self) -> (Class, bool, Tag) {
174 (*self).der_tag_info()
175 }
176
177 fn der_write_content<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
178 (*self).der_write_content(target)
179 }
180}
181
182#[macro_export]
186macro_rules! impl_toder_from_tober {
187 (TY $ty:ty) => {
188 impl $crate::ToDer for $ty
189 where
190 $ty: ToBer,
191 {
192 type Encoder = <$ty as ToBer>::Encoder;
193
194 fn der_content_len(&self) -> Length {
195 <$ty as ToBer>::ber_content_len(self)
196 }
197
198 fn der_tag_info(&self) -> (Class, bool, Tag) {
199 <$ty as ToBer>::ber_tag_info(self)
200 }
201
202 fn der_write_content<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
203 <$ty as ToBer>::ber_write_content(self, target)
204 }
205 }
206 };
207 (LFT $lft:lifetime, $ty:ty) => {
208 impl<$lft> $crate::ToDer for $ty
209 where
210 $ty: ToBer,
211 {
212 type Encoder = <$ty as ToBer>::Encoder;
213
214 fn der_content_len(&self) -> Length {
215 <$ty as ToBer>::ber_content_len(self)
216 }
217
218 fn der_tag_info(&self) -> (Class, bool, Tag) {
219 <$ty as ToBer>::ber_tag_info(self)
220 }
221
222 fn der_write_content<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
223 <$ty as ToBer>::ber_write_content(self, target)
224 }
225 }
226 };
227}
228
229pub fn der_length_constructed_items<'a, T, IT>(iter: IT) -> Length
238where
239 T: ToDer + 'a,
240 IT: Iterator<Item = &'a T>,
241{
242 iter.map(|t| t.der_total_len()).sum()
243}