ironrdp_pdu/rdp/capability_sets/
glyph_cache.rs1#[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}