@@ -2,7 +2,11 @@ use super::{AsRangedCoord, Ranged};
2
2
use std:: fmt:: { Debug , Formatter , Result as FmtResult } ;
3
3
use std:: ops:: Range ;
4
4
5
- /// The trait indicates the coordinate is discrete, so that we can draw histogram on it
5
+ /// The trait indicates the coordinate is discrete
6
+ /// This means we can bidirectionally map the range value to 0 to N
7
+ /// in which N is the number of distinct values of the range.
8
+ ///
9
+ /// This is useful since for a histgoram, this is an abstraction of bucket.
6
10
pub trait DiscreteRanged
7
11
where
8
12
Self : Ranged ,
@@ -15,12 +19,18 @@ where
15
19
16
20
/// Map a value to the index
17
21
///
22
+ /// Note: This function doesn't guareentee return None when the value is out of range.
23
+ /// The only way to confirm the value is in the range is to examing the return value isn't
24
+ /// larger than self.size.
25
+ ///
18
26
/// - `value`: The value to map
19
27
/// - **returns** The index of the value
20
28
fn index_of ( & self , value : & Self :: ValueType ) -> Option < usize > ;
21
29
22
30
/// Reverse map the index to the value
23
31
///
32
+ /// Note: This function doesn't guareentee returning None when the index is out of range.
33
+ ///
24
34
/// - `value`: The index to map
25
35
/// - **returns** The value
26
36
fn from_index ( & self , index : usize ) -> Option < Self :: ValueType > ;
34
44
{
35
45
DiscreteValueIter ( self , 0 , self . size ( ) )
36
46
}
47
+
48
+ /// Returns the previous value in this range
49
+ ///
50
+ /// Normally, it's based on the `from_index` and `index_of` function. But for
51
+ /// some of the coord spec, it's possible that we value faster implementation.
52
+ /// If this is the case, we can impelemnet the type specific impl for the `previous`
53
+ /// and `next`.
54
+ ///
55
+ /// - `value`: The current value
56
+ /// - **returns**: The value piror to current value
57
+ fn previous ( & self , value : & Self :: ValueType ) -> Option < Self :: ValueType > {
58
+ if let Some ( idx) = self . index_of ( value) {
59
+ if idx > 0 {
60
+ return self . from_index ( idx - 1 ) ;
61
+ }
62
+ }
63
+ None
64
+ }
65
+
66
+ /// Returns the next value in this range
67
+ ///
68
+ /// Normally, it's based on the `from_index` and `index_of` function. But for
69
+ /// some of the coord spec, it's possible that we value faster implementation.
70
+ /// If this is the case, we can impelemnet the type specific impl for the `previous`
71
+ /// and `next`.
72
+ ///
73
+ /// - `value`: The current value
74
+ /// - **returns**: The value next to current value
75
+ fn next ( & self , value : & Self :: ValueType ) -> Option < Self :: ValueType > {
76
+ if let Some ( idx) = self . index_of ( value) {
77
+ if idx + 1 < self . size ( ) {
78
+ return self . from_index ( idx + 1 ) ;
79
+ }
80
+ }
81
+ None
82
+ }
37
83
}
38
84
39
85
/// The axis decorator that makes key-point in the center of the value range
@@ -173,8 +219,12 @@ mod test {
173
219
assert_eq ! ( 21 , values. len( ) ) ;
174
220
175
221
for ( expected, value) in ( -10 ..=10 ) . zip ( values) {
176
- assert_eq ! ( expected, value)
222
+ assert_eq ! ( expected, value) ;
177
223
}
224
+ assert_eq ! ( range. next( & 5 ) , Some ( 6 ) ) ;
225
+ assert_eq ! ( range. next( & 10 ) , None ) ;
226
+ assert_eq ! ( range. previous( & -10 ) , None ) ;
227
+ assert_eq ! ( range. previous( & 10 ) , Some ( 9 ) ) ;
178
228
}
179
229
180
230
#[ test]
0 commit comments