Skip to main content

rasn/types/strings/
general.rs

1use super::{
2    AsnType, Constraints, Decode, Decoder, Encode, Encoder, Identifier, StaticPermittedAlphabet,
3    Tag, constrained,
4};
5
6use crate::error::strings::PermittedAlphabetError;
7use alloc::vec::Vec;
8use once_cell::race::OnceBox;
9
10/// A "general" string containing the `C0` Controls plane, `SPACE`,
11/// Basic Latin, `DELETE`, and Latin-1 Supplement characters.
12#[derive(Debug, Default, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
13pub struct GeneralString(pub(super) Vec<u8>);
14
15static CHARACTER_MAP: OnceBox<alloc::collections::BTreeMap<u32, u32>> = OnceBox::new();
16static INDEX_MAP: OnceBox<alloc::collections::BTreeMap<u32, u32>> = OnceBox::new();
17
18impl GeneralString {
19    /// Attempts to convert the provided bytes into [Self].
20    ///
21    /// # Errors
22    /// If any of the provided bytes does not match the allowed character set.
23    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PermittedAlphabetError> {
24        Ok(Self(Self::try_from_slice(bytes)?))
25    }
26
27    /// Provides a slice of bytes representing the current value.
28    #[must_use]
29    pub fn as_bytes(&self) -> &[u8] {
30        &self.0
31    }
32}
33
34impl StaticPermittedAlphabet for GeneralString {
35    type T = u8;
36    const CHARACTER_SET: &'static [u32] = &[
37        // 0x00..=0x1F, // C0 Controls (C set)
38        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
39        0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
40        0x1E, 0x1F, //  0x20, SPACE
41        0x20, // 0x21..=0x7E, Basic Latin (G set)
42        0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
43        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E,
44        0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
45        0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
46        0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
47        0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
48        0x7B, 0x7C, 0x7D, 0x7E, //  0x7F, DELETE
49        0x7F, //  0xA1..=0xFF, Latin-1 Supplement (G set)
50        0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
51        0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
52        0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD,
53        0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC,
54        0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
55        0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
56        0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
57    ];
58    const CHARACTER_SET_NAME: constrained::CharacterSetName =
59        constrained::CharacterSetName::General;
60    fn chars(&self) -> impl Iterator<Item = u32> + '_ {
61        self.0.iter().map(|&byte| byte as u32)
62    }
63    fn push_char(&mut self, ch: u32) {
64        self.0.push(ch as u8);
65    }
66    fn index_map() -> &'static alloc::collections::BTreeMap<u32, u32> {
67        INDEX_MAP.get_or_init(Self::build_index_map)
68    }
69
70    fn character_map() -> &'static alloc::collections::BTreeMap<u32, u32> {
71        CHARACTER_MAP.get_or_init(Self::build_character_map)
72    }
73}
74
75impl AsnType for GeneralString {
76    const TAG: Tag = Tag::GENERAL_STRING;
77    const IDENTIFIER: Identifier = Identifier::GENERAL_STRING;
78}
79
80impl Decode for GeneralString {
81    fn decode_with_tag_and_constraints<D: Decoder>(
82        decoder: &mut D,
83        tag: Tag,
84        constraints: Constraints,
85    ) -> Result<Self, D::Error> {
86        decoder.decode_general_string(tag, constraints)
87    }
88}
89
90impl Encode for GeneralString {
91    fn encode_with_tag_and_constraints<'b, E: Encoder<'b>>(
92        &self,
93        encoder: &mut E,
94        tag: Tag,
95        constraints: Constraints,
96        identifier: Identifier,
97    ) -> Result<(), E::Error> {
98        encoder
99            .encode_general_string(tag, constraints, self, identifier)
100            .map(drop)
101    }
102}