1use serde::{Deserialize, Serialize};
2
3use crate::types::{identifiers::FaultyPeer, PeerIndex};
4
5#[derive(thiserror::Error, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6pub enum PrimitiveError {
7 #[error("Serialization Failed: {0}.")]
9 SerializationFailed(String),
10 #[error("Deserialization Failed: {0}.")]
11 DeserializationFailed(String),
12
13 #[error("Wrong Opening: Expected {0}, got {1}.")]
15 WrongOpening(String, String),
16 #[error("Wrong Echo from {0}.")]
17 WrongEcho(FaultyPeer),
18 #[error("Wrong signature: {0}.")]
19 WrongSignature(String),
20 #[error("Wrong MAC for {0}. Expected {1:?}, got {2:?}.")]
21 WrongMACFor(FaultyPeer, String, String),
22 #[error("Wrong MAC. Expected {0:?}, got {1:?}.")]
23 WrongMAC(String, String),
24 #[error("Wrong correlation. {0}")]
25 WrongCorrelation(String),
26
27 #[error("Invalid Size: expected {0} elements, got {1}")]
29 InvalidSize(usize, usize),
30 #[error("Minimum Length Error: expected at least {0} elements, got {1}")]
31 MinimumLength(usize, usize),
32 #[error("Invalid Parameters: {0}")]
33 InvalidParameters(String),
34 #[error("PeerIndex out of bounds: {0} ∉ [0, {1}].")]
35 InvalidPeerIndex(PeerIndex, usize),
36
37 #[error("Zero value sampled for type {0}")]
39 ZeroValueSampled(String),
40}
41
42impl From<quinn::rustls::Error> for PrimitiveError {
43 fn from(err: quinn::rustls::Error) -> Self {
44 PrimitiveError::InvalidParameters(err.to_string())
45 }
46}
47
48impl From<Vec<PrimitiveError>> for PrimitiveError {
49 fn from(errors: Vec<PrimitiveError>) -> Self {
52 if errors.is_empty() {
53 return PrimitiveError::InvalidParameters(
54 "Cannot aggregate an empty list of errors.".to_owned(),
55 );
56 };
57 if errors.len() == 1 {
58 return errors.into_iter().next().unwrap();
59 }
60
61 let (peers, expect, receiver, invalid_errs) = errors.into_iter().fold(
62 (vec![], vec![], vec![], vec![]),
63 |(mut peers, mut expect, mut receiver, mut invalid_errors), e| {
64 match e {
65 PrimitiveError::WrongMACFor(p, e, r) => {
66 peers.push(p);
67 expect.push(e);
68 receiver.push(r);
69 }
70 PrimitiveError::WrongEcho(p) => {
71 peers.push(p);
72 }
73 _ => invalid_errors.push(e.to_string()),
74 }
75 (peers, expect, receiver, invalid_errors)
76 },
77 );
78 if !invalid_errs.is_empty() {
79 return PrimitiveError::InvalidParameters(
80 "Only WrongMACFor|WrongEcho can be aggregated. Got: ".to_owned()
81 + &invalid_errs.join(", "),
82 );
83 }
84 match (peers, expect.as_slice(), receiver.as_slice()) {
85 (peers, [], []) => PrimitiveError::WrongEcho(FaultyPeer::Multiple(peers)),
86 (peers, expect, receiver) if peers.len() == expect.len() => {
87 PrimitiveError::WrongMACFor(
88 FaultyPeer::Multiple(peers),
89 expect.join(", "),
90 receiver.join(", "),
91 )
92 }
93 _ => PrimitiveError::InvalidParameters(
94 "All errors must be of the same type to be aggregated".to_owned(),
95 ),
96 }
97 }
98}
99impl PrimitiveError {
100 pub(crate) fn blame(self, peer_to_blame: PeerIndex) -> PrimitiveError {
102 match self {
103 PrimitiveError::WrongMAC(expect, receiver) => {
104 PrimitiveError::WrongMACFor(FaultyPeer::Foreign(peer_to_blame), expect, receiver)
105 }
106 PrimitiveError::WrongMACFor(peers, expect, receiver) => {
107 PrimitiveError::WrongMACFor(peers.push(peer_to_blame), expect, receiver)
108 }
109 _ => self,
110 }
111 }
112}