1use crate::common::TagClass;
2
3#[derive(Clone, PartialEq, Debug, Eq)]
5pub struct StructureTag {
6 pub class: TagClass,
7 pub id: u64,
8 pub payload: PL,
9}
10
11#[derive(Clone, PartialEq, Debug, Eq)]
13pub enum PL {
14 P(Vec<u8>),
16 C(Vec<StructureTag>),
18}
19
20impl StructureTag {
21 pub fn match_class(self, class: TagClass) -> Option<Self> {
22 if self.class == class {
23 Some(self)
24 } else {
25 None
26 }
27 }
28
29 pub fn match_id(self, id: u64) -> Option<Self> {
30 if self.id == id { Some(self) } else { None }
31 }
32
33 pub fn expect_constructed(self) -> Option<Vec<StructureTag>> {
34 match self.payload {
35 PL::P(_) => None,
36 PL::C(i) => Some(i),
37 }
38 }
39
40 pub fn expect_primitive(self) -> Option<Vec<u8>> {
41 match self.payload {
42 PL::P(i) => Some(i),
43 PL::C(_) => None,
44 }
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use crate::common::TagClass;
52
53 #[test]
54 fn expect_exact() {
55 let tag = StructureTag {
56 class: TagClass::Application,
57 id: 65u64,
58 payload: PL::C(vec![StructureTag {
59 class: TagClass::Universal,
60 id: 2u64,
61 payload: PL::P(vec![0x16, 0x16]),
62 }]),
63 };
64
65 let out = tag
66 .clone()
67 .match_class(TagClass::Application)
68 .and_then(|x| x.match_id(65u64));
69
70 assert_eq!(out, Some(tag));
71 }
72
73 #[test]
74 fn expect_inner() {
75 let tag = StructureTag {
76 class: TagClass::Application,
77 id: 65u64,
78 payload: PL::C(vec![
79 StructureTag {
80 class: TagClass::Universal,
81 id: 2u64,
82 payload: PL::P(vec![0x16, 0x16]),
83 },
84 StructureTag {
85 class: TagClass::Application,
86 id: 3u64,
87 payload: PL::P(vec![0x3, 0x3]),
88 },
89 ]),
90 };
91
92 let mut subt = tag.expect_constructed().unwrap();
93
94 let b = subt
95 .pop()
96 .unwrap()
97 .match_class(TagClass::Application)
98 .and_then(|x| x.match_id(3));
99 let a = subt
100 .pop()
101 .unwrap()
102 .match_class(TagClass::Universal)
103 .and_then(|x| x.match_id(2));
104
105 assert!(a.is_some());
106 assert!(b.is_some());
107 }
108}