qubit_text_codec/error/charset_decode_error.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use core::fmt;
11use std::error::Error;
12
13use crate::{
14 Charset,
15 CharsetDecodeErrorKind,
16};
17
18/// Error reported by a charset decoder.
19///
20/// The error always carries the charset, error kind, and input unit index at
21/// which the failure was detected. Errors that decode a raw numeric value, such
22/// as invalid UTF-32 units, carry that value through [`Self::kind`] and
23/// [`Self::value`].
24#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub struct CharsetDecodeError {
26 /// Charset being decoded when this error was detected.
27 charset: Charset,
28 /// Failure category describing the decoding error.
29 kind: CharsetDecodeErrorKind,
30 /// Input unit index at which decoding failure occurred.
31 index: usize,
32}
33
34/// Result type returned by charset decoders.
35///
36/// # Type Parameters
37///
38/// - `T`: Successful value produced by a decoding operation.
39pub type CharsetDecodeResult<T> = Result<T, CharsetDecodeError>;
40
41impl CharsetDecodeError {
42 /// Creates a decoding error.
43 ///
44 /// # Parameters
45 ///
46 /// - `charset`: The charset being decoded.
47 /// - `kind`: The failure category.
48 /// - `index`: The input unit index where the failure was detected.
49 ///
50 /// # Returns
51 ///
52 /// Returns a decoding error carrying the supplied context.
53 #[inline]
54 pub const fn new(charset: Charset, kind: CharsetDecodeErrorKind, index: usize) -> Self {
55 Self { charset, kind, index }
56 }
57
58 /// Returns the charset being decoded.
59 ///
60 /// # Returns
61 ///
62 /// Returns the stored [`Charset`].
63 #[inline]
64 pub const fn charset(self) -> Charset {
65 self.charset
66 }
67
68 /// Returns the decoding error kind.
69 ///
70 /// # Returns
71 ///
72 /// Returns the stored [`CharsetDecodeErrorKind`].
73 #[inline]
74 pub const fn kind(self) -> CharsetDecodeErrorKind {
75 self.kind
76 }
77
78 /// Returns the input unit index associated with this error.
79 ///
80 /// # Returns
81 ///
82 /// Returns the index at which the error was detected.
83 #[inline]
84 pub const fn index(self) -> usize {
85 self.index
86 }
87
88 /// Returns required input units for this decoding error, if reported.
89 ///
90 /// # Returns
91 ///
92 /// Returns `Some(required)` for [`CharsetDecodeErrorKind::IncompleteSequence`],
93 /// otherwise `None`.
94 #[inline]
95 pub const fn required(self) -> Option<usize> {
96 self.kind.required()
97 }
98
99 /// Returns available input units for this decoding error, if reported.
100 ///
101 /// # Returns
102 ///
103 /// Returns `Some(available)` for [`CharsetDecodeErrorKind::IncompleteSequence`],
104 /// otherwise `None`.
105 #[inline]
106 pub const fn available(self) -> Option<usize> {
107 self.kind.available()
108 }
109
110 /// Returns the raw value associated with this error.
111 ///
112 /// # Returns
113 ///
114 /// Returns `Some(value)` when the error kind carries a raw unit or code
115 /// point value, or `None` for kinds without an associated value.
116 #[inline]
117 pub const fn value(self) -> Option<u32> {
118 self.kind.value()
119 }
120
121 /// Offsets this error by a base unit index.
122 ///
123 /// # Parameters
124 ///
125 /// - `base`: The base index to add to the stored index.
126 ///
127 /// # Returns
128 ///
129 /// Returns a copy of this error with its index shifted by `base`.
130 #[inline]
131 pub const fn offset_by(self, base: usize) -> Self {
132 Self {
133 charset: self.charset,
134 kind: self.kind,
135 index: self.index + base,
136 }
137 }
138}
139
140impl fmt::Display for CharsetDecodeError {
141 /// Formats this decoding error.
142 ///
143 /// # Parameters
144 ///
145 /// - `formatter`: The formatter receiving the diagnostic message.
146 ///
147 /// # Errors
148 ///
149 /// Returns any formatting error reported by `formatter`.
150 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
151 if let Some(value) = self.kind.value() {
152 write!(
153 formatter,
154 "{} decoding error at index {} for value 0x{:x}: {}",
155 self.charset, self.index, value, self.kind,
156 )
157 } else {
158 write!(
159 formatter,
160 "{} decoding error at index {}: {}",
161 self.charset, self.index, self.kind,
162 )
163 }
164 }
165}
166
167impl Error for CharsetDecodeError {}