1 use std::hash::{Hash, Hasher};
2 use std::cmp::Ordering;
3 
4 use crate::packet::Tag;
5 use crate::packet;
6 use crate::Packet;
7 
8 /// Holds an unknown packet.
9 ///
10 /// This is used by the parser to hold packets that it doesn't know
11 /// how to process rather than abort.
12 ///
13 /// This packet effectively holds a binary blob.
14 ///
15 /// # A note on equality
16 ///
17 /// Two `Unknown` packets are considered equal if their tags and their
18 /// bodies are equal.
19 #[derive(Debug)]
20 pub struct Unknown {
21     /// CTB packet header fields.
22     pub(crate) common: packet::Common,
23     /// Packet tag.
24     tag: Tag,
25     /// Error that caused parsing or processing to abort.
26     error: anyhow::Error,
27     /// The unknown data packet is a container packet, but cannot
28     /// store packets.
29     ///
30     /// This is written when serialized, and set by the packet parser
31     /// if `buffer_unread_content` is used.
32     container: packet::Container,
33 }
34 
35 impl PartialEq for Unknown {
eq(&self, other: &Unknown) -> bool36     fn eq(&self, other: &Unknown) -> bool {
37         self.tag == other.tag
38             && self.container == other.container
39     }
40 }
41 
42 impl Eq for Unknown { }
43 
44 impl Hash for Unknown {
hash<H: Hasher>(&self, state: &mut H)45     fn hash<H: Hasher>(&self, state: &mut H) {
46         self.tag.hash(state);
47         self.container.hash(state);
48     }
49 }
50 
51 impl Clone for Unknown {
clone(&self) -> Self52     fn clone(&self) -> Self {
53         Unknown {
54             common: self.common.clone(),
55             tag: self.tag,
56             error: anyhow::anyhow!("{}", self.error),
57             container: self.container.clone(),
58         }
59     }
60 }
61 
62 
63 impl Unknown {
64     /// Returns a new `Unknown` packet.
new(tag: Tag, error: anyhow::Error) -> Self65     pub fn new(tag: Tag, error: anyhow::Error) -> Self {
66         Unknown {
67             common: Default::default(),
68             tag,
69             error,
70             container: packet::Container::default_unprocessed(),
71         }
72     }
73 
74     /// Gets the unknown packet's tag.
tag(&self) -> Tag75     pub fn tag(&self) -> Tag {
76         self.tag
77     }
78 
79     /// Sets the unknown packet's tag.
set_tag(&mut self, tag: Tag) -> Tag80     pub fn set_tag(&mut self, tag: Tag) -> Tag {
81         ::std::mem::replace(&mut self.tag, tag)
82     }
83 
84     /// Gets the unknown packet's error.
85     ///
86     /// This is the error that caused parsing or processing to abort.
error(&self) -> &anyhow::Error87     pub fn error(&self) -> &anyhow::Error {
88         &self.error
89     }
90 
91     /// Sets the unknown packet's error.
92     ///
93     /// This is the error that caused parsing or processing to abort.
set_error(&mut self, error: anyhow::Error) -> anyhow::Error94     pub fn set_error(&mut self, error: anyhow::Error) -> anyhow::Error {
95         ::std::mem::replace(&mut self.error, error)
96     }
97 
98     /// Best effort Ord implementation.
99     ///
100     /// The Cert canonicalization needs to order Unknown packets.
101     /// However, due to potential streaming, Unknown cannot implement
102     /// Eq.  This is cheating a little, we simply ignore the streaming
103     /// case.
104     pub(crate) // For cert/mod.rs
best_effort_cmp(&self, other: &Unknown) -> Ordering105     fn best_effort_cmp(&self, other: &Unknown) -> Ordering {
106         self.tag.cmp(&other.tag).then_with(|| self.body().cmp(&other.body()))
107     }
108 }
109 
110 impl_body_forwards!(Unknown);
111 
112 impl From<Unknown> for Packet {
from(s: Unknown) -> Self113     fn from(s: Unknown) -> Self {
114         Packet::Unknown(s)
115     }
116 }
117