#[cfg(not(feature = "std"))]
use alloc::{
string::{String, ToString},
vec::Vec,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OctetString {
bytes: Vec<u8>,
}
impl OctetString {
pub fn new(bytes: Vec<u8>) -> Self {
Self { bytes }
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn into_vec(self) -> Vec<u8> {
self.bytes
}
}
impl From<Vec<u8>> for OctetString {
fn from(bytes: Vec<u8>) -> Self {
Self::new(bytes)
}
}
impl From<OctetString> for Vec<u8> {
fn from(s: OctetString) -> Self {
s.into_vec()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OctetStringRef<'a> {
bytes: &'a [u8],
}
impl<'a> OctetStringRef<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
Self { bytes }
}
pub fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
pub fn to_owned(&self) -> OctetString {
OctetString::new(self.bytes.to_vec())
}
}
impl crate::traits::Decode<'_> for OctetString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_OCTET_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_OCTET_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
Ok(OctetString::new(bytes.to_vec()))
}
}
impl<'a> crate::traits::Decode<'a> for OctetStringRef<'a> {
fn decode(decoder: &mut crate::der::decoder::Decoder<'a>) -> crate::Result<Self> {
use crate::tag::TAG_OCTET_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_OCTET_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?; Ok(OctetStringRef::new(bytes))
}
}
impl<'a> crate::traits::Encode for OctetStringRef<'a> {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_OCTET_STRING;
let tag = crate::Tag::universal(TAG_OCTET_STRING);
encoder.write_tag(tag)?;
encoder.write_length(self.bytes.len())?;
encoder.write_bytes(self.bytes);
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let length_len = crate::Length::Definite(self.bytes.len()).encoded_len()?;
Ok(tag_len + length_len + self.bytes.len())
}
}
impl<'a> crate::traits::Tagged for OctetStringRef<'a> {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_OCTET_STRING)
}
}
impl<'a> crate::traits::DecodeImplicit<'a> for OctetStringRef<'a> {
fn decode_implicit(content: &'a [u8], _encoding: crate::Encoding) -> crate::Result<Self> {
Ok(OctetStringRef::new(content))
}
}
impl crate::traits::Encode for OctetString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_OCTET_STRING;
let tag = crate::Tag::universal(TAG_OCTET_STRING);
encoder.write_tag(tag)?;
encoder.write_length(self.bytes.len())?;
encoder.write_bytes(&self.bytes);
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let length_len = crate::Length::Definite(self.bytes.len()).encoded_len()?;
Ok(tag_len + length_len + self.bytes.len())
}
}
impl crate::traits::Tagged for OctetString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_OCTET_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BitString {
bytes: Vec<u8>,
unused_bits: u8,
}
impl BitString {
pub fn new(bytes: Vec<u8>, unused_bits: u8) -> crate::Result<Self> {
if unused_bits > 7 {
return Err(crate::Error::InvalidEncoding {
position: 0,
tag: crate::Tag::universal(crate::tag::TAG_BIT_STRING),
#[cfg(feature = "std")]
reason: format!("Invalid unused bits value: {}", unused_bits),
#[cfg(not(feature = "std"))]
reason: "Invalid unused bits value",
});
}
if !bytes.is_empty() && unused_bits > 0 {
let last_byte = bytes[bytes.len() - 1];
let mask = (1u8 << unused_bits) - 1;
if (last_byte & mask) != 0 {
return Err(crate::Error::DerViolation {
position: 0,
#[cfg(feature = "std")]
reason: "Unused bits in last byte must be zero".to_string(),
#[cfg(not(feature = "std"))]
reason: "Unused bits in last byte must be zero",
});
}
}
Ok(Self { bytes, unused_bits })
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn unused_bits(&self) -> u8 {
self.unused_bits
}
pub fn bit_len(&self) -> usize {
if self.bytes.is_empty() {
0
} else {
self.bytes.len() * 8 - self.unused_bits as usize
}
}
}
impl crate::traits::Decode<'_> for BitString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_BIT_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_BIT_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
if len == 0 {
return Err(crate::Error::InvalidEncoding {
position: decoder.position(),
tag,
#[cfg(feature = "std")]
reason: "BIT STRING length cannot be 0".to_string(),
#[cfg(not(feature = "std"))]
reason: "BIT STRING length cannot be 0",
});
}
let bytes = decoder.read_bytes(len)?;
let unused_bits = bytes[0];
if unused_bits > 7 {
return Err(crate::Error::InvalidEncoding {
position: decoder.position(),
tag,
#[cfg(feature = "std")]
reason: format!("Invalid unused bits value: {}", unused_bits),
#[cfg(not(feature = "std"))]
reason: "Invalid unused bits value",
});
}
if decoder.encoding() == crate::Encoding::Der && len > 1 && unused_bits > 0 {
let last_byte = bytes[len - 1];
let mask = (1u8 << unused_bits) - 1;
if (last_byte & mask) != 0 {
return Err(crate::Error::DerViolation {
position: decoder.position(),
#[cfg(feature = "std")]
reason: "Unused bits in last byte must be zero".to_string(),
#[cfg(not(feature = "std"))]
reason: "Unused bits in last byte must be zero",
});
}
}
Ok(BitString {
bytes: bytes[1..].to_vec(),
unused_bits,
})
}
}
impl crate::traits::Encode for BitString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_BIT_STRING;
let tag = crate::Tag::universal(TAG_BIT_STRING);
encoder.write_tag(tag)?;
encoder.write_length(1 + self.bytes.len())?;
encoder.write_bytes(&[self.unused_bits]);
encoder.write_bytes(&self.bytes);
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let content_len = 1 + self.bytes.len();
let length_len = crate::Length::Definite(content_len).encoded_len()?;
Ok(tag_len + length_len + content_len)
}
}
impl crate::traits::Tagged for BitString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_BIT_STRING)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BitStringRef<'a> {
bytes: &'a [u8],
unused_bits: u8,
}
impl<'a> BitStringRef<'a> {
pub fn new(bytes: &'a [u8], unused_bits: u8) -> crate::Result<Self> {
if unused_bits > 7 {
return Err(crate::Error::InvalidEncoding {
position: 0,
tag: crate::Tag::universal(crate::tag::TAG_BIT_STRING),
#[cfg(feature = "std")]
reason: format!("Invalid unused bits value: {}", unused_bits),
#[cfg(not(feature = "std"))]
reason: "Invalid unused bits value",
});
}
if !bytes.is_empty() && unused_bits > 0 {
let last_byte = bytes[bytes.len() - 1];
let mask = (1u8 << unused_bits) - 1;
if (last_byte & mask) != 0 {
return Err(crate::Error::DerViolation {
position: 0,
#[cfg(feature = "std")]
reason: "Unused bits in last byte must be zero".to_string(),
#[cfg(not(feature = "std"))]
reason: "Unused bits in last byte must be zero",
});
}
}
Ok(Self { bytes, unused_bits })
}
pub fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
pub fn unused_bits(&self) -> u8 {
self.unused_bits
}
pub fn bit_len(&self) -> usize {
if self.bytes.is_empty() {
0
} else {
self.bytes.len() * 8 - self.unused_bits as usize
}
}
pub fn to_owned(&self) -> BitString {
BitString::new(self.bytes.to_vec(), self.unused_bits).unwrap()
}
}
impl<'a> crate::traits::Decode<'a> for BitStringRef<'a> {
fn decode(decoder: &mut crate::der::decoder::Decoder<'a>) -> crate::Result<Self> {
use crate::tag::TAG_BIT_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_BIT_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
if len == 0 {
return Err(crate::Error::InvalidEncoding {
position: decoder.position(),
tag,
#[cfg(feature = "std")]
reason: "BIT STRING length cannot be 0".to_string(),
#[cfg(not(feature = "std"))]
reason: "BIT STRING length cannot be 0",
});
}
let bytes = decoder.read_bytes(len)?;
let unused_bits = bytes[0];
if unused_bits > 7 {
return Err(crate::Error::InvalidEncoding {
position: decoder.position(),
tag,
#[cfg(feature = "std")]
reason: format!("Invalid unused bits value: {}", unused_bits),
#[cfg(not(feature = "std"))]
reason: "Invalid unused bits value",
});
}
if decoder.encoding() == crate::Encoding::Der && len > 1 && unused_bits > 0 {
let last_byte = bytes[len - 1];
let mask = (1u8 << unused_bits) - 1;
if (last_byte & mask) != 0 {
return Err(crate::Error::DerViolation {
position: decoder.position(),
#[cfg(feature = "std")]
reason: "Unused bits in last byte must be zero".to_string(),
#[cfg(not(feature = "std"))]
reason: "Unused bits in last byte must be zero",
});
}
}
Ok(BitStringRef {
bytes: &bytes[1..], unused_bits,
})
}
}
impl<'a> crate::traits::Encode for BitStringRef<'a> {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_BIT_STRING;
let tag = crate::Tag::universal(TAG_BIT_STRING);
encoder.write_tag(tag)?;
encoder.write_length(1 + self.bytes.len())?;
encoder.write_bytes(&[self.unused_bits]);
encoder.write_bytes(self.bytes);
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let content_len = 1 + self.bytes.len();
let length_len = crate::Length::Definite(content_len).encoded_len()?;
Ok(tag_len + length_len + content_len)
}
}
impl<'a> crate::traits::Tagged for BitStringRef<'a> {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_BIT_STRING)
}
}
impl<'a> crate::traits::DecodeImplicit<'a> for BitStringRef<'a> {
fn decode_implicit(content: &'a [u8], _encoding: crate::Encoding) -> crate::Result<Self> {
if content.is_empty() {
return Err(crate::Error::UnexpectedEof { position: 0 });
}
let unused_bits = content[0];
BitStringRef::new(&content[1..], unused_bits)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Utf8String(pub String);
impl Utf8String {
pub fn new(s: String) -> Self {
Self(s)
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
impl From<String> for Utf8String {
fn from(s: String) -> Self {
Self::new(s)
}
}
impl From<Utf8String> for String {
fn from(s: Utf8String) -> Self {
s.into_string()
}
}
impl crate::traits::Decode<'_> for Utf8String {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_UTF8_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_UTF8_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
let s = core::str::from_utf8(bytes).map_err(|_| crate::Error::InvalidString {
position: decoder.position(),
string_type: "UTF8String",
#[cfg(feature = "std")]
reason: "Invalid UTF-8 encoding".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid UTF-8 encoding",
})?;
Ok(Utf8String::new(s.to_string()))
}
}
impl crate::traits::Encode for Utf8String {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_UTF8_STRING;
let tag = crate::Tag::universal(TAG_UTF8_STRING);
encoder.write_tag(tag)?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(self.0.as_bytes());
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(tag_len + length_len + self.0.len())
}
}
impl crate::traits::Tagged for Utf8String {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_UTF8_STRING)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Utf8StringRef<'a>(&'a str);
impl<'a> Utf8StringRef<'a> {
pub fn new(s: &'a str) -> Self {
Self(s)
}
pub fn as_str(&self) -> &'a str {
self.0
}
pub fn to_owned(&self) -> Utf8String {
Utf8String::new(self.0.to_string())
}
}
impl<'a> crate::traits::Decode<'a> for Utf8StringRef<'a> {
fn decode(decoder: &mut crate::der::decoder::Decoder<'a>) -> crate::Result<Self> {
use crate::tag::TAG_UTF8_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_UTF8_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
let s = core::str::from_utf8(bytes).map_err(|_| crate::Error::InvalidString {
position: decoder.position(),
string_type: "UTF8String",
#[cfg(feature = "std")]
reason: "Invalid UTF-8 encoding".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid UTF-8 encoding",
})?;
Ok(Utf8StringRef::new(s))
}
}
impl<'a> crate::traits::Encode for Utf8StringRef<'a> {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_UTF8_STRING;
let tag = crate::Tag::universal(TAG_UTF8_STRING);
encoder.write_tag(tag)?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(self.0.as_bytes());
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(tag_len + length_len + self.0.len())
}
}
impl<'a> crate::traits::Tagged for Utf8StringRef<'a> {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_UTF8_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PrintableString(pub String);
impl PrintableString {
pub fn new(s: String) -> crate::Result<Self> {
if !Self::is_valid(&s) {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "PrintableString",
#[cfg(feature = "std")]
reason: "String contains invalid characters for PrintableString".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid characters for PrintableString",
});
}
Ok(Self(s))
}
fn is_valid(s: &str) -> bool {
s.chars().all(|c| {
matches!(c,
'A'..='Z' | 'a'..='z' | '0'..='9' |
' ' | '\'' | '(' | ')' | '+' | ',' | '-' | '.' | '/' | ':' | '=' | '?'
)
})
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
impl crate::traits::Decode<'_> for PrintableString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_PRINTABLE_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_PRINTABLE_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
let s = core::str::from_utf8(bytes).map_err(|_| crate::Error::InvalidString {
position: decoder.position(),
string_type: "PrintableString",
#[cfg(feature = "std")]
reason: "Invalid UTF-8/ASCII encoding".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid UTF-8/ASCII encoding",
})?;
if !PrintableString::is_valid(s) {
return Err(crate::Error::InvalidString {
position: decoder.position(),
string_type: "PrintableString",
#[cfg(feature = "std")]
reason: "String contains invalid characters for PrintableString".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid characters for PrintableString",
});
}
Ok(PrintableString(s.to_string()))
}
}
impl crate::traits::Encode for PrintableString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_PRINTABLE_STRING;
let tag = crate::Tag::universal(TAG_PRINTABLE_STRING);
encoder.write_tag(tag)?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(self.0.as_bytes());
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(tag_len + length_len + self.0.len())
}
}
impl crate::traits::Tagged for PrintableString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_PRINTABLE_STRING)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PrintableStringRef<'a>(&'a str);
impl<'a> PrintableStringRef<'a> {
pub fn new(s: &'a str) -> crate::Result<Self> {
if !PrintableString::is_valid(s) {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "PrintableString",
#[cfg(feature = "std")]
reason: "String contains invalid characters for PrintableString".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid characters for PrintableString",
});
}
Ok(Self(s))
}
pub fn as_str(&self) -> &'a str {
self.0
}
pub fn to_owned(&self) -> PrintableString {
PrintableString::new(self.0.to_string()).unwrap()
}
}
impl<'a> crate::traits::Decode<'a> for PrintableStringRef<'a> {
fn decode(decoder: &mut crate::der::decoder::Decoder<'a>) -> crate::Result<Self> {
use crate::tag::TAG_PRINTABLE_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_PRINTABLE_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
let s = core::str::from_utf8(bytes).map_err(|_| crate::Error::InvalidString {
position: decoder.position(),
string_type: "PrintableString",
#[cfg(feature = "std")]
reason: "Invalid UTF-8/ASCII encoding".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid UTF-8/ASCII encoding",
})?;
if !PrintableString::is_valid(s) {
return Err(crate::Error::InvalidString {
position: decoder.position(),
string_type: "PrintableString",
#[cfg(feature = "std")]
reason: "String contains invalid characters for PrintableString".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid characters for PrintableString",
});
}
Ok(PrintableStringRef(s))
}
}
impl<'a> crate::traits::Encode for PrintableStringRef<'a> {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_PRINTABLE_STRING;
let tag = crate::Tag::universal(TAG_PRINTABLE_STRING);
encoder.write_tag(tag)?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(self.0.as_bytes());
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(tag_len + length_len + self.0.len())
}
}
impl<'a> crate::traits::Tagged for PrintableStringRef<'a> {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_PRINTABLE_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IA5String(pub String);
impl IA5String {
pub fn new(s: String) -> crate::Result<Self> {
if !s.is_ascii() {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "IA5String",
#[cfg(feature = "std")]
reason: "String contains non-ASCII characters".to_string(),
#[cfg(not(feature = "std"))]
reason: "Non-ASCII characters",
});
}
Ok(Self(s))
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
impl crate::traits::Decode<'_> for IA5String {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_IA5_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_IA5_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
let s = core::str::from_utf8(bytes).map_err(|_| crate::Error::InvalidString {
position: decoder.position(),
string_type: "IA5String",
#[cfg(feature = "std")]
reason: "Invalid UTF-8/ASCII encoding".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid UTF-8/ASCII encoding",
})?;
if !s.is_ascii() {
return Err(crate::Error::InvalidString {
position: decoder.position(),
string_type: "IA5String",
#[cfg(feature = "std")]
reason: "String contains non-ASCII characters".to_string(),
#[cfg(not(feature = "std"))]
reason: "Non-ASCII characters",
});
}
Ok(IA5String(s.to_string()))
}
}
impl crate::traits::Encode for IA5String {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_IA5_STRING;
let tag = crate::Tag::universal(TAG_IA5_STRING);
encoder.write_tag(tag)?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(self.0.as_bytes());
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(tag_len + length_len + self.0.len())
}
}
impl crate::traits::Tagged for IA5String {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_IA5_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NumericString(pub String);
impl NumericString {
pub fn new(s: String) -> crate::Result<Self> {
if !s.chars().all(|c| c.is_ascii_digit() || c == ' ') {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "NumericString",
#[cfg(feature = "std")]
reason: "String contains invalid characters for NumericString".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid characters for NumericString",
});
}
Ok(Self(s))
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
impl crate::traits::Decode<'_> for NumericString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_NUMERIC_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_NUMERIC_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
let s = core::str::from_utf8(bytes).map_err(|_| crate::Error::InvalidString {
position: decoder.position(),
string_type: "NumericString",
#[cfg(feature = "std")]
reason: "Invalid ASCII encoding".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid ASCII encoding",
})?;
NumericString::new(s.to_string())
}
}
impl crate::traits::Encode for NumericString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_NUMERIC_STRING;
encoder.write_tag(crate::Tag::universal(TAG_NUMERIC_STRING))?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(self.0.as_bytes());
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(1 + length_len + self.0.len())
}
}
impl crate::traits::Tagged for NumericString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_NUMERIC_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TeletexString(pub Vec<u8>);
impl TeletexString {
pub fn new(bytes: Vec<u8>) -> Self {
Self(bytes)
}
pub fn from_latin1(s: &str) -> crate::Result<Self> {
if s.is_ascii() {
return Ok(Self(s.as_bytes().to_vec()));
}
let mut bytes = Vec::with_capacity(s.len());
for c in s.chars() {
if c as u32 > 0xFF {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "TeletexString",
#[cfg(feature = "std")]
reason: format!(
"character U+{:04X} is outside Latin-1 range (U+0000..=U+00FF)",
c as u32
),
#[cfg(not(feature = "std"))]
reason: "character outside Latin-1 range (U+0000..=U+00FF)",
});
}
bytes.push(c as u8);
}
Ok(Self(bytes))
}
pub fn from_latin1_string(s: String) -> crate::Result<Self> {
if s.is_ascii() {
return Ok(Self(s.into_bytes()));
}
let mut bytes = Vec::with_capacity(s.len());
for c in s.chars() {
if c as u32 > 0xFF {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "TeletexString",
#[cfg(feature = "std")]
reason: format!(
"character U+{:04X} is outside Latin-1 range (U+0000..=U+00FF)",
c as u32
),
#[cfg(not(feature = "std"))]
reason: "character outside Latin-1 range (U+0000..=U+00FF)",
});
}
bytes.push(c as u8);
}
Ok(Self(bytes))
}
pub fn from_str_lossy(s: &str) -> Self {
Self(s.chars().map(|c| c as u8).collect())
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn as_latin1_string(&self) -> String {
self.0.iter().map(|&b| b as char).collect()
}
pub fn into_vec(self) -> Vec<u8> {
self.0
}
}
impl crate::traits::Decode<'_> for TeletexString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_TELETEX_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_TELETEX_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
Ok(TeletexString::new(bytes.to_vec()))
}
}
impl crate::traits::Encode for TeletexString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_TELETEX_STRING;
encoder.write_tag(crate::Tag::universal(TAG_TELETEX_STRING))?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(&self.0);
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(1 + length_len + self.0.len())
}
}
impl crate::traits::Tagged for TeletexString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_TELETEX_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VisibleString(pub String);
impl VisibleString {
pub fn new(s: String) -> crate::Result<Self> {
if !s.bytes().all(|b| (0x20..=0x7e).contains(&b)) {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "VisibleString",
#[cfg(feature = "std")]
reason: "String contains invalid characters for VisibleString".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid characters for VisibleString",
});
}
Ok(Self(s))
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
impl crate::traits::Decode<'_> for VisibleString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_VISIBLE_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_VISIBLE_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
let s = core::str::from_utf8(bytes).map_err(|_| crate::Error::InvalidString {
position: decoder.position(),
string_type: "VisibleString",
#[cfg(feature = "std")]
reason: "Invalid ASCII encoding".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid ASCII encoding",
})?;
VisibleString::new(s.to_string())
}
}
impl crate::traits::Encode for VisibleString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_VISIBLE_STRING;
encoder.write_tag(crate::Tag::universal(TAG_VISIBLE_STRING))?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(self.0.as_bytes());
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(1 + length_len + self.0.len())
}
}
impl crate::traits::Tagged for VisibleString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_VISIBLE_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GeneralString(pub Vec<u8>);
impl GeneralString {
pub fn new(bytes: Vec<u8>) -> Self {
Self(bytes)
}
pub fn from_ascii(s: &str) -> crate::Result<Self> {
if !s.is_ascii() {
let c = s.chars().find(|c| !c.is_ascii()).unwrap();
return Err(crate::Error::InvalidString {
position: 0,
string_type: "GeneralString",
#[cfg(feature = "std")]
reason: format!(
"character U+{:04X} is outside ASCII range (U+0000..=U+007F)",
c as u32
),
#[cfg(not(feature = "std"))]
reason: "character outside ASCII range (U+0000..=U+007F)",
});
}
Ok(Self(s.as_bytes().to_vec()))
}
pub fn from_ascii_string(s: String) -> crate::Result<Self> {
if !s.is_ascii() {
let c = s.chars().find(|c| !c.is_ascii()).unwrap();
return Err(crate::Error::InvalidString {
position: 0,
string_type: "GeneralString",
#[cfg(feature = "std")]
reason: format!(
"character U+{:04X} is outside ASCII range (U+0000..=U+007F)",
c as u32
),
#[cfg(not(feature = "std"))]
reason: "character outside ASCII range (U+0000..=U+007F)",
});
}
Ok(Self(s.into_bytes()))
}
pub fn from_str_lossy(s: &str) -> Self {
Self(s.chars().map(|c| c as u8).collect())
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn as_latin1_string(&self) -> String {
self.0.iter().map(|&b| b as char).collect()
}
pub fn into_vec(self) -> Vec<u8> {
self.0
}
}
impl crate::traits::Decode<'_> for GeneralString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_GENERAL_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_GENERAL_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
Ok(GeneralString::new(bytes.to_vec()))
}
}
impl crate::traits::Encode for GeneralString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_GENERAL_STRING;
encoder.write_tag(crate::Tag::universal(TAG_GENERAL_STRING))?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(&self.0);
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(1 + length_len + self.0.len())
}
}
impl crate::traits::Tagged for GeneralString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_GENERAL_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UniversalString(pub String);
impl UniversalString {
pub fn new(s: String) -> Self {
Self(s)
}
pub fn from_ucs4_be(bytes: &[u8]) -> crate::Result<Self> {
if !bytes.len().is_multiple_of(4) {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "UniversalString",
#[cfg(feature = "std")]
reason: format!("UCS-4 byte length {} is not a multiple of 4", bytes.len()),
#[cfg(not(feature = "std"))]
reason: "UCS-4 byte length is not a multiple of 4",
});
}
let mut s = String::with_capacity(bytes.len() / 4);
for chunk in bytes.chunks(4) {
let code_point = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
let c = char::from_u32(code_point).ok_or_else(|| crate::Error::InvalidString {
position: 0,
string_type: "UniversalString",
#[cfg(feature = "std")]
reason: format!("Invalid Unicode code point: U+{:04X}", code_point),
#[cfg(not(feature = "std"))]
reason: "Invalid Unicode code point",
})?;
s.push(c);
}
Ok(Self(s))
}
pub fn to_ucs4_be(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(self.0.chars().count() * 4);
for c in self.0.chars() {
bytes.extend_from_slice(&(c as u32).to_be_bytes());
}
bytes
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
impl crate::traits::Decode<'_> for UniversalString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_UNIVERSAL_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_UNIVERSAL_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
UniversalString::from_ucs4_be(bytes)
}
}
impl crate::traits::Encode for UniversalString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_UNIVERSAL_STRING;
let ucs4 = self.to_ucs4_be();
encoder.write_tag(crate::Tag::universal(TAG_UNIVERSAL_STRING))?;
encoder.write_length(ucs4.len())?;
encoder.write_bytes(&ucs4);
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let content_len = self.0.chars().count() * 4;
let length_len = crate::Length::Definite(content_len).encoded_len()?;
Ok(1 + length_len + content_len)
}
}
impl crate::traits::Tagged for UniversalString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_UNIVERSAL_STRING)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BmpString(pub String);
impl BmpString {
pub fn new(s: String) -> crate::Result<Self> {
if s.chars().any(|c| c as u32 > 0xFFFF) {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "BMPString",
#[cfg(feature = "std")]
reason: "String contains characters outside the Basic Multilingual Plane"
.to_string(),
#[cfg(not(feature = "std"))]
reason: "Character outside BMP",
});
}
Ok(Self(s))
}
pub fn from_ucs2_be(bytes: &[u8]) -> crate::Result<Self> {
if !bytes.len().is_multiple_of(2) {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "BMPString",
#[cfg(feature = "std")]
reason: format!("UCS-2 byte length {} is not even", bytes.len()),
#[cfg(not(feature = "std"))]
reason: "UCS-2 byte length is not even",
});
}
let mut s = String::with_capacity(bytes.len() / 2);
for chunk in bytes.chunks(2) {
let code_unit = u16::from_be_bytes([chunk[0], chunk[1]]);
if (0xD800..=0xDFFF).contains(&code_unit) {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "BMPString",
#[cfg(feature = "std")]
reason: format!(
"Surrogate code unit U+{:04X} is not valid in BMPString",
code_unit
),
#[cfg(not(feature = "std"))]
reason: "Surrogate code unit in BMPString",
});
}
let c = char::from_u32(code_unit as u32).unwrap();
s.push(c);
}
Ok(Self(s))
}
pub fn to_ucs2_be(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(self.0.chars().count() * 2);
for c in self.0.chars() {
bytes.extend_from_slice(&(c as u16).to_be_bytes());
}
bytes
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
impl crate::traits::Decode<'_> for BmpString {
fn decode(decoder: &mut crate::der::decoder::Decoder) -> crate::Result<Self> {
use crate::tag::TAG_BMP_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_BMP_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
BmpString::from_ucs2_be(bytes)
}
}
impl crate::traits::Encode for BmpString {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_BMP_STRING;
let ucs2 = self.to_ucs2_be();
encoder.write_tag(crate::Tag::universal(TAG_BMP_STRING))?;
encoder.write_length(ucs2.len())?;
encoder.write_bytes(&ucs2);
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let content_len = self.0.chars().count() * 2;
let length_len = crate::Length::Definite(content_len).encoded_len()?;
Ok(1 + length_len + content_len)
}
}
impl crate::traits::Tagged for BmpString {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_BMP_STRING)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IA5StringRef<'a>(&'a str);
impl<'a> IA5StringRef<'a> {
pub fn new(s: &'a str) -> crate::Result<Self> {
if !s.is_ascii() {
return Err(crate::Error::InvalidString {
position: 0,
string_type: "IA5String",
#[cfg(feature = "std")]
reason: "String contains non-ASCII characters".to_string(),
#[cfg(not(feature = "std"))]
reason: "Non-ASCII characters",
});
}
Ok(Self(s))
}
pub fn as_str(&self) -> &'a str {
self.0
}
pub fn to_owned(&self) -> IA5String {
IA5String::new(self.0.to_string()).unwrap()
}
}
impl<'a> crate::traits::Decode<'a> for IA5StringRef<'a> {
fn decode(decoder: &mut crate::der::decoder::Decoder<'a>) -> crate::Result<Self> {
use crate::tag::TAG_IA5_STRING;
let tag = decoder.read_tag()?;
let expected_tag = crate::Tag::universal(TAG_IA5_STRING);
if tag != expected_tag {
return Err(crate::Error::UnexpectedTag {
position: decoder.position(),
expected: expected_tag,
actual: tag,
});
}
let length = decoder.read_length()?;
let len = length.definite()?;
let bytes = decoder.read_bytes(len)?;
let s = core::str::from_utf8(bytes).map_err(|_| crate::Error::InvalidString {
position: decoder.position(),
string_type: "IA5String",
#[cfg(feature = "std")]
reason: "Invalid UTF-8/ASCII encoding".to_string(),
#[cfg(not(feature = "std"))]
reason: "Invalid UTF-8/ASCII encoding",
})?;
if !s.is_ascii() {
return Err(crate::Error::InvalidString {
position: decoder.position(),
string_type: "IA5String",
#[cfg(feature = "std")]
reason: "String contains non-ASCII characters".to_string(),
#[cfg(not(feature = "std"))]
reason: "Non-ASCII characters",
});
}
Ok(IA5StringRef(s))
}
}
impl<'a> crate::traits::Encode for IA5StringRef<'a> {
fn encode(&self, encoder: &mut crate::der::encoder::Encoder) -> crate::Result<()> {
use crate::tag::TAG_IA5_STRING;
let tag = crate::Tag::universal(TAG_IA5_STRING);
encoder.write_tag(tag)?;
encoder.write_length(self.0.len())?;
encoder.write_bytes(self.0.as_bytes());
Ok(())
}
fn encoded_len(&self) -> crate::Result<usize> {
let tag_len = 1;
let length_len = crate::Length::Definite(self.0.len()).encoded_len()?;
Ok(tag_len + length_len + self.0.len())
}
}
impl<'a> crate::traits::Tagged for IA5StringRef<'a> {
fn tag() -> crate::Tag {
crate::Tag::universal(crate::tag::TAG_IA5_STRING)
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for OctetString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(&crate::serde_impl::bytes_to_hex(self.as_bytes()))
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for OctetString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let hex = <String as serde::Deserialize<'de>>::deserialize(d)?;
let bytes = crate::serde_impl::hex_to_bytes::<D::Error>(&hex)?;
Ok(OctetString::new(bytes))
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Serialize for OctetStringRef<'a> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(&crate::serde_impl::bytes_to_hex(self.as_bytes()))
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for BitString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeStruct;
let mut st = s.serialize_struct("BitString", 2)?;
st.serialize_field("bytes", &crate::serde_impl::bytes_to_hex(self.as_bytes()))?;
st.serialize_field("unused_bits", &self.unused_bits())?;
st.end()
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for BitString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
struct BitStringVisitor;
impl<'de> serde::de::Visitor<'de> for BitStringVisitor {
type Value = BitString;
fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(
f,
"a BitString with \"bytes\" (hex) and \"unused_bits\" fields"
)
}
fn visit_map<A: serde::de::MapAccess<'de>>(
self,
mut map: A,
) -> Result<BitString, A::Error> {
let mut bytes_hex: Option<String> = None;
let mut unused_bits: Option<u8> = None;
while let Some(key) = map.next_key::<String>()? {
match key.as_str() {
"bytes" => bytes_hex = Some(map.next_value()?),
"unused_bits" => unused_bits = Some(map.next_value()?),
_ => {
let _ = map.next_value::<serde::de::IgnoredAny>()?;
}
}
}
let bytes_hex =
bytes_hex.ok_or_else(|| serde::de::Error::missing_field("bytes"))?;
let unused_bits =
unused_bits.ok_or_else(|| serde::de::Error::missing_field("unused_bits"))?;
let bytes = crate::serde_impl::hex_to_bytes::<A::Error>(&bytes_hex)?;
BitString::new(bytes, unused_bits)
.map_err(|_| serde::de::Error::custom("invalid BitString"))
}
}
d.deserialize_map(BitStringVisitor)
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Serialize for BitStringRef<'a> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeStruct;
let mut st = s.serialize_struct("BitString", 2)?;
st.serialize_field("bytes", &crate::serde_impl::bytes_to_hex(self.as_bytes()))?;
st.serialize_field("unused_bits", &self.unused_bits())?;
st.end()
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for Utf8String {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Utf8String {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let v = <String as serde::Deserialize<'de>>::deserialize(d)?;
Ok(Utf8String::new(v))
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Serialize for Utf8StringRef<'a> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for PrintableString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for PrintableString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let v = <String as serde::Deserialize<'de>>::deserialize(d)?;
PrintableString::new(v).map_err(|_| serde::de::Error::custom("invalid PrintableString"))
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Serialize for PrintableStringRef<'a> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for IA5String {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for IA5String {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let v = <String as serde::Deserialize<'de>>::deserialize(d)?;
IA5String::new(v).map_err(|_| serde::de::Error::custom("invalid IA5String"))
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Serialize for IA5StringRef<'a> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.0)
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for NumericString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for NumericString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let v = <String as serde::Deserialize<'de>>::deserialize(d)?;
NumericString::new(v).map_err(|_| serde::de::Error::custom("invalid NumericString"))
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for TeletexString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(&crate::serde_impl::bytes_to_hex(self.as_bytes()))
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for TeletexString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let hex = <String as serde::Deserialize<'de>>::deserialize(d)?;
let bytes = crate::serde_impl::hex_to_bytes::<D::Error>(&hex)?;
Ok(TeletexString::new(bytes))
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for VisibleString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for VisibleString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let v = <String as serde::Deserialize<'de>>::deserialize(d)?;
VisibleString::new(v).map_err(|_| serde::de::Error::custom("invalid VisibleString"))
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for GeneralString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(&crate::serde_impl::bytes_to_hex(self.as_bytes()))
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for GeneralString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let hex = <String as serde::Deserialize<'de>>::deserialize(d)?;
let bytes = crate::serde_impl::hex_to_bytes::<D::Error>(&hex)?;
Ok(GeneralString::new(bytes))
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for UniversalString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for UniversalString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let v = <String as serde::Deserialize<'de>>::deserialize(d)?;
Ok(UniversalString::new(v))
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for BmpString {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(&self.0)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for BmpString {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let v = <String as serde::Deserialize<'de>>::deserialize(d)?;
BmpString::new(v).map_err(|_| serde::de::Error::custom("invalid BmpString"))
}
}