x690/
lib.rs

1//! # X.690 Encoding Rules Library
2//!
3//! This library provides comprehensive support for X.690 encoding rules, which define how ASN.1
4//! (Abstract Syntax Notation One) data structures are encoded for transmission and storage.
5//!
6//! ## Overview
7//!
8//! X.690 defines several encoding rules:
9//! - **BER (Basic Encoding Rules)**: The most flexible encoding, supporting both definite and indefinite lengths
10//! - **CER (Canonical Encoding Rules)**: A restricted form of BER that produces canonical encodings
11//! - **DER (Distinguished Encoding Rules)**: A restricted form of BER that produces unique encodings
12//!
13//! This library focuses on BER encoding and decoding, providing a complete implementation
14//! of the X.690 specification.
15//!
16//! ## Key Features
17//!
18//! - Complete BER encoding and decoding support
19//! - Support for all ASN.1 universal types
20//! - Efficient memory management with zero-copy operations where possible
21//! - Comprehensive error handling with detailed error information
22//! - Support for both definite and indefinite length encoding
23//! - Tag and length encoding/decoding utilities
24
25pub mod ber;
26#[cfg(feature = "der")]
27pub mod der;
28pub mod codec;
29pub mod parsing;
30pub(crate) mod utils;
31
32pub use crate::ber::*;
33pub use crate::codec::*;
34pub use crate::parsing::*;
35pub use crate::utils::primitive;
36
37use crate::utils::likely;
38use wildboar_asn1::error::{ASN1Error, ASN1ErrorCode, ASN1Result};
39use wildboar_asn1::{
40    ByteSlice, CharacterString, EmbeddedPDV, ExternalEncoding,
41    ExternalIdentification, GeneralizedTime,
42    PresentationContextSwitchingTypeIdentification, Tag, TagClass, TagNumber,
43    UTCTime,
44    UNIV_TAG_INTEGER,
45    UNIV_TAG_OBJECT_IDENTIFIER, UNIV_TAG_OCTET_STRING,
46    UNIV_TAG_OBJECT_DESCRIPTOR, BIT_STRING, BOOLEAN, DATE, DATE_TIME,
47    DURATION_EQUIVALENT, EXTERNAL, INTEGER, OBJECT_IDENTIFIER,
48    OCTET_STRING, REAL, RELATIVE_OID, TIME, TIME_OF_DAY,
49};
50use wildboar_asn1::{ENUMERATED, read_i64, DURATION, ComponentSpec, TagSelector};
51use std::borrow::Cow;
52use std::io::{Error, ErrorKind, Result, Write};
53use std::mem::size_of;
54use std::sync::Arc;
55use bytes::{Bytes, BytesMut, BufMut};
56
57/// Tag class bits for `UNIVERSAL` tags in X.690 encoding
58pub const X690_TAG_CLASS_UNIVERSAL: u8 = 0b0000_0000;
59
60/// Tag class bits for `APPLICATION` tags in X.690 encoding
61pub const X690_TAG_CLASS_APPLICATION: u8 = 0b0100_0000;
62
63/// Tag class bits for `CONTEXT` tags in X.690 encoding
64pub const X690_TAG_CLASS_CONTEXT: u8 = 0b1000_0000;
65
66/// Tag class bits for `PRIVATE` tags in X.690 encoding
67pub const X690_TAG_CLASS_PRIVATE: u8 = 0b1100_0000;
68
69/// Special `REAL` value constant for positive infinity
70pub const X690_SPECIAL_REAL_PLUS_INFINITY: u8 = 0b0000_0000;
71
72/// Special `REAL` value constant for negative infinity
73pub const X690_SPECIAL_REAL_MINUS_INFINITY: u8 = 0b0000_0001;
74
75/// Special `REAL` value constant for Not-a-Number (NaN)
76pub const X690_SPECIAL_REAL_NOT_A_NUMBER: u8 = 0b0000_0010;
77
78/// Special `REAL` value constant for negative zero
79pub const X690_SPECIAL_REAL_MINUS_ZERO: u8 = 0b0000_0011;
80
81/// Flag indicating a special `REAL` value
82pub const X690_REAL_SPECIAL: u8 = 0b0100_0000;
83
84/// Base encoding constant for base-10 `REAL` values
85pub const X690_REAL_BASE10: u8 = 0b0000_0000;
86
87/// Base encoding constant for binary `REAL` values
88pub const X690_REAL_BINARY: u8 = 0b1000_0000;
89
90/// Sign bit constant for positive `REAL` values
91pub const X690_REAL_POSITIVE: u8 = 0b0000_0000;
92
93/// Sign bit constant for negative `REAL` values
94pub const X690_REAL_NEGATIVE: u8 = 0b0100_0000;
95
96/// Bit mask for extracting the sign bit from `REAL` encoding
97pub const X690_REAL_SIGN_MASK: u8 = 0b0100_0000;
98
99/// Bit mask for extracting the base bits from `REAL` encoding
100pub const X690_REAL_BASE_MASK: u8 = 0b0011_0000;
101
102/// Base encoding constant for base-2 `REAL` values
103pub const X690_REAL_BASE_2: u8 = 0b0000_0000;
104
105/// Base encoding constant for base-8 `REAL` values
106pub const X690_REAL_BASE_8: u8 = 0b0001_0000;
107
108/// Base encoding constant for base-16 `REAL` values
109pub const X690_REAL_BASE_16: u8 = 0b0010_0000;
110
111/// Reserved base encoding constant for `REAL` values
112pub const X690_REAL_BASE_RESERVED: u8 = 0b0011_0000;
113
114/// Bit mask for extracting binary scaling factor from `REAL` encoding
115pub const X690_REAL_BINARY_SCALING_MASK: u8 = 0b0000_1100;
116
117/// Bit mask for extracting exponent format from `REAL` encoding
118pub const X690_REAL_EXPONENT_FORMAT_MASK: u8 = 0b0000_0011;
119
120/// Exponent format constant for 1-octet exponent
121pub const X690_REAL_EXPONENT_FORMAT_1_OCTET: u8 = 0b0000_0000;
122
123/// Exponent format constant for 2-octet exponent
124pub const X690_REAL_EXPONENT_FORMAT_2_OCTET: u8 = 0b0000_0001;
125
126/// Exponent format constant for 3-octet exponent
127pub const X690_REAL_EXPONENT_FORMAT_3_OCTET: u8 = 0b0000_0010;
128
129/// Exponent format constant for variable-length exponent
130pub const X690_REAL_EXPONENT_FORMAT_VAR_OCTET: u8 = 0b0000_0011;
131
132/// ISO 6093 NR1 format constant for `REAL` encoding
133pub const X690_REAL_NR1: u8 = 1;
134
135/// ISO 6093 NR2 format constant for `REAL` encoding
136pub const X690_REAL_NR2: u8 = 2;
137
138/// ISO 6093 NR3 format constant for `REAL` encoding
139pub const X690_REAL_NR3: u8 = 3;
140
141/// Represents the length of an X.690 encoded element
142///
143/// In X.690 encoding, lengths can be either definite (a specific number of octets)
144/// or indefinite (marked with a special value and terminated by end-of-content markers).
145#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq)]
146pub enum X690Length {
147    /// Definite length with a specific number of octets
148    Definite(usize),
149    /// Indefinite length, terminated by end-of-content markers
150    Indefinite,
151}
152
153/// Represents the value content of an X.690 encoded element
154///
155/// X.690 values can be stored in different forms depending on how they were created
156/// and whether they need to be serialized for transmission.
157#[derive(Clone, Debug, Hash)]
158pub enum X690Value {
159    /// A primitive value stored as raw bytes
160    Primitive(Bytes),
161    /// A constructed value containing child elements
162    Constructed(Arc<Vec<X690Element>>),
163    /// A value that has been serialized to bytes (for lazy decoding or faster encoding)
164    Serialized(Bytes),
165}
166
167impl X690Value {
168
169    /// Returns the length of the content octets in bytes
170    ///
171    /// For primitive values, this is the length of the raw bytes.
172    /// For constructed values, this is the sum of all child element lengths.
173    /// For serialized values, this decodes the serialized data to determine the length.
174    pub fn len(&self) -> usize {
175        match self {
176            X690Value::Primitive(v) => v.len(),
177            X690Value::Constructed(components) => {
178                let mut sum: usize = 0;
179                for component in components.iter() {
180                    sum += component.len();
181                }
182                sum
183            },
184            X690Value::Serialized(v) => {
185                match BER.decode_from_slice(&v) {
186                    Ok((_, el)) => el.len(),
187                    Err(_) => return 0,
188                }
189            }
190        }
191    }
192
193    /// Creates a constructed value from a single explicit element
194    ///
195    /// This is used when an element needs to be wrapped in an explicit tag.
196    #[inline]
197    pub fn from_explicit(inner: X690Element) -> Self {
198        X690Value::Constructed(Arc::new(Vec::from([ inner ])))
199    }
200
201    /// Returns the components of a constructed value
202    ///
203    /// For constructed values, returns the child elements.
204    /// For serialized values, decodes the serialized data and returns the components.
205    /// For primitive values, returns an error.
206    pub fn components(&self) -> ASN1Result<Arc<Vec<X690Element>>> {
207        match self {
208            X690Value::Constructed(components) => Ok(components.clone()),
209            X690Value::Serialized(v) => {
210                let (_, el) = BER.decode_from_slice(&v)?;
211                el.value.components()
212            },
213            _ => Err(ASN1Error::new(ASN1ErrorCode::invalid_construction)),
214        }
215    }
216
217}
218
219/// Represents a complete X.690 encoded element with tag and value
220///
221/// An `X690Element` contains a tag that identifies the type and class of the element,
222/// and a value that contains the actual data. The value can be primitive (raw bytes),
223/// constructed (containing child elements), or serialized (encoded bytes).
224#[derive(Clone, Debug, Hash)]
225pub struct X690Element {
226    /// The tag identifying the type and class of this element
227    pub tag: Tag,
228    /// The value content of this element
229    pub value: X690Value,
230}
231
232impl X690Element {
233
234    /// Creates a new `X690Element` with the specified tag and value
235    #[inline]
236    pub const fn new(tag: Tag, value: X690Value) -> X690Element {
237        X690Element { tag, value }
238    }
239
240    /// Returns the total length of this element in bytes when encoded
241    ///
242    /// This includes the tag bytes, length bytes, and value bytes.
243    pub fn len(&self) -> usize {
244        let tag_length: usize = get_written_x690_tag_length(self.tag.tag_number);
245        let value_length = self.value.len();
246        let length_length: usize = get_written_x690_length_length(value_length);
247        let ret = tag_length + length_length + value_length;
248        ret
249    }
250
251    /// Returns true if this element is constructed (contains child elements)
252    ///
253    /// For serialized values, this checks the constructed bit in the tag.
254    /// For constructed values, this always returns true.
255    /// For primitive values, this always returns false.
256    #[inline]
257    pub fn is_constructed (&self) -> bool {
258        if let X690Value::Serialized(v) = &self.value {
259            return v.get(0).is_some_and(|b| (*b & 0b0010_0000) == 0b0010_0000);
260        }
261        if let X690Value::Constructed(_) = self.value {
262            true
263        } else {
264            false
265        }
266    }
267
268    /// Returns the components of this element if it is constructed
269    ///
270    /// This is a convenience method that delegates to the value's [`X690Value::components`] method.
271    #[inline]
272    pub fn components (&self) -> ASN1Result<Arc<Vec<X690Element>>> {
273        self.value.components()
274    }
275
276    /// Returns the inner element if this is an explicit wrapper
277    ///
278    /// For explicit tagged values, this returns the single child element.
279    /// For other values, this returns an error.
280    pub fn inner(&self) -> ASN1Result<X690Element> {
281        match &self.value {
282            X690Value::Constructed(components) => {
283                if components.len() != 1 {
284                    return Err(self.to_asn1_error(ASN1ErrorCode::invalid_construction));
285                }
286                Ok(components[0].clone())
287            },
288            X690Value::Serialized(v) => {
289                let (_, el) = BER.decode_from_slice(&v)?;
290                el.inner()
291            },
292            _ => Err(self.to_asn1_error(ASN1ErrorCode::invalid_construction)),
293        }
294    }
295
296    /// Returns the content octets of this element
297    ///
298    /// For primitive values, returns the raw bytes.
299    /// For constructed values, serializes the child elements and returns the bytes.
300    /// For serialized values, decodes and returns the content octets.
301    pub fn content_octets <'a> (&'a self) -> ASN1Result<Cow<'a, [u8]>> {
302        match &self.value {
303            X690Value::Primitive(v) => Ok(Cow::Borrowed(&v)),
304            X690Value::Constructed(_) => {
305                let mut output = BytesMut::with_capacity(self.len()).writer();
306                x690_write_value(&mut output, &self.value)?;
307                Ok(Cow::Owned(output.into_inner().into()))
308            },
309            X690Value::Serialized(v) => {
310                let (_, el) = BER.decode_from_slice(v).unwrap();
311                match el.value {
312                    X690Value::Primitive(inner) => Ok(Cow::Owned(inner.to_vec())),
313                    X690Value::Constructed(_) => {
314                        let mut output = BytesMut::with_capacity(el.len()).writer();
315                        x690_write_value(&mut output, &el.value)?;
316                        Ok(Cow::Owned(output.into_inner().into()))
317                    },
318                    _ => panic!("ASN.1 / X.690 decoding returned serialized value"),
319                }
320            }
321        }
322    }
323
324    /// Creates an `ASN1Error` with information from this element
325    ///
326    /// This is useful for creating detailed error messages that include
327    /// information about the element that caused the error.
328    #[inline]
329    pub fn to_asn1_error (&self, errcode: ASN1ErrorCode) -> ASN1Error {
330        ASN1Error {
331            error_code: errcode,
332            component_name: None,
333            tag: Some(Tag::new(self.tag.tag_class, self.tag.tag_number)),
334            length: Some(self.len()),
335            constructed: Some(self.is_constructed()),
336            value_preview: None,
337            bytes_read: None,
338            values_read: None,
339            err_source: None,
340        }
341    }
342
343    /// Creates an `ASN1Error` with information from this element and a component name
344    ///
345    /// This is useful for creating detailed error messages that include
346    /// information about the element and the specific component that caused the error.
347    pub fn to_asn1_err_named (&self, errcode: ASN1ErrorCode, name: &str) -> ASN1Error {
348        let mut e = self.to_asn1_error(errcode);
349        e.component_name = Some(name.to_string());
350        e
351    }
352
353    /// Returns `true` if this element is empty
354    ///
355    /// For primitive values, checks if the byte length is zero.
356    /// For constructed values, checks if there are no child elements.
357    /// For serialized values, checks if the serialized data is minimal (just tag and length).
358    #[inline]
359    pub fn is_empty (&self) -> bool {
360        match &self.value {
361            X690Value::Primitive(v) => v.len() == 0,
362            X690Value::Constructed(components) => components.len() == 0,
363            X690Value::Serialized(v) => v.len() <= 2,
364        }
365    }
366
367}
368
369impl From<i8> for X690Element {
370    /// Converts an `i8` to an `X690Element` by encoding it as an `INTEGER`
371    #[inline]
372    fn from(value: i8) -> Self {
373        BER.encode_i8(value).unwrap()
374    }
375}
376
377impl From<i16> for X690Element {
378    /// Converts an `i16` to an `X690Element` by encoding it as an `INTEGER`
379    #[inline]
380    fn from(value: i16) -> Self {
381        BER.encode_i16(value).unwrap()
382    }
383}
384
385impl From<i32> for X690Element {
386    /// Converts an `i32` to an `X690Element` by encoding it as an `INTEGER`
387    #[inline]
388    fn from(value: i32) -> Self {
389        BER.encode_i32(value).unwrap()
390    }
391}
392
393impl From<i64> for X690Element {
394    /// Converts an `i64` to an `X690Element` by encoding it as an `INTEGER`
395    #[inline]
396    fn from(value: i64) -> Self {
397        BER.encode_i64(value).unwrap()
398    }
399}
400
401impl From<u8> for X690Element {
402    /// Converts a `u8` to an `X690Element` by encoding it as an `INTEGER`
403    #[inline]
404    fn from(value: u8) -> Self {
405        BER.encode_u8(value).unwrap()
406    }
407}
408
409impl From<u16> for X690Element {
410    /// Converts a `u16` to an `X690Element` by encoding it as an `INTEGER`
411    #[inline]
412    fn from(value: u16) -> Self {
413        BER.encode_u16(value).unwrap()
414    }
415}
416
417impl From<u32> for X690Element {
418    /// Converts a `u32` to an `X690Element` by encoding it as an `INTEGER`
419    #[inline]
420    fn from(value: u32) -> Self {
421        BER.encode_u32(value).unwrap()
422    }
423}
424
425impl From<u64> for X690Element {
426    /// Converts a `u64` to an ``X690Element`` by encoding it as an `INTEGER`
427    #[inline]
428    fn from(value: u64) -> Self {
429        BER.encode_u64(value).unwrap()
430    }
431}
432
433impl From<OBJECT_IDENTIFIER> for X690Element {
434    /// Converts an `OBJECT_IDENTIFIER` to an `X690Element` by encoding it
435    #[inline]
436    fn from(value: OBJECT_IDENTIFIER) -> Self {
437        X690Element::from(&value)
438    }
439}
440
441impl From<&OBJECT_IDENTIFIER> for X690Element {
442    /// Converts a reference to an `OBJECT_IDENTIFIER` to an `X690Element` by encoding it
443    #[inline]
444    fn from(value: &OBJECT_IDENTIFIER) -> Self {
445        BER.encode_object_identifier(value).unwrap()
446    }
447}
448
449impl From<bool> for X690Element {
450    /// Converts a bool to an X690Element by encoding it as a BOOLEAN
451    #[inline]
452    fn from(value: bool) -> Self {
453        BER.encode_boolean(&value).unwrap()
454    }
455}
456
457impl From<DATE> for X690Element {
458    /// Converts a `DATE` to an `X690Element` by encoding it
459    #[inline]
460    fn from(value: DATE) -> Self {
461        BER.encode_date(&value).unwrap()
462    }
463}
464
465impl From<TIME_OF_DAY> for X690Element {
466    /// Converts a `TIME_OF_DAY` to an `X690Element` by encoding it
467    #[inline]
468    fn from(value: TIME_OF_DAY) -> Self {
469        BER.encode_time_of_day(&value).unwrap()
470    }
471}
472
473impl From<DATE_TIME> for X690Element {
474    /// Converts a `DATE_TIME` to an `X690Element` by encoding it
475    #[inline]
476    fn from(value: DATE_TIME) -> Self {
477        BER.encode_date_time(&value).unwrap()
478    }
479}
480
481impl From<TIME> for X690Element {
482    /// Converts a `TIME` to an `X690Element` by encoding it
483    #[inline]
484    fn from(value: TIME) -> Self {
485        BER.encode_time(&value).unwrap()
486    }
487}
488
489impl From<DURATION> for X690Element {
490    /// Converts a `DURATION` to an `X690Element` by encoding it
491    #[inline]
492    fn from(value: DURATION) -> Self {
493        BER.encode_duration(&value).unwrap()
494    }
495}
496
497impl TryInto<i8> for X690Element {
498    type Error = ASN1Error;
499    /// Attempts to decode an X690Element as an `i8` `INTEGER`
500    #[inline]
501    fn try_into(self) -> ASN1Result<i8> {
502        BER.decode_i8(&self)
503    }
504}
505
506impl TryInto<i16> for X690Element {
507    type Error = ASN1Error;
508    /// Attempts to decode an X690Element as an `i16` `INTEGER`
509    #[inline]
510    fn try_into(self) -> ASN1Result<i16> {
511        BER.decode_i16(&self)
512    }
513}
514
515impl TryInto<i32> for X690Element {
516    type Error = ASN1Error;
517    /// Attempts to decode an X690Element as an `i32` `INTEGER`
518    #[inline]
519    fn try_into(self) -> ASN1Result<i32> {
520        BER.decode_i32(&self)
521    }
522}
523
524impl TryInto<i64> for X690Element {
525    type Error = ASN1Error;
526    /// Attempts to decode an X690Element as an `i64` `INTEGER`
527    #[inline]
528    fn try_into(self) -> ASN1Result<i64> {
529        BER.decode_i64(&self)
530    }
531}
532
533impl TryInto<i128> for X690Element {
534    type Error = ASN1Error;
535    /// Attempts to decode an X690Element as an `i128` `INTEGER`
536    #[inline]
537    fn try_into(self) -> ASN1Result<i128> {
538        BER.decode_i128(&self)
539    }
540}
541
542impl TryInto<u8> for X690Element {
543    type Error = ASN1Error;
544    /// Attempts to decode an X690Element as a `u8` `INTEGER`
545    #[inline]
546    fn try_into(self) -> ASN1Result<u8> {
547        BER.decode_u8(&self)
548    }
549}
550
551impl TryInto<u16> for X690Element {
552    type Error = ASN1Error;
553    /// Attempts to decode an X690Element as a `u16` `INTEGER`
554    #[inline]
555    fn try_into(self) -> ASN1Result<u16> {
556        BER.decode_u16(&self)
557    }
558}
559
560impl TryInto<u32> for X690Element {
561    type Error = ASN1Error;
562    /// Attempts to decode an X690Element as a `u32` `INTEGER`
563    #[inline]
564    fn try_into(self) -> ASN1Result<u32> {
565        BER.decode_u32(&self)
566    }
567}
568
569impl TryInto<u64> for X690Element {
570    type Error = ASN1Error;
571    /// Attempts to decode an X690Element as a `u64` `INTEGER`
572    #[inline]
573    fn try_into(self) -> ASN1Result<u64> {
574        BER.decode_u64(&self)
575    }
576}
577
578impl TryInto<u128> for X690Element {
579    type Error = ASN1Error;
580    /// Attempts to decode an X690Element as a `u128` `INTEGER`
581    #[inline]
582    fn try_into(self) -> ASN1Result<u128> {
583        BER.decode_u128(&self)
584    }
585}
586
587impl TryInto<BOOLEAN> for X690Element {
588    type Error = ASN1Error;
589    /// Attempts to decode an X690Element as a `BOOLEAN`
590    #[inline]
591    fn try_into(self) -> ASN1Result<BOOLEAN> {
592        BER.decode_boolean(&self)
593    }
594}
595
596impl PartialEq for X690Element {
597    /// Compares two X690Elements for equality
598    ///
599    /// For serialized values, this decodes them first before comparison.
600    /// Primitive values are compared by their raw bytes.
601    /// Constructed values are compared by their child elements.
602    fn eq(&self, other: &Self) -> bool {
603        // Helper to decode if serialized, else return reference to self
604        fn as_decoded<'a>(el: &'a X690Element) -> Cow<'a, X690Element> {
605            match &el.value {
606                X690Value::Serialized(bytes) => {
607                    match BER.decode_from_slice(bytes) {
608                        Ok((_, decoded)) => Cow::Owned(decoded),
609                        Err(_) => Cow::Borrowed(el), // fallback: treat as not equal
610                    }
611                }
612                _ => Cow::Borrowed(el),
613            }
614        }
615
616        let left = as_decoded(self);
617        let right = as_decoded(other);
618
619        match (&left.value, &right.value) {
620            (X690Value::Primitive(a), X690Value::Primitive(b)) => a == b,
621            (X690Value::Constructed(a), X690Value::Constructed(b)) => {
622                if a.len() != b.len() {
623                    return false;
624                }
625                a.iter().zip(b.iter()).all(|(x, y)| x == y)
626            }
627            (X690Value::Primitive(_), _) | (X690Value::Constructed(_), _) | (_, X690Value::Primitive(_)) | (_, X690Value::Constructed(_)) => false,
628            // Should not reach here, as all Serialized are decoded above
629            _ => false,
630        }
631    }
632}
633
634impl Eq for X690Element {}
635
636/// Decodes an X.690 tag from a byte slice
637///
638/// Returns a tuple containing:
639/// - The number of bytes read
640/// - The decoded tag
641/// - Whether the tag is constructed
642///
643/// This function handles both short and long tag formats as specified in X.690.
644pub fn x690_decode_tag(bytes: ByteSlice) -> ASN1Result<(usize, Tag, bool)> {
645    if bytes.len() == 0 {
646        return Err(ASN1Error::new(ASN1ErrorCode::tlv_truncated));
647    }
648    let mut bytes_read = 1;
649    let tag_class = match (bytes[0] & 0b1100_0000) >> 6 {
650        0 => TagClass::UNIVERSAL,
651        1 => TagClass::APPLICATION,
652        2 => TagClass::CONTEXT,
653        3 => TagClass::PRIVATE,
654        _ => panic!("Impossible tag class"),
655    };
656    let constructed = (bytes[0] & 0b0010_0000) > 0;
657    let mut tag_number: TagNumber = 0;
658
659    if (bytes[0] & 0b00011111) == 0b00011111 {
660        // If it is a long tag...
661        for byte in bytes[1..].iter() {
662            let final_byte: bool = ((*byte) & 0b1000_0000) == 0;
663            if (tag_number > 0) && !final_byte {
664                // tag_number > 0 means we've already processed one byte.
665                // Tag encoded on more than 14 bits / two bytes.
666                return Err(ASN1Error::new(ASN1ErrorCode::tag_too_big));
667            }
668            let seven_bits = ((*byte) & 0b0111_1111) as u16;
669            if !final_byte && (seven_bits == 0) {
670                // You cannot encode a long tag with padding bytes.
671                return Err(ASN1Error::new(ASN1ErrorCode::padding_in_tag_number));
672            }
673            tag_number <<= 7;
674            tag_number += seven_bits;
675            bytes_read += 1;
676            if final_byte {
677                break;
678            }
679        }
680        if tag_number <= 30 {
681            // This could have been encoded in short form.
682            return Err(ASN1Error::new(ASN1ErrorCode::tag_number_could_have_used_short_form));
683        }
684    } else {
685        tag_number = (bytes[0] & 0b00011111) as TagNumber;
686    }
687
688    let tag = Tag::new(tag_class, tag_number);
689    Ok((bytes_read, tag, constructed))
690}
691
692/// Calculates the total length of tag and length bytes in an X.690 encoding
693///
694/// This function examines the first few bytes to determine how many bytes
695/// are used for the tag and length encoding, without actually decoding the values.
696pub fn get_x690_tag_and_length_length(bytes: ByteSlice) -> usize {
697    if bytes.len() == 0 {
698        return 0;
699    }
700    let mut len: usize = 1;
701    if (bytes[0] & 0b00011111) == 0b00011111 {
702        // If it is a long tag...
703        for byte in bytes[1..].iter() {
704            len += 1; // Even the byte without the continuation flag set should be counted.
705            if ((*byte) & 0b1000_0000) == 0 {
706                break;
707            }
708        }
709    }
710    if len >= bytes.len() {
711        return len;
712    }
713    let length_byte_0 = bytes[len - 1];
714    len += 1;
715    if (length_byte_0 & 0b1000_0000) == 0 {
716        // Short definite form or indefinite form.
717        return len;
718    }
719    (length_byte_0 & 0b0111_1111) as usize
720}
721
722/// Calculates the number of bytes needed to encode a number in base-128 format
723///
724/// Base-128 encoding is used for long tag numbers and other variable-length `INTEGER`s
725/// in X.690 encoding.
726const fn base_128_len(num: u32) -> usize {
727    if likely(num < 128) {
728        return 1;
729    }
730    let mut l = 0;
731    let mut i = num;
732    while i > 0 {
733        l += 1;
734        i >>= 7;
735    }
736    return l;
737}
738
739/// Writes a number in base-128 format to a writer
740///
741/// Base-128 encoding uses 7 bits per byte with a continuation bit in the high bit.
742/// This is used for encoding long tag numbers and other variable-length `INTEGER`s.
743///
744/// Returns the number of bytes written.
745fn write_base_128<W>(output: &mut W, mut num: u32) -> Result<usize>
746where
747    W: Write,
748{
749    #[cfg(feature = "likely_stable")]
750    if likely(num < 128) {
751        return output.write(&[num as u8]);
752    }
753
754    // A u32 can take up to 5 bytes.
755    let mut encoded: [u8; 5] = [0; 5];
756    let mut byte_count: usize = 0;
757    while num > 0b0111_1111 {
758        encoded[byte_count] = (num & 0b0111_1111) as u8 | 0b1000_0000;
759        byte_count += 1;
760        num >>= 7;
761    }
762    encoded[byte_count] = num as u8;
763    output.write(&encoded[0..byte_count+1])
764}
765
766/// Calculates the number of bytes needed to encode a tag number
767///
768/// Tag numbers less than 31 use the short form (1 byte).
769/// Tag numbers 31 and above use the long form with base-128 encoding.
770pub const fn get_written_x690_tag_length(tagnum: TagNumber) -> usize {
771    if tagnum < 31 {
772        // See ITU Rec. X.690 (2021), Section 8.1.2.4.
773        return 1;
774    }
775    base_128_len(tagnum as u32) + 1
776}
777
778/// Calculates the number of bytes needed to encode a length value
779///
780/// Lengths 0-127 use the short form (1 byte).
781/// Longer lengths use the long form with a length indicator byte followed by the length value.
782pub const fn get_written_x690_length_length(len: usize) -> usize {
783    if len <= 127 {
784        // See ITU Rec. X.690 (2021), Section 8.1.3.3, "NOTE"
785        return 1;
786    }
787    let octets_needed: usize = match len {
788        0..=255 => 1,
789        256..=65535 => 2,
790        65536..=16777215 => 3,
791        16777216..=4294967295 => 4,
792        _ => return 5, // This is 4GB * 255. It's more than enough for anything.
793    };
794    octets_needed + 1
795}
796
797/// Writes an X.690 tag to a writer
798///
799/// This function handles both short and long tag formats as specified in X.690.
800/// The tag includes the class, constructed bit, and tag number.
801///
802/// Returns the number of bytes written.
803pub fn x690_write_tag<W>(
804    output: &mut W,
805    class: TagClass,
806    constructed: bool,
807    tagnum: TagNumber,
808) -> Result<usize>
809where
810    W: Write,
811{
812    let k: u8 = match class {
813        TagClass::UNIVERSAL => X690_TAG_CLASS_UNIVERSAL,
814        TagClass::APPLICATION => X690_TAG_CLASS_APPLICATION,
815        TagClass::CONTEXT => X690_TAG_CLASS_CONTEXT,
816        TagClass::PRIVATE => X690_TAG_CLASS_PRIVATE,
817    };
818    if tagnum < 31 {
819        // See ITU Rec. X.690 (2021), Section 8.1.2.4.
820        return output.write(&[k
821            | if constructed {
822                0b0010_0000
823            } else {
824                0b0000_0000
825            }
826            | tagnum as u8]);
827    } else {
828        let first_byte_result = output.write(&[k
829            | if constructed {
830                0b0010_0000
831            } else {
832                0b0000_0000
833            }
834            | 0b0001_1111u8]);
835        if let Err(e) = first_byte_result {
836            return Err(e);
837        }
838        return write_base_128(output, tagnum.into());
839    }
840}
841
842/// Writes an X.690 length to a writer
843///
844/// This function handles both short and long length formats as specified in X.690.
845/// Lengths 0-127 use the short form, longer lengths use the long form.
846///
847/// Returns the number of bytes written.
848pub fn x690_write_length<W>(output: &mut W, length: usize) -> Result<usize>
849where
850    W: Write,
851{
852    if length <= 127 {
853        // See ITU Rec. X.690 (2021), Section 8.1.3.3, "NOTE"
854        return output.write(&[length as u8]);
855    } else {
856        // Calculate num of octets needed.
857        // write 0b1000_0000 | octets needed
858        let octets_needed: u8 = match length {
859            0..=255 => 1,
860            256..=65535 => 2,
861            65536..=16777215 => 3,
862            16777216..=4294967295 => 4,
863            _ => return Err(Error::from(ErrorKind::Unsupported)),
864        };
865        let length_bytes = length.to_be_bytes();
866        output.write(&[0b1000_0000 | octets_needed])?;
867        output.write(&length_bytes[std::mem::size_of::<usize>()-octets_needed as usize..])
868    }
869}
870
871/// Writes a `BOOLEAN` value in X.690 format
872///
873/// `BOOLEAN` values are encoded as a single octet: 0xFF for true, 0x00 for false.
874///
875/// Returns the number of bytes written.
876#[inline]
877pub fn x690_write_boolean_value<W>(output: &mut W, value: &BOOLEAN) -> Result<usize>
878where
879    W: Write,
880{
881    if *value {
882        return output.write(&[0xFF]);
883    } else {
884        return output.write(&[0x00]);
885    }
886}
887
888/// Writes an `INTEGER` value in X.690 format
889///
890/// `INTEGER` values are written as raw bytes in big-endian format.
891///
892/// Returns the number of bytes written.
893#[inline]
894pub fn x690_write_integer_value<W>(output: &mut W, value: &INTEGER) -> Result<usize>
895where
896    W: Write,
897{
898    if value.len() == 0 {
899        return Err(std::io::Error::from(ErrorKind::InvalidData));
900    }
901    if value.len() == 1 {
902        return output.write(value);
903    }
904    if value[0] == 0x00 && (value[1] & 0b1000_0000) == 0 {
905        return Err(std::io::Error::from(ErrorKind::InvalidData));
906    }
907    if value[0] == 0xFF && (value[1] & 0b1000_0000) > 0 {
908        return Err(std::io::Error::from(ErrorKind::InvalidData));
909    }
910    output.write(value)
911}
912
913/// Writes an i64 value in X.690 `INTEGER` format
914///
915/// This function handles the encoding of i64 values as `INTEGER` types,
916/// including proper handling of sign extension and padding.
917///
918/// Returns the number of bytes written.
919pub fn x690_write_i64_value<W>(output: &mut W, value: i64) -> Result<usize>
920where
921    W: Write,
922{
923    let bytes: [u8; 8] = value.to_be_bytes();
924    let padding_byte: u8 = if value >= 0 { 0x00 } else { 0xFF };
925    let mut number_of_padding_bytes: usize = 0;
926    for byte in bytes {
927        if byte == padding_byte {
928            number_of_padding_bytes += 1;
929        } else {
930            break;
931        }
932    }
933    let mut bytes_written: usize = 0;
934    if (number_of_padding_bytes == size_of::<i64>())
935        || (value >= 0 && ((bytes[number_of_padding_bytes] & 0b1000_0000) > 0))
936        || (value < 0 && ((bytes[number_of_padding_bytes] & 0b1000_0000) == 0)) {
937        bytes_written += output.write(&[padding_byte])?;
938    }
939    bytes_written += output.write(&(bytes[number_of_padding_bytes..size_of::<i64>()]))?;
940    Ok(bytes_written)
941}
942
943/// Writes an `ENUMERATED` value in X.690 format
944///
945/// `ENUMERATED` values are encoded the same as `INTEGER` values.
946///
947/// Returns the number of bytes written.
948#[inline]
949pub fn x690_write_enum_value<W>(output: &mut W, value: &ENUMERATED) -> Result<usize>
950where
951    W: Write,
952{
953    x690_write_i64_value(output, *value)
954}
955
956/// Writes a `BIT STRING` value in X.690 format
957///
958/// `BIT STRING` values include a trailing bits count byte followed by the actual bits.
959///
960/// Returns the number of bytes written.
961pub fn x690_write_bit_string_value<W>(output: &mut W, value: &BIT_STRING) -> Result<usize>
962where
963    W: Write,
964{
965    let trailing_bits = value.get_trailing_bits_count();
966    output.write(&[trailing_bits])?;
967    if trailing_bits == 0 {
968        let bytes_written = output.write(value.get_bytes_ref())?;
969        return Ok(bytes_written + 1);
970    }
971    // Otherwise, we check if the trailing bits are set and fix that.
972    let maybe_last_byte = value.get_bytes_ref().last();
973    let der_violated;
974    let bytes = value.get_bytes_ref();
975    let correct_last_byte: u8;
976    if let Some(last_byte) = maybe_last_byte {
977        let trailing_bits_mask = !(0xFFu8 << trailing_bits);
978        der_violated = (last_byte & trailing_bits_mask) > 0;
979        correct_last_byte = last_byte & (0xFFu8 << trailing_bits);
980    } else {
981        return Err(std::io::Error::from(ErrorKind::InvalidData));
982    }
983
984    // No violation? Just write the whole thing.
985    if likely(!der_violated) {
986        let bytes_written = output.write(value.get_bytes_ref())?;
987        return Ok(bytes_written + 1);
988    }
989
990    debug_assert!(maybe_last_byte.is_some());
991    let mut bytes_written = output.write(&bytes[..bytes.len() - 1])?;
992    bytes_written += output.write(&[ correct_last_byte ])?;
993    Ok(bytes_written + 1)
994}
995
996/// Writes an `OCTET STRING` value in X.690 format
997///
998/// `OCTET STRING` values are written as raw bytes.
999///
1000/// Returns the number of bytes written.
1001#[inline]
1002pub fn x690_write_octet_string_value<W>(output: &mut W, value: &OCTET_STRING) -> Result<usize>
1003where
1004    W: Write,
1005{
1006    output.write(value)
1007}
1008
1009/// Writes an `OBJECT IDENTIFIER` value in X.690 format
1010///
1011/// `OBJECT IDENTIFIER` values are encoded using the X.690 encoding format.
1012///
1013/// Returns the number of bytes written.
1014#[inline]
1015pub fn x690_write_object_identifier_value<W>(
1016    output: &mut W,
1017    value: &OBJECT_IDENTIFIER,
1018) -> Result<usize>
1019where
1020    W: Write,
1021{
1022    output.write(value.as_x690_slice())
1023}
1024
1025/// Writes an `ObjectDescriptor` value in X.690 format
1026///
1027/// `ObjectDescriptor` values are written as UTF-8 encoded strings.
1028///
1029/// Returns the number of bytes written.
1030#[inline]
1031pub fn x690_write_object_descriptor_value<W>(
1032    output: &mut W,
1033    value: &str,
1034) -> Result<usize>
1035where
1036    W: Write,
1037{
1038    output.write(value.as_bytes())
1039}
1040
1041/// Encode the components of an `EXTERNAL` value as X.690-encoded elements
1042///
1043/// This function encodes the components of an `EXTERNAL` value as X.690-encoded elements.
1044/// It handles the encoding of the identification, data value descriptor, and data value.
1045///
1046/// # Arguments
1047/// * `value` - The `EXTERNAL` value to encode
1048///
1049/// # Returns
1050/// A vector of X.690-encoded elements representing the components of the `EXTERNAL` value
1051///
1052/// To be a complete `EXTERNAL` value, these MUST be contained within a "parent" element
1053/// having tag `[UNIVERSAL 8]` and it MUST be constructed.
1054pub fn x690_encode_external_components (value: &EXTERNAL) -> Result<Vec<X690Element>> {
1055    let mut inner_elements: Vec<X690Element> = Vec::with_capacity(4);
1056    match &value.identification {
1057        ExternalIdentification::syntax(oid) => {
1058            let mut bytes = BytesMut::new().writer();
1059            x690_write_object_identifier_value(&mut bytes, &oid)?;
1060            let element = X690Element::new(
1061                Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OBJECT_IDENTIFIER),
1062                X690Value::Primitive(bytes.into_inner().into()),
1063            );
1064            inner_elements.push(element);
1065        }
1066        ExternalIdentification::presentation_context_id(pci) => {
1067            let mut bytes = BytesMut::new().writer();
1068            x690_write_integer_value(&mut bytes, pci)?;
1069            let element = X690Element::new(
1070                Tag::new(TagClass::UNIVERSAL, UNIV_TAG_INTEGER),
1071                X690Value::Primitive(bytes.into_inner().into()),
1072            );
1073            inner_elements.push(element);
1074        }
1075        ExternalIdentification::context_negotiation(cn) => {
1076            let mut direct_ref_bytes = BytesMut::new().writer();
1077            x690_write_object_identifier_value(&mut direct_ref_bytes, &cn.transfer_syntax)?;
1078            let direct_ref_element = X690Element::new(
1079                Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OBJECT_IDENTIFIER),
1080                X690Value::Primitive(direct_ref_bytes.into_inner().into()),
1081            );
1082            inner_elements.push(direct_ref_element);
1083            let mut indirect_ref_bytes = BytesMut::new().writer();
1084            x690_write_integer_value(&mut indirect_ref_bytes, &cn.presentation_context_id)?;
1085            let indirect_ref_element = X690Element::new(
1086                Tag::new(TagClass::UNIVERSAL, UNIV_TAG_INTEGER),
1087                X690Value::Primitive(indirect_ref_bytes.into_inner().into()),
1088            );
1089            inner_elements.push(indirect_ref_element);
1090        }
1091    };
1092    match &value.data_value_descriptor {
1093        Some(dvd) => {
1094            let mut bytes = BytesMut::new().writer();
1095            x690_write_object_descriptor_value(&mut bytes, &dvd)?;
1096            let element = X690Element::new(
1097                Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OBJECT_DESCRIPTOR),
1098                X690Value::Primitive(bytes.into_inner().into()),
1099            );
1100            inner_elements.push(element);
1101        }
1102        None => (),
1103    };
1104    let mut data_value_bytes = BytesMut::new().writer();
1105    match &value.data_value {
1106        ExternalEncoding::single_ASN1_type(t) => {
1107            let el = BER.encode_any(t)?;
1108            x690_write_tlv(&mut data_value_bytes, &el)?
1109        },
1110        ExternalEncoding::octet_aligned(o) => x690_write_octet_string_value(&mut data_value_bytes, o)?,
1111        ExternalEncoding::arbitrary(b) => x690_write_bit_string_value(&mut data_value_bytes, b)?,
1112    };
1113    let data_value_element = X690Element::new(
1114        Tag::new(TagClass::CONTEXT, 1),
1115        X690Value::Primitive(data_value_bytes.into_inner().into()),
1116    );
1117    inner_elements.push(data_value_element);
1118    Ok(inner_elements)
1119}
1120
1121/// Write an `EXTERNAL` value as an X.690-encoded element
1122///
1123/// This function writes an `EXTERNAL` value as an X.690-encoded element.
1124/// It handles the encoding of the identification, data value descriptor,
1125/// and data value.
1126///
1127/// # Arguments
1128/// * `output` - The writable stream to write the `EXTERNAL` value to
1129///
1130/// # Returns
1131/// The number of bytes written to the writable stream
1132///
1133/// NOTE: This has to be encoded in a strange way that is detailed in ITU-T
1134/// Recommendation X.690, Section 8.18.
1135pub fn x690_write_external_value<W>(output: &mut W, value: &EXTERNAL) -> Result<usize>
1136where
1137    W: Write,
1138{
1139    let components = x690_encode_external_components(value)?;
1140    let mut bytes_written: usize = 0;
1141    for component in components {
1142        bytes_written += x690_write_tlv(output, &component)?;
1143    }
1144    Ok(bytes_written)
1145}
1146
1147/// Write a `REAL` value as an X.690-encoded element
1148///
1149/// This function writes a `REAL` value as an X.690-encoded element.
1150/// It handles the encoding of the value according to ITU Recommendation
1151/// X.690, Section 8.5.
1152///
1153/// This adheres to the Basic Encoding Rules (BER) encoding of `REAL` values,
1154/// but not necessarily the Distinguished Encoding Rules (DER) encoding or
1155/// the Canonical Encoding Rules (CER).
1156///
1157/// # Arguments
1158/// * `output` - The writable stream to write the `REAL` value to
1159///
1160/// # Returns
1161/// The number of bytes written to the writable stream
1162///
1163pub fn x690_write_real_value<W>(output: &mut W, value: &REAL) -> Result<usize>
1164where
1165    W: Write,
1166{
1167    // This may seem like a floating precision problem, but this is how the
1168    // `num` crate does it:
1169    // https://github.com/rust-num/num-traits/blob/5397a1c27124af874e42d3d185f78d8ce01ecf69/src/identities.rs#L61
1170    let is_zero = *value == 0.0;
1171    // If the real value is the value plus zero, there shall be no contents octets in the encoding.
1172    if is_zero {
1173        return Ok(0);
1174    }
1175    // If the real value is the value minus zero, then it shall be encoded as specified in 8.5.9.
1176    if is_zero && value.is_sign_negative() {
1177        return output.write(&[X690_REAL_SPECIAL | X690_SPECIAL_REAL_MINUS_ZERO]);
1178    }
1179
1180    if value.is_nan() {
1181        return output.write(&[X690_REAL_SPECIAL | X690_SPECIAL_REAL_NOT_A_NUMBER]);
1182    }
1183
1184    if value.is_infinite() {
1185        if value.is_sign_negative() {
1186            return output.write(&[X690_REAL_SPECIAL | X690_SPECIAL_REAL_MINUS_INFINITY]);
1187        } else {
1188            return output.write(&[X690_REAL_SPECIAL | X690_SPECIAL_REAL_PLUS_INFINITY]);
1189        }
1190    }
1191
1192    let sign_bit: u8 = if value.is_sign_negative() {
1193        X690_REAL_NEGATIVE
1194    } else {
1195        X690_REAL_POSITIVE
1196    };
1197    let base_bits: u8 = X690_REAL_BASE_2;
1198    let scaling_factor: u8 = 0;
1199    let bits = value.to_bits();
1200    let mantissa_mask = (1u64 << 52) - 1;
1201    let mantissa: u64 = bits & mantissa_mask;
1202    let biased_exp = ((bits >> 52) & 0x7FF) as u16;
1203
1204    // For normal numbers, add the implicit leading 1
1205    let mut mantissa = if biased_exp != 0 { mantissa | (1u64 << 52) } else { mantissa };
1206    let mut exponent = if biased_exp != 0 { biased_exp as i16 - 1023 - 52 } else { -1023 - 51 };
1207
1208    // Normalize - remove trailing zeros
1209    while mantissa > 0 && mantissa & 1 == 0 {
1210        mantissa >>= 1;
1211        exponent += 1;
1212    }
1213
1214    let e_bytes = exponent.to_be_bytes();
1215    let mut bytes_written: usize = 0;
1216    if exponent > u8::MAX as i16 {
1217        let byte0: u8 = X690_REAL_BINARY
1218            | sign_bit
1219            | base_bits
1220            | scaling_factor
1221            | X690_REAL_EXPONENT_FORMAT_2_OCTET;
1222        bytes_written += output.write(&[byte0, e_bytes[0], e_bytes[1]])?;
1223    } else {
1224        let byte0: u8 = X690_REAL_BINARY
1225            | sign_bit
1226            | base_bits
1227            | scaling_factor
1228            | X690_REAL_EXPONENT_FORMAT_1_OCTET;
1229        bytes_written += output.write(&[byte0, e_bytes[1]])?;
1230    };
1231
1232    return match x690_write_i64_value(output, mantissa as i64) {
1233        Err(e) => return Err(e),
1234        Ok(wrote) => Ok(wrote + bytes_written),
1235    };
1236}
1237
1238/// Encode the `identification` field of a context-switching type
1239///
1240/// This function encodes the `identification` field of a context-switching type,
1241/// such as an `EXTERNAL` or `EMBEDDED PDV`, as an X.690-encoded element.
1242///
1243/// Returns the X.690-encoded element.
1244///
1245/// # Arguments
1246/// * `id` - The `PresentationContextSwitchingTypeIdentification` value to convert
1247///
1248/// # Returns
1249/// The X.690-encoded element.
1250///
1251pub fn x690_encode_context_switching_identification(
1252    id: &PresentationContextSwitchingTypeIdentification,
1253) -> Result<X690Element> {
1254    match id {
1255        PresentationContextSwitchingTypeIdentification::syntaxes(syntaxes) => {
1256            let mut abstract_value_bytes = BytesMut::new().writer();
1257            let mut transfer_value_bytes = BytesMut::new().writer();
1258            x690_write_object_identifier_value(
1259                &mut abstract_value_bytes,
1260                &syntaxes.r#abstract,
1261            )?;
1262            x690_write_object_identifier_value(&mut transfer_value_bytes, &syntaxes.transfer)?;
1263            let mut syntaxes_elements: Vec<X690Element> = Vec::with_capacity(2);
1264            syntaxes_elements.push(X690Element::new(
1265                Tag::new(TagClass::CONTEXT, 0),
1266                X690Value::Primitive(abstract_value_bytes.into_inner().into()),
1267            ));
1268            syntaxes_elements.push(X690Element::new(
1269                Tag::new(TagClass::CONTEXT, 1),
1270                X690Value::Primitive(transfer_value_bytes.into_inner().into()),
1271            ));
1272            let element = X690Element::new(
1273                Tag::new(TagClass::CONTEXT, 0),
1274                X690Value::Constructed(Arc::new(syntaxes_elements)),
1275            );
1276            return Ok(X690Element::new(
1277                Tag::new(TagClass::CONTEXT, 0),
1278                X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1279            ));
1280        }
1281        PresentationContextSwitchingTypeIdentification::syntax(oid) => {
1282            // We assume that, on average, each OID arc is encoded on two bytes.
1283            let mut bytes = BytesMut::with_capacity(oid.as_x690_slice().len()).writer();
1284            x690_write_object_identifier_value(&mut bytes, &oid)?;
1285            let element = X690Element::new(
1286                Tag::new(TagClass::CONTEXT, 1),
1287                X690Value::Primitive(bytes.into_inner().into()),
1288            );
1289            return Ok(X690Element::new(
1290                Tag::new(TagClass::CONTEXT, 0),
1291                X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1292            ));
1293        }
1294        PresentationContextSwitchingTypeIdentification::presentation_context_id(pci) => {
1295            let mut bytes = BytesMut::with_capacity(pci.len()).writer();
1296            x690_write_integer_value(&mut bytes, pci)?;
1297            let element = X690Element::new(
1298                Tag::new(TagClass::CONTEXT, 2),
1299                X690Value::Primitive(bytes.into_inner().into()),
1300            );
1301            return Ok(X690Element::new(
1302                Tag::new(TagClass::CONTEXT, 0),
1303                X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1304            ));
1305        }
1306        PresentationContextSwitchingTypeIdentification::context_negotiation(cn) => {
1307            let mut pci_bytes = BytesMut::new().writer();
1308            x690_write_integer_value(&mut pci_bytes, &cn.presentation_context_id)?;
1309            let pci_element = X690Element::new(
1310                Tag::new(TagClass::CONTEXT, 0),
1311                X690Value::Primitive(pci_bytes.into_inner().into()),
1312            );
1313            let mut transfer_syntax_bytes = BytesMut::new().writer();
1314            x690_write_object_identifier_value(
1315                &mut transfer_syntax_bytes,
1316                &cn.transfer_syntax,
1317            )?;
1318            let transfer_syntax_element = X690Element::new(
1319                Tag::new(TagClass::CONTEXT, 1),
1320                X690Value::Primitive(transfer_syntax_bytes.into_inner().into()),
1321            );
1322            let cn_elements: Vec<X690Element> = vec![pci_element, transfer_syntax_element];
1323            let element = X690Element::new(
1324                Tag::new(TagClass::CONTEXT, 3),
1325                X690Value::Constructed(Arc::new(cn_elements)),
1326            );
1327            return Ok(X690Element::new(
1328                Tag::new(TagClass::CONTEXT, 0),
1329                X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1330            ));
1331        }
1332        PresentationContextSwitchingTypeIdentification::transfer_syntax(ts) => {
1333            let mut bytes = BytesMut::new().writer();
1334            x690_write_object_identifier_value(&mut bytes, &ts)?;
1335            let element = X690Element::new(
1336                Tag::new(TagClass::CONTEXT, 4),
1337                X690Value::Primitive(bytes.into_inner().into()),
1338            );
1339            return Ok(X690Element::new(
1340                Tag::new(TagClass::CONTEXT, 0),
1341                X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1342            ));
1343        }
1344        PresentationContextSwitchingTypeIdentification::fixed => {
1345            let element = X690Element::new(
1346                Tag::new(TagClass::CONTEXT, 5),
1347                X690Value::Primitive(Bytes::new()),
1348            );
1349            return Ok(X690Element::new(
1350                Tag::new(TagClass::CONTEXT, 0),
1351                X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1352            ));
1353        }
1354    }
1355}
1356
1357/// Encode the components of an `EMBEDDED PDV` value as X.690-encoded elements
1358///
1359/// This function encodes the components of an `EMBEDDED PDV` value as X.690-encoded elements.
1360/// It handles the encoding of the `identification` and `data-value`.
1361///
1362/// # Arguments
1363/// * `value` - The `EMBEDDED PDV` value to encode
1364///
1365/// To be a complete `EMBEDDED PDV` value, these MUST be contained within a "parent" element
1366/// having tag `[UNIVERSAL 11]` and it MUST be constructed.
1367pub fn x690_encode_embedded_pdv_components (value: &EmbeddedPDV) -> Result<Vec<X690Element>> {
1368    let id = x690_encode_context_switching_identification(&value.identification)?;
1369    let mut data_value_bytes = BytesMut::new().writer();
1370    x690_write_octet_string_value(&mut data_value_bytes, &value.data_value)?;
1371    let data_value_element = X690Element::new(
1372        Tag::new(TagClass::CONTEXT, 1),
1373        X690Value::Primitive(data_value_bytes.into_inner().into()),
1374    );
1375    Ok(vec![id, data_value_element])
1376}
1377
1378/// Write an `EMBEDDED PDV` value as an X.690-encoded element
1379///
1380/// This function writes an `EMBEDDED PDV` value as an X.690-encoded element.
1381/// It handles the encoding of the `identification`, data value descriptor,
1382/// and `data-value`.
1383///
1384/// # Arguments
1385/// * `output` - The writable stream to write the `EMBEDDED PDV` value to
1386/// * `value` - The `EMBEDDED PDV` value to write
1387///
1388/// # Returns
1389/// The number of bytes written to the writable stream
1390///
1391pub fn x690_write_embedded_pdv_value<W>(output: &mut W, value: &EmbeddedPDV) -> Result<usize>
1392where
1393    W: Write,
1394{
1395    let components: Vec<X690Element> = x690_encode_embedded_pdv_components(value)?;
1396    let mut bytes_written: usize = 0;
1397    for component in components {
1398        bytes_written += x690_write_tlv(output, &component)?;
1399    }
1400    Ok(bytes_written)
1401}
1402
1403/// Write a `UTF8String` value as an X.690-encoded element, returning the number of bytes written
1404#[inline]
1405pub fn x690_write_utf8_string_value<W>(output: &mut W, value: &str) -> Result<usize>
1406where
1407    W: Write,
1408{
1409    output.write(value.as_bytes())
1410}
1411
1412/// Write a `RELATIVE-OID` value as an X.690-encoded element, returning the number of bytes written
1413#[inline]
1414pub fn x690_write_relative_oid_value<W>(output: &mut W, value: &RELATIVE_OID) -> Result<usize>
1415where
1416    W: Write,
1417{
1418    output.write(value.as_x690_slice())
1419}
1420
1421/// Write a `TIME` value as an X.690-encoded element, returning the number of bytes written
1422#[inline]
1423pub fn x690_write_time_value<W>(output: &mut W, value: &TIME) -> Result<usize>
1424where
1425    W: Write,
1426{
1427    output.write(value.as_bytes())
1428}
1429
1430/// Write a `UTCTime` value as an X.690-encoded element, returning the number of bytes written
1431#[inline]
1432pub fn x690_write_utc_time_value<W>(output: &mut W, value: &UTCTime) -> Result<usize>
1433where
1434    W: Write,
1435{
1436    output.write(value.to_string().as_bytes())
1437}
1438
1439/// Write a `GeneralizedTime` value as an X.690-encoded element, returning the number of bytes written
1440#[inline]
1441pub fn x690_write_generalized_time_value<W>(
1442    output: &mut W,
1443    value: &GeneralizedTime,
1444) -> Result<usize>
1445where
1446    W: Write,
1447{
1448    output.write(value.to_string().as_bytes())
1449}
1450
1451/// Write a `UniversalString` value as an X.690-encoded element, returning the number of bytes written
1452#[inline]
1453pub fn x690_write_universal_string_value<W>(
1454    output: &mut W,
1455    value: &[u32],
1456) -> Result<usize>
1457where
1458    W: Write,
1459{
1460    for c in value {
1461        output.write(&c.to_be_bytes())?;
1462    }
1463    Ok(value.len() * 4)
1464}
1465
1466/// Encode the components of a `CharacterString` value as X.690-encoded elements
1467///
1468/// This function encodes the components of a `CharacterString` value as X.690-encoded elements.
1469/// It handles the encoding of the `identification` and `string-value` fields.
1470///
1471/// # Arguments
1472/// * `value` - The `CharacterString` value to encode
1473///
1474/// # Returns
1475/// A vector of X.690-encoded elements representing the components of the `CharacterString` value
1476///
1477/// To be a complete `CharacterString` value, these MUST be contained within a "parent" element
1478/// having tag `[UNIVERSAL 29]` and it MUST be constructed.
1479pub fn x690_encode_character_string_components (value: &CharacterString) -> Result<Vec<X690Element>> {
1480    let id = x690_encode_context_switching_identification(&value.identification)?;
1481    let mut data_value_bytes = BytesMut::new().writer();
1482    x690_write_octet_string_value(&mut data_value_bytes, &value.string_value)?;
1483    let data_value_element = X690Element::new(
1484        Tag::new(TagClass::CONTEXT, 1),
1485        X690Value::Primitive(data_value_bytes.into_inner().into()),
1486    );
1487    Ok(vec![id, data_value_element])
1488}
1489
1490/// Write a `CharacterString` value as an X.690-encoded element, returning the number of bytes written
1491///
1492/// This function writes a `CharacterString` value as an X.690-encoded element.
1493/// It handles the encoding of the `identification` and `string-value` fields.
1494///
1495/// # Arguments
1496/// * `output` - The writable stream to write the `CharacterString` value to
1497/// * `value` - The `CharacterString` value to write
1498///
1499/// # Returns
1500/// The number of bytes written to the writable stream
1501///
1502pub fn x690_write_character_string_value<W>(
1503    output: &mut W,
1504    value: &CharacterString,
1505) -> Result<usize>
1506where
1507    W: Write,
1508{
1509    let components: Vec<X690Element> = x690_encode_character_string_components(value)?;
1510    let mut bytes_written: usize = 0;
1511    for component in components {
1512        bytes_written += x690_write_tlv(output, &component)?;
1513    }
1514    Ok(bytes_written)
1515}
1516
1517/// Write a `BMPString` value as an X.690-encoded element, returning the number of bytes written
1518pub fn x690_write_bmp_string_value<W>(output: &mut W, value: &[u16]) -> Result<usize>
1519where
1520    W: Write,
1521{
1522    for c in value {
1523        output.write(&c.to_be_bytes())?;
1524    }
1525    Ok(value.len() * 2)
1526}
1527
1528/// Write a string value as an X.690-encoded element, returning the number of bytes written
1529#[inline]
1530pub fn x690_write_string_value<W>(output: &mut W, value: &str) -> Result<usize>
1531where
1532    W: Write,
1533{
1534    output.write(value.as_bytes())
1535}
1536
1537/// Write a `DATE` value as an X.690-encoded element, returning the number of bytes written
1538pub fn x690_write_date_value<W>(output: &mut W, value: &DATE) -> Result<usize>
1539where
1540    W: Write,
1541{
1542    if value.month > 12 || value.month == 0 || value.day > 31 || value.day == 0 {
1543        return Err(Error::from(ErrorKind::InvalidData));
1544    }
1545    output.write(value.to_num_string().as_bytes())
1546}
1547
1548/// Write a `TIME-OF-DAY` value as an X.690-encoded element, returning the number of bytes written
1549pub fn x690_write_time_of_day_value<W>(output: &mut W, value: &TIME_OF_DAY) -> Result<usize>
1550where
1551    W: Write,
1552{
1553    if value.hour > 23 || value.minute > 59 || value.second > 59 {
1554        return Err(Error::from(ErrorKind::InvalidData));
1555    }
1556    output.write(value.to_num_string().as_bytes())
1557}
1558
1559/// Write a `DATE-TIME` value as an X.690-encoded element, returning the number of bytes written
1560pub fn x690_write_date_time_value<W>(output: &mut W, value: &DATE_TIME) -> Result<usize>
1561where
1562    W: Write,
1563{
1564    output.write(value.to_num_string().as_bytes())
1565}
1566
1567/// Write a `DURATION` value as an X.690-encoded element, returning the number of bytes written
1568pub fn x690_write_duration_value<W>(output: &mut W, value: &DURATION_EQUIVALENT) -> Result<usize>
1569where
1570    W: Write,
1571{
1572    output.write(&value.to_string().as_bytes()[1..]) // Skip the "P"
1573}
1574
1575/// Write an X.690-encoded value to a writable stream, returning the number of bytes written
1576fn x690_write_value<W>(output: &mut W, encoding: &X690Value) -> Result<usize>
1577where
1578    W: Write,
1579{
1580    match encoding {
1581        X690Value::Primitive(v) => output.write(&v),
1582        X690Value::Constructed(components) => {
1583            let mut sum: usize = 0;
1584            for component in components.iter() {
1585                sum += x690_write_tlv(output, component)?;
1586            }
1587            Ok(sum)
1588        },
1589        X690Value::Serialized(v) => {
1590            let (_, el) = BER.decode_from_slice(&v)?;
1591            x690_write_value(output, &el.value)
1592        }
1593    }
1594}
1595
1596/// Write an X.690-encoded element to a writable stream, returning the number of bytes written
1597pub fn x690_write_tlv<W>(output: &mut W, node: &X690Element) -> Result<usize>
1598where
1599    W: Write,
1600{
1601    if let X690Value::Serialized(serialized) = &node.value {
1602        return output.write(&serialized);
1603    }
1604    let mut bytes_written: usize = 0;
1605    bytes_written += x690_write_tag(output, node.tag.tag_class, node.is_constructed(), node.tag.tag_number)?;
1606    bytes_written += x690_write_length(output, node.value.len())?;
1607    bytes_written += x690_write_value(output, &node.value)?;
1608    Ok(bytes_written)
1609}
1610
1611/// Deconstruct an X.690-encoded element that could be primitively-constructed
1612///
1613/// The X.690 encoding rules allow for some universal types to be either
1614/// primitively-constructed or constructed. However, for the purposes of
1615/// validation or decoding, we may want to "deconstruct" such constructed
1616/// values to a single primitive value.
1617///
1618/// One such example is the `GeneralizedTime`. While it may be constructed,
1619/// it might be difficult to implement parsing and validation when it is
1620/// split across multiple X.690 tag-length-value (TLV) elements.
1621///
1622/// If the element is already primitively constructed, this just returns a
1623/// reference to it, so no copying overhead is incurred.
1624pub fn deconstruct<'a>(el: &'a X690Element) -> ASN1Result<Cow<'a, [u8]>> {
1625    match &el.value {
1626        X690Value::Primitive(bytes) => Ok(Cow::Borrowed(bytes)),
1627        X690Value::Constructed(children) => {
1628            let mut deconstructed_value = BytesMut::new();
1629            for child in children.iter() {
1630                /* Just to be clear, this is 100% intentional. In ITU X.690, it says that the substrings of a string
1631                type are to have OCTET STRING tags and it even has examples where it confirms this visually. */
1632                if child.tag.tag_class != TagClass::UNIVERSAL
1633                    || child.tag.tag_number != UNIV_TAG_OCTET_STRING
1634                {
1635                    let mut err =
1636                        ASN1Error::new(ASN1ErrorCode::string_constructed_with_invalid_tagging);
1637                    err.tag = Some(Tag::new(el.tag.tag_class, el.tag.tag_number));
1638                    err.length = Some(el.len());
1639                    err.constructed = Some(true);
1640                    return Err(err);
1641                }
1642                let deconstructed_child = deconstruct(&child)?;
1643                deconstructed_value.put(deconstructed_child.as_ref());
1644            }
1645            Ok(Cow::Owned(Vec::<u8>::from(deconstructed_value)))
1646        },
1647        X690Value::Serialized(v) => {
1648            let (_, el) = BER.decode_from_slice(&v)?;
1649            Ok(Cow::Owned(deconstruct(&el)?.into_owned()))
1650        }
1651    }
1652}
1653
1654/// Read a `BOOLEAN` value from an X.690-encoded element's content octets
1655pub const fn x690_read_boolean_value(value_bytes: ByteSlice) -> ASN1Result<BOOLEAN> {
1656    if value_bytes.len() != 1 {
1657        let err = ASN1Error::new(ASN1ErrorCode::x690_boolean_not_one_byte);
1658        return Err(err);
1659    }
1660    Ok(value_bytes[0] > 0)
1661}
1662
1663/// Read an `INTEGER` value from an X.690-encoded element's content octets
1664#[inline]
1665pub fn x690_read_integer_value(value_bytes: ByteSlice) -> ASN1Result<INTEGER> {
1666    // Intentionally not validating this. Most integers are small and correct.
1667    // If they have padding, its obvious how to handle that.
1668    Ok(Vec::from(value_bytes))
1669}
1670
1671/// Read an `i64` value from an X.690-encoded element's content octets
1672#[inline]
1673pub fn x690_read_i64_value(value_bytes: ByteSlice) -> ASN1Result<i64> {
1674    match read_i64(value_bytes) {
1675        Some(v) => Ok(v),
1676        None => Err(ASN1Error::new(ASN1ErrorCode::value_too_big)),
1677    }
1678}
1679
1680/// Read an `ENUMERATED` value from an X.690-encoded element's content octets
1681#[inline]
1682pub fn x690_read_enum_value(value_bytes: ByteSlice) -> ASN1Result<ENUMERATED> {
1683    x690_read_i64_value(value_bytes)
1684}
1685
1686/// Read an `OBJECT IDENTIFIER` value from an X.690-encoded element's content octets
1687#[inline]
1688pub fn x690_read_object_identifier_value(value_bytes: ByteSlice) -> ASN1Result<OBJECT_IDENTIFIER> {
1689    OBJECT_IDENTIFIER::from_x690_encoding_slice(value_bytes)
1690}
1691
1692/// Read a `RELATIVE-OID` value from an X.690-encoded element's content octets
1693#[inline]
1694pub fn x690_read_relative_oid_value(value_bytes: ByteSlice) -> ASN1Result<RELATIVE_OID> {
1695    RELATIVE_OID::from_x690_encoding_slice(value_bytes)
1696}
1697
1698/// Read a `DATE` value from an X.690-encoded element's content octets
1699#[inline]
1700pub fn x690_read_date_value(value_bytes: ByteSlice) -> ASN1Result<DATE> {
1701    DATE::try_from(value_bytes)
1702}
1703
1704/// Read a `TIME-OF-DAY` value from an X.690-encoded element's content octets
1705#[inline]
1706pub fn x690_read_time_of_day_value(value_bytes: ByteSlice) -> ASN1Result<TIME_OF_DAY> {
1707    TIME_OF_DAY::try_from(value_bytes)
1708}
1709
1710/// Read a `DATE-TIME` value from an X.690-encoded element's content octets
1711#[inline]
1712pub fn x690_read_date_time_value(value_bytes: ByteSlice) -> ASN1Result<DATE_TIME> {
1713    DATE_TIME::try_from(value_bytes)
1714}
1715
1716/// Read a `DURATION` value from an X.690-encoded element's content octets
1717#[inline]
1718pub fn x690_read_duration_value(value_bytes: ByteSlice) -> ASN1Result<DURATION> {
1719    DURATION::try_from(value_bytes)
1720}
1721
1722/// A trait for relating an X.690-encoded element to something
1723pub trait RelateTLV {
1724
1725    /// Relate something to an X.690-encoded tag-length-value (TLV) element
1726    fn relate_tlv (&mut self, el: &X690Element);
1727}
1728
1729impl RelateTLV for ASN1Error {
1730    fn relate_tlv (&mut self, el: &X690Element) {
1731        self.tag = Some(el.tag);
1732        self.constructed = Some(el.is_constructed());
1733        self.length = Some(el.len());
1734    }
1735}
1736
1737/// The Root Component Type List (RCTL) #1 for the X.690-specific encoding of
1738/// an `EXTERNAL` value as described in ITU Recommendation X.690, Section 8.18.
1739///
1740/// For reference, the full ASN.1 for this is:
1741///
1742/// ```asn1
1743/// [UNIVERSAL 8] IMPLICIT SEQUENCE {
1744///     direct-reference        OBJECT IDENTIFIER OPTIONAL,
1745///     indirect-reference      INTEGER OPTIONAL,
1746///     data-value-descriptor   ObjectDescriptor OPTIONAL,
1747///     encoding CHOICE {
1748///         single-ASN1-type    [0] ABSTRACT-SYNTAX.&Type,
1749///         octet-aligned       [1] IMPLICIT OCTET STRING,
1750///         arbitrary           [2] IMPLICIT BIT STRING } }
1751/// ```
1752pub const _RCTL1_FOR_EXTERNAL: &[ComponentSpec; 4] = &[
1753    ComponentSpec::new(
1754        "direct-reference",
1755        true,
1756        TagSelector::tag((
1757            TagClass::UNIVERSAL,
1758            UNIV_TAG_OBJECT_IDENTIFIER,
1759        )),
1760        None,
1761        None,
1762    ),
1763    ComponentSpec::new(
1764        "indirect-reference",
1765        true,
1766        TagSelector::tag((TagClass::UNIVERSAL, UNIV_TAG_INTEGER)),
1767        None,
1768        None,
1769    ),
1770    ComponentSpec::new(
1771        "data-value-descriptor",
1772        true,
1773        TagSelector::tag((
1774            TagClass::UNIVERSAL,
1775            UNIV_TAG_OBJECT_DESCRIPTOR,
1776        )),
1777        None,
1778        None,
1779    ),
1780    ComponentSpec::new(
1781        "encoding",
1782        false,
1783        TagSelector::or(&[
1784            &TagSelector::tag((TagClass::CONTEXT, 0)),
1785            &TagSelector::tag((TagClass::CONTEXT, 1)),
1786            &TagSelector::tag((TagClass::CONTEXT, 2)),
1787        ]),
1788        None,
1789        None,
1790    ),
1791];
1792
1793/// The Extended Attribute List (EAL) for the X.690-specific encoding of
1794/// an `EXTERNAL` value as described in ITU Recommendation X.690, Section 8.18.
1795/// It is empty, so this is basically just a formality.
1796pub const _EAL_FOR_EXTERNAL: &[ComponentSpec; 0] = &[];
1797
1798/// The Root Component Type List (RCTL) #2 for the X.690-specific encoding of
1799/// an `EXTERNAL` value as described in ITU Recommendation X.690, Section 8.18.
1800/// It is empty, so this is basically just a formality.
1801pub const _RCTL2_FOR_EXTERNAL: &[ComponentSpec; 0] = &[];
1802
1803#[cfg(test)]
1804mod tests {
1805
1806    use super::*;
1807    use std::sync::Arc;
1808    use wildboar_asn1::{
1809        Tag,
1810        TagClass,
1811        UNIV_TAG_OCTET_STRING,
1812        UNIV_TAG_BOOLEAN,
1813        UNIV_TAG_SEQUENCE,
1814    };
1815    use bytes::Bytes;
1816
1817    #[test]
1818    fn test_x690_write_boolean_value() {
1819        let mut output = BytesMut::new().writer();
1820        crate::x690_write_boolean_value(&mut output, &true).unwrap();
1821        crate::x690_write_boolean_value(&mut output, &false).unwrap();
1822        let output: Bytes = output.into_inner().into();
1823        assert_eq!(output.len(), 2);
1824        assert!(output.starts_with(&[0xFF, 0x00]));
1825    }
1826
1827    #[test]
1828    fn test_x690_write_integer_value() {
1829        let mut output = BytesMut::new();
1830        let mut i = 0;
1831        for value in -128i8..127i8 {
1832            let mut out = output.writer();
1833            crate::x690_write_enum_value(&mut out, &i64::from(value)).unwrap();
1834            output = out.into_inner();
1835            assert_eq!(output[i] as i8, value);
1836            i += 1;
1837        }
1838        assert_eq!(output.len(), 255);
1839    }
1840
1841    #[test]
1842    fn test_x690_write_octet_string_value() {
1843        let mut output = BytesMut::new().writer();
1844        let bytes: Vec<u8> = vec![1, 3, 5, 7, 9];
1845        crate::x690_write_octet_string_value(&mut output, &bytes).unwrap();
1846        let output: Bytes = output.into_inner().into();
1847        assert_eq!(output.len(), 5);
1848        assert!(output.starts_with(&[1, 3, 5, 7, 9]));
1849    }
1850
1851    #[test]
1852    fn test_x690_write_object_identifier_value() {
1853        let mut output = BytesMut::new().writer();
1854        let oid = wildboar_asn1::OBJECT_IDENTIFIER::try_from(vec![2u32, 5, 4, 3]).unwrap();
1855        crate::x690_write_object_identifier_value(&mut output, &oid).unwrap();
1856        let output: Bytes = output.into_inner().into();
1857        assert_eq!(output.len(), 3);
1858        assert!(output.starts_with(&[0x55, 0x04, 0x03]));
1859    }
1860
1861    #[test]
1862    fn test_x690_write_object_descriptor_value() {
1863        let mut output = BytesMut::new().writer();
1864        let value = String::from("commonName");
1865        crate::x690_write_object_descriptor_value(&mut output, &value).unwrap();
1866        let output: Bytes = output.into_inner().into();
1867        assert_eq!(output.len(), value.len());
1868        assert_eq!(
1869            String::from_utf8(output.into()).unwrap(),
1870            String::from("commonName")
1871        );
1872    }
1873
1874    #[test]
1875    fn test_x690_write_real_value() {
1876        let output = BytesMut::new();
1877        let value = 1.2345;
1878        crate::x690_write_real_value(&mut output.writer(), &value).unwrap();
1879    }
1880
1881    #[test]
1882    fn test_constructed_encoding() {
1883        let asn1_data = X690Element::new(
1884            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_SEQUENCE),
1885            crate::X690Value::Constructed(Arc::new(vec![
1886                X690Element::new(
1887                    Tag::new(TagClass::UNIVERSAL, UNIV_TAG_BOOLEAN),
1888                    crate::X690Value::Primitive(Bytes::copy_from_slice(&[ 0xFF ])),
1889                ),
1890                X690Element::new(
1891                    Tag::new(TagClass::UNIVERSAL, UNIV_TAG_INTEGER),
1892                    crate::X690Value::Primitive(Bytes::copy_from_slice(&[ 0x01, 0x03 ])),
1893                ),
1894            ])),
1895        );
1896        let mut output = Vec::new();
1897        match x690_write_tlv(&mut output, &asn1_data) {
1898            Ok(bytes_written) => {
1899                assert_eq!(bytes_written, 9);
1900            }
1901            Err(e) => panic!("{}", e),
1902        }
1903        assert!(output.starts_with(&[
1904            X690_TAG_CLASS_UNIVERSAL
1905            | 0b0010_0000 // Constructed
1906            | UNIV_TAG_SEQUENCE as u8,
1907            0x07,
1908            0x01,
1909            0x01,
1910            0xFF,
1911            0x02,
1912            0x02,
1913            0x01,
1914            0x03,
1915        ]));
1916    }
1917
1918    #[test]
1919    fn test_ber_decode_definite_short() {
1920        let encoded_data: Vec<u8> = vec![
1921            X690_TAG_CLASS_UNIVERSAL
1922            | 0b0010_0000 // Constructed
1923            | UNIV_TAG_SEQUENCE as u8,
1924            0x06,
1925            0x01,
1926            0x01,
1927            0xFF,
1928            0x02,
1929            0x01,
1930            0x7F,
1931        ];
1932        match BER.decode_from_slice(encoded_data.as_slice()) {
1933            Ok((bytes_read, el)) => {
1934                assert_eq!(bytes_read, 8);
1935                assert_eq!(el.tag.tag_class, TagClass::UNIVERSAL);
1936                assert_eq!(el.tag.tag_number, UNIV_TAG_SEQUENCE);
1937                if let X690Value::Constructed(children) = el.value {
1938                    assert_eq!(children.len(), 2);
1939                    assert_eq!(children[0].tag.tag_class, TagClass::UNIVERSAL);
1940                    assert_eq!(children[1].tag.tag_class, TagClass::UNIVERSAL);
1941                    assert_eq!(children[0].tag.tag_number, UNIV_TAG_BOOLEAN);
1942                    assert_eq!(children[1].tag.tag_number, UNIV_TAG_INTEGER);
1943                } else {
1944                    panic!("Decoded non-constructed.");
1945                }
1946            }
1947            Err(e) => panic!("{}", e),
1948        };
1949    }
1950
1951    #[test]
1952    fn test_ber_decode_indefinite() {
1953        let encoded_data: Vec<u8> = vec![
1954            X690_TAG_CLASS_UNIVERSAL
1955            | 0b0010_0000 // Constructed
1956            | UNIV_TAG_SEQUENCE as u8,
1957            0x80, // Indefinite length
1958            0x01,
1959            0x01,
1960            0xFF,
1961            0x02,
1962            0x01,
1963            0x7F,
1964            0x00, // End of content
1965            0x00,
1966        ];
1967        match BER.decode_from_slice(encoded_data.as_slice()) {
1968            Ok((bytes_read, el)) => {
1969                assert_eq!(bytes_read, 10);
1970                assert_eq!(el.tag.tag_class, TagClass::UNIVERSAL);
1971                assert_eq!(el.tag.tag_number, UNIV_TAG_SEQUENCE);
1972                if let X690Value::Constructed(children) = el.value {
1973                    assert_eq!(children.len(), 2);
1974                    assert_eq!(children[0].tag.tag_class, TagClass::UNIVERSAL);
1975                    assert_eq!(children[1].tag.tag_class, TagClass::UNIVERSAL);
1976                    assert_eq!(children[0].tag.tag_number, UNIV_TAG_BOOLEAN);
1977                    assert_eq!(children[1].tag.tag_number, UNIV_TAG_INTEGER);
1978                } else {
1979                    panic!("Decoded non-constructed.");
1980                }
1981            }
1982            Err(e) => panic!("{}", e),
1983        };
1984    }
1985
1986    #[test]
1987    fn test_deconstruct_primitive() {
1988        // Test deconstructing a primitive value
1989        let bytes = Bytes::copy_from_slice(&[0x01, 0x02, 0x03, 0x04]);
1990        let element = X690Element::new(
1991            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
1992            X690Value::Primitive(bytes.clone()),
1993        );
1994
1995        let result = deconstruct(&element).unwrap();
1996        assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
1997        // Should be borrowed since it's a primitive
1998        assert!(matches!(result, Cow::Borrowed(_)));
1999    }
2000
2001    #[test]
2002    fn test_deconstruct_constructed_valid() {
2003        // Test deconstructing a constructed value with valid OCTET STRING children
2004        let child1 = X690Element::new(
2005            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2006            X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2007        );
2008        let child2 = X690Element::new(
2009            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2010            X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2011        );
2012
2013        let element = X690Element::new(
2014            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2015            X690Value::Constructed(Arc::new(vec![child1, child2])),
2016        );
2017
2018        let result = deconstruct(&element).unwrap();
2019        assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2020        // Should be owned since it's constructed
2021        assert!(matches!(result, Cow::Owned(_)));
2022    }
2023
2024    #[test]
2025    fn test_deconstruct_constructed_invalid_tag_class() {
2026        // Test deconstructing a constructed value with invalid tag class
2027        let child = X690Element::new(
2028            Tag::new(TagClass::APPLICATION, UNIV_TAG_OCTET_STRING), // Wrong tag class
2029            X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2030        );
2031
2032        let element = X690Element::new(
2033            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2034            X690Value::Constructed(Arc::new(vec![child])),
2035        );
2036
2037        let result = deconstruct(&element);
2038        assert!(result.is_err());
2039        let err = result.unwrap_err();
2040        assert_eq!(err.error_code, ASN1ErrorCode::string_constructed_with_invalid_tagging);
2041    }
2042
2043    #[test]
2044    fn test_deconstruct_constructed_invalid_tag_number() {
2045        // Test deconstructing a constructed value with invalid tag number
2046        let child = X690Element::new(
2047            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_INTEGER), // Wrong tag number
2048            X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2049        );
2050
2051        let element = X690Element::new(
2052            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2053            X690Value::Constructed(Arc::new(vec![child])),
2054        );
2055
2056        let result = deconstruct(&element);
2057        assert!(result.is_err());
2058        let err = result.unwrap_err();
2059        assert_eq!(err.error_code, ASN1ErrorCode::string_constructed_with_invalid_tagging);
2060    }
2061
2062    #[test]
2063    fn test_deconstruct_constructed_nested() {
2064        // Test deconstructing a constructed value with nested constructed children
2065        let grandchild1 = X690Element::new(
2066            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2067            X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2068        );
2069        let grandchild2 = X690Element::new(
2070            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2071            X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2072        );
2073
2074        let child = X690Element::new(
2075            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2076            X690Value::Constructed(Arc::new(vec![grandchild1, grandchild2])),
2077        );
2078
2079        let element = X690Element::new(
2080            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2081            X690Value::Constructed(Arc::new(vec![child])),
2082        );
2083
2084        let result = deconstruct(&element).unwrap();
2085        assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2086    }
2087
2088    #[test]
2089    fn test_deconstruct_constructed_empty() {
2090        // Test deconstructing a constructed value with no children
2091        let element = X690Element::new(
2092            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2093            X690Value::Constructed(Arc::new(vec![])),
2094        );
2095
2096        let result = deconstruct(&element).unwrap();
2097        let empty: [u8; 0] = [];
2098        assert_eq!(result.as_ref(), &empty);
2099    }
2100
2101    #[test]
2102    fn test_deconstruct_serialized() {
2103        // Test deconstructing a serialized value
2104        let inner_bytes = Bytes::copy_from_slice(&[0x01, 0x02, 0x03, 0x04]);
2105        let inner_element = X690Element::new(
2106            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2107            X690Value::Primitive(inner_bytes),
2108        );
2109
2110        // Create a serialized version by encoding the inner element
2111        let mut serialized = Vec::new();
2112        x690_write_tlv(&mut serialized, &inner_element).unwrap();
2113
2114        let element = X690Element::new(
2115            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2116            X690Value::Serialized(Bytes::copy_from_slice(&serialized)),
2117        );
2118
2119        let result = deconstruct(&element).unwrap();
2120        assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2121        // Should be owned since it's serialized
2122        assert!(matches!(result, Cow::Owned(_)));
2123    }
2124
2125    #[test]
2126    fn test_deconstruct_serialized_constructed() {
2127        // Test deconstructing a serialized constructed value
2128        let child1 = X690Element::new(
2129            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2130            X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2131        );
2132        let child2 = X690Element::new(
2133            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2134            X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2135        );
2136
2137        let inner_element = X690Element::new(
2138            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2139            X690Value::Constructed(Arc::new(vec![child1, child2])),
2140        );
2141
2142        // Create a serialized version by encoding the inner element
2143        let mut serialized = Vec::new();
2144        x690_write_tlv(&mut serialized, &inner_element).unwrap();
2145
2146        let element = X690Element::new(
2147            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2148            X690Value::Serialized(Bytes::copy_from_slice(&serialized)),
2149        );
2150
2151        let result = deconstruct(&element).unwrap();
2152        assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2153    }
2154
2155    #[test]
2156    fn test_deconstruct_mixed_constructed() {
2157        // Test deconstructing a constructed value with mixed primitive and constructed children
2158        let primitive_child = X690Element::new(
2159            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2160            X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2161        );
2162
2163        let grandchild1 = X690Element::new(
2164            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2165            X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2166        );
2167        let grandchild2 = X690Element::new(
2168            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2169            X690Value::Primitive(Bytes::copy_from_slice(&[0x05, 0x06])),
2170        );
2171
2172        let constructed_child = X690Element::new(
2173            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2174            X690Value::Constructed(Arc::new(vec![grandchild1, grandchild2])),
2175        );
2176
2177        let element = X690Element::new(
2178            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2179            X690Value::Constructed(Arc::new(vec![primitive_child, constructed_child])),
2180        );
2181
2182        let result = deconstruct(&element).unwrap();
2183        assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
2184    }
2185
2186    #[test]
2187    fn test_deconstruct_large_data() {
2188        // Test deconstructing with larger data to ensure performance
2189        let mut children = Vec::new();
2190        let mut expected = Vec::new();
2191
2192        for i in 0..100 {
2193            let data = vec![i as u8, (i + 1) as u8, (i + 2) as u8];
2194            expected.extend_from_slice(&data);
2195
2196            let child = X690Element::new(
2197                Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2198                X690Value::Primitive(Bytes::copy_from_slice(&data)),
2199            );
2200            children.push(child);
2201        }
2202
2203        let element = X690Element::new(
2204            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2205            X690Value::Constructed(Arc::new(children)),
2206        );
2207
2208        let result = deconstruct(&element).unwrap();
2209        assert_eq!(result.as_ref(), &expected);
2210    }
2211
2212    #[test]
2213    fn test_deconstruct_serialized_invalid_data() {
2214        // Test deconstructing a serialized value with invalid data
2215        let element = X690Element::new(
2216            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2217            X690Value::Serialized(Bytes::copy_from_slice(&[0x01, 0x02, 0x03])), // Invalid BER
2218        );
2219
2220        let result = deconstruct(&element);
2221        assert!(result.is_err());
2222    }
2223
2224    #[test]
2225    fn test_element_equality_1() {
2226        let element1 = X690Element::new(
2227            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2228            X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2229        );
2230        let element2 = X690Element::new(
2231            Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2232            X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2233        );
2234        assert_eq!(element1, element2);
2235    }
2236
2237}