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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
use crate::prelude::*;
/// A set of supported ASN.1 codecs. Can be used to dynamically encode types
/// into different codecs at runtime.
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum Codec {
/// X.691 — Packed Encoding Rules (Aligned)
Aper,
/// X.690 — Basic Encoding Rules
Ber,
/// X.690 — Canonical Encoding Rules
Cer,
/// X.690 — Distinguished Encoding Rules
Der,
/// X.691 — Packed Encoding Rules (Unaligned)
Uper,
/// [JSON Encoding Rules](https://obj-sys.com/docs/JSONEncodingRules.pdf)
Jer,
/// X.696 — Octet Encoding Rules
Oer,
/// X.696 — Canonical Octet Encoding Rules
Coer,
/// X.693 — XML Encoding Rules
Xer,
/// ASN.1 Value Notation (X.680 text format)
Avn,
}
impl core::fmt::Display for Codec {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Aper => write!(f, "APER"),
Self::Ber => write!(f, "BER"),
Self::Cer => write!(f, "CER"),
Self::Der => write!(f, "DER"),
Self::Uper => write!(f, "UPER"),
Self::Jer => write!(f, "JER"),
Self::Oer => write!(f, "OER"),
Self::Coer => write!(f, "COER"),
Self::Xer => write!(f, "XER"),
Self::Avn => write!(f, "AVN"),
}
}
}
impl Codec {
/// Encodes a given value based on the value of `Codec`.
/// This method shall be used when using binary-based encoding rules.
///
/// # Errors
/// - If the value fails to be encoded returns `EncodeError` struct.
pub fn encode_to_binary<T: Encode>(
self,
value: &T,
) -> Result<alloc::vec::Vec<u8>, crate::error::EncodeError> {
match self {
Self::Aper => crate::aper::encode(value),
Self::Ber => crate::ber::encode(value),
Self::Cer => crate::cer::encode(value),
Self::Der => crate::der::encode(value),
Self::Uper => crate::uper::encode(value),
Self::Jer => crate::jer::encode(value).map(alloc::string::String::into_bytes),
Self::Oer => crate::oer::encode(value),
Self::Coer => crate::coer::encode(value),
Self::Xer => crate::xer::encode(value),
Self::Avn => crate::avn::encode(value).map(alloc::string::String::into_bytes),
}
}
/// Decodes `input` to `D` based on the value of `Codec`.
/// This method shall be used when using binary-based encoding rules.
///
/// # Errors
/// - If `D` cannot be decoded from `input` returns `DecodeError` struct.
pub fn decode_from_binary<D: Decode>(
&self,
input: &[u8],
) -> Result<D, crate::error::DecodeError> {
match self {
Self::Aper => crate::aper::decode(input),
Self::Ber => crate::ber::decode(input),
Self::Cer => crate::cer::decode(input),
Self::Der => crate::der::decode(input),
Self::Uper => crate::uper::decode(input),
Self::Oer => crate::oer::decode(input),
Self::Coer => crate::coer::decode(input),
Self::Xer => crate::xer::decode(input),
Self::Jer => alloc::string::String::from_utf8(input.to_vec()).map_or_else(
|e| {
Err(crate::error::DecodeError::from_kind(
crate::error::DecodeErrorKind::Custom {
msg: alloc::format!("Failed to decode JER from UTF8 bytes: {e:?}"),
},
*self,
))
},
|s| crate::jer::decode(&s),
),
Self::Avn => alloc::string::String::from_utf8(input.to_vec()).map_or_else(
|e| {
Err(crate::error::DecodeError::from_kind(
crate::error::DecodeErrorKind::Custom {
msg: alloc::format!("Failed to decode AVN from UTF8 bytes: {e:?}"),
},
*self,
))
},
|s| crate::avn::decode(&s),
),
}
}
/// Decodes `input` to `D` based on the encoded defined by `Codec`, returning the decoded value and the remaining input.
pub fn decode_from_binary_with_remainder<'input, D: Decode>(
&self,
input: &'input [u8],
) -> Result<(D, &'input [u8]), crate::error::DecodeError> {
match self {
Self::Aper => crate::aper::decode_with_remainder(input),
Self::Ber => crate::ber::decode_with_remainder(input),
Self::Cer => crate::cer::decode_with_remainder(input),
Self::Der => crate::der::decode_with_remainder(input),
Self::Uper => crate::uper::decode_with_remainder(input),
Self::Oer => crate::oer::decode_with_remainder(input),
Self::Coer => crate::coer::decode_with_remainder(input),
Self::Xer => Err(crate::error::DecodeError::from_kind(
crate::error::DecodeErrorKind::Custom {
msg: "XER does not support decoding with remainder. ".into(),
},
*self,
)),
Self::Jer => Err(crate::error::DecodeError::from_kind(
crate::error::DecodeErrorKind::Custom {
msg: "JER does not support decoding with remainder. ".into(),
},
*self,
)),
Self::Avn => Err(crate::error::DecodeError::from_kind(
crate::error::DecodeErrorKind::Custom {
msg: "AVN does not support decoding with remainder. ".into(),
},
*self,
)),
}
}
/// Encodes a given value based on the value of `Codec`.
/// This method shall be used when using text-based encoding rules.
///
/// # Errors
/// - If the value fails to be encoded, or if trying to encode using
/// binary-based encoding rules, returns `EncodeError` struct.
pub fn encode_to_string<T: Encode>(
self,
value: &T,
) -> Result<alloc::string::String, crate::error::EncodeError> {
match self {
Self::Jer => crate::jer::encode(value),
Self::Avn => crate::avn::encode(value),
codec => Err(crate::error::EncodeError::from_kind(
crate::error::EncodeErrorKind::Custom {
msg: alloc::format!(
"{codec} is a binary-based encoding. Call `Codec::encode_to_binary` instead."
),
},
codec,
)),
}
}
/// Decodes `input` to `D` based on the value of `Codec`.
/// This method shall be used when using text-based encoding rules.
///
/// # Errors
/// - If `D` cannot be decoded from `input`, or if trying to decode using
/// binary-based encoding rules, returns `DecodeError` struct.
pub fn decode_from_str<D: Decode>(&self, input: &str) -> Result<D, crate::error::DecodeError> {
match self {
Self::Jer => crate::jer::decode(input),
Self::Avn => crate::avn::decode(input),
codec => Err(crate::error::DecodeError::from_kind(
crate::error::DecodeErrorKind::Custom {
msg: alloc::format!(
"{codec} is a binary-based encoding. Call `Codec::decode_from_binary` instead."
),
},
*codec,
)),
}
}
}