1use serde::{de::DeserializeOwned, Deserialize, Serialize};
2use wincode::{SchemaRead, SchemaReadOwned, SchemaWrite};
3
4use crate::types::{identifiers::FaultyPeer, PeerId, PeerIndex};
5
6mod builder_error;
7
8pub use builder_error::BuilderError;
9
10pub trait Error:
12 std::error::Error
13 + Clone
14 + PartialEq
15 + Eq
16 + Serialize
17 + DeserializeOwned
18 + SchemaReadOwned
19 + SchemaWrite
20 + Send
21 + Sync
22{
23}
24impl<T> Error for T where
25 T: std::error::Error
26 + Clone
27 + PartialEq
28 + Eq
29 + Serialize
30 + DeserializeOwned
31 + SchemaReadOwned
32 + SchemaWrite
33 + Send
34 + Sync
35{
36}
37
38#[derive(
39 thiserror::Error, Debug, Clone, Serialize, Deserialize, SchemaRead, SchemaWrite, PartialEq, Eq,
40)]
41#[repr(C)]
42pub enum PrimitiveError {
43 #[error("Serialization Failed: {0}.")]
45 SerializationFailed(String),
46 #[error("Deserialization Failed: {0}.")]
47 DeserializationFailed(String),
48
49 #[error("Wrong Opening: Expected {0}, got {1}.")]
51 WrongOpening(String, String),
52 #[error("Wrong Opening for {0}: Expected {1}, got {2}.")]
53 WrongOpeningFor(FaultyPeer, String, String),
54 #[error("Wrong Echo from {0}.")]
55 WrongEcho(FaultyPeer),
56 #[error("Wrong signature: {0}.")]
57 WrongSignature(String),
58 #[error("Wrong MAC for {0}: got {1:?}.")]
59 WrongMACFor(FaultyPeer, String),
60 #[error("Wrong MAC: got {0:?}.")]
61 WrongMAC(String),
62 #[error("Wrong correlation. {0}")]
63 WrongCorrelation(String),
64
65 #[error("Invalid Size: expected {0} elements, got {1}")]
67 InvalidSize(usize, usize),
68 #[error("Minimum Length Error: expected at least {0} elements, got {1}")]
69 MinimumLength(usize, usize),
70 #[error("Invalid Parameters: {0}")]
71 InvalidParameters(String),
72 #[error("PeerIndex out of bounds: {0} ∉ [0, {1}].")]
73 InvalidPeerIndex(PeerIndex, usize),
74 #[error("Invalid peer ID: {0}")]
75 InvalidPeerId(PeerId),
76
77 #[error("Zero value sampled for type {0}")]
79 ZeroValueSampled(String),
80}
81
82impl From<quinn::rustls::Error> for PrimitiveError {
83 fn from(err: quinn::rustls::Error) -> Self {
84 PrimitiveError::InvalidParameters(err.to_string())
85 }
86}
87
88impl From<Vec<PrimitiveError>> for PrimitiveError {
89 fn from(errors: Vec<PrimitiveError>) -> Self {
92 if errors.is_empty() {
93 return PrimitiveError::InvalidParameters(
94 "Cannot aggregate an empty list of errors.".to_owned(),
95 );
96 };
97 if errors.len() == 1 {
98 return errors.into_iter().next().unwrap();
99 }
100
101 let (peers, receiver, invalid_errs) = errors.into_iter().fold(
102 (vec![], vec![], vec![]),
103 |(mut peers, mut receiver, mut invalid_errors), e| {
104 match e {
105 PrimitiveError::WrongMACFor(p, r) => {
106 peers.push(p);
107 receiver.push(r);
108 }
109 PrimitiveError::WrongEcho(p) => {
110 peers.push(p);
111 }
112 _ => invalid_errors.push(e.to_string()),
113 }
114 (peers, receiver, invalid_errors)
115 },
116 );
117 if !invalid_errs.is_empty() {
118 return PrimitiveError::InvalidParameters(
119 "Only WrongMACFor|WrongEcho can be aggregated. Got: ".to_owned()
120 + &invalid_errs.join(", "),
121 );
122 }
123 match (peers, receiver.as_slice()) {
124 (peers, []) => PrimitiveError::WrongEcho(FaultyPeer::Multiple(peers)),
125 (peers, receiver) if peers.len() == receiver.len() => {
126 PrimitiveError::WrongMACFor(FaultyPeer::Multiple(peers), receiver.join(", "))
127 }
128 _ => PrimitiveError::InvalidParameters(
129 "All errors must be of the same type to be aggregated".to_owned(),
130 ),
131 }
132 }
133}
134impl PrimitiveError {
135 pub fn blame(self, peer_to_blame: PeerIndex) -> PrimitiveError {
137 match self {
138 PrimitiveError::WrongMAC(receiver) => {
139 PrimitiveError::WrongMACFor(FaultyPeer::Foreign(peer_to_blame), receiver)
140 }
141 PrimitiveError::WrongMACFor(peers, receiver) => {
142 PrimitiveError::WrongMACFor(peers.push(peer_to_blame), receiver)
143 }
144 PrimitiveError::WrongOpening(expected, got) => {
145 PrimitiveError::WrongOpeningFor(FaultyPeer::Foreign(peer_to_blame), expected, got)
146 }
147 PrimitiveError::WrongOpeningFor(peers, expected, got) => {
148 PrimitiveError::WrongOpeningFor(peers.push(peer_to_blame), expected, got)
149 }
150 _ => self,
151 }
152 }
153}