amaru_kernel/utils/
string.rs1use std::fmt::{Debug, Display};
16
17use itertools::Itertools;
18
19use crate::{Bytes, cbor, from_cbor};
20
21pub fn encode_bech32(hrp: &str, payload: &[u8]) -> Result<String, Box<dyn std::error::Error>> {
22 let hrp = bech32::Hrp::parse(hrp)?;
23 Ok(bech32::encode::<bech32::Bech32>(hrp, payload)?)
24}
25
26pub fn display_collection<T>(collection: impl IntoIterator<Item = T>) -> String
27where
28 T: std::fmt::Display,
29{
30 collection.into_iter().collect::<Vec<_>>().list_to_string(", ")
31}
32
33pub trait ListToString {
36 fn list_to_string(&self, separator: &str) -> String;
37}
38
39impl<I, H> ListToString for I
40where
41 for<'a> &'a I: IntoIterator<Item = &'a H>,
42 H: Display,
43{
44 fn list_to_string(&self, separator: &str) -> String {
45 self.into_iter().join(separator)
46 }
47}
48
49pub trait ListsToString {
53 fn lists_to_string(&self, intra_separator: &str, inter_separator: &str) -> String;
54}
55
56impl<H, I, J> ListsToString for J
57where
58 for<'a> &'a I: IntoIterator<Item = &'a H>,
59 for<'a> &'a J: IntoIterator<Item = &'a I>,
60 H: Display,
61{
62 fn lists_to_string(&self, intra_separator: &str, inter_separator: &str) -> String {
63 self.into_iter()
64 .map(|l| format!("[{}]", l.list_to_string(intra_separator)))
65 .collect::<Vec<_>>()
66 .list_to_string(inter_separator)
67 }
68}
69
70pub trait ListDebug {
74 fn list_debug(&self, separator: &str) -> String;
75}
76
77impl<I, H> ListDebug for I
78where
79 for<'a> &'a I: IntoIterator<Item = &'a H>,
80 H: Debug,
81{
82 fn list_debug(&self, separator: &str) -> String {
83 self.into_iter().map(|h| format!("{h:?}")).join(separator)
84 }
85}
86
87pub trait ListsDebug {
91 fn lists_debug(&self, intra_separator: &str, inter_separator: &str) -> String;
92}
93
94impl<H, I, J> ListsDebug for J
95where
96 for<'a> &'a I: IntoIterator<Item = &'a H>,
97 for<'a> &'a J: IntoIterator<Item = &'a I>,
98 H: Debug,
99{
100 fn lists_debug(&self, intra_separator: &str, inter_separator: &str) -> String {
101 self.into_iter()
102 .map(|l| format!("[{}]", l.list_debug(intra_separator)))
103 .collect::<Vec<_>>()
104 .list_to_string(inter_separator)
105 }
106}
107
108pub fn blanket_try_from_hex_bytes<T, I: for<'d> cbor::Decode<'d, ()>>(
111 s: &str,
112 new: impl Fn(Bytes, I) -> T,
113) -> Result<T, String> {
114 let original_bytes = Bytes::from(hex::decode(s.as_bytes()).map_err(|e| e.to_string())?);
115
116 let value = from_cbor(&original_bytes).ok_or_else(|| "failed to decode from CBOR".to_string())?;
117
118 Ok(new(original_bytes, value))
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn make_a_string_from_a_list() {
127 let actual = vec![1, 2, 3].list_to_string(", ");
128 assert_eq!(actual, "1, 2, 3");
129 }
130
131 #[test]
132 fn make_a_debug_string_from_a_list() {
133 let actual = vec![Some(1), None, Some(3)].list_debug(", ");
134 assert_eq!(actual, "Some(1), None, Some(3)");
135 }
136
137 #[test]
138 fn make_a_string_from_a_list_of_lists() {
139 let actual = vec![vec![1, 2], vec![3]].lists_to_string(", ", " | ");
140 assert_eq!(actual, "[1, 2] | [3]");
141 }
142}