Skip to content

Commit

Permalink
feat:add graphic string support (#410)
Browse files Browse the repository at this point in the history
  • Loading branch information
privatepatrick authored Jan 30, 2025
1 parent 7677b0b commit 28a2652
Show file tree
Hide file tree
Showing 17 changed files with 228 additions and 13 deletions.
12 changes: 12 additions & 0 deletions src/ber/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,18 @@ impl<'input> crate::Decoder for Decoder<'input> {
.map_err(|e| DecodeError::permitted_alphabet_error(e, self.codec()))
}

fn decode_graphic_string(
&mut self,
tag: Tag,
constraints: Constraints,
) -> Result<types::GraphicString> {
<types::GraphicString>::try_from(
self.decode_octet_string::<Cow<[u8]>>(tag, constraints)?
.as_ref(),
)
.map_err(|e| DecodeError::permitted_alphabet_error(e, self.codec()))
}

fn decode_generalized_time(&mut self, tag: Tag) -> Result<types::GeneralizedTime> {
let string = self.decode_utf8_string(tag, Constraints::default())?;
if self.config.encoding_rules.is_ber() {
Expand Down
9 changes: 9 additions & 0 deletions src/ber/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,15 @@ impl crate::Encoder<'_> for Encoder {
self.encode_octet_string_(tag, value)
}

fn encode_graphic_string(
&mut self,
tag: Tag,
_constraints: Constraints,
value: &types::GraphicString,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string_(tag, value)
}

fn encode_printable_string(
&mut self,
tag: Tag,
Expand Down
9 changes: 8 additions & 1 deletion src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,20 @@ pub trait Decoder<const RCL: usize = 0, const ECL: usize = 0>: Sized {
constraints: Constraints,
) -> Result<types::VisibleString, Self::Error>;

/// Decode a `Ia5String` identified by `tag` from the available input.
/// Decode a `GeneralString` identified by `tag` from the available input.
fn decode_general_string(
&mut self,
tag: Tag,
constraints: Constraints,
) -> Result<types::GeneralString, Self::Error>;

/// Decode a `GraphicString` identified by `tag` from the available input.
fn decode_graphic_string(
&mut self,
tag: Tag,
constraints: Constraints,
) -> Result<types::GraphicString, Self::Error>;

/// Decode a `Ia5String` identified by `tag` from the available input.
fn decode_ia5_string(
&mut self,
Expand Down
8 changes: 8 additions & 0 deletions src/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ pub trait Encoder<'encoder, const RCL: usize = 0, const ECL: usize = 0> {
value: &types::GeneralString,
) -> Result<Self::Ok, Self::Error>;

/// Encode a `GraphicString` value.
fn encode_graphic_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &types::GraphicString,
) -> Result<Self::Ok, Self::Error>;

/// Encode a `Utf8String` value.
fn encode_utf8_string(
&mut self,
Expand Down
6 changes: 3 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ mod string;
pub mod strings {
//! Errors specific to string conversions, permitted alphabets, and other type problems.
pub use super::string::{
InvalidBmpString, InvalidGeneralString, InvalidIA5String, InvalidNumericString,
InvalidPrintableString, InvalidRestrictedString, InvalidTeletexString,
InvalidVisibleString, PermittedAlphabetError,
InvalidBmpString, InvalidGeneralString, InvalidGraphicString, InvalidIA5String,
InvalidNumericString, InvalidPrintableString, InvalidRestrictedString,
InvalidTeletexString, InvalidVisibleString, PermittedAlphabetError,
};
}

Expand Down
12 changes: 12 additions & 0 deletions src/error/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ pub struct InvalidGeneralString {
pub character: u32,
}

/// A character which does not match the allowed character set for General.
#[derive(snafu::Snafu, Debug)]
#[snafu(visibility(pub))]
#[snafu(display("Invalid graphic string, character decimal value: {}", character))]
pub struct InvalidGraphicString {
/// The invalid character.
pub character: u32,
}

/// A character which does not match the allowed character set for IA5.
#[derive(snafu::Snafu, Debug)]
#[snafu(visibility(pub))]
Expand Down Expand Up @@ -77,6 +86,7 @@ macro_rules! from_u32 {
from_u32!(
InvalidBmpString,
InvalidGeneralString,
InvalidGraphicString,
InvalidIA5String,
InvalidNumericString,
InvalidPrintableString,
Expand All @@ -90,6 +100,7 @@ from_u32!(
pub enum InvalidRestrictedString {
InvalidBmpString(InvalidBmpString),
InvalidGeneralString(InvalidGeneralString),
InvalidGraphicString(InvalidGraphicString),
InvalidIA5String(InvalidIA5String),
InvalidNumericString(InvalidNumericString),
InvalidPrintableString(InvalidPrintableString),
Expand All @@ -102,6 +113,7 @@ impl core::fmt::Display for InvalidRestrictedString {
match self {
InvalidRestrictedString::InvalidBmpString(e) => write!(f, "{}", e),
InvalidRestrictedString::InvalidGeneralString(e) => write!(f, "{}", e),
InvalidRestrictedString::InvalidGraphicString(e) => write!(f, "{}", e),
InvalidRestrictedString::InvalidIA5String(e) => write!(f, "{}", e),
InvalidRestrictedString::InvalidNumericString(e) => write!(f, "{}", e),
InvalidRestrictedString::InvalidPrintableString(e) => write!(f, "{}", e),
Expand Down
16 changes: 16 additions & 0 deletions src/jer/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,22 @@ impl crate::Decoder for Decoder {
})
}

fn decode_graphic_string(
&mut self,
_t: Tag,
_c: Constraints,
) -> Result<GraphicString, Self::Error> {
decode_jer_value!(Self::string_from_value, self.stack)?
.try_into()
.map_err(|e| {
DecodeError::string_conversion_failed(
Tag::GRAPHIC_STRING,
alloc::format!("Error transforming GeneralString: {e:?}"),
crate::Codec::Jer,
)
})
}

fn decode_ia5_string(&mut self, _t: Tag, _c: Constraints) -> Result<Ia5String, Self::Error> {
decode_jer_value!(Self::string_from_value, self.stack)?
.try_into()
Expand Down
12 changes: 12 additions & 0 deletions src/jer/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,18 @@ impl crate::Encoder<'_> for Encoder {
))
}

fn encode_graphic_string(
&mut self,
_t: Tag,
_c: crate::types::Constraints,
value: &crate::types::GraphicString,
) -> Result<Self::Ok, Self::Error> {
self.update_root_or_constructed(Value::String(
alloc::string::String::from_utf8(value.to_vec())
.map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
))
}

fn encode_utf8_string(
&mut self,
_t: Tag,
Expand Down
12 changes: 10 additions & 2 deletions src/oer/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use crate::{
self,
fields::{Field, Fields},
Any, BitString, BmpString, Constraints, Constructed, DecodeChoice, Enumerated,
GeneralString, GeneralizedTime, Ia5String, IntegerType, NumericString, ObjectIdentifier,
PrintableString, SetOf, Tag, TeletexString, UtcTime, VisibleString,
GeneralString, GeneralizedTime, GraphicString, Ia5String, IntegerType, NumericString,
ObjectIdentifier, PrintableString, SetOf, Tag, TeletexString, UtcTime, VisibleString,
},
Codec,
};
Expand Down Expand Up @@ -722,6 +722,14 @@ impl<'input, const RFC: usize, const EFC: usize> crate::Decoder for Decoder<'inp
self.parse_known_multiplier_string(&constraints)
}

fn decode_graphic_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<GraphicString, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}

fn decode_ia5_string(
&mut self,
_: Tag,
Expand Down
14 changes: 12 additions & 2 deletions src/oer/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use crate::{
oer::EncodingRules,
types::{
Any, BitStr, BmpString, Choice, Constraints, Constructed, Date, Enumerated, GeneralString,
GeneralizedTime, Ia5String, IntegerType, NumericString, PrintableString, RealType, SetOf,
Tag, TeletexString, UtcTime, VisibleString,
GeneralizedTime, GraphicString, Ia5String, IntegerType, NumericString, PrintableString,
RealType, SetOf, Tag, TeletexString, UtcTime, VisibleString,
},
Codec, Encode,
};
Expand Down Expand Up @@ -794,6 +794,16 @@ impl<'buffer, const RFC: usize, const EFC: usize> crate::Encoder<'buffer>
self.encode_octet_string(tag, constraints, value)
}

fn encode_graphic_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &GraphicString,
) -> Result<Self::Ok, Self::Error> {
// Seems like it can be encoded as it is...
self.encode_octet_string(tag, constraints, value)
}

fn encode_utf8_string(
&mut self,
tag: Tag,
Expand Down
15 changes: 15 additions & 0 deletions src/per/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,21 @@ impl<'input, const RFC: usize, const EFC: usize> crate::Decoder for Decoder<'inp
})
}

fn decode_graphic_string(
&mut self,
tag: Tag,
constraints: Constraints,
) -> Result<types::GraphicString> {
<types::GraphicString>::try_from(self.decode_octet_string::<Vec<u8>>(tag, constraints)?)
.map_err(|e| {
DecodeError::string_conversion_failed(
Tag::GRAPHIC_STRING,
e.to_string(),
self.codec(),
)
})
}

fn decode_generalized_time(&mut self, tag: Tag) -> Result<types::GeneralizedTime> {
let bytes = self.decode_octet_string::<Cow<[u8]>>(tag, Constraints::default())?;

Expand Down
9 changes: 9 additions & 0 deletions src/per/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,15 @@ impl<const RFC: usize, const EFC: usize> crate::Encoder<'_> for Encoder<RFC, EFC
self.encode_octet_string(tag, Constraints::default(), value)
}

fn encode_graphic_string(
&mut self,
tag: Tag,
_: Constraints,
value: &types::GraphicString,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, Constraints::default(), value)
}

fn encode_printable_string(
&mut self,
tag: Tag,
Expand Down
4 changes: 2 additions & 2 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ pub use {
prefix::{Explicit, Implicit},
strings::{
BitStr, BitString, BmpString, FixedBitString, FixedOctetString, GeneralString,
Ia5String, NumericString, OctetString, PrintableString, TeletexString, Utf8String,
VisibleString,
GraphicString, Ia5String, NumericString, OctetString, PrintableString, TeletexString,
Utf8String, VisibleString,
},
tag::{Class, Tag, TagTree},
},
Expand Down
3 changes: 3 additions & 0 deletions src/types/strings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod bit;
mod bmp;
mod constrained;
mod general;
mod graphic;
mod ia5;
mod numeric;
mod octet;
Expand All @@ -18,6 +19,7 @@ pub use {
bit::{BitStr, BitString, FixedBitString},
bmp::BmpString,
general::GeneralString,
graphic::GraphicString,
ia5::Ia5String,
numeric::NumericString,
octet::{FixedOctetString, OctetString},
Expand Down Expand Up @@ -109,6 +111,7 @@ macro_rules! impl_restricted_core_traits {
impl_restricted_core_traits!(
(BmpString, u16),
(GeneralString, u8),
(GraphicString, u8),
(Ia5String, u8),
(NumericString, u8),
(PrintableString, u8),
Expand Down
3 changes: 3 additions & 0 deletions src/types/strings/constrained.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::types;
pub(crate) enum CharacterSetName {
Bmp,
General,
Graphic,
IA5,
Numeric,
Printable,
Expand All @@ -22,6 +23,7 @@ impl fmt::Display for CharacterSetName {
match self {
Self::Bmp => write!(f, "BMPString"),
Self::General => write!(f, "GeneralString"),
Self::Graphic => write!(f, "GraphicString"),
Self::IA5 => write!(f, "IA5String"),
Self::Numeric => write!(f, "NumericString"),
Self::Printable => write!(f, "PrintableString"),
Expand Down Expand Up @@ -54,6 +56,7 @@ pub(crate) trait StaticPermittedAlphabet: Sized + Default {
match Self::CHARACTER_SET_NAME {
CharacterSetName::Bmp => InvalidRestrictedString::InvalidBmpString(ch.into()),
CharacterSetName::General => InvalidRestrictedString::InvalidGeneralString(ch.into()),
CharacterSetName::Graphic => InvalidRestrictedString::InvalidGraphicString(ch.into()),
CharacterSetName::IA5 => InvalidRestrictedString::InvalidIA5String(ch.into()),
CharacterSetName::Numeric => InvalidRestrictedString::InvalidNumericString(ch.into()),
CharacterSetName::Printable => {
Expand Down
Loading

0 comments on commit 28a2652

Please sign in to comment.