1use crate::coord::ranged1d::{
2 AsRangedCoord, DefaultFormatting, DiscreteRanged, KeyPointHint, Ranged,
3};
4use 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)]
10pub struct RangedSlice<'a, T: PartialEq>(&'a [T]);
11
12impl<'a, T: PartialEq> Ranged for RangedSlice<'a, T> {
13 type FormatOption = DefaultFormatting;
14 type ValueType = &'a T;
15
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
21 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
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
47impl<'a, T: PartialEq> DiscreteRanged for RangedSlice<'a, T> {
48 fn size(&self) -> usize {
49 self.0.len()
50 }
51
52 fn index_of(&self, value: &&'a T) -> Option<usize> {
53 self.0.iter().position(|x| &x == value)
54 }
55
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
64impl<'a, T: PartialEq> From<&'a [T]> for RangedSlice<'a, T> {
65 fn from(range: &'a [T]) -> Self {
66 RangedSlice(range)
67 }
68}
69
70impl<'a, T: PartialEq> AsRangedCoord for &'a [T] {
71 type CoordDescType = RangedSlice<'a, T>;
72 type Value = &'a T;
73}
74
75#[cfg(test)]
76mod test {
77 use super::*;
78 #[test]
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]
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