secure_gate/traits/decoding/
bech32.rs1#[cfg(feature = "encoding-bech32")]
4use super::super::helpers::bech32::{encode_lower, Bech32Large, Fe32, Fe32IterExt, Hrp};
5#[cfg(feature = "encoding-bech32")]
6use crate::error::Bech32Error;
7
8#[cfg(feature = "encoding-bech32")]
9pub trait FromBech32Str {
18 fn try_from_bech32(&self) -> Result<(String, Vec<u8>), Bech32Error>;
20
21 fn try_from_bech32_expect_hrp(&self, expected_hrp: &str) -> Result<Vec<u8>, Bech32Error>;
23}
24
25#[cfg(feature = "encoding-bech32")]
27impl<T: AsRef<str> + ?Sized> FromBech32Str for T {
28 fn try_from_bech32(&self) -> Result<(String, Vec<u8>), Bech32Error> {
29 let s = self.as_ref();
30 if let Some(pos) = s.find('1') {
31 let hrp_str = &s[..pos];
32 let data_str = &s[pos + 1..];
33 let hrp = Hrp::parse(hrp_str).map_err(|_| Bech32Error::InvalidHrp)?;
34 if data_str.len() < 6 {
36 return Err(Bech32Error::OperationFailed);
37 }
38 let data_part = &data_str[..data_str.len() - 6];
39 let mut fe32s = Vec::new();
40 for c in data_part.chars() {
41 let fe = Fe32::from_char(c).map_err(|_| Bech32Error::OperationFailed)?;
42 fe32s.push(fe);
43 }
44 let data: Vec<u8> = fe32s.iter().copied().fes_to_bytes().collect();
45 let re_encoded = encode_lower::<Bech32Large>(hrp, &data)
47 .map_err(|_| Bech32Error::OperationFailed)?;
48 if re_encoded != s {
49 return Err(Bech32Error::OperationFailed);
50 }
51 if data.is_empty() {
52 return Err(Bech32Error::OperationFailed);
53 }
54 Ok((hrp.to_string(), data))
55 } else {
56 Err(Bech32Error::OperationFailed)
57 }
58 }
59
60 fn try_from_bech32_expect_hrp(&self, expected_hrp: &str) -> Result<Vec<u8>, Bech32Error> {
61 let (hrp, data) = self.try_from_bech32()?;
62 if !hrp.to_string().eq_ignore_ascii_case(expected_hrp) {
63 return Err(Bech32Error::UnexpectedHrp {
64 expected: expected_hrp.to_string(),
65 got: hrp.to_string(),
66 });
67 }
68 Ok(data)
69 }
70}