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