File
Blob: firmware/vendor/str0m/src/rtp/rtcp/list.rs
| 1 | use std::fmt; |
| 2 | use std::ops::Index; |
| 3 | |
| 4 | /// List containing max 31 items. |
| 5 | #[derive(Clone, PartialEq, Eq)] |
| 6 | pub struct ReportList<T>([Option<T>; 31]); |
| 7 | |
| 8 | impl<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 | |
| 63 | impl<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 | |
| 106 | pub(crate) mod private { |
| 107 | pub trait WordSized { |
| 108 | fn word_size(&self) -> usize; |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | impl<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 | |
| 120 | impl<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 | |
| 131 | impl<'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 | |
| 140 | impl<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 | |
| 149 | pub struct Iter<'a, T>(&'a ReportList<T>, usize); |
| 150 | |
| 151 | pub struct IterOwned<T>(ReportList<T>, usize); |
| 152 | |
| 153 | impl<'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 | |
| 170 | impl<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 | |
| 186 | impl<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 | |
| 194 | impl<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)] |
| 210 | mod 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 | } |