1use std::{slice::Iter, vec::IntoIter};
2
3use mpd_protocol::response::Frame;
4
5use crate::tag::Tag;
6
7#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct List<const N: usize> {
12 primary_tag: Tag,
13 groupings: [Tag; N],
14 fields: Vec<(Tag, String)>,
15}
16
17impl List<0> {
18 pub fn values(&self) -> ListValuesIter<'_> {
20 ListValuesIter(self.fields.iter())
21 }
22}
23
24impl<const N: usize> List<N> {
25 pub(crate) fn from_frame(primary_tag: Tag, groupings: [Tag; N], frame: Frame) -> List<N> {
26 let fields = frame
27 .into_iter()
28 .map(|(tag, value)| (Tag::try_from(tag.as_ref()).unwrap(), value))
30 .collect();
31
32 List {
33 primary_tag,
34 groupings,
35 fields,
36 }
37 }
38
39 pub fn grouped_values(&self) -> GroupedListValuesIter<'_, N> {
45 GroupedListValuesIter {
46 primary_tag: &self.primary_tag,
47 grouping_tags: &self.groupings,
48 grouping_values: [""; N],
49 fields: self.fields.iter(),
50 }
51 }
52
53 pub fn grouped_by(&self) -> &[Tag; N] {
55 &self.groupings
56 }
57
58 pub fn into_raw_values(self) -> Vec<(Tag, String)> {
60 self.fields
61 }
62}
63
64impl<'a> IntoIterator for &'a List<0> {
65 type Item = &'a str;
66
67 type IntoIter = ListValuesIter<'a>;
68
69 fn into_iter(self) -> Self::IntoIter {
70 self.values()
71 }
72}
73
74impl IntoIterator for List<0> {
75 type Item = String;
76
77 type IntoIter = ListValuesIntoIter;
78
79 fn into_iter(self) -> Self::IntoIter {
80 ListValuesIntoIter(self.fields.into_iter())
81 }
82}
83
84#[derive(Clone, Debug)]
88pub struct GroupedListValuesIter<'a, const N: usize> {
89 primary_tag: &'a Tag,
90 grouping_tags: &'a [Tag; N],
91 grouping_values: [&'a str; N],
92 fields: Iter<'a, (Tag, String)>,
93}
94
95impl<'a, const N: usize> Iterator for GroupedListValuesIter<'a, N> {
96 type Item = (&'a str, [&'a str; N]);
97
98 fn next(&mut self) -> Option<Self::Item> {
99 loop {
100 let (tag, value) = self.fields.next()?;
101
102 if tag == self.primary_tag {
103 break Some((value, self.grouping_values));
104 }
105
106 let idx = self.grouping_tags.iter().position(|t| t == tag).unwrap();
107 self.grouping_values[idx] = value;
108 }
109 }
110}
111
112#[derive(Clone, Debug)]
114pub struct ListValuesIter<'a>(Iter<'a, (Tag, String)>);
115
116impl<'a> Iterator for ListValuesIter<'a> {
117 type Item = &'a str;
118
119 fn next(&mut self) -> Option<Self::Item> {
120 self.0.next().map(|(_, v)| &**v)
121 }
122
123 fn size_hint(&self) -> (usize, Option<usize>) {
124 self.0.size_hint()
125 }
126
127 fn count(self) -> usize {
128 self.0.count()
129 }
130
131 fn nth(&mut self, n: usize) -> Option<Self::Item> {
132 self.0.nth(n).map(|(_, v)| &**v)
133 }
134
135 fn last(self) -> Option<Self::Item>
136 where
137 Self: Sized,
138 {
139 self.0.last().map(|(_, v)| &**v)
140 }
141}
142
143impl<'a> DoubleEndedIterator for ListValuesIter<'a> {
144 fn next_back(&mut self) -> Option<Self::Item> {
145 self.0.next_back().map(|(_, v)| &**v)
146 }
147
148 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
149 self.0.nth_back(n).map(|(_, v)| &**v)
150 }
151}
152
153impl<'a> ExactSizeIterator for ListValuesIter<'a> {}
154
155#[derive(Debug)]
157pub struct ListValuesIntoIter(IntoIter<(Tag, String)>);
158
159impl Iterator for ListValuesIntoIter {
160 type Item = String;
161
162 fn next(&mut self) -> Option<Self::Item> {
163 self.0.next().map(|(_, v)| v)
164 }
165
166 fn size_hint(&self) -> (usize, Option<usize>) {
167 self.0.size_hint()
168 }
169
170 fn count(self) -> usize {
171 self.0.count()
172 }
173
174 fn nth(&mut self, n: usize) -> Option<Self::Item> {
175 self.0.nth(n).map(|(_, v)| v)
176 }
177
178 fn last(self) -> Option<Self::Item>
179 where
180 Self: Sized,
181 {
182 self.0.last().map(|(_, v)| v)
183 }
184}
185
186impl DoubleEndedIterator for ListValuesIntoIter {
187 fn next_back(&mut self) -> Option<Self::Item> {
188 self.0.next_back().map(|(_, v)| v)
189 }
190
191 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
192 self.0.nth_back(n).map(|(_, v)| v)
193 }
194}
195
196impl ExactSizeIterator for ListValuesIntoIter {}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn grouped_iterator() {
204 let fields = vec![
205 (Tag::AlbumArtist, String::from("Foo")),
206 (Tag::Album, String::from("Bar")),
207 (Tag::Title, String::from("Title 1")),
208 (Tag::Title, String::from("Title 2")),
209 (Tag::Album, String::from("Quz")),
210 (Tag::Title, String::from("Title 3")),
211 (Tag::AlbumArtist, String::from("Asdf")),
212 (Tag::Album, String::from("Qwert")),
213 (Tag::Title, String::from("Title 4")),
214 ];
215
216 let mut iter = GroupedListValuesIter {
217 primary_tag: &Tag::Title,
218 grouping_tags: &[Tag::Album, Tag::AlbumArtist],
219 grouping_values: [""; 2],
220 fields: fields.iter(),
221 };
222
223 assert_eq!(iter.next(), Some(("Title 1", ["Bar", "Foo"])));
224 assert_eq!(iter.next(), Some(("Title 2", ["Bar", "Foo"])));
225 assert_eq!(iter.next(), Some(("Title 3", ["Quz", "Foo"])));
226 assert_eq!(iter.next(), Some(("Title 4", ["Qwert", "Asdf"])));
227 assert_eq!(iter.next(), None);
228 }
229}