1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Encoding data in BER.
//!
//! _Note: This guide is still work in progress and will be extended._
//!
//! In many cases, BER requires that a value can state the length of its
//! encoded content before actually starting to encode this content. Since
//! this requires duplicate code in many cases, we have decided to use
//! placeholder objects for encoding. These placeholders, called value
//! encoders, are available for most built-in types as well as for various
//! constructions such as tuples, a specific type can produce a
//! value encoder by manufacturing it from these existing parts.
//!
//! To return to the example from the decoding guide. It was using this
//! ASN.1:
//!
//!
//! ```text
//! EncapsulatedContentInfo  ::=  SEQUENCE  {
//!     eContentType ContentType,
//!     eContent [0] EXPLICIT OCTET STRING OPTIONAL
//! }
//!
//! ContentType  ::=  OBJECT IDENTIFIER
//! ```
//!
//! The structure was represented by this Rust struct:
//!
//! ```
//! use bcder::{Oid, OctetString};
//!
//! pub struct EncapsulatedContentInfo {
//!     content_type: Oid,
//!     content: Option<OctetString>,
//! }
//! ```
//! 
//! The value encoders all implement the trait [`encode::Values`] which
//! represents a sequence of BER-encodable values. The implementation of
//! our struct could return such an encoder like this:
//!
//! ```
//! # use bcder::{Oid, OctetString};
//! # use bcder::encode::PrimitiveContent;
//! use bcder::Tag;
//! use bcder::encode;
//!
//! # pub struct EncapsulatedContentInfo {
//! #     content_type: Oid,
//! #     content: Option<OctetString>,
//! # }
//! # 
//! impl EncapsulatedContentInfo {
//!     pub fn encode(self) -> impl encode::Values {
//!         self.encode_as(Tag::SEQUENCE)
//!     }
//!
//!     pub fn encode_as(self, tag: Tag) -> impl encode::Values {
//!         encode::sequence_as(tag, (
//!             self.content_type.encode(),
//!             self.content.map(|s| s.encode())
//!         ))
//!     }
//! }
//! ```
//!
//! The conventional name for the method produces a value encoder with the
//! natural tag is `encode`. If necessary, `encode_as` should be present to
//! allow getting a value encoder with a chosen tag for implicit tagging.
//!
//! The signature of these methods will most likely require a lifetime bound
//! for the return value as in the example above, if the returned value
//! contains references to the value or its elements. This is completely fine,
//! since typically the returned value will only be used to encode the value
//! right away and then dropped.
//!
//! [`encode::Values`]: ../../encode/trait.Values.html