rasn/
codec.rs

1use crate::prelude::*;
2
3/// A set of supported ASN.1 codecs. Can be used to dynamically encode types
4/// into different codecs at runtime.
5#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
6#[non_exhaustive]
7pub enum Codec {
8    /// X.691 — Packed Encoding Rules (Aligned)
9    Aper,
10    /// X.690 — Basic Encoding Rules
11    Ber,
12    /// X.690 — Canonical Encoding Rules
13    Cer,
14    /// X.690 — Distinguished Encoding Rules
15    Der,
16    /// X.691 — Packed Encoding Rules (Unaligned)
17    Uper,
18    /// [JSON Encoding Rules](https://obj-sys.com/docs/JSONEncodingRules.pdf)
19    Jer,
20    /// X.696 — Octet Encoding Rules
21    Oer,
22    /// X.696 — Canonical Octet Encoding Rules
23    Coer,
24}
25
26impl core::fmt::Display for Codec {
27    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
28        match self {
29            Self::Aper => write!(f, "APER"),
30            Self::Ber => write!(f, "BER"),
31            Self::Cer => write!(f, "CER"),
32            Self::Der => write!(f, "DER"),
33            Self::Uper => write!(f, "UPER"),
34            Self::Jer => write!(f, "JER"),
35            Self::Oer => write!(f, "OER"),
36            Self::Coer => write!(f, "COER"),
37        }
38    }
39}
40
41impl Codec {
42    /// Encodes a given value based on the value of `Codec`.
43    /// This method shall be used when using binary-based encoding rules.
44    ///
45    /// # Errors
46    /// - If the value fails to be encoded returns `EncodeError` struct.
47    pub fn encode_to_binary<T: Encode>(
48        self,
49        value: &T,
50    ) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
51        match self {
52            Self::Aper => crate::aper::encode(value),
53            Self::Ber => crate::ber::encode(value),
54            Self::Cer => crate::cer::encode(value),
55            Self::Der => crate::der::encode(value),
56            Self::Uper => crate::uper::encode(value),
57            Self::Jer => crate::jer::encode(value).map(alloc::string::String::into_bytes),
58            Self::Oer => crate::oer::encode(value),
59            Self::Coer => crate::coer::encode(value),
60        }
61    }
62
63    /// Decodes `input` to `D` based on the value of `Codec`.
64    /// This method shall be used when using binary-based encoding rules.
65    ///
66    /// # Errors
67    /// - If `D` cannot be decoded from `input` returns `DecodeError` struct.
68    pub fn decode_from_binary<D: Decode>(
69        &self,
70        input: &[u8],
71    ) -> Result<D, crate::error::DecodeError> {
72        match self {
73            Self::Aper => crate::aper::decode(input),
74            Self::Ber => crate::ber::decode(input),
75            Self::Cer => crate::cer::decode(input),
76            Self::Der => crate::der::decode(input),
77            Self::Uper => crate::uper::decode(input),
78            Self::Oer => crate::oer::decode(input),
79            Self::Coer => crate::coer::decode(input),
80            Self::Jer => alloc::string::String::from_utf8(input.to_vec()).map_or_else(
81                |e| {
82                    Err(crate::error::DecodeError::from_kind(
83                        crate::error::DecodeErrorKind::Custom {
84                            msg: alloc::format!("Failed to decode JER from UTF8 bytes: {e:?}"),
85                        },
86                        *self,
87                    ))
88                },
89                |s| crate::jer::decode(&s),
90            ),
91        }
92    }
93
94    /// Encodes a given value based on the value of `Codec`.
95    /// This method shall be used when using text-based encoding rules.
96    ///
97    /// # Errors
98    /// - If the value fails to be encoded, or if trying to encode using
99    ///   binary-based encoding rules, returns `EncodeError` struct.
100    pub fn encode_to_string<T: Encode>(
101        self,
102        value: &T,
103    ) -> Result<alloc::string::String, crate::error::EncodeError> {
104        match self {
105            Self::Jer => crate::jer::encode(value),
106            codec => Err(crate::error::EncodeError::from_kind(
107                crate::error::EncodeErrorKind::Custom {
108                    msg: alloc::format!("{codec} is a binary-based encoding. Call `Codec::encode_to_binary` instead."),
109                },
110                codec,
111            )),
112        }
113    }
114
115    /// Decodes `input` to `D` based on the value of `Codec`.
116    /// This method shall be used when using text-based encoding rules.
117    ///
118    /// # Errors
119    /// - If `D` cannot be decoded from `input`, or if trying to decode using
120    ///   binary-based encoding rules, returns `DecodeError` struct.
121    pub fn decode_from_str<D: Decode>(&self, input: &str) -> Result<D, crate::error::DecodeError> {
122        match self {
123            Self::Jer => crate::jer::decode(input),
124            codec => Err(crate::error::DecodeError::from_kind(
125                crate::error::DecodeErrorKind::Custom {
126                    msg: alloc::format!("{codec} is a text-based encoding. Call `Codec::decode_from_binary` instead."),
127                },
128                *codec,
129            )),
130        }
131    }
132}