1use common::TagClass;
2
3#[cfg(feature = "serde")]
4extern crate serde;
5
6#[derive(Clone, PartialEq, Debug, Eq)]
8pub struct StructureTag {
9 pub class: TagClass,
10 pub id: u64,
11 pub payload: PL,
12}
13
14#[cfg(feature = "serde")]
15impl self::serde::Serialize for StructureTag {
16 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
17 where
18 S: self::serde::Serializer,
19 {
20 use self::serde::ser::SerializeStruct;
21 let mut seq = serializer.serialize_struct("StructureTag", 3)?;
22 seq.serialize_field("class", &self.class)?;
23 seq.serialize_field("element", &self.id)?;
24 match self.payload {
25 PL::P(ref v) => seq.serialize_field("payload", v),
26 PL::C(ref v) => seq.serialize_field("payload", v),
27 }?;
28 seq.end()
29 }
30}
31
32#[derive(Clone, PartialEq, Debug, Eq)]
34pub enum PL {
35 P(Vec<u8>),
37 C(Vec<StructureTag>),
39}
40
41#[cfg(feature = "serde")]
42impl self::serde::Serialize for PL {
43 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
44 where
45 S: self::serde::Serializer,
46 {
47 match *self {
48 PL::P(ref v) => serializer.serialize_bytes(v),
49 PL::C(ref v) => {
50 use self::serde::ser::SerializeSeq;
51 let mut ser = serializer.serialize_seq(Some(v.len()))?;
52 for e in v {
53 ser.serialize_element(e)?;
54 }
55 ser.end()
56 }
57 }
58 }
59}
60
61impl StructureTag {
62 pub fn match_class(self, class: TagClass) -> Option<Self> {
63 if self.class == class {
64 Some(self)
65 } else {
66 None
67 }
68 }
69
70 pub fn match_id(self, id: u64) -> Option<Self> {
71 if self.id == id {
72 Some(self)
73 } else {
74 None
75 }
76 }
77
78 pub fn expect_constructed(self) -> Option<Vec<StructureTag>> {
79 match self.payload {
80 PL::P(_) => None,
81 PL::C(i) => Some(i),
82 }
83 }
84
85 pub fn expect_primitive(self) -> Option<Vec<u8>> {
86 match self.payload {
87 PL::P(i) => Some(i),
88 PL::C(_) => None,
89 }
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use common::TagClass;
97
98 #[test]
99 fn expect_exact() {
100 let tag = StructureTag {
101 class: TagClass::Application,
102 id: 65u64,
103 payload: PL::C(vec![StructureTag {
104 class: TagClass::Universal,
105 id: 2u64,
106 payload: PL::P(vec![0x16, 0x16]),
107 }]),
108 };
109
110 let out = tag
111 .clone()
112 .match_class(TagClass::Application)
113 .and_then(|x| x.match_id(65u64));
114
115 assert_eq!(out, Some(tag));
116 }
117
118 #[test]
119 fn expect_inner() {
120 let tag = StructureTag {
121 class: TagClass::Application,
122 id: 65u64,
123 payload: PL::C(vec![
124 StructureTag {
125 class: TagClass::Universal,
126 id: 2u64,
127 payload: PL::P(vec![0x16, 0x16]),
128 },
129 StructureTag {
130 class: TagClass::Application,
131 id: 3u64,
132 payload: PL::P(vec![0x3, 0x3]),
133 },
134 ]),
135 };
136
137 let mut subt = tag.expect_constructed().unwrap();
138
139 let b = subt
140 .pop()
141 .unwrap()
142 .match_class(TagClass::Application)
143 .and_then(|x| x.match_id(3));
144 let a = subt
145 .pop()
146 .unwrap()
147 .match_class(TagClass::Universal)
148 .and_then(|x| x.match_id(2));
149
150 assert!(a.is_some());
151 assert!(b.is_some());
152 }
153}