Skip to main content

multi_base/
error.rs

1// SPDX-License-Identifier: MIT
2
3#[cfg(not(feature = "std"))]
4use alloc::format;
5
6/// Type alias to use this library's [`Error`] type in a `Result`.
7pub type Result<T> = core::result::Result<T, Error>;
8
9/// Error types for multibase operations.
10///
11/// This enum uses `thiserror` for ergonomic error handling.
12///
13/// # Non-exhaustive
14///
15/// This enum is marked `#[non_exhaustive]` to allow adding new error variants
16/// in the future without breaking changes.
17#[derive(Debug, thiserror::Error)]
18#[non_exhaustive]
19pub enum Error {
20    /// Unknown base code encountered.
21    ///
22    /// The provided character does not correspond to any known base encoding
23    /// in the multibase specification.
24    #[error("unknown base code: {code}")]
25    UnknownBase {
26        /// The invalid base code character.
27        code: char,
28    },
29
30    /// Invalid base string format.
31    ///
32    /// The string could not be decoded using the specified base encoding.
33    /// This is a generic decoding error when the specific cause is unknown.
34    #[error("invalid base string")]
35    InvalidBaseString,
36
37    /// Base-x decoding failed.
38    ///
39    /// Used for Base10, Base36, and Base58 variants that use the `base-x` library.
40    #[error("base-x decoding failed")]
41    BaseXDecode,
42
43    /// Base256Emoji decoding failed.
44    ///
45    /// The input string contained invalid emoji sequences or could not be
46    /// decoded as Base256Emoji.
47    #[error("base256emoji decoding failed")]
48    Base256EmojiDecode,
49
50    /// Data-encoding decoding failed.
51    ///
52    /// Used for Base2, Base8, Base16, Base32, Base64 variants that use
53    /// the `data-encoding` library.
54    #[error("data-encoding decoding failed: {message}")]
55    DataEncodingDecode {
56        /// The error message from data-encoding.
57        #[cfg(feature = "std")]
58        message: std::string::String,
59        /// The error message from data-encoding (no_std).
60        #[cfg(not(feature = "std"))]
61        message: alloc::string::String,
62    },
63
64    /// Empty input string.
65    ///
66    /// The decode function was called with an empty string, which cannot
67    /// contain a valid base code prefix.
68    #[error("empty input string")]
69    EmptyInput,
70}
71
72// Implement PartialEq
73impl PartialEq for Error {
74    fn eq(&self, other: &Self) -> bool {
75        match (self, other) {
76            (Error::UnknownBase { code: c1 }, Error::UnknownBase { code: c2 }) => c1 == c2,
77            (Error::InvalidBaseString, Error::InvalidBaseString) => true,
78            (Error::EmptyInput, Error::EmptyInput) => true,
79            (Error::BaseXDecode, Error::BaseXDecode) => true,
80            (Error::Base256EmojiDecode, Error::Base256EmojiDecode) => true,
81            (
82                Error::DataEncodingDecode { message: m1 },
83                Error::DataEncodingDecode { message: m2 },
84            ) => m1 == m2,
85            _ => false,
86        }
87    }
88}
89
90// Implement Eq
91impl Eq for Error {}
92
93// Implement Clone
94impl Clone for Error {
95    fn clone(&self) -> Self {
96        match self {
97            Error::UnknownBase { code } => Error::UnknownBase { code: *code },
98            Error::InvalidBaseString => Error::InvalidBaseString,
99            Error::BaseXDecode => Error::BaseXDecode,
100            Error::Base256EmojiDecode => Error::Base256EmojiDecode,
101            Error::DataEncodingDecode { message } => Error::DataEncodingDecode {
102                message: message.clone(),
103            },
104            Error::EmptyInput => Error::EmptyInput,
105        }
106    }
107}
108
109// Manual From implementations for error conversions
110impl From<base_x::DecodeError> for Error {
111    fn from(_: base_x::DecodeError) -> Self {
112        Error::BaseXDecode
113    }
114}
115
116impl From<data_encoding::DecodeError> for Error {
117    fn from(err: data_encoding::DecodeError) -> Self {
118        #[cfg(feature = "std")]
119        let message = std::format!("{}", err);
120        #[cfg(not(feature = "std"))]
121        let message = format!("{}", err);
122
123        Error::DataEncodingDecode { message }
124    }
125}