1use unic_char_range::CharRange;
16
17#[derive(Copy, Clone, Debug)]
21pub enum CharDataTable<V: 'static> {
22 #[doc(hidden)] Direct(&'static [(char, V)]),
23 #[doc(hidden)] Range(&'static [(CharRange, V)]),
24}
25
26impl<V> Default for CharDataTable<V> {
27 fn default() -> Self {
28 CharDataTable::Direct(&[])
29 }
30}
31
32impl<V> CharDataTable<V> {
33 pub fn contains(&self, needle: char) -> bool {
35 match *self {
36 CharDataTable::Direct(table) => {
37 table.binary_search_by_key(&needle, |&(k, _)| k).is_ok()
38 }
39 CharDataTable::Range(table) => table
40 .binary_search_by(|&(range, _)| range.cmp(needle))
41 .is_ok(),
42 }
43 }
44}
45
46impl<V: Copy> CharDataTable<V> {
47 pub fn find(&self, needle: char) -> Option<V> {
49 match *self {
50 CharDataTable::Direct(table) => table
51 .binary_search_by_key(&needle, |&(k, _)| k)
52 .map(|idx| table[idx].1)
53 .ok(),
54 CharDataTable::Range(table) => table
55 .binary_search_by(|&(range, _)| range.cmp(needle))
56 .map(|idx| table[idx].1)
57 .ok(),
58 }
59 }
60}
61
62impl<V: Copy + Default> CharDataTable<V> {
63 pub fn find_or_default(&self, needle: char) -> V {
65 self.find(needle).unwrap_or_else(Default::default)
66 }
67}
68
69pub struct CharDataTableIter<'a, V: 'static>(&'a CharDataTable<V>, usize);
71
72impl<'a, V: Copy> Iterator for CharDataTableIter<'a, V> {
73 type Item = (CharRange, V);
74
75 fn next(&mut self) -> Option<Self::Item> {
76 match *self.0 {
77 CharDataTable::Direct(arr) => if self.1 >= arr.len() {
78 None
79 } else {
80 let idx = self.1;
81 self.1 += 1;
82 let (ch, v) = arr[idx];
83 Some((chars!(ch..=ch), v))
84 },
85 CharDataTable::Range(arr) => if self.1 >= arr.len() {
86 None
87 } else {
88 let idx = self.1;
89 self.1 += 1;
90 Some(arr[idx])
91 },
92 }
93 }
94}
95
96impl<V> CharDataTable<V> {
97 pub fn iter(&self) -> CharDataTableIter<V> {
99 CharDataTableIter(&self, 0)
100 }
101}