cfx_addr/
errors.rs

1// Copyright 2021 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4//
5// Modification based on https://github.com/hlb8122/rust-bitcoincash-addr in MIT License.
6// A copy of the original license is included in LICENSE.rust-bitcoincash-addr.
7
8use super::consts::AddressType;
9
10use std::{error::Error, fmt};
11
12/// Error concerning encoding of cfx_base32_addr.
13#[derive(Debug, PartialEq, Eq, Clone)]
14pub enum EncodingError {
15    InvalidAddressType(u8),
16    InvalidLength(usize),
17    InvalidNetworkId(u64),
18}
19
20impl fmt::Display for EncodingError {
21    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22        match self {
23            Self::InvalidAddressType(type_byte) => {
24                write!(f, "unrecognized type bits 0x{:02x}", type_byte)
25            }
26            Self::InvalidLength(length) => {
27                write!(f, "invalid length ({})", length)
28            }
29            Self::InvalidNetworkId(network_id) => {
30                write!(f, "invalid network_id (reserved: {})", network_id)
31            }
32        }
33    }
34}
35
36impl Error for EncodingError {
37    fn cause(&self) -> Option<&dyn Error> { None }
38
39    fn description(&self) -> &str { "invalid length" }
40}
41
42/// Error concerning decoding of cfx_base32_addr.
43#[derive(Debug, PartialEq, Eq, Clone)]
44pub enum DecodingError {
45    /// Invalid length (length).
46    InvalidLength(usize),
47    /// Zero or multiple prefixes.
48    NoPrefix,
49    /// Failed to match known prefixes (prefix).
50    InvalidPrefix(String),
51    /// Failed to match known options.
52    InvalidOption(OptionError),
53    /// Checksum failed (checksum).
54    ChecksumFailed(u64),
55    /// Unexpected character (char).
56    InvalidChar(char),
57    /// Padding is invalid. Either padding_bits > from_bits or
58    /// padding is non-zero.
59    InvalidPadding {
60        from_bits: u8,
61        padding_bits: u8,
62        padding: u16,
63    },
64    /// Version byte was not recognized.
65    VersionNotRecognized(u8),
66    /// Upper and lowercase address string.
67    MixedCase,
68}
69
70#[derive(Debug, PartialEq, Eq, Clone)]
71pub enum OptionError {
72    /// The option string isn't in a valid format.
73    ParseError(String),
74    /// The address type specified in option doesn't match the decoded address.
75    /// The got can be an Err(()) because decoded address may have invalid
76    /// address type.
77    AddressTypeMismatch {
78        expected: AddressType,
79        got: Result<AddressType, ()>,
80    },
81    /// The address type is invalid.
82    InvalidAddressType(String),
83}
84
85impl fmt::Display for DecodingError {
86    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87        match self {
88            DecodingError::ChecksumFailed(actual) => {
89                write!(f, "invalid checksum (actual {} != 0)", actual)
90            }
91            DecodingError::InvalidChar(index) => {
92                write!(f, "invalid char ({})", index)
93            }
94            DecodingError::InvalidLength(length) => {
95                write!(f, "invalid length ({})", length)
96            }
97            DecodingError::InvalidPadding {
98                from_bits,
99                padding_bits,
100                padding,
101            } => {
102                write!(f, "invalid padding (")?;
103                if padding_bits >= from_bits {
104                    write!(
105                        f,
106                        "padding_bits({}) >= from_bits({})",
107                        padding_bits, from_bits
108                    )?;
109                    if *padding != 0 {
110                        write!(f, ", padding({:#b}) is non-zero)", padding)?;
111                    }
112                } else {
113                    write!(f, "padding({:#b}) is non-zero)", padding)?;
114                }
115                Ok(())
116            }
117            DecodingError::InvalidPrefix(prefix) => {
118                write!(f, "invalid prefix ({})", prefix)
119            }
120            DecodingError::InvalidOption(option_error) => match option_error {
121                OptionError::AddressTypeMismatch { expected, got } => {
122                    write!(f, "expected address type specified in option {:?}, decoded address type {:?}", expected, got)
123                }
124                OptionError::ParseError(option_str) => {
125                    write!(f, "invalid option string ({})", option_str)
126                }
127                OptionError::InvalidAddressType(type_str) => {
128                    write!(f, "invalid address type ({})", type_str)
129                }
130            },
131            DecodingError::NoPrefix => write!(f, "zero or multiple prefixes"),
132            DecodingError::MixedCase => write!(f, "mixed case string"),
133            DecodingError::VersionNotRecognized(c) => {
134                write!(f, "version byte ({}) not recognized", c)
135            }
136        }
137    }
138}
139
140impl Error for DecodingError {
141    fn cause(&self) -> Option<&dyn Error> { None }
142
143    fn description(&self) -> &str {
144        match self {
145            DecodingError::ChecksumFailed { .. } => "invalid checksum",
146            DecodingError::InvalidChar(_) => "invalid char",
147            DecodingError::InvalidLength(_) => "invalid length",
148            DecodingError::InvalidOption(option_error) => match option_error {
149                OptionError::AddressTypeMismatch { .. } => {
150                    "decoded address does not match address type in option"
151                }
152                OptionError::ParseError(_) => "invalid option",
153                OptionError::InvalidAddressType(_) => "invalid address type",
154            },
155            DecodingError::InvalidPadding { .. } => "invalid padding",
156            DecodingError::InvalidPrefix(_) => "invalid prefix",
157            DecodingError::NoPrefix => "zero or multiple prefixes",
158            DecodingError::MixedCase => "mixed case string",
159            DecodingError::VersionNotRecognized(_) => {
160                "version byte not recognized"
161            }
162        }
163    }
164}