chartml_core/scales/
ordinal.rs1pub struct ScaleOrdinal {
4 domain: Vec<String>,
5 range: Vec<String>,
6}
7
8impl ScaleOrdinal {
9 pub fn new(domain: Vec<String>, range: Vec<String>) -> Self {
11 Self { domain, range }
12 }
13
14 pub fn map(&self, value: &str) -> Option<&str> {
18 if self.range.is_empty() {
19 return None;
20 }
21 let index = self.domain.iter().position(|d| d == value)?;
22 Some(&self.range[index % self.range.len()])
23 }
24
25 pub fn map_index(&self, index: usize) -> Option<&str> {
28 if self.range.is_empty() {
29 return None;
30 }
31 Some(&self.range[index % self.range.len()])
32 }
33
34 pub fn domain(&self) -> &[String] {
36 &self.domain
37 }
38
39 pub fn range(&self) -> &[String] {
41 &self.range
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 #![allow(clippy::unwrap_used)]
48 use super::*;
49
50 #[test]
51 fn ordinal_basic_mapping() {
52 let scale = ScaleOrdinal::new(
53 vec!["a".into(), "b".into(), "c".into()],
54 vec!["red".into(), "green".into(), "blue".into()],
55 );
56 assert_eq!(scale.map("a"), Some("red"));
57 assert_eq!(scale.map("b"), Some("green"));
58 assert_eq!(scale.map("c"), Some("blue"));
59 }
60
61 #[test]
62 fn ordinal_cycling() {
63 let scale = ScaleOrdinal::new(
64 vec!["a".into(), "b".into(), "c".into(), "d".into()],
65 vec!["red".into(), "green".into()],
66 );
67 assert_eq!(scale.map("a"), Some("red"));
68 assert_eq!(scale.map("b"), Some("green"));
69 assert_eq!(scale.map("c"), Some("red")); assert_eq!(scale.map("d"), Some("green")); }
72
73 #[test]
74 fn ordinal_unknown_returns_none() {
75 let scale = ScaleOrdinal::new(
76 vec!["a".into(), "b".into()],
77 vec!["red".into(), "green".into()],
78 );
79 assert_eq!(scale.map("unknown"), None);
80 }
81
82 #[test]
83 fn ordinal_empty_range() {
84 let scale = ScaleOrdinal::new(
85 vec!["a".into(), "b".into()],
86 vec![],
87 );
88 assert_eq!(scale.map("a"), None);
89 }
90
91 #[test]
92 fn ordinal_map_index() {
93 let scale = ScaleOrdinal::new(
94 vec!["a".into(), "b".into()],
95 vec!["red".into(), "green".into(), "blue".into()],
96 );
97 assert_eq!(scale.map_index(0), Some("red"));
98 assert_eq!(scale.map_index(1), Some("green"));
99 assert_eq!(scale.map_index(2), Some("blue"));
100 assert_eq!(scale.map_index(3), Some("red")); }
102}