Skip to main content

asn1/
writer.rs

1use crate::types::{Asn1Writable, SimpleAsn1Writable};
2use crate::Tag;
3#[cfg(not(feature = "std"))]
4use alloc::vec::Vec;
5use alloc::{fmt, vec};
6
7/// `WriteError` are returned when there is an error writing the ASN.1 data.
8#[derive(PartialEq, Eq, Debug)]
9pub enum WriteError {
10    AllocationError,
11    InvalidSetOrdering,
12}
13
14impl fmt::Display for WriteError {
15    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16        match self {
17            WriteError::AllocationError => write!(f, "allocation error"),
18            WriteError::InvalidSetOrdering => {
19                write!(f, "SET elements are not in DER order")
20            }
21        }
22    }
23}
24
25#[cfg(feature = "std")]
26impl std::error::Error for WriteError {}
27
28pub type WriteResult<T = ()> = Result<T, WriteError>;
29
30pub struct WriteBuf(Vec<u8>);
31
32impl WriteBuf {
33    #[inline]
34    pub(crate) fn new(data: Vec<u8>) -> WriteBuf {
35        WriteBuf(data)
36    }
37
38    #[inline]
39    pub(crate) fn len(&self) -> usize {
40        self.0.len()
41    }
42
43    #[inline]
44    pub(crate) fn as_slice(&self) -> &[u8] {
45        self.0.as_slice()
46    }
47
48    #[inline]
49    pub(crate) fn as_mut_slice(&mut self) -> &mut [u8] {
50        self.0.as_mut_slice()
51    }
52
53    // Reserve space for up to `len` additional bytes.
54    #[inline]
55    pub fn reserve_additional(&mut self, len: usize) -> WriteResult {
56        self.0
57            .try_reserve(len)
58            .map_err(|_| WriteError::AllocationError)?;
59
60        Ok(())
61    }
62
63    #[inline]
64    pub fn push_byte(&mut self, b: u8) -> WriteResult {
65        self.reserve_additional(1)?;
66        self.0.push(b);
67        Ok(())
68    }
69
70    #[inline]
71    pub fn push_slice(&mut self, data: &[u8]) -> WriteResult {
72        self.reserve_additional(data.len())?;
73
74        self.0.extend_from_slice(data);
75        Ok(())
76    }
77}
78
79fn _length_length(length: usize) -> u8 {
80    (usize::BITS - length.leading_zeros()).div_ceil(8) as u8
81}
82
83/// Calculate the number of bytes needed to encode a length field for the given content length.
84/// This includes the length-of-length byte for lengths >= 128.
85pub(crate) fn length_encoding_size(content_length: usize) -> usize {
86    if content_length < 128 {
87        1
88    } else {
89        1 + _length_length(content_length) as usize
90    }
91}
92
93fn _insert_at_position(buf: &mut WriteBuf, pos: usize, data: &[u8]) -> WriteResult {
94    for _ in 0..data.len() {
95        buf.push_byte(0)?;
96    }
97    let src_range = pos..buf.len() - data.len();
98    buf.as_mut_slice().copy_within(src_range, pos + data.len());
99    buf.as_mut_slice()[pos..pos + data.len()].copy_from_slice(data);
100
101    Ok(())
102}
103
104/// Encapsulates an ongoing write. For almost all use-cases the correct
105/// entrypoint is [`write()`] or [`write_single()`].
106pub struct Writer<'a> {
107    pub(crate) buf: &'a mut WriteBuf,
108}
109
110impl Writer<'_> {
111    #[inline]
112    #[doc(hidden)]
113    pub fn new(buf: &mut WriteBuf) -> Writer<'_> {
114        Writer { buf }
115    }
116
117    /// Writes a single element to the output.
118    #[inline]
119    pub fn write_element<T: Asn1Writable>(&mut self, val: &T) -> Result<(), T::Error> {
120        if let Some(len) = val.encoded_length() {
121            self.buf.reserve_additional(len)?;
122        }
123        val.write(self)
124    }
125
126    /// Writes a TLV with the specified tag where the value is any bytes
127    /// written to the `Vec` in the callback. The length portion of the
128    /// TLV is automatically computed.
129    ///
130    /// If `content_length` is provided, it reduces the number of
131    /// re-allocations required.
132    #[inline]
133    pub fn write_tlv<E: From<WriteError>, F: FnOnce(&mut WriteBuf) -> Result<(), E>>(
134        &mut self,
135        tag: Tag,
136        content_length: Option<usize>,
137        body: F,
138    ) -> Result<(), E> {
139        tag.write_to(self.buf)?;
140
141        match content_length {
142            Some(len) => {
143                // Optimized path: write the correct length encoding upfront
144                if len < 128 {
145                    self.buf.push_byte(len as u8)?;
146                } else {
147                    let num_length_bytes = _length_length(len);
148                    self.buf.push_byte(0x80 | num_length_bytes)?;
149                    for i in (1..=num_length_bytes).rev() {
150                        self.buf.push_byte((len >> ((i - 1) * 8)) as u8)?;
151                    }
152                }
153                let start_len = self.buf.len();
154                body(self.buf)?;
155                assert_eq!(len, self.buf.len() - start_len);
156                Ok(())
157            }
158            None => {
159                // Write a placeholder and then fix the length up later as
160                // required.
161                self.buf.push_byte(0)?;
162                let start_len = self.buf.len();
163                body(self.buf)?;
164                self.insert_length(start_len)?;
165                Ok(())
166            }
167        }
168    }
169
170    #[inline]
171    fn insert_length(&mut self, start_len: usize) -> WriteResult {
172        let added_len = self.buf.len() - start_len;
173        if added_len >= 128 {
174            let n = _length_length(added_len);
175            self.buf.as_mut_slice()[start_len - 1] = 0x80 | n;
176            let mut length_buf = [0u8; 8];
177            for (pos, i) in (1..=n).rev().enumerate() {
178                length_buf[pos] = (added_len >> ((i - 1) * 8)) as u8;
179            }
180            _insert_at_position(self.buf, start_len, &length_buf[..n as usize])?;
181        } else {
182            self.buf.as_mut_slice()[start_len - 1] = added_len as u8;
183        }
184
185        Ok(())
186    }
187
188    /// This is an alias for `write_element::<Explicit<T, tag>>`.
189    pub fn write_explicit_element<T: Asn1Writable>(
190        &mut self,
191        val: &T,
192        tag: u32,
193    ) -> Result<(), T::Error> {
194        let tag = crate::explicit_tag(tag);
195        self.write_tlv(tag, val.encoded_length(), |dest| {
196            Writer::new(dest).write_element(val)
197        })
198    }
199
200    /// This is an alias for `write_element::<Implicit<T, tag>>`.
201    pub fn write_implicit_element<T: SimpleAsn1Writable>(
202        &mut self,
203        val: &T,
204        tag: u32,
205    ) -> Result<(), T::Error> {
206        let tag = crate::implicit_tag(tag, T::TAG);
207        self.write_tlv(tag, val.data_length(), |dest| val.write_data(dest))
208    }
209}
210
211/// Constructs a writer and invokes a callback which writes ASN.1 elements into
212/// the writer, then returns the generated DER bytes.
213#[inline]
214pub fn write<E: From<WriteError>, F: Fn(&mut Writer<'_>) -> Result<(), E>>(
215    f: F,
216) -> Result<Vec<u8>, E> {
217    let mut v = WriteBuf::new(vec![]);
218    let mut w = Writer::new(&mut v);
219    f(&mut w)?;
220    Ok(v.0)
221}
222
223/// Writes a single top-level ASN.1 element, returning the generated DER bytes.
224/// Most often this will be used where `T` is a type with
225/// `#[derive(asn1::Asn1Write)]`.
226pub fn write_single<T: Asn1Writable>(v: &T) -> Result<Vec<u8>, T::Error> {
227    write(|w| w.write_element(v))
228}
229
230#[cfg(test)]
231mod tests {
232    #[cfg(not(feature = "std"))]
233    use alloc::boxed::Box;
234    #[cfg(not(feature = "std"))]
235    use alloc::vec;
236
237    use super::{_insert_at_position, write, write_single, WriteBuf, Writer};
238    use crate::types::{Asn1Writable, SimpleAsn1Writable};
239    use crate::{
240        parse_single, BMPString, BigInt, BigUint, BitString, Choice1, Choice2, Choice3, DateTime,
241        Enumerated, Explicit, GeneralizedTime, IA5String, Implicit, ObjectIdentifier,
242        OctetStringEncoded, OwnedBigInt, OwnedBigUint, OwnedBitString, PrintableString, Sequence,
243        SequenceOf, SequenceOfWriter, SequenceWriter, Set, SetElementWriter, SetOf, SetOfWriter,
244        SetWriter, Tag, Tlv, UniversalString, UtcTime, Utf8String, VisibleString, WriteError,
245        X509GeneralizedTime,
246    };
247    #[cfg(not(feature = "std"))]
248    use alloc::vec::Vec;
249
250    fn assert_writes<T>(data: &[(T, &[u8])])
251    where
252        T: Asn1Writable,
253        T::Error: core::fmt::Debug,
254    {
255        for (val, expected) in data {
256            let result = write_single(val).unwrap();
257            assert_eq!(&result, expected);
258        }
259    }
260
261    #[test]
262    fn test_insert_at_position() {
263        let mut v = WriteBuf::new(vec![1, 2, 3, 4]);
264        _insert_at_position(&mut v, 2, &[5, 6]).unwrap();
265        assert_eq!(v.as_slice(), &[1, 2, 5, 6, 3, 4]);
266    }
267
268    #[test]
269    fn test_write_error_eq() {
270        let e1 = WriteError::AllocationError;
271        let e2 = WriteError::AllocationError;
272
273        assert_eq!(e1, e2);
274    }
275
276    #[test]
277    fn test_write_element() {
278        assert_eq!(write(|w| w.write_element(&())).unwrap(), b"\x05\x00");
279    }
280
281    #[test]
282    fn test_write_null() {
283        assert_writes::<()>(&[((), b"\x05\x00")]);
284    }
285
286    #[test]
287    fn test_write_bool() {
288        assert_writes::<bool>(&[(false, b"\x01\x01\x00"), (true, b"\x01\x01\xff")]);
289    }
290
291    #[test]
292    fn test_write_octet_string() {
293        assert_writes::<&[u8]>(&[
294            (b"", b"\x04\x00"),
295            (b"\x01\x02\x03", b"\x04\x03\x01\x02\x03"),
296            (b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", b"\x04\x81\x81aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
297            (b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", b"\x04\x82\x01\x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
298        ]);
299
300        assert_writes::<[u8; 0]>(&[([], b"\x04\x00")]);
301        assert_writes::<[u8; 1]>(&[([1], b"\x04\x01\x01")]);
302        assert_writes::<[u8; 2]>(&[([2, 3], b"\x04\x02\x02\x03")]);
303    }
304
305    #[test]
306    fn test_write_octet_string_encoded() {
307        assert_writes::<OctetStringEncoded<bool>>(&[
308            (OctetStringEncoded::new(true), b"\x04\x03\x01\x01\xff"),
309            (OctetStringEncoded::new(false), b"\x04\x03\x01\x01\x00"),
310        ]);
311    }
312
313    #[test]
314    fn test_write_printable_string() {
315        assert_writes::<PrintableString<'_>>(&[
316            (
317                PrintableString::new("Test User 1").unwrap(),
318                b"\x13\x0bTest User 1",
319            ),
320            (
321                PrintableString::new("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").unwrap(),
322                b"\x13\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
323            ),
324        ]);
325    }
326
327    #[test]
328    fn test_write_ia5string() {
329        assert_writes::<IA5String<'_>>(&[
330            (
331                IA5String::new("Test User 1").unwrap(),
332                b"\x16\x0bTest User 1",
333            ),
334            (
335                IA5String::new("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").unwrap(),
336                b"\x16\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
337            ),
338        ]);
339    }
340
341    #[test]
342    fn test_write_utf8string() {
343        assert_writes::<Utf8String<'_>>(&[
344            (
345                Utf8String::new("Test User 1"),
346                b"\x0c\x0bTest User 1",
347            ),
348            (
349                Utf8String::new("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
350                b"\x0c\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
351            ),
352        ]);
353    }
354
355    #[test]
356    fn test_write_visiblestring() {
357        assert_writes::<VisibleString<'_>>(&[
358            (
359                VisibleString::new("Test User 1").unwrap(),
360                b"\x1a\x0bTest User 1",
361            ),
362            (
363                VisibleString::new("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").unwrap(),
364                b"\x1a\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
365            ),
366        ]);
367    }
368
369    #[test]
370    fn test_write_bmpstring() {
371        assert_writes::<BMPString<'_>>(&[(
372            BMPString::new(b"\x00a\x00b\x00c").unwrap(),
373            b"\x1e\x06\x00a\x00b\x00c",
374        )]);
375    }
376
377    #[test]
378    fn test_write_universalstring() {
379        assert_writes::<UniversalString<'_>>(&[(
380            UniversalString::new(b"\x00\x00\x00a\x00\x00\x00b\x00\x00\x00c").unwrap(),
381            b"\x1c\x0c\x00\x00\x00a\x00\x00\x00b\x00\x00\x00c",
382        )]);
383    }
384
385    #[test]
386    fn test_write_i64() {
387        assert_writes::<i64>(&[
388            (0, b"\x02\x01\x00"),
389            (127, b"\x02\x01\x7f"),
390            (128, b"\x02\x02\x00\x80"),
391            (255, b"\x02\x02\x00\xff"),
392            (256, b"\x02\x02\x01\x00"),
393            (-1, b"\x02\x01\xff"),
394            (-128, b"\x02\x01\x80"),
395            (-129, b"\x02\x02\xff\x7f"),
396        ]);
397    }
398
399    #[test]
400    fn test_write_u64() {
401        assert_writes::<u64>(&[(
402            12356915591483590945,
403            b"\x02\x09\x00\xab\x7c\x95\x42\xbd\xdd\x89\x21",
404        )]);
405    }
406
407    #[test]
408    fn test_write_i32() {
409        assert_writes::<i32>(&[
410            (0, b"\x02\x01\x00"),
411            (127, b"\x02\x01\x7f"),
412            (128, b"\x02\x02\x00\x80"),
413            (255, b"\x02\x02\x00\xff"),
414            (256, b"\x02\x02\x01\x00"),
415            (-1, b"\x02\x01\xff"),
416            (-128, b"\x02\x01\x80"),
417            (-129, b"\x02\x02\xff\x7f"),
418        ]);
419    }
420
421    #[test]
422    fn test_write_u16() {
423        assert_writes::<u16>(&[
424            (0, b"\x02\x01\x00"),
425            (1, b"\x02\x01\x01"),
426            (256, b"\x02\x02\x01\x00"),
427            (65535, b"\x02\x03\x00\xff\xff"),
428        ]);
429    }
430
431    #[test]
432    fn test_write_i16() {
433        assert_writes::<i16>(&[
434            (0, b"\x02\x01\x00"),
435            (1, b"\x02\x01\x01"),
436            (-256, b"\x02\x02\xff\x00"),
437            (-1, b"\x02\x01\xff"),
438            (-32768, b"\x02\x02\x80\x00"),
439            (32767, b"\x02\x02\x7f\xff"),
440        ]);
441    }
442
443    #[test]
444    fn test_write_nonzeroi8_like_underlying() {
445        use std::num::NonZeroI8;
446        for val in [1, -1, i8::MIN, i8::MAX] {
447            assert_eq!(
448                write_single::<i8>(&val).unwrap(),
449                write_single(&NonZeroI8::new(val).unwrap()).unwrap()
450            );
451        }
452    }
453
454    #[test]
455    fn test_write_nonzeroi16_like_underlying() {
456        use std::num::NonZeroI16;
457        for val in [1, -1, i16::MIN, i16::MAX] {
458            assert_eq!(
459                write_single::<i16>(&val).unwrap(),
460                write_single(&NonZeroI16::new(val).unwrap()).unwrap()
461            );
462        }
463    }
464
465    #[test]
466    fn test_write_nonzeroi32_like_underlying() {
467        use std::num::NonZeroI32;
468        for val in [1, -1, i32::MIN, i32::MAX] {
469            assert_eq!(
470                write_single::<i32>(&val).unwrap(),
471                write_single(&NonZeroI32::new(val).unwrap()).unwrap()
472            );
473        }
474    }
475
476    #[test]
477    fn test_write_nonzeroi64_like_underlying() {
478        use std::num::NonZeroI64;
479        for val in [1, -1, i64::MIN, i64::MAX] {
480            assert_eq!(
481                write_single::<i64>(&val).unwrap(),
482                write_single(&NonZeroI64::new(val).unwrap()).unwrap()
483            );
484        }
485    }
486
487    #[test]
488    fn test_write_nonzerou8_like_underlying() {
489        use std::num::NonZeroU8;
490        for val in [1, u8::MAX] {
491            assert_eq!(
492                write_single::<u8>(&val).unwrap(),
493                write_single(&NonZeroU8::new(val).unwrap()).unwrap()
494            );
495        }
496    }
497
498    #[test]
499    fn test_write_nonzerou16_like_underlying() {
500        use std::num::NonZeroU16;
501        for val in [1, u16::MAX] {
502            assert_eq!(
503                write_single::<u16>(&val).unwrap(),
504                write_single(&NonZeroU16::new(val).unwrap()).unwrap()
505            );
506        }
507    }
508
509    #[test]
510    fn test_write_nonzerou32_like_underlying() {
511        use std::num::NonZeroU32;
512        for val in [1, u32::MAX] {
513            assert_eq!(
514                write_single::<u32>(&val).unwrap(),
515                write_single(&NonZeroU32::new(val).unwrap()).unwrap()
516            );
517        }
518    }
519
520    #[test]
521    fn test_write_nonzerou64_like_underlying() {
522        use std::num::NonZeroU64;
523        for val in [1, u64::MAX] {
524            assert_eq!(
525                write_single::<u64>(&val).unwrap(),
526                write_single(&NonZeroU64::new(val).unwrap()).unwrap()
527            );
528        }
529    }
530
531    #[test]
532    fn test_write_u8() {
533        assert_writes::<u8>(&[
534            (0, b"\x02\x01\x00"),
535            (127, b"\x02\x01\x7f"),
536            (128, b"\x02\x02\x00\x80"),
537        ]);
538    }
539
540    #[test]
541    fn test_write_i8() {
542        assert_writes::<i8>(&[
543            (0, b"\x02\x01\x00"),
544            (127, b"\x02\x01\x7f"),
545            (-1, b"\x02\x01\xff"),
546            (-128, b"\x02\x01\x80"),
547        ]);
548    }
549
550    #[test]
551    fn test_write_biguint() {
552        assert_writes::<BigUint<'_>>(&[
553            (BigUint::new(b"\x00\xff").unwrap(), b"\x02\x02\x00\xff"),
554            (
555                BigUint::new(b"\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff").unwrap(),
556                b"\x02\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
557            ),
558        ]);
559    }
560
561    #[test]
562    fn test_write_ownedbiguint() {
563        assert_writes::<OwnedBigUint>(&[
564            (
565                OwnedBigUint::new(b"\x00\xff".to_vec()).unwrap(),
566                b"\x02\x02\x00\xff",
567            ),
568            (
569                OwnedBigUint::new(b"\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff".to_vec())
570                    .unwrap(),
571                b"\x02\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
572            ),
573        ]);
574    }
575
576    #[test]
577    fn test_write_bigint() {
578        assert_writes::<BigInt<'_>>(&[
579            (BigInt::new(b"\xff").unwrap(), b"\x02\x01\xff"),
580            (
581                BigInt::new(b"\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff").unwrap(),
582                b"\x02\x0c\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
583            ),
584        ]);
585    }
586
587    #[test]
588    fn test_write_ownedbigint() {
589        assert_writes::<OwnedBigInt>(&[
590            (OwnedBigInt::new(b"\xff".to_vec()).unwrap(), b"\x02\x01\xff"),
591            (
592                OwnedBigInt::new(b"\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff".to_vec())
593                    .unwrap(),
594                b"\x02\x0c\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
595            ),
596        ]);
597    }
598
599    #[test]
600    fn test_write_object_identifier() {
601        assert_writes::<ObjectIdentifier>(&[
602            (
603                ObjectIdentifier::from_string("1.2.840.113549").unwrap(),
604                b"\x06\x06\x2a\x86\x48\x86\xf7\x0d",
605            ),
606            (
607                ObjectIdentifier::from_string("1.2.3.4").unwrap(),
608                b"\x06\x03\x2a\x03\x04",
609            ),
610            (
611                ObjectIdentifier::from_string("1.2.840.133549.1.1.5").unwrap(),
612                b"\x06\x09\x2a\x86\x48\x88\x93\x2d\x01\x01\x05",
613            ),
614            (
615                ObjectIdentifier::from_string("2.100.3").unwrap(),
616                b"\x06\x03\x81\x34\x03",
617            ),
618            (
619                ObjectIdentifier::from_string("2.4.0").unwrap(),
620                b"\x06\x02\x54\x00",
621            ),
622        ]);
623    }
624
625    #[test]
626    fn test_write_bit_string() {
627        assert_writes::<BitString<'_>>(&[
628            (BitString::new(b"", 0).unwrap(), b"\x03\x01\x00"),
629            (BitString::new(b"\x80", 7).unwrap(), b"\x03\x02\x07\x80"),
630            (
631                BitString::new(b"\x81\xf0", 4).unwrap(),
632                b"\x03\x03\x04\x81\xf0",
633            ),
634        ]);
635
636        assert_writes::<OwnedBitString>(&[
637            (OwnedBitString::new(vec![], 0).unwrap(), b"\x03\x01\x00"),
638            (
639                OwnedBitString::new(vec![0x80], 7).unwrap(),
640                b"\x03\x02\x07\x80",
641            ),
642            (
643                OwnedBitString::new(vec![0x81, 0xf0], 4).unwrap(),
644                b"\x03\x03\x04\x81\xf0",
645            ),
646        ]);
647    }
648
649    #[test]
650    fn test_write_utctime() {
651        assert_writes::<UtcTime>(&[
652            (
653                UtcTime::new(DateTime::new(1991, 5, 6, 23, 45, 40).unwrap()).unwrap(),
654                b"\x17\x0d910506234540Z",
655            ),
656            (
657                UtcTime::new(DateTime::new(1970, 1, 1, 0, 0, 0).unwrap()).unwrap(),
658                b"\x17\x0d700101000000Z",
659            ),
660            (
661                UtcTime::new(DateTime::new(2009, 11, 15, 22, 56, 16).unwrap()).unwrap(),
662                b"\x17\x0d091115225616Z",
663            ),
664        ]);
665    }
666
667    #[test]
668    fn test_write_x509_generalizedtime() {
669        assert_writes(&[
670            (
671                X509GeneralizedTime::new(DateTime::new(1991, 5, 6, 23, 45, 40).unwrap()).unwrap(),
672                b"\x18\x0f19910506234540Z",
673            ),
674            (
675                X509GeneralizedTime::new(DateTime::new(1970, 1, 1, 0, 0, 0).unwrap()).unwrap(),
676                b"\x18\x0f19700101000000Z",
677            ),
678            (
679                X509GeneralizedTime::new(DateTime::new(2009, 11, 15, 22, 56, 16).unwrap()).unwrap(),
680                b"\x18\x0f20091115225616Z",
681            ),
682        ]);
683    }
684
685    #[test]
686    fn test_write_generalizedtime() {
687        assert_writes(&[
688            (
689                GeneralizedTime::new(DateTime::new(1991, 5, 6, 23, 45, 40).unwrap(), Some(1_234))
690                    .unwrap(),
691                b"\x18\x1919910506234540.000001234Z",
692            ),
693            (
694                GeneralizedTime::new(DateTime::new(1991, 5, 6, 23, 45, 40).unwrap(), Some(1))
695                    .unwrap(),
696                b"\x18\x1919910506234540.000000001Z",
697            ),
698            (
699                GeneralizedTime::new(DateTime::new(1970, 1, 1, 0, 0, 0).unwrap(), None).unwrap(),
700                b"\x18\x0f19700101000000Z",
701            ),
702            (
703                GeneralizedTime::new(
704                    DateTime::new(2009, 11, 15, 22, 56, 16).unwrap(),
705                    Some(100_000_000),
706                )
707                .unwrap(),
708                b"\x18\x1120091115225616.1Z",
709            ),
710            (
711                GeneralizedTime::new(
712                    DateTime::new(2009, 11, 15, 22, 56, 16).unwrap(),
713                    Some(999_999_999),
714                )
715                .unwrap(),
716                b"\x18\x1920091115225616.999999999Z",
717            ),
718        ]);
719    }
720
721    #[test]
722    fn test_write_enumerated() {
723        assert_writes::<Enumerated>(&[
724            (Enumerated::new(0), b"\x0a\x01\x00"),
725            (Enumerated::new(12), b"\x0a\x01\x0c"),
726        ]);
727    }
728
729    #[test]
730    fn test_write_sequence() {
731        assert_eq!(
732            write(|w| {
733                w.write_element(&SequenceWriter::new(&|w: &mut Writer<'_>| {
734                    w.write_element(&())
735                }))
736            })
737            .unwrap(),
738            b"\x30\x02\x05\x00"
739        );
740        assert_eq!(
741            write(|w| {
742                w.write_element(&SequenceWriter::new(&|w: &mut Writer<'_>| {
743                    w.write_element(&true)
744                }))
745            })
746            .unwrap(),
747            b"\x30\x03\x01\x01\xff"
748        );
749        assert_eq!(
750            write(|w| {
751                w.write_element(&SequenceWriter::new(&|w: &mut Writer<'_>| {
752                    w.write_element(&b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
753                }))
754            }).unwrap(),
755            b"\x30\x81\x84\x04\x81\x81aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
756        );
757
758        assert_writes(&[(
759            parse_single::<Sequence<'_>>(b"\x30\x06\x01\x01\xff\x02\x01\x06").unwrap(),
760            b"\x30\x06\x01\x01\xff\x02\x01\x06",
761        )]);
762    }
763
764    #[test]
765    fn test_write_sequence_of() {
766        assert_writes::<SequenceOfWriter<'_, u8, &[u8]>>(&[
767            (SequenceOfWriter::new(&[]), b"\x30\x00"),
768            (
769                SequenceOfWriter::new(&[1u8, 2, 3]),
770                b"\x30\x09\x02\x01\x01\x02\x01\x02\x02\x01\x03",
771            ),
772        ]);
773        assert_writes::<SequenceOfWriter<'_, u8, Vec<u8>>>(&[
774            (SequenceOfWriter::new(vec![]), b"\x30\x00"),
775            (
776                SequenceOfWriter::new(vec![1u8, 2, 3]),
777                b"\x30\x09\x02\x01\x01\x02\x01\x02\x02\x01\x03",
778            ),
779        ]);
780        assert_writes::<SequenceOfWriter<'_, SequenceWriter<'_>, &[SequenceWriter<'_>]>>(&[
781            (SequenceOfWriter::new(&[]), b"\x30\x00"),
782            (
783                SequenceOfWriter::new(&[SequenceWriter::new(&|_w| Ok(()))]),
784                b"\x30\x02\x30\x00",
785            ),
786            (
787                SequenceOfWriter::new(&[SequenceWriter::new(&|w: &mut Writer<'_>| {
788                    w.write_element(&1u64)
789                })]),
790                b"\x30\x05\x30\x03\x02\x01\x01",
791            ),
792        ]);
793
794        assert_writes(&[(
795            parse_single::<SequenceOf<'_, u64>>(b"\x30\x06\x02\x01\x05\x02\x01\x07").unwrap(),
796            b"\x30\x06\x02\x01\x05\x02\x01\x07",
797        )]);
798    }
799
800    #[test]
801    fn test_write_set() {
802        assert_eq!(
803            write(|w| {
804                w.write_element(&SetWriter::new(&|w: &mut SetElementWriter<'_>| {
805                    w.write_element(&())
806                }))
807            })
808            .unwrap(),
809            b"\x31\x02\x05\x00"
810        );
811        assert_eq!(
812            write(|w| {
813                w.write_element(&SetWriter::new(&|w: &mut SetElementWriter<'_>| {
814                    w.write_element(&true)
815                }))
816            })
817            .unwrap(),
818            b"\x31\x03\x01\x01\xff"
819        );
820        assert_eq!(
821            write(|w| {
822                w.write_element(&SetWriter::new(&|w: &mut SetElementWriter<'_>| {
823                    w.write_element(&b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
824                }))
825            }).unwrap(),
826            b"\x31\x81\x84\x04\x81\x81aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
827        );
828
829        assert_writes(&[(
830            parse_single::<Set<'_>>(b"\x31\x06\x01\x01\xff\x02\x01\x06").unwrap(),
831            b"\x31\x06\x01\x01\xff\x02\x01\x06",
832        )]);
833
834        assert!(write(|w| {
835            w.write_element(&SetWriter::new(&|w: &mut SetElementWriter<'_>| {
836                w.write_element(&true)?; // tag 0x01
837                w.write_element(&1i64) // tag 0x02
838            }))
839        })
840        .is_ok());
841
842        assert_eq!(
843            write(|w| {
844                w.write_element(&SetWriter::new(&|w: &mut SetElementWriter<'_>| {
845                    w.write_element(&1i64)?; // tag 0x02
846                    w.write_element(&true) // tag 0x01
847                }))
848            }),
849            Err(WriteError::InvalidSetOrdering)
850        );
851
852        assert_eq!(
853            write(|w| {
854                w.write_element(&SetWriter::new(&|w: &mut SetElementWriter<'_>| {
855                    w.write_element(&true)?;
856                    w.write_element(&Some(1i64))
857                }))
858            })
859            .unwrap(),
860            b"\x31\x06\x01\x01\xff\x02\x01\x01"
861        );
862
863        assert_eq!(
864            write(|w| {
865                w.write_element(&SetWriter::new(&|w: &mut SetElementWriter<'_>| {
866                    w.write_element(&true)?;
867                    w.write_element(&Option::<i64>::None)
868                }))
869            })
870            .unwrap(),
871            b"\x31\x03\x01\x01\xff"
872        );
873    }
874
875    #[test]
876    fn test_write_set_of() {
877        assert_writes::<SetOfWriter<'_, u8, &[u8]>>(&[
878            (SetOfWriter::new(&[]), b"\x31\x00"),
879            (SetOfWriter::new(&[1u8]), b"\x31\x03\x02\x01\x01"),
880            (
881                SetOfWriter::new(&[1, 2, 3]),
882                b"\x31\x09\x02\x01\x01\x02\x01\x02\x02\x01\x03",
883            ),
884            (
885                SetOfWriter::new(&[3, 2, 1]),
886                b"\x31\x09\x02\x01\x01\x02\x01\x02\x02\x01\x03",
887            ),
888        ]);
889        assert_writes(&[
890            (SetOfWriter::new(vec![]), b"\x31\x00"),
891            (SetOfWriter::new(vec![1u8]), b"\x31\x03\x02\x01\x01"),
892            (
893                SetOfWriter::new(vec![1, 2, 3]),
894                b"\x31\x09\x02\x01\x01\x02\x01\x02\x02\x01\x03",
895            ),
896            (
897                SetOfWriter::new(vec![3, 2, 1]),
898                b"\x31\x09\x02\x01\x01\x02\x01\x02\x02\x01\x03",
899            ),
900        ]);
901
902        assert_writes(&[(
903            parse_single::<SetOf<'_, u64>>(b"\x31\x06\x02\x01\x05\x02\x01\x07").unwrap(),
904            b"\x31\x06\x02\x01\x05\x02\x01\x07",
905        )]);
906    }
907
908    #[test]
909    fn test_write_implicit() {
910        assert_writes::<Implicit<bool, 2>>(&[
911            (Implicit::new(true), b"\x82\x01\xff"),
912            (Implicit::new(false), b"\x82\x01\x00"),
913        ]);
914
915        assert_eq!(
916            write(|w| { w.write_implicit_element(&true, 2) }).unwrap(),
917            b"\x82\x01\xff"
918        );
919
920        assert_eq!(
921            write(|w| {
922                w.write_implicit_element(&SequenceWriter::new(&|_w| Ok::<_, WriteError>(())), 2)
923            })
924            .unwrap(),
925            b"\xa2\x00"
926        );
927    }
928
929    #[test]
930    fn test_write_explicit() {
931        assert_writes::<Explicit<bool, 2>>(&[
932            (Explicit::new(true), b"\xa2\x03\x01\x01\xff"),
933            (Explicit::new(false), b"\xa2\x03\x01\x01\x00"),
934        ]);
935
936        assert_eq!(
937            write(|w| { w.write_explicit_element(&true, 2) }).unwrap(),
938            b"\xa2\x03\x01\x01\xff"
939        );
940    }
941
942    #[test]
943    fn test_write_option() {
944        assert_writes::<Option<bool>>(&[
945            (Some(true), b"\x01\x01\xff"),
946            (Some(false), b"\x01\x01\x00"),
947            (None, b""),
948        ]);
949    }
950
951    #[test]
952    fn test_write_choice() {
953        assert_writes::<Choice1<bool>>(&[(Choice1::ChoiceA(true), b"\x01\x01\xff")]);
954
955        assert_writes::<Choice2<bool, i64>>(&[
956            (Choice2::ChoiceA(true), b"\x01\x01\xff"),
957            (Choice2::ChoiceB(18), b"\x02\x01\x12"),
958        ]);
959
960        assert_writes::<Choice3<bool, i64, ()>>(&[
961            (Choice3::ChoiceA(true), b"\x01\x01\xff"),
962            (Choice3::ChoiceB(18), b"\x02\x01\x12"),
963            (Choice3::ChoiceC(()), b"\x05\x00"),
964        ]);
965    }
966
967    #[test]
968    fn test_write_tlv() {
969        assert_writes(&[
970            (
971                parse_single::<Tlv<'_>>(b"\x01\x01\x00").unwrap(),
972                b"\x01\x01\x00",
973            ),
974            (
975                parse_single::<Tlv<'_>>(b"\x1f\x81\x80\x01\x00").unwrap(),
976                b"\x1f\x81\x80\x01\x00",
977            ),
978            (
979                parse_single::<Tlv<'_>>(b"\x1f\x1f\x00").unwrap(),
980                b"\x1f\x1f\x00",
981            ),
982        ]);
983    }
984
985    #[test]
986    fn test_write_box() {
987        assert_writes(&[
988            (Box::new(12u8), b"\x02\x01\x0c"),
989            (Box::new(0), b"\x02\x01\x00"),
990        ]);
991    }
992
993    #[test]
994    fn test_write_error_display() {
995        use alloc::string::ToString;
996        assert_eq!(&WriteError::AllocationError.to_string(), "allocation error");
997        assert_eq!(
998            &WriteError::InvalidSetOrdering.to_string(),
999            "SET elements are not in DER order"
1000        );
1001    }
1002
1003    #[test]
1004    fn test_custom_write_error() {
1005        #[derive(Debug, PartialEq, Eq)]
1006        enum CustomError {
1007            Write(WriteError),
1008            Custom,
1009        }
1010
1011        impl From<WriteError> for CustomError {
1012            fn from(e: WriteError) -> Self {
1013                CustomError::Write(e)
1014            }
1015        }
1016
1017        struct FailingWriter;
1018
1019        impl SimpleAsn1Writable for FailingWriter {
1020            type Error = CustomError;
1021            const TAG: Tag = Tag::primitive(0x04);
1022
1023            fn write_data(&self, _dest: &mut WriteBuf) -> Result<(), CustomError> {
1024                Err(CustomError::Custom)
1025            }
1026
1027            fn data_length(&self) -> Option<usize> {
1028                Some(0)
1029            }
1030        }
1031
1032        let result = write_single(&FailingWriter);
1033        assert_eq!(result, Err(CustomError::Custom));
1034
1035        assert_eq!(
1036            CustomError::from(WriteError::AllocationError),
1037            CustomError::Write(WriteError::AllocationError)
1038        );
1039    }
1040}