rodio/source/
from_iter.rs1use std::time::Duration;
2
3use super::SeekError;
4use crate::common::{ChannelCount, SampleRate};
5use crate::math::nz;
6use crate::Source;
7
8pub fn from_iter<I>(iterator: I) -> FromIter<I::IntoIter>
16where
17 I: IntoIterator,
18{
19 let mut iterator = iterator.into_iter();
20 let first_source = iterator.next();
21
22 FromIter {
23 iterator,
24 current_source: first_source,
25 }
26}
27
28#[derive(Clone)]
30pub struct FromIter<I>
31where
32 I: Iterator,
33{
34 iterator: I,
36 current_source: Option<I::Item>,
38}
39
40impl<I> Iterator for FromIter<I>
41where
42 I: Iterator,
43 I::Item: Iterator + Source,
44{
45 type Item = <I::Item as Iterator>::Item;
46
47 #[inline]
48 fn next(&mut self) -> Option<Self::Item> {
49 loop {
50 if let Some(src) = &mut self.current_source {
51 if let Some(value) = src.next() {
52 return Some(value);
53 }
54 }
55
56 if let Some(src) = self.iterator.next() {
57 self.current_source = Some(src);
58 } else {
59 return None;
60 }
61 }
62 }
63
64 #[inline]
65 fn size_hint(&self) -> (usize, Option<usize>) {
66 if let Some(cur) = &self.current_source {
67 (cur.size_hint().0, None)
68 } else {
69 (0, None)
70 }
71 }
72}
73
74impl<I> Source for FromIter<I>
75where
76 I: Iterator,
77 I::Item: Iterator + Source,
78{
79 #[inline]
80 fn current_span_len(&self) -> Option<usize> {
81 const THRESHOLD: usize = 10240;
92
93 if let Some(src) = &self.current_source {
95 if !src.is_exhausted() {
96 return src.current_span_len();
97 }
98 }
99
100 if let Some(src) = &self.current_source {
102 if let Some(val) = src.size_hint().1 {
103 if val < THRESHOLD && val != 0 {
104 return Some(val);
105 }
106 }
107 }
108
109 Some(THRESHOLD)
111 }
112
113 #[inline]
114 fn channels(&self) -> ChannelCount {
115 if let Some(src) = &self.current_source {
116 src.channels()
117 } else {
118 nz!(2)
120 }
121 }
122
123 #[inline]
124 fn sample_rate(&self) -> SampleRate {
125 if let Some(src) = &self.current_source {
126 src.sample_rate()
127 } else {
128 nz!(44100)
130 }
131 }
132
133 #[inline]
134 fn total_duration(&self) -> Option<Duration> {
135 None
136 }
137
138 #[inline]
139 fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
140 if let Some(source) = self.current_source.as_mut() {
141 source.try_seek(pos)
142 } else {
143 Ok(())
144 }
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use crate::buffer::SamplesBuffer;
151 use crate::math::nz;
152 use crate::source::{from_iter, Source};
153
154 #[test]
155 fn basic() {
156 let mut rx = from_iter((0..2).map(|n| {
157 if n == 0 {
158 SamplesBuffer::new(nz!(1), nz!(48000), vec![10.0, -10.0, 10.0, -10.0])
159 } else if n == 1 {
160 SamplesBuffer::new(nz!(2), nz!(96000), vec![5.0, 5.0, 5.0, 5.0])
161 } else {
162 unreachable!()
163 }
164 }));
165
166 assert_eq!(rx.channels(), nz!(1));
167 assert_eq!(rx.sample_rate().get(), 48000);
168 assert_eq!(rx.next(), Some(10.0));
169 assert_eq!(rx.next(), Some(-10.0));
170 assert_eq!(rx.next(), Some(10.0));
171 assert_eq!(rx.next(), Some(-10.0));
172 assert_eq!(rx.next(), Some(5.0));
176 assert_eq!(rx.next(), Some(5.0));
177 assert_eq!(rx.next(), Some(5.0));
178 assert_eq!(rx.next(), Some(5.0));
179 assert_eq!(rx.next(), None);
180 }
181}