1use std::{fmt, io};
5
6use crate::{ChunkNum, TreeNode};
7
8#[derive(Debug)]
10pub enum DecodeError {
11 ParentNotFound(TreeNode),
13 LeafNotFound(ChunkNum),
15 ParentHashMismatch(TreeNode),
17 LeafHashMismatch(ChunkNum),
19 Io(io::Error),
21}
22
23impl fmt::Display for DecodeError {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 fmt::Debug::fmt(self, f)
26 }
27}
28
29impl std::error::Error for DecodeError {
30 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
31 match self {
32 Self::Io(e) => Some(e),
33 _ => None,
34 }
35 }
36}
37
38impl From<io::Error> for DecodeError {
39 fn from(e: io::Error) -> Self {
40 Self::Io(e)
41 }
42}
43
44impl From<DecodeError> for io::Error {
45 fn from(e: DecodeError) -> Self {
46 match e {
47 DecodeError::Io(e) => e,
48 DecodeError::ParentHashMismatch(node) => io::Error::new(
49 io::ErrorKind::InvalidData,
50 format!(
51 "parent hash mismatch (level {}, block {})",
52 node.level(),
53 node.mid().0
54 ),
55 ),
56 DecodeError::LeafHashMismatch(chunk) => io::Error::new(
57 io::ErrorKind::InvalidData,
58 format!("leaf hash mismatch (offset {})", chunk.to_bytes()),
59 ),
60 DecodeError::LeafNotFound(_) => io::Error::new(io::ErrorKind::UnexpectedEof, e),
61 DecodeError::ParentNotFound(_) => io::Error::new(io::ErrorKind::UnexpectedEof, e),
62 }
63 }
64}
65
66impl DecodeError {
67 pub(crate) fn maybe_parent_not_found(e: io::Error, node: TreeNode) -> Self {
68 if e.kind() == io::ErrorKind::UnexpectedEof {
69 Self::ParentNotFound(node)
70 } else {
71 Self::Io(e)
72 }
73 }
74
75 pub(crate) fn maybe_leaf_not_found(e: io::Error, chunk: ChunkNum) -> Self {
76 if e.kind() == io::ErrorKind::UnexpectedEof {
77 Self::LeafNotFound(chunk)
78 } else {
79 Self::Io(e)
80 }
81 }
82}
83
84#[derive(Debug)]
90#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
91pub enum EncodeError {
92 ParentHashMismatch(TreeNode),
94 LeafHashMismatch(ChunkNum),
96 ParentWrite(TreeNode),
98 LeafWrite(ChunkNum),
100 SizeMismatch,
102 #[cfg_attr(feature = "serde", serde(with = "crate::io_error_serde"))]
104 Io(io::Error),
105}
106
107impl fmt::Display for EncodeError {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 fmt::Debug::fmt(self, f)
110 }
111}
112
113impl std::error::Error for EncodeError {
114 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
115 match self {
116 EncodeError::Io(e) => Some(e),
117 _ => None,
118 }
119 }
120}
121
122impl From<EncodeError> for io::Error {
123 fn from(e: EncodeError) -> Self {
124 match e {
125 EncodeError::Io(e) => e,
126 EncodeError::ParentHashMismatch(node) => io::Error::new(
127 io::ErrorKind::InvalidData,
128 format!(
129 "parent hash mismatch (level {}, block {})",
130 node.level(),
131 node.mid().0
132 ),
133 ),
134 EncodeError::LeafHashMismatch(chunk) => io::Error::new(
135 io::ErrorKind::InvalidData,
136 format!("leaf hash mismatch at {}", chunk.to_bytes()),
137 ),
138 EncodeError::ParentWrite(node) => io::Error::new(
139 io::ErrorKind::ConnectionReset,
140 format!(
141 "parent write failed (level {}, block {})",
142 node.level(),
143 node.mid().0
144 ),
145 ),
146 EncodeError::LeafWrite(chunk) => io::Error::new(
147 io::ErrorKind::ConnectionReset,
148 format!("leaf write failed at {}", chunk.to_bytes()),
149 ),
150 EncodeError::SizeMismatch => {
151 io::Error::new(io::ErrorKind::InvalidData, "size mismatch")
152 }
153 }
154 }
155}
156
157impl From<io::Error> for EncodeError {
158 fn from(e: io::Error) -> Self {
159 Self::Io(e)
160 }
161}
162
163impl EncodeError {
164 #[cfg(feature = "tokio_fsm")]
165 pub(crate) fn maybe_parent_write(e: io::Error, node: TreeNode) -> Self {
166 if e.kind() == io::ErrorKind::ConnectionReset {
167 Self::ParentWrite(node)
168 } else {
169 Self::Io(e)
170 }
171 }
172
173 #[cfg(feature = "tokio_fsm")]
174 pub(crate) fn maybe_leaf_write(e: io::Error, chunk: ChunkNum) -> Self {
175 if e.kind() == io::ErrorKind::ConnectionReset {
176 Self::LeafWrite(chunk)
177 } else {
178 Self::Io(e)
179 }
180 }
181}