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
/// This module contains a [`Marker`] which is appended before each value to tell you the type.
use crate::Error;

/// The inner marker just telling you the type.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum InnerMarker {
    I64,
    I32,
    I16,
    I8,
    U64,
    U32,
    U16,
    U8,
    F64,
    String,
    Bool,
    Object,
}

impl InnerMarker {
    pub fn size(&self) -> Option<usize> {
        Some(match self {
            InnerMarker::I64 | InnerMarker::U64 | InnerMarker::F64 => 8,
            InnerMarker::I32 | InnerMarker::U32 => 4,
            InnerMarker::I16 | InnerMarker::U16 => 2,
            InnerMarker::I8 | InnerMarker::U8 | InnerMarker::Bool => 1,
            InnerMarker::String | InnerMarker::Object => return None,
        })
    }
}

/// A marker appended before Epee values which tell you the type of the field and if
/// its a sequence.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Marker {
    pub inner_marker: InnerMarker,
    pub is_seq: bool,
}

impl Marker {
    pub(crate) const fn new(inner_marker: InnerMarker) -> Self {
        Marker {
            inner_marker,
            is_seq: false,
        }
    }
    pub const fn into_seq(self) -> Self {
        if self.is_seq {
            panic!("Sequence of sequence not allowed!");
        }
        if matches!(self.inner_marker, InnerMarker::U8) {
            return Marker {
                inner_marker: InnerMarker::String,
                is_seq: false,
            };
        }

        Marker {
            inner_marker: self.inner_marker,
            is_seq: true,
        }
    }

    pub const fn as_u8(&self) -> u8 {
        let marker_val = match self.inner_marker {
            InnerMarker::I64 => 1,
            InnerMarker::I32 => 2,
            InnerMarker::I16 => 3,
            InnerMarker::I8 => 4,
            InnerMarker::U64 => 5,
            InnerMarker::U32 => 6,
            InnerMarker::U16 => 7,
            InnerMarker::U8 => 8,
            InnerMarker::F64 => 9,
            InnerMarker::String => 10,
            InnerMarker::Bool => 11,
            InnerMarker::Object => 12,
        };

        if self.is_seq {
            marker_val | 0x80
        } else {
            marker_val
        }
    }
}

impl TryFrom<u8> for Marker {
    type Error = Error;

    fn try_from(mut value: u8) -> Result<Self, Self::Error> {
        let is_seq = value & 0x80 > 0;

        if is_seq {
            value ^= 0x80;
        }

        let inner_marker = match value {
            1 => InnerMarker::I64,
            2 => InnerMarker::I32,
            3 => InnerMarker::I16,
            4 => InnerMarker::I8,
            5 => InnerMarker::U64,
            6 => InnerMarker::U32,
            7 => InnerMarker::U16,
            8 => InnerMarker::U8,
            9 => InnerMarker::F64,
            10 => InnerMarker::String,
            11 => InnerMarker::Bool,
            12 => InnerMarker::Object,
            _ => return Err(Error::Format("Unknown value Marker")),
        };

        Ok(Marker {
            inner_marker,
            is_seq,
        })
    }
}