widestring/
error.rs

1//! Errors returned by functions in this crate.
2
3#[cfg(feature = "alloc")]
4#[allow(unused_imports)]
5use alloc::vec::Vec;
6
7/// An error returned to indicate a problem with nul values occurred.
8///
9/// The error will either being a [`MissingNulTerminator`] or [`ContainsNul`].
10/// The error optionally returns the ownership of the invalid vector whenever a vector was owned.
11#[derive(Debug, Clone)]
12pub enum NulError<C> {
13    /// A terminating nul value was missing.
14    MissingNulTerminator(MissingNulTerminator),
15    /// An interior nul value was found.
16    ContainsNul(ContainsNul<C>),
17}
18
19impl<C> NulError<C> {
20    /// Consumes this error, returning the underlying vector of values which generated the error in
21    /// the first place.
22    #[inline]
23    #[cfg(feature = "alloc")]
24    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
25    #[must_use]
26    pub fn into_vec(self) -> Option<Vec<C>> {
27        match self {
28            Self::MissingNulTerminator(_) => None,
29            Self::ContainsNul(e) => e.into_vec(),
30        }
31    }
32}
33
34impl<C> core::fmt::Display for NulError<C> {
35    #[inline]
36    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
37        match self {
38            Self::MissingNulTerminator(e) => e.fmt(f),
39            Self::ContainsNul(e) => e.fmt(f),
40        }
41    }
42}
43
44#[cfg(feature = "std")]
45impl<C> std::error::Error for NulError<C>
46where
47    C: core::fmt::Debug + 'static,
48{
49    #[inline]
50    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
51        match self {
52            Self::MissingNulTerminator(e) => Some(e),
53            Self::ContainsNul(e) => Some(e),
54        }
55    }
56}
57
58impl<C> From<MissingNulTerminator> for NulError<C> {
59    #[inline]
60    fn from(value: MissingNulTerminator) -> Self {
61        Self::MissingNulTerminator(value)
62    }
63}
64
65impl<C> From<ContainsNul<C>> for NulError<C> {
66    #[inline]
67    fn from(value: ContainsNul<C>) -> Self {
68        Self::ContainsNul(value)
69    }
70}
71
72/// An error returned from to indicate that a terminating nul value was missing.
73#[derive(Debug, Clone)]
74pub struct MissingNulTerminator {
75    _unused: (),
76}
77
78impl MissingNulTerminator {
79    pub(crate) fn new() -> Self {
80        Self { _unused: () }
81    }
82}
83
84impl core::fmt::Display for MissingNulTerminator {
85    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
86        write!(f, "missing terminating nul value")
87    }
88}
89
90#[cfg(feature = "std")]
91impl std::error::Error for MissingNulTerminator {}
92
93/// An error returned to indicate that an invalid nul value was found in a string.
94///
95/// The error indicates the position in the vector where the nul value was found, as well as
96/// returning the ownership of the invalid vector.
97#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
98#[derive(Debug, Clone)]
99pub struct ContainsNul<C> {
100    index: usize,
101    #[cfg(feature = "alloc")]
102    pub(crate) inner: Option<Vec<C>>,
103    #[cfg(not(feature = "alloc"))]
104    _p: core::marker::PhantomData<C>,
105}
106
107impl<C> ContainsNul<C> {
108    #[cfg(feature = "alloc")]
109    pub(crate) fn new(index: usize, v: Vec<C>) -> Self {
110        Self {
111            index,
112            inner: Some(v),
113        }
114    }
115
116    #[cfg(feature = "alloc")]
117    pub(crate) fn empty(index: usize) -> Self {
118        Self { index, inner: None }
119    }
120
121    #[cfg(not(feature = "alloc"))]
122    pub(crate) fn empty(index: usize) -> Self {
123        Self {
124            index,
125            _p: core::marker::PhantomData,
126        }
127    }
128
129    /// Returns the index of the invalid nul value in the slice.
130    #[inline]
131    #[must_use]
132    pub fn nul_position(&self) -> usize {
133        self.index
134    }
135
136    /// Consumes this error, returning the underlying vector of values which generated the error in
137    /// the first place.
138    ///
139    /// If the sequence that generated the error was a reference to a slice instead of a [`Vec`],
140    /// this will return [`None`].
141    #[inline]
142    #[cfg(feature = "alloc")]
143    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
144    #[must_use]
145    pub fn into_vec(self) -> Option<Vec<C>> {
146        self.inner
147    }
148}
149
150impl<C> core::fmt::Display for ContainsNul<C> {
151    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
152        write!(f, "invalid nul value found at position {}", self.index)
153    }
154}
155
156#[cfg(feature = "std")]
157impl<C> std::error::Error for ContainsNul<C> where C: core::fmt::Debug {}
158
159/// An error that can be returned when decoding UTF-16 code points.
160///
161/// This struct is created when using the [`DecodeUtf16`][crate::iter::DecodeUtf16] iterator.
162#[derive(Debug, Clone, PartialEq, Eq)]
163pub struct DecodeUtf16Error {
164    unpaired_surrogate: u16,
165}
166
167impl DecodeUtf16Error {
168    pub(crate) fn new(unpaired_surrogate: u16) -> Self {
169        Self { unpaired_surrogate }
170    }
171
172    /// Returns the unpaired surrogate which caused this error.
173    #[must_use]
174    pub fn unpaired_surrogate(&self) -> u16 {
175        self.unpaired_surrogate
176    }
177}
178
179impl core::fmt::Display for DecodeUtf16Error {
180    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181        write!(f, "unpaired surrogate found: {:x}", self.unpaired_surrogate)
182    }
183}
184
185#[cfg(feature = "std")]
186impl std::error::Error for DecodeUtf16Error {}
187
188/// An error that can be returned when decoding UTF-32 code points.
189///
190/// This error occurs when a [`u32`] value is outside the 21-bit Unicode code point range
191/// (>`U+10FFFF`) or is a UTF-16 surrogate value.
192#[derive(Debug, Clone)]
193pub struct DecodeUtf32Error {
194    code: u32,
195}
196
197impl DecodeUtf32Error {
198    pub(crate) fn new(code: u32) -> Self {
199        Self { code }
200    }
201
202    /// Returns the invalid code point value which caused the error.
203    #[must_use]
204    pub fn invalid_code_point(&self) -> u32 {
205        self.code
206    }
207}
208
209impl core::fmt::Display for DecodeUtf32Error {
210    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211        write!(f, "invalid UTF-32 code point: {:x}", self.code)
212    }
213}
214
215#[cfg(feature = "std")]
216impl std::error::Error for DecodeUtf32Error {}
217
218/// Errors which can occur when attempting to interpret a sequence of `u16` as UTF-16.
219#[derive(Debug, Clone)]
220pub struct Utf16Error {
221    index: usize,
222    source: DecodeUtf16Error,
223    #[cfg(feature = "alloc")]
224    inner: Option<Vec<u16>>,
225}
226
227impl Utf16Error {
228    #[cfg(feature = "alloc")]
229    pub(crate) fn new(inner: Vec<u16>, index: usize, source: DecodeUtf16Error) -> Self {
230        Self {
231            inner: Some(inner),
232            index,
233            source,
234        }
235    }
236
237    #[cfg(feature = "alloc")]
238    pub(crate) fn empty(index: usize, source: DecodeUtf16Error) -> Self {
239        Self {
240            index,
241            source,
242            inner: None,
243        }
244    }
245
246    #[cfg(not(feature = "alloc"))]
247    pub(crate) fn empty(index: usize, source: DecodeUtf16Error) -> Self {
248        Self { index, source }
249    }
250
251    /// Returns the index in the given string at which the invalid UTF-16 value occurred.
252    #[must_use]
253    pub fn index(&self) -> usize {
254        self.index
255    }
256
257    /// Consumes this error, returning the underlying vector of values which generated the error in
258    /// the first place.
259    ///
260    /// If the sequence that generated the error was a reference to a slice instead of a [`Vec`],
261    /// this will return [`None`].
262    #[inline]
263    #[cfg(feature = "alloc")]
264    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
265    #[must_use]
266    pub fn into_vec(self) -> Option<Vec<u16>> {
267        self.inner
268    }
269}
270
271impl core::fmt::Display for Utf16Error {
272    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
273        write!(
274            f,
275            "unpaired UTF-16 surrogate {:x} at index {}",
276            self.source.unpaired_surrogate(),
277            self.index
278        )
279    }
280}
281
282#[cfg(feature = "std")]
283impl std::error::Error for Utf16Error {
284    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
285        Some(&self.source)
286    }
287}
288
289/// Errors which can occur when attempting to interpret a sequence of `u32` as UTF-32.
290#[derive(Debug, Clone)]
291pub struct Utf32Error {
292    index: usize,
293    source: DecodeUtf32Error,
294    #[cfg(feature = "alloc")]
295    inner: Option<Vec<u32>>,
296}
297
298impl Utf32Error {
299    #[cfg(feature = "alloc")]
300    pub(crate) fn new(inner: Vec<u32>, index: usize, source: DecodeUtf32Error) -> Self {
301        Self {
302            inner: Some(inner),
303            index,
304            source,
305        }
306    }
307
308    #[cfg(feature = "alloc")]
309    pub(crate) fn empty(index: usize, source: DecodeUtf32Error) -> Self {
310        Self {
311            index,
312            source,
313            inner: None,
314        }
315    }
316
317    #[cfg(not(feature = "alloc"))]
318    pub(crate) fn empty(index: usize, source: DecodeUtf32Error) -> Self {
319        Self { index, source }
320    }
321
322    /// Returns the index in the given string at which the invalid UTF-32 value occurred.
323    #[must_use]
324    pub fn index(&self) -> usize {
325        self.index
326    }
327
328    /// Consumes this error, returning the underlying vector of values which generated the error in
329    /// the first place.
330    ///
331    /// If the sequence that generated the error was a reference to a slice instead of a [`Vec`],
332    /// this will return [`None`].
333    #[inline]
334    #[cfg(feature = "alloc")]
335    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
336    #[must_use]
337    pub fn into_vec(self) -> Option<Vec<u32>> {
338        self.inner
339    }
340}
341
342impl core::fmt::Display for Utf32Error {
343    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
344        write!(
345            f,
346            "invalid UTF-32 value {:x} at index {}",
347            self.source.invalid_code_point(),
348            self.index
349        )
350    }
351}
352
353#[cfg(feature = "std")]
354impl std::error::Error for Utf32Error {
355    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
356        Some(&self.source)
357    }
358}