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
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,
}
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"),
}
}
}
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),
}
}
/// 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::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.clone(),
))
},
|s| crate::jer::decode(&s),
),
}
}
/// 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),
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),
codec => Err(crate::error::DecodeError::from_kind(
crate::error::DecodeErrorKind::Custom {
msg: alloc::format!("{codec} is a text-based encoding. Call `Codec::decode_from_binary` instead."),
},
codec.clone(),
)),
}
}
}