rasn/types/strings/
graphic.rs

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