// SPDX-License-Identifier: CC0-1.0 //! Error code for the `base58` crate. use core::convert::Infallible; use core::fmt; use internals::write_err; /// An error occurred during base58 decoding (with checksum). #[derive(Debug, Clone, PartialEq, Eq)] pub struct Error(pub(super) ErrorInner); #[derive(Debug, Clone, PartialEq, Eq)] pub(super) enum ErrorInner { /// Invalid character while decoding. Decode(InvalidCharacterError), /// Checksum was not correct. IncorrectChecksum(IncorrectChecksumError), /// Checked data was too short. TooShort(TooShortError), } impl From for Error { fn from(never: Infallible) -> Self { match never {} } } impl From for ErrorInner { fn from(never: Infallible) -> Self { match never {} } } impl Error { /// Returns the invalid base58 ssscharacter, if encountered. pub fn invalid_character(&self) -> Option { match self.0 { ErrorInner::Decode(ref e) => Some(e.invalid_character()), _ => None, } } /// Returns the incorrect checksum along with the expected checksum, if encountered. pub fn incorrect_checksum(&self) -> Option<(u32, u32)> { match self.0 { ErrorInner::IncorrectChecksum(ref e) => Some((e.incorrect, e.expected)), _ => None, } } /// Returns the invalid base58 string length (require at least 4 bytes for checksum), if encountered. pub fn invalid_length(&self) -> Option { match self.0 { ErrorInner::TooShort(ref e) => Some(e.length), _ => None, } } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use ErrorInner::*; match self.0 { Decode(ref e) => write_err!(f, "decode"; e), IncorrectChecksum(ref e) => write_err!(f, "incorrect checksum"; e), TooShort(ref e) => write_err!(f, "too short"; e), } } } #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { use ErrorInner::*; match self.0 { Decode(ref e) => Some(e), IncorrectChecksum(ref e) => Some(e), TooShort(ref e) => Some(e), } } } impl From for Error { fn from(e: InvalidCharacterError) -> Self { Self(ErrorInner::Decode(e)) } } impl From for Error { fn from(e: IncorrectChecksumError) -> Self { Self(ErrorInner::IncorrectChecksum(e)) } } impl From for Error { fn from(e: TooShortError) -> Self { Self(ErrorInner::TooShort(e)) } } /// Checksum was not correct. #[derive(Debug, Clone, PartialEq, Eq)] pub(super) struct IncorrectChecksumError { /// The incorrect checksum. pub(super) incorrect: u32, /// The expected checksum. pub(super) expected: u32, } impl From for IncorrectChecksumError { fn from(never: Infallible) -> Self { match never {} } } impl fmt::Display for IncorrectChecksumError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "base58 checksum {:#x} does not match expected {:#x}", self.incorrect, self.expected ) } } #[cfg(feature = "std")] impl std::error::Error for IncorrectChecksumError {} /// The decode base58 data was too short (require at least 4 bytes for checksum). #[derive(Debug, Clone, PartialEq, Eq)] pub(super) struct TooShortError { /// The length of the decoded data. pub(super) length: usize, } impl From for TooShortError { fn from(never: Infallible) -> Self { match never {} } } impl fmt::Display for TooShortError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "base58 decoded data was not long enough, must be at least 4 byte: {}", self.length ) } } #[cfg(feature = "std")] impl std::error::Error for TooShortError {} /// Found a invalid ASCII byte while decoding base58 string. #[derive(Debug, Clone, PartialEq, Eq)] pub struct InvalidCharacterError(pub(super) InvalidCharacterErrorInner); #[derive(Debug, Clone, PartialEq, Eq)] pub(super) struct InvalidCharacterErrorInner { pub(super) invalid: u8, } impl From for InvalidCharacterError { fn from(never: Infallible) -> Self { match never {} } } impl From for InvalidCharacterErrorInner { fn from(never: Infallible) -> Self { match never {} } } impl InvalidCharacterError { pub(super) fn new(invalid: u8) -> Self { Self(InvalidCharacterErrorInner { invalid }) } /// Returns the invalid base58 character. pub fn invalid_character(&self) -> u8 { self.0.invalid } } impl fmt::Display for InvalidCharacterError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "invalid base58 character {:#x}", self.0.invalid) } } #[cfg(feature = "std")] impl std::error::Error for InvalidCharacterError {}