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