Skip to content

Commit 473adc5

Browse files
committed
Add previous and next function to discrete trait
1 parent d8b6cb3 commit 473adc5

File tree

1 file changed

+52
-2
lines changed

1 file changed

+52
-2
lines changed

src/coord/discrete.rs

+52-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ use super::{AsRangedCoord, Ranged};
22
use std::fmt::{Debug, Formatter, Result as FmtResult};
33
use std::ops::Range;
44

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.
610
pub trait DiscreteRanged
711
where
812
Self: Ranged,
@@ -15,12 +19,18 @@ where
1519

1620
/// Map a value to the index
1721
///
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+
///
1826
/// - `value`: The value to map
1927
/// - **returns** The index of the value
2028
fn index_of(&self, value: &Self::ValueType) -> Option<usize>;
2129

2230
/// Reverse map the index to the value
2331
///
32+
/// Note: This function doesn't guareentee returning None when the index is out of range.
33+
///
2434
/// - `value`: The index to map
2535
/// - **returns** The value
2636
fn from_index(&self, index: usize) -> Option<Self::ValueType>;
@@ -34,6 +44,42 @@ where
3444
{
3545
DiscreteValueIter(self, 0, self.size())
3646
}
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+
}
3783
}
3884

3985
/// The axis decorator that makes key-point in the center of the value range
@@ -173,8 +219,12 @@ mod test {
173219
assert_eq!(21, values.len());
174220

175221
for (expected, value) in (-10..=10).zip(values) {
176-
assert_eq!(expected, value)
222+
assert_eq!(expected, value);
177223
}
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));
178228
}
179229

180230
#[test]

0 commit comments

Comments
 (0)