1use crate::{
2 read::Read,
3 types::essential::{convert::bool_from_word, Word},
4};
5use core::fmt::{Debug, Display};
6use thiserror::Error;
7
8pub trait Decode: Sized {
10 type Error: Error;
12 fn decode<R: Read>(r: &mut R) -> Result<Self, Self::Error>;
14}
15
16pub trait Error: Debug + Display {}
18
19pub trait FromReadError {
21 fn from_read_error<E: Debug + Display>(err: E) -> Self;
23}
24
25#[derive(Debug, Error)]
28#[error("failed to read enough bytes: expected `{expected}`, found `{found}`")]
29pub struct NotEnoughWords {
30 pub expected: usize,
32 pub found: usize,
34}
35
36#[derive(Debug, Error)]
38#[error("reader error: {0}")]
39pub struct ReadError(String);
40
41#[derive(Debug, Error)]
43pub enum SizedError {
44 #[error("{0}")]
46 Reader(#[from] ReadError),
47 #[error("{0}")]
49 NotEnoughWords(#[from] NotEnoughWords),
50}
51
52#[derive(Debug, Error)]
54#[error("`bool` expected `0` or `1`, found `{0}`")]
55pub struct BoolInvalid(pub Word);
56
57#[derive(Debug, Error)]
59pub enum BoolError {
60 #[error("{0}")]
62 Sized(#[from] SizedError),
63 #[error("{0}")]
65 Invalid(#[from] BoolInvalid),
66}
67
68#[derive(Debug, Error)]
70pub enum PairError<A, B> {
71 #[error("{0}")]
72 Left(A),
73 #[error("{0}")]
74 Right(B),
75}
76
77impl<T: Debug + Display> Error for T {}
78
79impl FromReadError for ReadError {
80 fn from_read_error<E: Debug + Display>(err: E) -> Self {
81 ReadError(format!("{err}"))
82 }
83}
84
85impl FromReadError for SizedError {
86 fn from_read_error<E: Debug + Display>(err: E) -> Self {
87 Self::Reader(ReadError::from_read_error(err))
88 }
89}
90
91impl FromReadError for BoolError {
92 fn from_read_error<E: Debug + Display>(err: E) -> Self {
93 Self::Sized(SizedError::from_read_error(err))
94 }
95}
96
97impl Decode for Word {
98 type Error = SizedError;
99 fn decode<R: Read>(r: &mut R) -> Result<Self, Self::Error> {
100 let [w] = read_exact(r)?;
101 Ok(w)
102 }
103}
104
105impl Decode for bool {
106 type Error = BoolError;
107 fn decode<R: Read>(r: &mut R) -> Result<Self, Self::Error> {
108 let [w] = read_exact(r)?;
109 bool_from_word(w).ok_or(BoolInvalid(w)).map_err(From::from)
110 }
111}
112
113impl<T> Decode for Option<T>
114where
115 T: Decode,
116{
117 type Error = PairError<T::Error, SizedError>;
118
119 fn decode<R: Read>(r: &mut R) -> Result<Self, Self::Error> {
120 T::decode(r) .map_err(PairError::Left)
122 .and_then(|val| {
123 read_exact(r) .map_err(PairError::Right)
125 .map(|[tag]| if tag == 0 { None } else { Some(val) }) })
127 }
128}
129
130impl<const N: usize, T> Decode for [T; N]
131where
132 T: Decode,
133{
134 type Error = T::Error;
135 fn decode<R: Read>(r: &mut R) -> Result<Self, Self::Error> {
136 let mut vec = Vec::with_capacity(N);
138 for _ in 0..N {
139 vec.push(T::decode(r)?);
140 }
141 let mut elems = vec.into_iter();
142 Ok(core::array::from_fn(|_| {
143 elems.next().expect("Vec gauranteed to have len `N`")
144 }))
145 }
146}
147
148macro_rules! impl_decode_for_tuple {
150 (A, $($T:ident),+) => {
151 #[allow(unused_parens)]
152 impl<A: Decode, $($T: Decode),+> Decode for (A, $($T),+) {
153 type Error = PairError<A::Error, <($($T),+) as Decode>::Error>;
154 fn decode<R: Read>(r: &mut R) -> Result<Self, Self::Error> {
155 let a: A = <_>::decode(r).map_err(PairError::Left)?;
156 #[allow(non_snake_case)]
157 let ($($T),+): ($($T),+) = <_>::decode(r).map_err(PairError::Right)?;
158 Ok((a, $($T),+))
159 }
160 }
161 };
162}
163
164impl_decode_for_tuple!(A, B);
165impl_decode_for_tuple!(A, B, C);
166impl_decode_for_tuple!(A, B, C, D);
167impl_decode_for_tuple!(A, B, C, D, E);
168impl_decode_for_tuple!(A, B, C, D, E, F);
169impl_decode_for_tuple!(A, B, C, D, E, F, G);
170impl_decode_for_tuple!(A, B, C, D, E, F, G, H);
171impl_decode_for_tuple!(A, B, C, D, E, F, G, H, I);
172impl_decode_for_tuple!(A, B, C, D, E, F, G, H, I, J);
173impl_decode_for_tuple!(A, B, C, D, E, F, G, H, I, J, K);
174impl_decode_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
175
176fn read_exact<const N: usize, R: Read>(r: &mut R) -> Result<[Word; N], SizedError> {
177 let mut arr = [0; N];
178 let amt = r.read(&mut arr).map_err(SizedError::from_read_error)?;
179 if amt != N {
180 let err = NotEnoughWords {
181 expected: N,
182 found: amt,
183 };
184 return Err(err.into());
185 }
186 Ok(arr)
187}