Skip to main content

vest_lib/asn1/
ber.rs

1//! BER constructed-value formats and notation-style constructors.
2//!
3//! Recursive OCTET STRING, BIT STRING, and restricted-string formats accept
4//! definite and indefinite encodings for parsing
5//! and normalize to definite encodings for serialization.
6//! SEQUENCE and SEQUENCE OF similarly accept both length forms for parsing and normalize to definite for serialization.
7use crate::asn1::{
8    ASN1Fmt, BmpStringFmt, BoolFmt, Class, EnumeratedFmt, Ia5StringFmt, IntegerFmt, NullFmt,
9    NumericStringFmt, ObjectIdentifierFmt, PrintableStringFmt, RealFmt, TagFmt, TeletexStringFmt,
10    UniversalStringFmt, Utf8StringFmt, BER,
11};
12use crate::core::spec::SpecByteLen;
13use vstd::prelude::*;
14
15use super::modifiers::{defaulted, explicit_tag};
16pub use super::modifiers::{
17    implicitly_tagged as Implicit, ImplicitFmt, CHOICE, IMPLICIT, IMPLICIT_APPLICATION,
18    IMPLICIT_PRIVATE, OPTIONAL, REQUIRED,
19};
20use super::{GeneralizedTimeFmt, Integer16Fmt, Integer8Fmt, UtcTimeFmt};
21
22pub mod any;
23pub mod bit_string;
24pub mod char_string;
25pub mod octet_string;
26pub mod sequence;
27pub mod sequence_of;
28
29pub use any::*;
30pub use bit_string::*;
31pub use char_string::*;
32pub use octet_string::*;
33pub use sequence::*;
34pub use sequence_of::*;
35
36verus! {
37
38/// Control the maximum recursion depth for BER OCTET STRING and restricted character string parsing.
39pub const MAX_RECURSION_DEPTH: usize = 30;
40
41/// Uniform notation aliases used by schema generators.
42pub type BoolTlvFmt = ASN1Fmt<BoolFmt<BER>, BER>;
43
44pub type AnyTlvFmt = BerAnyFmt<MAX_RECURSION_DEPTH>;
45
46pub type IntegerTlvFmt = ASN1Fmt<IntegerFmt, BER>;
47
48pub type Integer8TlvFmt = ASN1Fmt<Integer8Fmt, BER>;
49
50pub type Integer16TlvFmt = ASN1Fmt<Integer16Fmt, BER>;
51
52pub type EnumeratedTlvFmt = ASN1Fmt<EnumeratedFmt, BER>;
53
54pub type Enumerated16TlvFmt = ASN1Fmt<Integer16Fmt, BER>;
55
56pub type ObjectIdentifierTlvFmt = ASN1Fmt<ObjectIdentifierFmt, BER>;
57
58pub type RealTlvFmt = ASN1Fmt<RealFmt<BER>, BER>;
59
60pub type BitStringTlvFmt = BerBitStringFmt<MAX_RECURSION_DEPTH>;
61
62pub type OctetStringTlvFmt = BerOctetStringFmt<MAX_RECURSION_DEPTH>;
63
64pub type NullTlvFmt = ASN1Fmt<NullFmt, BER>;
65
66pub type Utf8StringTlvFmt = BerUtf8StringFmt<MAX_RECURSION_DEPTH>;
67
68pub type PrintableStringTlvFmt = BerPrintableStringFmt<MAX_RECURSION_DEPTH>;
69
70pub type NumericStringTlvFmt = BerNumericStringFmt<MAX_RECURSION_DEPTH>;
71
72pub type TeletexStringTlvFmt = BerTeletexStringFmt<MAX_RECURSION_DEPTH>;
73
74pub type Ia5StringTlvFmt = BerIa5StringFmt<MAX_RECURSION_DEPTH>;
75
76pub type UtcTimeTlvFmt = ASN1Fmt<UtcTimeFmt<BER>, BER>;
77
78pub type GeneralizedTimeTlvFmt = ASN1Fmt<GeneralizedTimeFmt<BER>, BER>;
79
80pub type BmpStringTlvFmt = BerBmpStringFmt<MAX_RECURSION_DEPTH>;
81
82pub type UniversalStringTlvFmt = BerUniversalStringFmt<MAX_RECURSION_DEPTH>;
83
84pub type SequenceFmt<C> = BerSequenceFmt<C>;
85
86pub type SequenceOfFmt<C> = BerSequenceOfFmt<C>;
87
88pub type SetOfTlvFmt<C> = BerSequenceOfFmt<C>;
89
90pub type ExplicitFmt<C> = BerSequenceFmt<C>;
91
92pub type DefaultFmt<Field, Default, Rest> = super::DefaultedFmt<Field, Default, Rest, BER>;
93
94pub const BOOLEAN: BoolTlvFmt = ASN1Fmt(TagFmt::BOOLEAN, BoolFmt::<BER>);
95
96pub const ANY: AnyTlvFmt = BerAnyFmt;
97
98pub const INTEGER: IntegerTlvFmt = ASN1Fmt(TagFmt::INTEGER, IntegerFmt);
99
100pub const INTEGER8: Integer8TlvFmt = ASN1Fmt(TagFmt::INTEGER, Integer8Fmt);
101
102pub const INTEGER16: Integer16TlvFmt = ASN1Fmt(TagFmt::INTEGER, Integer16Fmt);
103
104pub const ENUMERATED: EnumeratedTlvFmt = ASN1Fmt(TagFmt::ENUMERATED, EnumeratedFmt);
105
106pub const ENUMERATED16: Enumerated16TlvFmt = ASN1Fmt(TagFmt::ENUMERATED, Integer16Fmt);
107
108pub const OBJECT_IDENTIFIER: ObjectIdentifierTlvFmt = ASN1Fmt(
109    TagFmt::OBJECT_IDENTIFIER,
110    ObjectIdentifierFmt,
111);
112
113pub const REAL: RealTlvFmt = ASN1Fmt(TagFmt::REAL, RealFmt::<BER>);
114
115pub const BIT_STRING: BitStringTlvFmt = BerBitStringFmt(TagFmt::BIT_STRING);
116
117pub const NULL: NullTlvFmt = ASN1Fmt(TagFmt::NULL, NullFmt);
118
119pub const UTC_TIME: UtcTimeTlvFmt = ASN1Fmt(TagFmt::UTC_TIME, UtcTimeFmt::<BER>);
120
121pub const GENERALIZED_TIME: GeneralizedTimeTlvFmt = ASN1Fmt(
122    TagFmt::GENERALIZED_TIME,
123    GeneralizedTimeFmt::<BER>,
124);
125
126pub const OCTET_STRING: OctetStringTlvFmt = BerOctetStringFmt(TagFmt::OCTET_STRING);
127
128pub const UTF8_STRING: Utf8StringTlvFmt = BerCharStringFmt(TagFmt::UTF8_STRING, Utf8StringFmt);
129
130pub const PRINTABLE_STRING: PrintableStringTlvFmt = BerCharStringFmt(
131    TagFmt::PRINTABLE_STRING,
132    PrintableStringFmt,
133);
134
135pub const NUMERIC_STRING: NumericStringTlvFmt = BerCharStringFmt(
136    TagFmt::NUMERIC_STRING,
137    NumericStringFmt,
138);
139
140pub const IA5_STRING: Ia5StringTlvFmt = BerCharStringFmt(TagFmt::IA5_STRING, Ia5StringFmt);
141
142pub const TELETEX_STRING: TeletexStringTlvFmt = BerCharStringFmt(
143    TagFmt::TELETEX_STRING,
144    TeletexStringFmt,
145);
146
147pub const BMP_STRING: BmpStringTlvFmt = BerCharStringFmt(TagFmt::BMP_STRING, BmpStringFmt);
148
149pub const UNIVERSAL_STRING: UniversalStringTlvFmt = BerCharStringFmt(
150    TagFmt::UNIVERSAL_STRING,
151    UniversalStringFmt,
152);
153
154/// Construct a BER `SEQUENCE`.
155#[allow(non_snake_case)]
156#[verifier::allow_in_spec]
157pub const fn SEQUENCE<C: Copy>(content: C) -> SequenceFmt<C>
158    returns
159        BerSequenceFmt(TagFmt::SEQUENCE, content),
160{
161    BerSequenceFmt::universal(content)
162}
163
164/// Construct a BER `SEQUENCE OF`.
165#[allow(non_snake_case)]
166#[verifier::allow_in_spec]
167pub const fn SEQUENCE_OF<C: Copy>(content: C) -> SequenceOfFmt<C>
168    returns
169        BerSequenceOfFmt(TagFmt::SEQUENCE, content),
170{
171    BerSequenceOfFmt::universal(content)
172}
173
174/// Construct a BER `SET OF`.
175#[allow(non_snake_case)]
176#[verifier::allow_in_spec]
177pub const fn SET_OF<C: Copy>(content: C) -> SetOfTlvFmt<C>
178    returns
179        BerSequenceOfFmt(TagFmt::SET, content),
180{
181    BerSequenceOfFmt(TagFmt::SET, content)
182}
183
184/// Apply an ASN.1 EXPLICIT tag with an arbitrary tag class.
185#[allow(non_snake_case)]
186#[verifier::allow_in_spec]
187pub const fn Explicit<C: Copy>(class: Class, number: u64, inner: C) -> ExplicitFmt<C>
188    returns
189        BerSequenceFmt(explicit_tag(class, number), inner),
190{
191    BerSequenceFmt(explicit_tag(class, number), inner)
192}
193
194#[allow(non_snake_case)]
195#[verifier::allow_in_spec]
196pub const fn EXPLICIT<C: Copy>(number: u64, inner: C) -> ExplicitFmt<C>
197    returns
198        Explicit(Class::ContextSpecific, number, inner),
199{
200    Explicit(Class::ContextSpecific, number, inner)
201}
202
203#[allow(non_snake_case)]
204#[verifier::allow_in_spec]
205pub const fn EXPLICIT_APPLICATION<C: Copy>(number: u64, inner: C) -> ExplicitFmt<C>
206    returns
207        Explicit(Class::Application, number, inner),
208{
209    Explicit(Class::Application, number, inner)
210}
211
212#[allow(non_snake_case)]
213#[verifier::allow_in_spec]
214pub const fn EXPLICIT_PRIVATE<C: Copy>(number: u64, inner: C) -> ExplicitFmt<C>
215    returns
216        Explicit(Class::Private, number, inner),
217{
218    Explicit(Class::Private, number, inner)
219}
220
221#[allow(non_snake_case)]
222#[verifier::allow_in_spec]
223pub const fn DEFAULT<Field, Rest>(field: Field, default: Field::T, cont: Rest) -> DefaultFmt<
224    Field,
225    Field::T,
226    Rest,
227> where Field: SpecByteLen
228    returns
229        defaulted::<Field, Rest, BER>(field, default, cont),
230{
231    defaulted::<Field, Rest, BER>(field, default, cont)
232}
233
234} // verus!
235#[cfg(all(test, feature = "alloc"))]
236mod tests {
237    use alloc::{string::String, vec::Vec};
238
239    use super::*;
240    use crate::asn1::{BmpString, Integer8Fmt};
241    use crate::combinators::Pair;
242    use crate::core::exec::{ParseErrorKind, Parser, Prepare, SerializerExt};
243
244    type Octets = BerOctetStringFmt<8>;
245
246    fn parse_universal(input: &[u8]) -> (usize, Vec<u8>) {
247        Octets::universal().parse(&input).unwrap()
248    }
249
250    fn integer_sequence() -> BerSequenceOfFmt<ASN1Fmt<Integer8Fmt, BER>> {
251        SEQUENCE_OF(ASN1Fmt(TagFmt::INTEGER, Integer8Fmt))
252    }
253
254    fn integer_fields_sequence(
255    ) -> BerSequenceFmt<Pair<ASN1Fmt<Integer8Fmt, BER>, ASN1Fmt<Integer8Fmt, BER>>> {
256        let integer = ASN1Fmt::<_, BER>(TagFmt::INTEGER, Integer8Fmt);
257        SEQUENCE(Pair(integer, integer))
258    }
259
260    #[test]
261    fn eoc_is_exactly_the_canonical_tag_and_zero_length_octet() {
262        let input = [0x00, 0x00, 0xff];
263        assert_eq!(EOC.parse(&&input[..]).unwrap(), (2, (TagFmt::EOC, 0u8)),);
264
265        for invalid in [
266            &[0x00][..],
267            &[0x00, 0x01],
268            &[0x20, 0x00],
269            &[0x40, 0x00],
270            &[0x1f, 0x00, 0x00],
271        ] {
272            assert!(EOC.parse(&invalid).is_err());
273        }
274
275        let value = (TagFmt::EOC, 0u8);
276        let mut output = [0xff; 2];
277        assert_eq!(EOC.prepare(&value).unwrap(), output.len());
278        EOC.serialize(&value, output.as_mut_slice());
279        assert_eq!(output, [0x00, 0x00]);
280    }
281
282    #[test]
283    fn ber_sequence_parses_definite_and_indefinite_schema_bodies() {
284        let format = integer_fields_sequence();
285        let definite = [0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02];
286        let indefinite = [0x30, 0x80, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x00, 0x00];
287
288        assert_eq!(
289            format.parse(&&definite[..]).unwrap(),
290            (definite.len(), (1i8, 2i8)),
291        );
292        assert_eq!(
293            format.parse(&&indefinite[..]).unwrap(),
294            (indefinite.len(), (1i8, 2i8)),
295        );
296
297        let missing_eoc = [0x30, 0x80, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02];
298        assert!(format.parse(&&missing_eoc[..]).is_err());
299
300        let extra_component = [
301            0x30, 0x80, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03, 0x00, 0x00,
302        ];
303        assert!(format.parse(&&extra_component[..]).is_err());
304    }
305
306    #[test]
307    fn ber_sequence_supports_implicit_tags_and_definite_normalization() {
308        let content = integer_fields_sequence().1;
309        let format = BerSequenceFmt::implicit(Class::ContextSpecific, 0, content);
310        let indefinite = [0xa0, 0x80, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x00, 0x00];
311        let (_, value) = format.parse(&&indefinite[..]).unwrap();
312        assert_eq!(value, (1i8, 2i8));
313
314        let mut output = vec![0; format.prepare(&value).unwrap()];
315        format.serialize(&value, output.as_mut_slice());
316        assert_eq!(output, [0xa0, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02]);
317
318        let universal = [0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02];
319        assert!(format.parse(&&universal[..]).is_err());
320    }
321
322    #[test]
323    fn ber_sequence_of_parses_definite_and_indefinite_forms() {
324        let format = integer_sequence();
325        let definite = [0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02];
326        let indefinite = [0x30, 0x80, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x00, 0x00];
327
328        assert_eq!(
329            format.parse(&&definite[..]).unwrap(),
330            (definite.len(), vec![1i8, 2i8]),
331        );
332        assert_eq!(
333            format.parse(&&indefinite[..]).unwrap(),
334            (indefinite.len(), vec![1i8, 2i8]),
335        );
336
337        let empty_definite = [0x30, 0x00];
338        let empty_indefinite = [0x30, 0x80, 0x00, 0x00];
339        assert_eq!(
340            format.parse(&&empty_definite[..]).unwrap(),
341            (empty_definite.len(), Vec::<i8>::new()),
342        );
343        assert_eq!(
344            format.parse(&&empty_indefinite[..]).unwrap(),
345            (empty_indefinite.len(), Vec::<i8>::new()),
346        );
347    }
348
349    #[test]
350    fn ber_sequence_of_supports_implicit_outer_tags() {
351        let element = ASN1Fmt::<_, BER>(TagFmt::INTEGER, Integer8Fmt);
352        let format = BerSequenceOfFmt::implicit(Class::ContextSpecific, 0, element);
353        let definite = [0xa0, 0x03, 0x02, 0x01, 0x01];
354        let indefinite = [0xa0, 0x80, 0x02, 0x01, 0x01, 0x00, 0x00];
355
356        assert_eq!(
357            format.parse(&&definite[..]).unwrap(),
358            (definite.len(), vec![1i8]),
359        );
360        assert_eq!(
361            format.parse(&&indefinite[..]).unwrap(),
362            (indefinite.len(), vec![1i8]),
363        );
364
365        let universal = [0x30, 0x03, 0x02, 0x01, 0x01];
366        assert!(format.parse(&&universal[..]).is_err());
367
368        let value = vec![1i8];
369        let mut output = vec![0; format.prepare(&value).unwrap()];
370        format.serialize(&value, output.as_mut_slice());
371        assert_eq!(output, definite);
372    }
373
374    #[test]
375    fn ber_sequence_of_serialization_normalizes_to_definite_form() {
376        let format = integer_sequence();
377        let indefinite = [0x30, 0x80, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x00, 0x00];
378        let (_, value) = format.parse(&&indefinite[..]).unwrap();
379        let mut output = vec![0; format.prepare(&value).unwrap()];
380        format.serialize(&value, output.as_mut_slice());
381
382        assert_eq!(output, [0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02]);
383    }
384
385    #[test]
386    fn nested_ber_sequence_of_delegates_indefinite_values_to_the_element_codec() {
387        let inner = integer_sequence();
388        let outer = SEQUENCE_OF(inner);
389        let input = [
390            0x30, 0x80, // outer indefinite SEQUENCE OF
391            0x30, 0x80, 0x02, 0x01, 0x01, 0x00, 0x00, // inner indefinite value
392            0x30, 0x03, 0x02, 0x01, 0x02, // inner definite value
393            0x00, 0x00, // outer EOC
394        ];
395
396        assert_eq!(
397            outer.parse(&&input[..]).unwrap(),
398            (input.len(), vec![vec![1i8], vec![2i8]]),
399        );
400    }
401
402    #[test]
403    fn ber_sequence_of_rejects_missing_eoc_and_non_elements() {
404        let format = integer_sequence();
405        let missing_eoc = [0x30, 0x80, 0x02, 0x01, 0x01];
406        assert!(format.parse(&&missing_eoc[..]).is_err());
407
408        let boolean_element = [0x30, 0x80, 0x01, 0x01, 0xff, 0x00, 0x00];
409        assert!(format.parse(&&boolean_element[..]).is_err());
410    }
411
412    #[test]
413    fn parses_primitive_and_definite_constructed_octet_strings() {
414        let primitive = [0x04, 0x03, b'a', b'b', b'c'];
415        assert_eq!(
416            parse_universal(&primitive),
417            (primitive.len(), b"abc".to_vec())
418        );
419
420        let constructed = [0x24, 0x07, 0x04, 0x02, b'a', b'b', 0x04, 0x01, b'c'];
421        assert_eq!(
422            parse_universal(&constructed),
423            (constructed.len(), b"abc".to_vec()),
424        );
425    }
426
427    #[test]
428    fn parses_indefinite_and_nested_constructed_octet_strings() {
429        let indefinite = [
430            0x24, 0x80, 0x04, 0x02, b'a', b'b', 0x04, 0x01, b'c', 0x00, 0x00,
431        ];
432        assert_eq!(
433            parse_universal(&indefinite),
434            (indefinite.len(), b"abc".to_vec()),
435        );
436
437        let nested = [
438            0x24, 0x80, 0x24, 0x80, 0x04, 0x01, b'a', 0x00, 0x00, 0x04, 0x01, b'b', 0x00, 0x00,
439        ];
440        assert_eq!(parse_universal(&nested), (nested.len(), b"ab".to_vec()));
441    }
442
443    #[test]
444    fn implicit_tagging_replaces_only_the_outer_tag() {
445        let format = Octets::implicit(Class::ContextSpecific, 0);
446
447        let primitive = [0x80, 0x03, b'a', b'b', b'c'];
448        assert_eq!(
449            format.parse(&&primitive[..]).unwrap(),
450            (primitive.len(), b"abc".to_vec()),
451        );
452
453        let constructed = [
454            0xa0, 0x80, 0x04, 0x02, b'a', b'b', 0x04, 0x01, b'c', 0x00, 0x00,
455        ];
456        assert_eq!(
457            format.parse(&&constructed[..]).unwrap(),
458            (constructed.len(), b"abc".to_vec()),
459        );
460
461        // Recursive components retain the universal OCTET STRING tag.
462        let retagged_child = [0xa0, 0x80, 0x80, 0x01, b'a', 0x00, 0x00];
463        assert_eq!(
464            format.parse(&&retagged_child[..]).unwrap_err().kind,
465            ParseErrorKind::InvalidTag,
466        );
467    }
468
469    #[test]
470    fn rejects_malformed_framing_and_enforces_the_recursion_limit() {
471        let missing_eoc = [0x24, 0x80, 0x04, 0x01, b'a'];
472        assert!(Octets::universal().parse(&&missing_eoc[..]).is_err());
473
474        let short_definite_body = [0x24, 0x04, 0x04, 0x01, b'a'];
475        assert!(Octets::universal()
476            .parse(&&short_definite_body[..])
477            .is_err());
478
479        let nested_2 = [
480            0x24, 0x80, 0x24, 0x80, 0x04, 0x01, b'a', 0x00, 0x00, 0x04, 0x01, b'b', 0x00, 0x00,
481        ];
482        assert!(BerOctetStringFmt::<1>::universal()
483            .parse(&&nested_2[..])
484            .is_err());
485    }
486
487    #[test]
488    fn serialization_normalizes_to_primitive_definite_form() {
489        let constructed = [
490            0x24, 0x80, 0x04, 0x02, b'a', b'b', 0x04, 0x01, b'c', 0x00, 0x00,
491        ];
492        let (_, value) = parse_universal(&constructed);
493        let format = Octets::universal();
494        let mut output = vec![0; format.prepare(value.as_slice()).unwrap()];
495        format.serialize(value.as_slice(), output.as_mut_slice());
496        assert_eq!(output, [0x04, 0x03, b'a', b'b', b'c']);
497
498        let implicit = Octets::implicit(Class::ContextSpecific, 0);
499        let mut output = vec![0; implicit.prepare(value.as_slice()).unwrap()];
500        implicit.serialize(value.as_slice(), output.as_mut_slice());
501        assert_eq!(output, [0x80, 0x03, b'a', b'b', b'c']);
502    }
503
504    #[test]
505    fn ber_utf8_string_validates_after_flattening_segments() {
506        type Format = BerUtf8StringFmt<8>;
507
508        // U+20AC is split in the middle of its three-octet UTF-8 encoding. Validating each
509        // primitive segment separately would reject this standards-permitted encoding.
510        let split_scalar = [
511            0x2c, 0x80, 0x04, 0x01, 0xe2, 0x04, 0x02, 0x82, 0xac, 0x00, 0x00,
512        ];
513        let (n, value) = Format::universal().parse(&&split_scalar[..]).unwrap();
514        assert_eq!(n, split_scalar.len());
515        assert_eq!(value.as_str(), "€");
516
517        let primitive = [0x0c, 0x03, 0xe2, 0x82, 0xac];
518        assert_eq!(
519            Format::universal()
520                .parse(&&primitive[..])
521                .unwrap()
522                .1
523                .as_str(),
524            "€"
525        );
526
527        let nested = [
528            0x2c, 0x80, // constructed UTF8String
529            0x24, 0x80, // nested universal constructed OCTET STRING
530            0x04, 0x01, 0xe2, 0x04, 0x02, 0x82, 0xac, 0x00, 0x00, // nested EOC
531            0x00, 0x00, // outer EOC
532        ];
533        assert_eq!(
534            Format::universal().parse(&&nested[..]).unwrap().1.as_str(),
535            "€"
536        );
537
538        let format = Format::universal();
539        let mut output = vec![0; format.prepare(&value).unwrap()];
540        format.serialize(&value, output.as_mut_slice());
541        assert_eq!(output, [0x0c, 0x03, 0xe2, 0x82, 0xac]);
542    }
543
544    #[test]
545    fn ber_restricted_strings_support_implicit_outer_tags() {
546        type Format = BerUtf8StringFmt<8>;
547        let format = Format::implicit(Class::ContextSpecific, 0);
548        let input = [
549            0xa0, 0x80, 0x04, 0x01, 0xe2, 0x04, 0x02, 0x82, 0xac, 0x00, 0x00,
550        ];
551        let (_, value) = format.parse(&&input[..]).unwrap();
552        assert_eq!(value.as_str(), "€");
553
554        let mut output = vec![0; format.prepare(&value).unwrap()];
555        format.serialize(&value, output.as_mut_slice());
556        assert_eq!(output, [0x80, 0x03, 0xe2, 0x82, 0xac]);
557    }
558
559    #[test]
560    fn ber_printable_and_ia5_validate_flattened_contents() {
561        let printable = [
562            0x33, 0x80, 0x04, 0x02, b'A', b'B', 0x04, 0x02, b'1', b'?', 0x00, 0x00,
563        ];
564        let (_, value) = BerPrintableStringFmt::<8>::universal()
565            .parse(&&printable[..])
566            .unwrap();
567        assert_eq!(value.inner(), "AB1?");
568
569        let invalid_ia5 = [0x36, 0x80, 0x04, 0x01, 0x80, 0x00, 0x00];
570        assert!(BerIa5StringFmt::<8>::universal()
571            .parse(&&invalid_ia5[..])
572            .is_err());
573    }
574
575    #[test]
576    fn ber_bmp_string_allows_code_units_to_cross_segments() {
577        type Format = BerBmpStringFmt<8>;
578
579        // BMPString "A" is 00 41. The code unit is deliberately split between children.
580        let split_code_unit = [0x3e, 0x80, 0x04, 0x01, 0x00, 0x04, 0x01, 0x41, 0x00, 0x00];
581        let (_, value) = Format::universal().parse(&&split_code_unit[..]).unwrap();
582        assert_eq!(value.inner(), "A");
583
584        let malformed = [0x1e, 0x01, 0x00];
585        assert!(Format::universal().parse(&&malformed[..]).is_err());
586        let surrogate = [0x1e, 0x02, 0xd8, 0x00];
587        assert!(Format::universal().parse(&&surrogate[..]).is_err());
588
589        let value = BmpString::new(String::from("A"));
590        let format = Format::universal();
591        let mut output = vec![0; format.prepare(&value).unwrap()];
592        format.serialize(&value, output.as_mut_slice());
593        assert_eq!(output, [0x1e, 0x02, 0x00, 0x41]);
594    }
595}