1#![no_std]
2#![deny(missing_docs)]
3extern crate alloc;
24
25use alloc::collections::BTreeMap;
26use alloc::string::String;
27use alloc::string::ToString;
28use alloc::vec::Vec;
29use alloc::sync::Arc;
30use core::fmt;
31
32#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
34pub struct StrCtx(Arc<[(&'static str, String)]>);
35
36impl fmt::Debug for StrCtx {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 f.write_str("[")?;
39 let mut first = true;
40 for (k, v) in self.0.iter() {
41 if first {
42 first = false;
43 } else {
44 f.write_str(",")?;
45 }
46 f.write_str(k)?;
47 f.write_str(":")?;
48 f.write_str(v)?;
49 }
50 f.write_str("]")?;
51 Ok(())
52 }
53}
54
55impl fmt::Display for StrCtx {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 write!(f, "{:?}", self)
58 }
59}
60
61impl<V: fmt::Display> FromIterator<(&'static str, V)> for StrCtx {
62 fn from_iter<T>(iter: T) -> Self
63 where
64 T: IntoIterator<Item = (&'static str, V)>,
65 {
66 Self(BTreeMap::from_iter(iter.into_iter().map(|(k, v)| {
67 (k, v.to_string())
68 })).into_iter().collect::<Vec<_>>().into_boxed_slice().into())
69 }
70}
71
72impl IntoIterator for StrCtx {
73 type Item = (&'static str, String);
74 type IntoIter = <Vec<(&'static str, String)> as IntoIterator>::IntoIter;
75
76 fn into_iter(self) -> Self::IntoIter {
77 self.0.to_vec().into_iter()
78 }
79}
80
81impl<'a> IntoIterator for &'a StrCtx {
82 type Item = &'a (&'static str, String);
83 type IntoIter = core::slice::Iter<'a, (&'static str, String)>;
84
85 fn into_iter(self) -> Self::IntoIter {
86 self.0.into_iter()
87 }
88}
89
90impl StrCtx {
91 pub fn derive<V, T>(&self, iter: T) -> Self
93 where
94 V: fmt::Display,
95 T: IntoIterator<Item = (&'static str, V)>,
96 {
97 Self::from_iter(self.into_iter().cloned().chain(iter.into_iter().map(|(k, v)| {
98 (k, v.to_string())
99 })))
100 }
101}