qubit_codec/transcode/
transcode_error.rs1use thiserror::Error;
11
12use super::capacity_error::CapacityError;
13
14#[derive(Clone, Copy, Debug, Eq, Error, Hash, PartialEq)]
24pub enum TranscodeError<E> {
25 #[error("invalid input index {index} for input length {len}")]
27 InvalidInputIndex {
28 index: usize,
30 len: usize,
32 },
33
34 #[error("invalid output index {index} for output length {len}")]
36 InvalidOutputIndex {
37 index: usize,
39 len: usize,
41 },
42
43 #[error(
45 "insufficient output at index {output_index}: required {required} units, available {available}"
46 )]
47 InsufficientOutput {
48 output_index: usize,
50 required: usize,
52 available: usize,
54 },
55
56 #[error("output length arithmetic overflow")]
58 OutputLengthOverflow,
59
60 #[error("{0}")]
62 Domain(#[source] E),
63}
64
65impl<E> TranscodeError<E> {
66 pub const fn domain(error: E) -> Self {
76 Self::Domain(error)
77 }
78
79 #[must_use]
81 pub const fn invalid_input_index(index: usize, len: usize) -> Self {
82 Self::InvalidInputIndex { index, len }
83 }
84
85 #[must_use]
87 pub const fn invalid_output_index(index: usize, len: usize) -> Self {
88 Self::InvalidOutputIndex { index, len }
89 }
90
91 #[must_use]
93 pub const fn insufficient_output(
94 output_index: usize,
95 required: usize,
96 available: usize,
97 ) -> Self {
98 Self::InsufficientOutput {
99 output_index,
100 required,
101 available,
102 }
103 }
104
105 #[must_use]
107 pub const fn output_length_overflow() -> Self {
108 Self::OutputLengthOverflow
109 }
110
111 #[must_use]
117 pub const fn is_domain(&self) -> bool {
118 matches!(self, Self::Domain(_))
119 }
120
121 #[must_use]
128 pub const fn domain_ref(&self) -> Option<&E> {
129 match self {
130 Self::Domain(error) => Some(error),
131 Self::InvalidInputIndex { .. }
132 | Self::InvalidOutputIndex { .. }
133 | Self::InsufficientOutput { .. }
134 | Self::OutputLengthOverflow => None,
135 }
136 }
137
138 #[inline]
153 pub fn map_domain<F, T>(self, f: F) -> TranscodeError<T>
154 where
155 F: FnOnce(E) -> T,
156 {
157 match self {
158 Self::InvalidInputIndex { index, len } => {
159 TranscodeError::InvalidInputIndex { index, len }
160 }
161 Self::InvalidOutputIndex { index, len } => {
162 TranscodeError::InvalidOutputIndex { index, len }
163 }
164 Self::InsufficientOutput {
165 output_index,
166 required,
167 available,
168 } => TranscodeError::InsufficientOutput {
169 output_index,
170 required,
171 available,
172 },
173 Self::OutputLengthOverflow => TranscodeError::OutputLengthOverflow,
174 Self::Domain(error) => TranscodeError::Domain(f(error)),
175 }
176 }
177
178 #[inline]
180 pub fn ensure_input_index(
181 input_len: usize,
182 input_index: usize,
183 ) -> Result<(), Self> {
184 if input_index > input_len {
185 return Err(Self::invalid_input_index(input_index, input_len));
186 }
187 Ok(())
188 }
189
190 #[inline]
192 pub fn ensure_output_index(
193 output_len: usize,
194 output_index: usize,
195 ) -> Result<(), Self> {
196 if output_index > output_len {
197 return Err(Self::invalid_output_index(output_index, output_len));
198 }
199 Ok(())
200 }
201
202 #[inline]
204 pub fn ensure_transcode_indices(
205 input_len: usize,
206 input_index: usize,
207 output_len: usize,
208 output_index: usize,
209 ) -> Result<(), Self> {
210 Self::ensure_input_index(input_len, input_index)?;
211 Self::ensure_output_index(output_len, output_index)
212 }
213
214 #[inline]
216 pub fn ensure_output_capacity(
217 output_len: usize,
218 output_index: usize,
219 required: usize,
220 ) -> Result<(), Self> {
221 Self::ensure_output_index(output_len, output_index)?;
222 let available = output_len - output_index;
223 if available < required {
224 return Err(Self::insufficient_output(
225 output_index,
226 required,
227 available,
228 ));
229 }
230 Ok(())
231 }
232
233 #[inline]
235 pub fn ensure_output_range(
236 output_len: usize,
237 output_index: usize,
238 range_len: usize,
239 required: usize,
240 ) -> Result<(), Self> {
241 Self::ensure_output_index(output_len, output_index)?;
242 if !qubit_io::UncheckedSlice::range_fits(
243 output_len,
244 output_index,
245 range_len,
246 ) {
247 return Err(Self::invalid_output_index(output_index, output_len));
248 }
249 if range_len < required {
250 return Err(Self::insufficient_output(
251 output_index,
252 required,
253 range_len,
254 ));
255 }
256 Ok(())
257 }
258}
259
260impl<E> From<CapacityError> for TranscodeError<E> {
261 #[inline(always)]
263 fn from(error: CapacityError) -> Self {
264 match error {
265 CapacityError::OutputLengthOverflow => Self::OutputLengthOverflow,
266 }
267 }
268}