ironrdp_pdu/rdp/capability_sets/
glyph_cache.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#[cfg(test)]
mod tests;

use ironrdp_core::{
    ensure_fixed_part_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor,
};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive};

pub const GLYPH_CACHE_NUM: usize = 10;

const GLYPH_CACHE_LENGTH: usize = 48;
const CACHE_DEFINITION_LENGTH: usize = 4;

#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum GlyphSupportLevel {
    None = 0,
    Partial = 1,
    Full = 2,
    Encode = 3,
}

#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
pub struct CacheDefinition {
    pub entries: u16,
    pub max_cell_size: u16,
}

impl CacheDefinition {
    const NAME: &'static str = "CacheDefinition";

    const FIXED_PART_SIZE: usize = CACHE_DEFINITION_LENGTH;
}

impl Encode for CacheDefinition {
    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
        ensure_fixed_part_size!(in: dst);

        dst.write_u16(self.entries);
        dst.write_u16(self.max_cell_size);

        Ok(())
    }

    fn name(&self) -> &'static str {
        Self::NAME
    }

    fn size(&self) -> usize {
        Self::FIXED_PART_SIZE
    }
}

impl<'de> Decode<'de> for CacheDefinition {
    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
        ensure_fixed_part_size!(in: src);

        let entries = src.read_u16();
        let max_cell_size = src.read_u16();

        Ok(CacheDefinition { entries, max_cell_size })
    }
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct GlyphCache {
    pub glyph_cache: [CacheDefinition; GLYPH_CACHE_NUM],
    pub frag_cache: CacheDefinition,
    pub glyph_support_level: GlyphSupportLevel,
}

impl GlyphCache {
    const NAME: &'static str = "GlyphCache";

    const FIXED_PART_SIZE: usize = GLYPH_CACHE_LENGTH;
}

impl Encode for GlyphCache {
    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
        ensure_fixed_part_size!(in: dst);

        for glyph in self.glyph_cache.iter() {
            glyph.encode(dst)?;
        }

        self.frag_cache.encode(dst)?;

        dst.write_u16(self.glyph_support_level.to_u16().unwrap());
        write_padding!(dst, 2);

        Ok(())
    }

    fn name(&self) -> &'static str {
        Self::NAME
    }

    fn size(&self) -> usize {
        Self::FIXED_PART_SIZE
    }
}

impl<'de> Decode<'de> for GlyphCache {
    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
        ensure_fixed_part_size!(in: src);

        let mut glyph_cache = [CacheDefinition::default(); GLYPH_CACHE_NUM];

        for glyph in glyph_cache.iter_mut() {
            *glyph = CacheDefinition::decode(src)?;
        }

        let frag_cache = CacheDefinition::decode(src)?;
        let glyph_support_level = GlyphSupportLevel::from_u16(src.read_u16())
            .ok_or_else(|| invalid_field_err!("glyphSupport", "invalid glyph support level"))?;
        let _padding = src.read_u16();

        Ok(GlyphCache {
            glyph_cache,
            frag_cache,
            glyph_support_level,
        })
    }
}