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