Skip to main content

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 {}