ironrdp_pdu/rdp/capability_sets/
glyph_cache.rs

1#[cfg(test)]
2mod tests;
3
4use ironrdp_core::{
5    ensure_fixed_part_size, invalid_field_err, write_padding, Decode, DecodeResult, Encode, EncodeResult, ReadCursor,
6    WriteCursor,
7};
8use num_derive::{FromPrimitive, ToPrimitive};
9use num_traits::{FromPrimitive as _, ToPrimitive as _};
10
11pub const GLYPH_CACHE_NUM: usize = 10;
12
13const GLYPH_CACHE_LENGTH: usize = 48;
14const CACHE_DEFINITION_LENGTH: usize = 4;
15
16#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
17pub enum GlyphSupportLevel {
18    None = 0,
19    Partial = 1,
20    Full = 2,
21    Encode = 3,
22}
23
24#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
25pub struct CacheDefinition {
26    pub entries: u16,
27    pub max_cell_size: u16,
28}
29
30impl CacheDefinition {
31    const NAME: &'static str = "CacheDefinition";
32
33    const FIXED_PART_SIZE: usize = CACHE_DEFINITION_LENGTH;
34}
35
36impl Encode for CacheDefinition {
37    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
38        ensure_fixed_part_size!(in: dst);
39
40        dst.write_u16(self.entries);
41        dst.write_u16(self.max_cell_size);
42
43        Ok(())
44    }
45
46    fn name(&self) -> &'static str {
47        Self::NAME
48    }
49
50    fn size(&self) -> usize {
51        Self::FIXED_PART_SIZE
52    }
53}
54
55impl<'de> Decode<'de> for CacheDefinition {
56    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
57        ensure_fixed_part_size!(in: src);
58
59        let entries = src.read_u16();
60        let max_cell_size = src.read_u16();
61
62        Ok(CacheDefinition { entries, max_cell_size })
63    }
64}
65
66#[derive(Debug, PartialEq, Eq, Clone)]
67pub struct GlyphCache {
68    pub glyph_cache: [CacheDefinition; GLYPH_CACHE_NUM],
69    pub frag_cache: CacheDefinition,
70    pub glyph_support_level: GlyphSupportLevel,
71}
72
73impl GlyphCache {
74    const NAME: &'static str = "GlyphCache";
75
76    const FIXED_PART_SIZE: usize = GLYPH_CACHE_LENGTH;
77}
78
79impl Encode for GlyphCache {
80    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
81        ensure_fixed_part_size!(in: dst);
82
83        for glyph in self.glyph_cache.iter() {
84            glyph.encode(dst)?;
85        }
86
87        self.frag_cache.encode(dst)?;
88
89        dst.write_u16(self.glyph_support_level.to_u16().unwrap());
90        write_padding!(dst, 2);
91
92        Ok(())
93    }
94
95    fn name(&self) -> &'static str {
96        Self::NAME
97    }
98
99    fn size(&self) -> usize {
100        Self::FIXED_PART_SIZE
101    }
102}
103
104impl<'de> Decode<'de> for GlyphCache {
105    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
106        ensure_fixed_part_size!(in: src);
107
108        let mut glyph_cache = [CacheDefinition::default(); GLYPH_CACHE_NUM];
109
110        for glyph in glyph_cache.iter_mut() {
111            *glyph = CacheDefinition::decode(src)?;
112        }
113
114        let frag_cache = CacheDefinition::decode(src)?;
115        let glyph_support_level = GlyphSupportLevel::from_u16(src.read_u16())
116            .ok_or_else(|| invalid_field_err!("glyphSupport", "invalid glyph support level"))?;
117        let _padding = src.read_u16();
118
119        Ok(GlyphCache {
120            glyph_cache,
121            frag_cache,
122            glyph_support_level,
123        })
124    }
125}