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