// Copyright 2017 The UNIC Project Developers. // // See the COPYRIGHT file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Character data tables used in UNIC. use unic_char_range::CharRange; /// A mapping from characters to some associated data. /// /// For the set case, use `()` as the associated value. #[derive(Copy, Clone, Debug)] pub enum CharDataTable { #[doc(hidden)] Direct(&'static [(char, V)]), #[doc(hidden)] Range(&'static [(CharRange, V)]), } impl Default for CharDataTable { fn default() -> Self { CharDataTable::Direct(&[]) } } impl CharDataTable { /// Does this table contain a mapping for a character? pub fn contains(&self, needle: char) -> bool { match *self { CharDataTable::Direct(table) => { table.binary_search_by_key(&needle, |&(k, _)| k).is_ok() } CharDataTable::Range(table) => table .binary_search_by(|&(range, _)| range.cmp_char(needle)) .is_ok(), } } } impl CharDataTable { /// Find the associated data for a character in this table. pub fn find(&self, needle: char) -> Option { match *self { CharDataTable::Direct(table) => table .binary_search_by_key(&needle, |&(k, _)| k) .map(|idx| table[idx].1) .ok(), CharDataTable::Range(table) => table .binary_search_by(|&(range, _)| range.cmp_char(needle)) .map(|idx| table[idx].1) .ok(), } } /// Find the range and the associated data for a character in the range table. pub fn find_with_range(&self, needle: char) -> Option<(CharRange, V)> { match *self { CharDataTable::Direct(_) => None, CharDataTable::Range(table) => table .binary_search_by(|&(range, _)| range.cmp_char(needle)) .map(|idx| table[idx]) .ok(), } } } impl CharDataTable { /// Find the associated data for a character in this table, or the default value if not entered. pub fn find_or_default(&self, needle: char) -> V { self.find(needle).unwrap_or_else(Default::default) } } /// Iterator for `CharDataTable`. Iterates over pairs `(CharRange, V)`. #[derive(Debug)] pub struct CharDataTableIter<'a, V: 'static>(&'a CharDataTable, usize); impl<'a, V: Copy> Iterator for CharDataTableIter<'a, V> { type Item = (CharRange, V); fn next(&mut self) -> Option { match *self.0 { CharDataTable::Direct(arr) => { if self.1 >= arr.len() { None } else { let idx = self.1; self.1 += 1; let (ch, v) = arr[idx]; Some((chars!(ch..=ch), v)) } } CharDataTable::Range(arr) => { if self.1 >= arr.len() { None } else { let idx = self.1; self.1 += 1; Some(arr[idx]) } } } } } impl CharDataTable { /// Iterate over the entries in this table. Yields pairs `(CharRange, V)`. pub fn iter(&self) -> CharDataTableIter<'_, V> { CharDataTableIter(self, 0) } }