cardano_serialization_lib/chain_crypto/
bech32.rs1use bech32::{Error as Bech32Error, FromBase32, ToBase32};
2use std::error::Error as StdError;
3use std::fmt;
4use std::result::Result as StdResult;
5
6pub type Result<T> = StdResult<T, Error>;
7
8pub trait Bech32 {
9 const BECH32_HRP: &'static str;
10
11 fn try_from_bech32_str(bech32_str: &str) -> Result<Self>
12 where
13 Self: Sized;
14
15 fn to_bech32_str(&self) -> String;
16}
17
18pub fn to_bech32_from_bytes<B: Bech32>(bytes: &[u8]) -> String {
19 bech32::encode(B::BECH32_HRP, bytes.to_base32())
20 .unwrap_or_else(|e| panic!("Failed to build bech32: {}", e))
21 .to_string()
22}
23
24pub fn try_from_bech32_to_bytes<B: Bech32>(bech32_str: &str) -> Result<Vec<u8>> {
25 let (hrp, bech32_data) = bech32::decode(bech32_str)?;
26 if hrp != B::BECH32_HRP {
27 return Err(Error::HrpInvalid {
28 expected: B::BECH32_HRP,
29 actual: hrp,
30 });
31 }
32 Vec::<u8>::from_base32(&bech32_data).map_err(Into::into)
33}
34
35#[derive(Debug)]
36pub enum Error {
37 Bech32Malformed(Bech32Error),
38 HrpInvalid {
39 expected: &'static str,
40 actual: String,
41 },
42 DataInvalid(Box<dyn StdError + Send + Sync + 'static>),
43}
44
45impl Error {
46 pub fn data_invalid(cause: impl StdError + Send + Sync + 'static) -> Self {
47 Error::DataInvalid(Box::new(cause))
48 }
49}
50
51impl From<Bech32Error> for Error {
52 fn from(error: Bech32Error) -> Self {
53 Error::Bech32Malformed(error)
54 }
55}
56
57impl fmt::Display for Error {
58 fn fmt(&self, f: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
59 match self {
60 Error::Bech32Malformed(_) => write!(f, "Failed to parse bech32, invalid data format"),
61 Error::HrpInvalid { expected, actual } => write!(
62 f,
63 "Parsed bech32 has invalid HRP prefix '{}', expected '{}'",
64 actual, expected
65 ),
66 Error::DataInvalid(_) => write!(f, "Failed to parse data decoded from bech32"),
67 }
68 }
69}
70
71impl StdError for Error {
72 fn source(&self) -> Option<&(dyn StdError + 'static)> {
73 match self {
74 Error::Bech32Malformed(cause) => Some(cause),
75 Error::DataInvalid(cause) => Some(&**cause),
76 _ => None,
77 }
78 }
79}