1#![allow(clippy::type_complexity)]
2use alloc::vec;
3use alloc::vec::Vec;
4use core::fmt::Debug;
5
6#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct Attribute<Ns, Att, Val>
9where
10 Ns: PartialEq + Clone + Debug,
11 Att: PartialEq + Clone + Debug,
12 Val: PartialEq + Clone + Debug,
13{
14 pub namespace: Option<Ns>,
18 pub name: Att,
21 pub value: Vec<Val>,
23}
24
25impl<Ns, Att, Val> Attribute<Ns, Att, Val>
26where
27 Ns: PartialEq + Clone + Debug,
28 Att: PartialEq + Clone + Debug,
29 Val: PartialEq + Clone + Debug,
30{
31 pub fn new(namespace: Option<Ns>, name: Att, value: Val) -> Self {
33 Attribute {
34 name,
35 value: vec![value],
36 namespace,
37 }
38 }
39
40 pub fn with_multiple_values(
42 namespace: Option<Ns>,
43 name: Att,
44 value: impl IntoIterator<Item = Val>,
45 ) -> Self {
46 Attribute {
47 name,
48 value: value.into_iter().collect(),
49 namespace,
50 }
51 }
52
53 pub fn name(&self) -> &Att {
55 &self.name
56 }
57
58 pub fn value(&self) -> &[Val] {
60 &self.value
61 }
62
63 pub fn namespace(&self) -> Option<&Ns> {
65 self.namespace.as_ref()
66 }
67}
68
69#[inline]
77pub fn attr<Ns, Att, Val>(name: Att, value: Val) -> Attribute<Ns, Att, Val>
78where
79 Ns: PartialEq + Clone + Debug,
80 Att: PartialEq + Clone + Debug,
81 Val: PartialEq + Clone + Debug,
82{
83 attr_ns(None, name, value)
84}
85
86#[inline]
95pub fn attr_ns<Ns, Att, Val>(
96 namespace: Option<Ns>,
97 name: Att,
98 value: Val,
99) -> Attribute<Ns, Att, Val>
100where
101 Ns: PartialEq + Clone + Debug,
102 Att: PartialEq + Clone + Debug,
103 Val: PartialEq + Clone + Debug,
104{
105 Attribute::new(namespace, name, value)
106}
107
108#[doc(hidden)]
110pub fn merge_attributes_of_same_name<Ns, Att, Val>(
111 attributes: &[&Attribute<Ns, Att, Val>],
112) -> Vec<Attribute<Ns, Att, Val>>
113where
114 Ns: PartialEq + Clone + Debug,
115 Att: PartialEq + Clone + Debug,
116 Val: PartialEq + Clone + Debug,
117{
118 let mut merged: Vec<Attribute<Ns, Att, Val>> = vec![];
119 for att in attributes {
120 if let Some(existing) =
121 merged.iter_mut().find(|m_att| m_att.name == att.name)
122 {
123 existing.value.extend(att.value.clone());
124 } else {
125 merged.push(Attribute {
126 namespace: None,
127 name: att.name.clone(),
128 value: att.value.clone(),
129 });
130 }
131 }
132 merged
133}
134
135#[doc(hidden)]
137pub fn group_attributes_per_name<Ns, Att, Val>(
138 attributes: &[Attribute<Ns, Att, Val>],
139) -> Vec<(&Att, Vec<&Attribute<Ns, Att, Val>>)>
140where
141 Ns: PartialEq + Clone + Debug,
142 Att: PartialEq + Clone + Debug,
143 Val: PartialEq + Clone + Debug,
144{
145 let mut grouped: Vec<(&Att, Vec<&Attribute<Ns, Att, Val>>)> = vec![];
146 for attr in attributes {
147 if let Some(existing) = grouped
148 .iter_mut()
149 .find(|(g_att, _)| **g_att == attr.name)
150 .map(|(_, attr)| attr)
151 {
152 existing.push(attr);
153 } else {
154 grouped.push((&attr.name, vec![attr]))
155 }
156 }
157 grouped
158}