use bytes::Bytes;
use crate::binary::*;
use crate::tree::Tree;
pub struct Decoder {
pub title: &'static str,
pub group: &'static str,
pub symbol: &'static str,
pub decode: fn(&Binary) -> Option<Tree>,
}
impl std::fmt::Debug for Decoder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Decoder")
.field("name", &self.title)
.finish()
}
}
inventory::collect!(Decoder);
pub fn all_decoders() -> Vec<&'static Decoder> {
inventory::iter::<Decoder>().collect()
}
#[derive(Clone, Debug)]
pub enum Input {
String(String),
Binary(Bytes),
}
#[derive(Debug)]
pub struct Candidate {
pub decoder: &'static Decoder,
pub annotations: Tree,
pub data: Binary,
}
pub fn decode_input(input: Input) -> Vec<Candidate> {
input_to_binaries(input)
.iter()
.flat_map(|b| {
all_decoders().into_iter().map(|d| {
(d.decode)(b).map(|a| Candidate {
decoder: d,
annotations: a,
data: b.clone(),
})
})
})
.flatten()
.collect()
}
fn input_to_binaries(input: Input) -> Vec<Binary> {
match input {
Input::String(s) => try_decode_string(&s),
Input::Binary(b) => {
let mut s = binary_to_string(&b)
.map(|s| try_decode_string(&s))
.unwrap_or_default();
s.push(Some(Binary::Raw(b)));
s
}
}
.into_iter()
.flatten()
.collect()
}
#[inline]
fn try_decode_string(s: &str) -> Vec<Option<Binary>> {
vec![
string_to_hex(s),
string_to_bech32(s),
string_to_base58(s),
string_to_base64(s),
]
}