Skip to main content

lber_serde/structures/
integer.rs

1use super::ASNTag;
2use common::TagClass;
3use structure;
4use universal;
5
6use std::default;
7
8/// Integer value.
9#[derive(Clone, Copy, Debug, PartialEq)]
10pub struct Integer {
11    pub id: u64,
12    pub class: TagClass,
13    pub inner: i64,
14}
15
16/// Integer with a different tag.
17#[derive(Clone, Copy, Debug, PartialEq)]
18pub struct Enumerated {
19    pub id: u64,
20    pub class: TagClass,
21    pub inner: i64,
22}
23
24fn i_e_into_structure(id: u64, class: TagClass, inner: i64) -> structure::StructureTag {
25    let mut count = 0u8;
26    let mut rem: i64 = if inner >= 0 { inner } else { inner * -1 };
27    while {
28        count += 1;
29        rem >>= 8;
30        rem > 0
31    } {}
32
33    // Ensure that the most significant bit is always 0, because BER uses signed numbers.
34    // We shift away all but the most significant bit and check that.
35    // See #21
36    if inner > 0 && inner >> ((8 * count) - 1) == 1 {
37        count += 1;
38    }
39
40    let mut count = count as usize;
41    let mut out: Vec<u8> = Vec::with_capacity(count);
42    let repr = inner.to_be_bytes();
43    if count > repr.len() {
44        out.push(0);
45        count -= 1;
46    }
47    out.extend_from_slice(&repr[repr.len() - count..]);
48
49    structure::StructureTag {
50        id: id,
51        class: class,
52        payload: structure::PL::P(out),
53    }
54}
55
56impl ASNTag for Integer {
57    fn into_structure(self) -> structure::StructureTag {
58        i_e_into_structure(self.id, self.class, self.inner)
59    }
60}
61
62impl ASNTag for Enumerated {
63    fn into_structure(self) -> structure::StructureTag {
64        i_e_into_structure(self.id, self.class, self.inner)
65    }
66}
67
68impl default::Default for Integer {
69    fn default() -> Integer {
70        Integer {
71            id: universal::Types::Integer as u64,
72            class: TagClass::Universal,
73            inner: 0i64,
74        }
75    }
76}
77
78impl default::Default for Enumerated {
79    fn default() -> Enumerated {
80        Enumerated {
81            id: universal::Types::Enumerated as u64,
82            class: TagClass::Universal,
83            inner: 0i64,
84        }
85    }
86}
87
88#[cfg(test)]
89mod test {
90    use super::i_e_into_structure;
91
92    use common::TagClass;
93    use structure;
94
95    #[test]
96    fn test_not_unnecessary_octets() {
97        // 127 can be encoded into 8 bits
98        let result = i_e_into_structure(2, TagClass::Universal, 127);
99        let correct = structure::PL::P(vec![127]);
100        assert_eq![result.payload, correct];
101    }
102
103    #[test]
104    fn test_not_positive_getting_negative() {
105        // 128 can be encoded cannot be encoded into a 8 bit signed number
106        // See #21
107        let result = i_e_into_structure(2, TagClass::Universal, 128);
108        let correct = structure::PL::P(vec![0, 128]);
109        assert_eq![result.payload, correct];
110    }
111}