1use super::*;
5
6#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
9pub struct ValueRange {
10 pub min: i32,
12 pub max: i32,
14 pub step: i32,
16}
17
18pub trait RangeUtil<T> {
20 fn length(&self) -> T;
22
23 fn contains(&self, val: T) -> bool;
25}
26
27impl RangeUtil<i32> for ValueRange {
28 fn length(&self) -> i32 {
29 (self.max - self.min).abs()
30 }
31
32 fn contains(&self, val: i32) -> bool {
33 val >= self.min && val <= self.max
34 }
35}
36
37impl RangeUtil<i32> for DbInterval {
39 fn length(&self) -> i32 {
40 (self.max - self.min).abs()
41 }
42
43 fn contains(&self, db: i32) -> bool {
44 db >= self.min && db <= self.max
45 }
46}
47
48pub trait ToValueRange {
50 fn to_valuerange(&self, range: &ValueRange) -> Option<ValueRange>;
51}
52
53impl ToValueRange for DbScale {
54 fn to_valuerange(&self, range: &ValueRange) -> Option<ValueRange> {
55 Some(*range)
56 }
57}
58
59impl ToValueRange for DbInterval {
60 fn to_valuerange(&self, range: &ValueRange) -> Option<ValueRange> {
61 Some(*range)
62 }
63}
64
65impl ToValueRange for DbRangeEntry {
66 fn to_valuerange(&self, range: &ValueRange) -> Option<ValueRange> {
67 Some(ValueRange {
68 min: self.min_val,
69 max: self.max_val,
70 step: range.step,
71 })
72 }
73}
74
75impl ToValueRange for DbRange {
76 fn to_valuerange(&self, range: &ValueRange) -> Option<ValueRange> {
77 let mut r = ValueRange {
78 min: i32::MAX,
79 max: i32::MIN,
80 step: range.step,
81 };
82 self.entries.iter().for_each(|entry| {
83 if !r.contains(entry.min_val) {
84 r.min = entry.min_val;
85 }
86 if !r.contains(entry.max_val) {
87 r.max = entry.max_val;
88 }
89 });
90 if r.min != i32::MAX && r.max != i32::MIN {
91 Some(r)
92 } else {
93 None
94 }
95 }
96}
97
98impl ToValueRange for Container {
99 fn to_valuerange(&self, range: &ValueRange) -> Option<ValueRange> {
100 let mut r = ValueRange {
101 min: i32::MAX,
102 max: i32::MIN,
103 step: range.step,
104 };
105 self.entries.iter().for_each(|entry| {
106 if let Some(range) = entry.to_valuerange(&range) {
107 if !r.contains(range.min) {
108 r.min = range.min;
109 }
110 if !r.contains(range.max) {
111 r.max = range.max;
112 }
113 }
114 });
115 if r.min != i32::MAX && r.max != i32::MIN {
116 Some(r)
117 } else {
118 None
119 }
120 }
121}
122
123impl ToValueRange for TlvItem {
124 fn to_valuerange(&self, range: &ValueRange) -> Option<ValueRange> {
125 match self {
126 TlvItem::DbRange(d) => d.to_valuerange(&range),
127 TlvItem::Container(d) => d.to_valuerange(&range),
128 TlvItem::DbScale(_) | TlvItem::DbInterval(_) => Some(*range),
129 _ => None,
130 }
131 }
132}
133
134#[derive(Debug, Clone, PartialEq, Eq)]
136pub enum ToDbIntervalError {
137 Range(
140 i32,
142 i32,
144 ),
145 Linearity,
147 Empty,
149 Unsupported,
151}
152
153impl std::fmt::Display for ToDbIntervalError {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 match self {
156 Self::Range(min_val, max_val) => write!(
157 f,
158 "Any entry out of range, min: {}, max: {}",
159 min_val, max_val
160 ),
161 Self::Linearity => write!(f, "Some entries for both of non-linear and linear value"),
162 Self::Empty => write!(f, "No entry for dB information"),
163 Self::Unsupported => write!(f, "Any entry without dB information"),
164 }
165 }
166}
167
168pub trait ToDbInterval {
170 fn to_dbinterval(&self, range: &ValueRange) -> Result<DbInterval, ToDbIntervalError>;
171}
172
173impl ToDbInterval for DbScale {
174 fn to_dbinterval(&self, range: &ValueRange) -> Result<DbInterval, ToDbIntervalError> {
175 Ok(DbInterval {
176 min: self.min,
177 max: self.min + range.length() * self.step as i32,
178 linear: false,
179 mute_avail: self.mute_avail,
180 })
181 }
182}
183
184impl ToDbInterval for DbInterval {
185 fn to_dbinterval(&self, _: &ValueRange) -> Result<DbInterval, ToDbIntervalError> {
186 Ok(*self)
187 }
188}
189
190impl ToDbInterval for DbRangeEntry {
191 fn to_dbinterval(&self, range: &ValueRange) -> Result<DbInterval, ToDbIntervalError> {
192 let r = ValueRange {
193 min: self.min_val,
194 max: self.max_val,
195 step: range.step,
196 };
197 match &self.data {
198 DbRangeEntryData::DbScale(d) => d.to_dbinterval(&r),
199 DbRangeEntryData::DbInterval(d) => Ok(*d),
200 DbRangeEntryData::DbRange(d) => d.to_dbinterval(&r),
201 }
202 }
203}
204
205impl ToDbInterval for DbRange {
206 fn to_dbinterval(&self, range: &ValueRange) -> Result<DbInterval, ToDbIntervalError> {
207 let entries = self
208 .entries
209 .iter()
210 .map(|entry| {
211 if range.contains(entry.min_val) && range.contains(entry.max_val) {
212 let r = ValueRange {
213 min: entry.min_val,
214 max: entry.max_val,
215 step: range.step,
216 };
217 entry.to_dbinterval(&r).and_then(|i| Ok((r, i)))
218 } else {
219 Err(ToDbIntervalError::Range(entry.min_val, entry.max_val))
220 }
221 })
222 .collect::<Result<Vec<_>, _>>()?;
223
224 if entries.len() > 0 {
225 let mut interval = entries[0].1;
226 entries[1..].iter().try_for_each(|entry| {
227 let i = entry.1;
228 if i.linear != interval.linear {
229 Err(ToDbIntervalError::Linearity)
230 } else {
231 if !interval.contains(i.min) {
232 interval.min = i.min;
233 interval.mute_avail = i.mute_avail;
234 }
235 if !interval.contains(i.max) {
236 interval.max = i.max;
237 }
238 Ok(())
239 }
240 })?;
241 Ok(interval)
242 } else {
243 Err(ToDbIntervalError::Empty)
244 }
245 }
246}
247
248impl ToDbInterval for Container {
249 fn to_dbinterval(&self, range: &ValueRange) -> Result<DbInterval, ToDbIntervalError> {
250 let intervals = self
251 .entries
252 .iter()
253 .map(|entry| entry.to_dbinterval(&range))
254 .collect::<Result<Vec<_>, _>>()?;
255
256 if intervals.len() > 0 {
257 let mut interval = intervals[0];
258 intervals[1..].iter().try_for_each(|i| {
259 if i.linear != interval.linear {
260 Err(ToDbIntervalError::Linearity)
261 } else {
262 if !interval.contains(i.min) {
263 interval.min = i.min;
264 interval.mute_avail = i.mute_avail;
265 }
266 if !interval.contains(i.max) {
267 interval.max = i.max;
268 }
269 Ok(())
270 }
271 })?;
272 Ok(interval)
273 } else {
274 Err(ToDbIntervalError::Empty)
275 }
276 }
277}
278
279impl ToDbInterval for TlvItem {
280 fn to_dbinterval(&self, range: &ValueRange) -> Result<DbInterval, ToDbIntervalError> {
281 match self {
282 TlvItem::Container(d) => d.to_dbinterval(&range),
283 TlvItem::DbRange(d) => d.to_dbinterval(&range),
284 TlvItem::DbScale(d) => d.to_dbinterval(&range),
285 TlvItem::DbInterval(d) => Ok(*d),
286 _ => Err(ToDbIntervalError::Unsupported),
287 }
288 }
289}
290
291#[cfg(test)]
292mod test {
293 use super::*;
294
295 #[test]
296 fn to_dbinterval_dbscale() {
297 let scale = &DbScale {
298 min: 100,
299 step: 10,
300 mute_avail: true,
301 };
302 let range = ValueRange {
303 min: 33,
304 max: 333,
305 step: 1,
306 };
307 let interval = scale.to_dbinterval(&range).unwrap();
308 assert_eq!(
309 interval,
310 DbInterval {
311 min: 100,
312 max: 3100,
313 linear: false,
314 mute_avail: true
315 }
316 );
317 }
318
319 #[test]
320 fn to_valuerange_dbrange() {
321 let first_data = DbInterval {
322 min: 1,
323 max: 5,
324 linear: false,
325 mute_avail: true,
326 };
327 let second_data = DbInterval {
328 min: 5,
329 max: 10,
330 linear: false,
331 mute_avail: false,
332 };
333 let third_data = DbInterval {
334 min: 10,
335 max: 20,
336 linear: false,
337 mute_avail: false,
338 };
339
340 let dbrange = DbRange {
341 entries: vec![
342 DbRangeEntry {
343 min_val: 0,
344 max_val: 10,
345 data: DbRangeEntryData::DbInterval(first_data),
346 },
347 DbRangeEntry {
348 min_val: 10,
349 max_val: 20,
350 data: DbRangeEntryData::DbInterval(second_data),
351 },
352 DbRangeEntry {
353 min_val: 20,
354 max_val: 40,
355 data: DbRangeEntryData::DbInterval(third_data),
356 },
357 ],
358 };
359 let r = ValueRange {
360 min: 0,
361 max: 40,
362 step: 1,
363 };
364 let range = dbrange.to_valuerange(&r).unwrap();
365 assert_eq!(range.min, 0);
366 assert_eq!(range.max, 40);
367 assert_eq!(range.step, 1);
368 }
369
370 #[test]
371 fn to_dbinterval_dbrange() {
372 let first_data = DbInterval {
373 min: 1,
374 max: 5,
375 linear: false,
376 mute_avail: true,
377 };
378 let second_data = DbInterval {
379 min: 5,
380 max: 10,
381 linear: false,
382 mute_avail: false,
383 };
384 let third_data = DbInterval {
385 min: 10,
386 max: 20,
387 linear: false,
388 mute_avail: false,
389 };
390 let range = DbRange {
391 entries: vec![
392 DbRangeEntry {
393 min_val: 0,
394 max_val: 10,
395 data: DbRangeEntryData::DbInterval(first_data),
396 },
397 DbRangeEntry {
398 min_val: 10,
399 max_val: 20,
400 data: DbRangeEntryData::DbInterval(second_data),
401 },
402 DbRangeEntry {
403 min_val: 20,
404 max_val: 40,
405 data: DbRangeEntryData::DbInterval(third_data),
406 },
407 ],
408 };
409 let r = ValueRange {
410 min: 0,
411 max: 40,
412 step: 1,
413 };
414 let interval = range.to_dbinterval(&r).unwrap();
415 assert_eq!(
416 interval,
417 DbInterval {
418 min: 1,
419 max: 20,
420 linear: false,
421 mute_avail: true
422 }
423 );
424 }
425}