Skip to content
File

Blob: firmware/vendor/str0m/src/rtp/rtcp/list.rs

rust253 lines
1use std::fmt;
2use std::ops::Index;
3 
4/// List containing max 31 items.
5#[derive(Clone, PartialEq, Eq)]
6pub struct ReportList<T>([Option<T>; 31]);
7 
8impl<T> ReportList<T> {
9 pub(crate) fn new() -> Self {
10 ReportList::default()
11 }
12 
13 /// Number of elements in the list.
14 pub fn len(&self) -> usize {
15 self.0.iter().position(|i| i.is_none()).unwrap_or(31)
16 }
17 
18 pub(crate) fn push(&mut self, v: T) {
19 let pos = self.len();
20 self.0[pos] = Some(v);
21 }
22 
23 /// Get element at position.
24 pub fn get(&self, i: usize) -> Option<&T> {
25 self.0[i].as_ref()
26 }
27 
28 /// Iterator over the elements in the list.
29 pub fn iter(&self) -> impl Iterator<Item = &T> {
30 self.into_iter()
31 }
32 
33 /// Tells if the list contains zero elements.
34 pub fn is_empty(&self) -> bool {
35 self.len() == 0
36 }
37 
38 pub(crate) fn lists_from_iter(iterator: impl IntoIterator<Item = T>) -> Vec<Self> {
39 let mut result = vec![];
40 let mut current = Self::default();
41 
42 for (i, item) in iterator.into_iter().enumerate() {
43 if i % 31 == 0 && i != 0 {
44 result.push(current);
45 current = Self::default();
46 }
47 
48 current.push(item);
49 }
50 
51 if !current.is_empty() {
52 result.push(current);
53 }
54 
55 result
56 }
57 
58 pub(crate) fn is_full(&self) -> bool {
59 self.len() == 31
60 }
61}
62 
63impl<T: private::WordSized> ReportList<T> {
64 pub(crate) fn append_all_possible(&mut self, other: &mut Self, mut words_left: usize) -> usize {
65 // Position where we start inserting in self.
66 let pos = self.len();
67 
68 // Max number we can move.
69 let max = (31 - pos).min(other.len());
70 
71 // after this loop ends, i will hold the number of items moved.
72 let mut i = 0;
73 loop {
74 if i == max {
75 break;
76 }
77 
78 // first borrow item from other, to check the item size will fit.
79 let item = other.0[i].as_ref().unwrap();
80 let item_size = item.word_size();
81 
82 // can we fit one more item?
83 if words_left < item_size {
84 break;
85 }
86 
87 // it fits, move it.
88 self.0[pos + i] = other.0[i].take();
89 
90 // reduce space left.
91 words_left -= item_size;
92 
93 i += 1;
94 }
95 
96 // shift down remaining in other
97 for j in i..31 {
98 other.0[j - i] = other.0[j].take();
99 }
100 
101 // return number of appended items.
102 i
103 }
104}
105 
106pub(crate) mod private {
107 pub trait WordSized {
108 fn word_size(&self) -> usize;
109 }
110}
111 
112impl<T> Index<usize> for ReportList<T> {
113 type Output = T;
114 
115 fn index(&self, index: usize) -> &Self::Output {
116 self.0[index].as_ref().unwrap()
117 }
118}
119 
120impl<T> Default for ReportList<T> {
121 fn default() -> Self {
122 // We don't want to require T: Copy.
123 ReportList([
124 None, None, None, None, None, None, None, None, None, None, None, None, None, None,
125 None, None, None, None, None, None, None, None, None, None, None, None, None, None,
126 None, None, None,
127 ])
128 }
129}
130 
131impl<'a, T> IntoIterator for &'a ReportList<T> {
132 type Item = &'a T;
133 type IntoIter = Iter<'a, T>;
134 
135 fn into_iter(self) -> Self::IntoIter {
136 Iter(self, 0)
137 }
138}
139 
140impl<T> IntoIterator for ReportList<T> {
141 type Item = T;
142 type IntoIter = IterOwned<T>;
143 
144 fn into_iter(self) -> Self::IntoIter {
145 IterOwned(self, 0)
146 }
147}
148 
149pub struct Iter<'a, T>(&'a ReportList<T>, usize);
150 
151pub struct IterOwned<T>(ReportList<T>, usize);
152 
153impl<'a, T> Iterator for Iter<'a, T> {
154 type Item = &'a T;
155 
156 fn next(&mut self) -> Option<Self::Item> {
157 if self.1 > 30 {
158 return None;
159 }
160 
161 let n = self.0.0[self.1].as_ref();
162 if n.is_some() {
163 self.1 += 1;
164 }
165 
166 n
167 }
168}
169 
170impl<T> Iterator for IterOwned<T> {
171 type Item = T;
172 
173 fn next(&mut self) -> Option<Self::Item> {
174 if self.1 > 30 {
175 return None;
176 }
177 
178 let n = self.0.0[self.1].take();
179 if n.is_some() {
180 self.1 += 1;
181 }
182 n
183 }
184}
185 
186impl<T> From<T> for ReportList<T> {
187 fn from(t: T) -> Self {
188 let mut l = ReportList::default();
189 l.push(t);
190 l
191 }
192}
193 
194impl<T: fmt::Debug> fmt::Debug for ReportList<T> {
195 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196 write!(f, "[")?;
197 let len = self.len();
198 for (i, s) in self.0.iter().filter_map(|f| f.as_ref()).enumerate() {
199 if i == len - 1 {
200 write!(f, "{s:?}")?;
201 } else {
202 write!(f, "{s:?},")?;
203 }
204 }
205 write!(f, "]")
206 }
207}
208 
209#[cfg(test)]
210mod test {
211 use super::ReportList;
212 
213 #[test]
214 fn test_lists_from_iter() {
215 let lists = ReportList::lists_from_iter(0..66);
216 
217 assert_eq!(lists.len(), 3);
218 assert_eq!(lists[0].len(), 31);
219 assert_eq!(lists[1].len(), 31);
220 assert_eq!(lists[2].len(), 4);
221 }
222 
223 #[test]
224 fn test_max_length_iter() {
225 let list = {
226 let mut list = ReportList::new();
227 for i in 1..=31 {
228 list.push(i);
229 }
230 
231 list
232 };
233 let sum: u64 = list.iter().sum();
234 
235 assert_eq!(sum, 496);
236 }
237 
238 #[test]
239 fn test_max_length_into_iter() {
240 let list = {
241 let mut list = ReportList::new();
242 for i in 1..=31 {
243 list.push(i);
244 }
245 
246 list
247 };
248 let sum: u64 = list.into_iter().sum();
249 
250 assert_eq!(sum, 496);
251 }
252}