1 use crate::coord::ranged1d::{
2     AsRangedCoord, DefaultFormatting, DiscreteRanged, KeyPointHint, Ranged,
3 };
4 use std::ops::Range;
5 
6 /// A range that is defined by a slice of values.
7 ///
8 /// Please note: the behavior of constructing an empty range may cause panic
9 #[derive(Clone)]
10 pub struct RangedSlice<'a, T: PartialEq>(&'a [T]);
11 
12 impl<'a, T: PartialEq> Ranged for RangedSlice<'a, T> {
13     type FormatOption = DefaultFormatting;
14     type ValueType = &'a T;
15 
range(&self) -> Range<&'a T>16     fn range(&self) -> Range<&'a T> {
17         // If inner slice is empty, we should always panic
18         &self.0[0]..&self.0[self.0.len() - 1]
19     }
20 
map(&self, value: &Self::ValueType, limit: (i32, i32)) -> i3221     fn map(&self, value: &Self::ValueType, limit: (i32, i32)) -> i32 {
22         match self.0.iter().position(|x| &x == value) {
23             Some(pos) => {
24                 let pixel_span = limit.1 - limit.0;
25                 let value_span = self.0.len() - 1;
26                 (f64::from(limit.0)
27                     + f64::from(pixel_span)
28                         * (f64::from(pos as u32) / f64::from(value_span as u32)))
29                 .round() as i32
30             }
31             None => limit.0,
32         }
33     }
34 
key_points<Hint: KeyPointHint>(&self, hint: Hint) -> Vec<Self::ValueType>35     fn key_points<Hint: KeyPointHint>(&self, hint: Hint) -> Vec<Self::ValueType> {
36         let max_points = hint.max_num_points();
37         let mut ret = vec![];
38         let intervals = (self.0.len() - 1) as f64;
39         let step = (intervals / max_points as f64 + 1.0) as usize;
40         for idx in (0..self.0.len()).step_by(step) {
41             ret.push(&self.0[idx]);
42         }
43         ret
44     }
45 }
46 
47 impl<'a, T: PartialEq> DiscreteRanged for RangedSlice<'a, T> {
size(&self) -> usize48     fn size(&self) -> usize {
49         self.0.len()
50     }
51 
index_of(&self, value: &&'a T) -> Option<usize>52     fn index_of(&self, value: &&'a T) -> Option<usize> {
53         self.0.iter().position(|x| &x == value)
54     }
55 
from_index(&self, index: usize) -> Option<&'a T>56     fn from_index(&self, index: usize) -> Option<&'a T> {
57         if self.0.len() <= index {
58             return None;
59         }
60         Some(&self.0[index])
61     }
62 }
63 
64 impl<'a, T: PartialEq> From<&'a [T]> for RangedSlice<'a, T> {
from(range: &'a [T]) -> Self65     fn from(range: &'a [T]) -> Self {
66         RangedSlice(range)
67     }
68 }
69 
70 impl<'a, T: PartialEq> AsRangedCoord for &'a [T] {
71     type CoordDescType = RangedSlice<'a, T>;
72     type Value = &'a T;
73 }
74 
75 #[cfg(test)]
76 mod test {
77     use super::*;
78     #[test]
test_slice_range()79     fn test_slice_range() {
80         let my_slice = [1, 2, 3, 0, -1, -2];
81         let slice_range: RangedSlice<i32> = my_slice[..].into();
82 
83         assert_eq!(slice_range.range(), &1..&-2);
84         assert_eq!(
85             slice_range.key_points(6),
86             my_slice.iter().collect::<Vec<_>>()
87         );
88         assert_eq!(slice_range.map(&&0, (0, 50)), 30);
89     }
90 
91     #[test]
test_slice_range_discrete()92     fn test_slice_range_discrete() {
93         let my_slice = [1, 2, 3, 0, -1, -2];
94         let slice_range: RangedSlice<i32> = my_slice[..].into();
95 
96         assert_eq!(slice_range.size(), 6);
97         assert_eq!(slice_range.index_of(&&3), Some(2));
98         assert_eq!(slice_range.from_index(2), Some(&3));
99     }
100 }
101