1use crate::IngressECIESValue;
2use std::fmt;
3use thiserror::Error;
45/// An error that occurs while reading or writing to an ECIES stream.
6#[derive(Debug, Error)]
7pub struct ECIESError {
8 inner: Box<ECIESErrorImpl>,
9}
1011impl ECIESError {
12/// Consumes the type and returns the error enum
13pub fn into_inner(self) -> ECIESErrorImpl {
14*self.inner
15 }
1617/// Returns a reference to the inner error
18pub const fn inner(&self) -> &ECIESErrorImpl {
19&self.inner
20 }
21}
2223impl fmt::Displayfor ECIESError {
24fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25fmt::Display::fmt(&*self.inner, f)
26 }
27}
2829/// An error that occurs while reading or writing to an ECIES stream.
30#[derive(Debug, Error)]
31pub enum ECIESErrorImpl {
32/// Error during IO
33#[error(transparent)]
34IO(std::io::Error),
35/// Error when checking the HMAC tag against the tag on the message being decrypted
36#[error("tag check failure in read_header")]
37TagCheckDecryptFailed,
38/// Error when checking the HMAC tag against the tag on the header
39#[error("tag check failure in read_header")]
40TagCheckHeaderFailed,
41/// Error when checking the HMAC tag against the tag on the body
42#[error("tag check failure in read_body")]
43TagCheckBodyFailed,
44/// Error when parsing AUTH data
45#[error("invalid auth data")]
46InvalidAuthData,
47/// Error when parsing ACK data
48#[error("invalid ack data")]
49InvalidAckData,
50/// Error when reading the header if its length is <3
51#[error("invalid body data")]
52InvalidHeader,
53/// Error when interacting with secp256k1
54#[error(transparent)]
55Secp256k1(secp256k1::Error),
56/// Error when decoding RLP data
57#[error(transparent)]
58RLPDecoding(alloy_rlp::Error),
59/// Error when converting to integer
60#[error(transparent)]
61FromInt(std::num::TryFromIntError),
62/// The encrypted data is not large enough for all fields
63#[error("encrypted data is not large enough for all fields")]
64EncryptedDataTooSmall,
65/// The initial header body is too large.
66#[error("initial header body is {body_size} but the max is {max_body_size}")]
67InitialHeaderBodyTooLarge {
68/// The body size from the header
69body_size: usize,
70/// The max body size
71max_body_size: usize,
72 },
73/// Error when trying to split an array beyond its length
74#[error("requested {idx} but array len is {len}")]
75OutOfBounds {
76/// The index you are trying to split at
77idx: usize,
78/// The length of the array
79len: usize,
80 },
81/// Error when handshaking with a peer (ack / auth)
82#[error("invalid handshake: expected {expected:?}, got {msg:?} instead")]
83InvalidHandshake {
84/// The expected return value from the peer
85expected: IngressECIESValue,
86/// The actual value returned from the peer
87msg: Option<IngressECIESValue>,
88 },
89/// Error when the stream was closed by the peer for being unreadable.
90 ///
91 /// This exact error case happens when the wrapped stream in
92 /// [`Framed`](tokio_util::codec::Framed) is closed by the peer, See
93 /// [`ConnectionReset`](std::io::ErrorKind::ConnectionReset) and the ecies codec fails to
94 /// decode a message from the (partially filled) buffer.
95#[error("stream closed due to not being readable")]
96UnreadableStream,
97/// Error when data is not received from peer for a prolonged period.
98#[error("never received data from remote peer")]
99StreamTimeout,
100}
101102impl From<ECIESErrorImpl> for ECIESError {
103fn from(source: ECIESErrorImpl) -> Self {
104Self { inner: Box::new(source) }
105 }
106}
107108impl From<std::io::Error> for ECIESError {
109fn from(source: std::io::Error) -> Self {
110ECIESErrorImpl::IO(source).into()
111 }
112}
113114impl From<secp256k1::Error> for ECIESError {
115fn from(source: secp256k1::Error) -> Self {
116ECIESErrorImpl::Secp256k1(source).into()
117 }
118}
119120impl From<alloy_rlp::Error> for ECIESError {
121fn from(source: alloy_rlp::Error) -> Self {
122ECIESErrorImpl::RLPDecoding(source).into()
123 }
124}
125126impl From<std::num::TryFromIntError> for ECIESError {
127fn from(source: std::num::TryFromIntError) -> Self {
128ECIESErrorImpl::FromInt(source).into()
129 }
130}