diff options
Diffstat (limited to 'vendor/unic-char-property/src/tables.rs')
-rw-r--r-- | vendor/unic-char-property/src/tables.rs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/vendor/unic-char-property/src/tables.rs b/vendor/unic-char-property/src/tables.rs new file mode 100644 index 000000000..ab419d552 --- /dev/null +++ b/vendor/unic-char-property/src/tables.rs @@ -0,0 +1,117 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<V: 'static> { + #[doc(hidden)] + Direct(&'static [(char, V)]), + #[doc(hidden)] + Range(&'static [(CharRange, V)]), +} + +impl<V> Default for CharDataTable<V> { + fn default() -> Self { + CharDataTable::Direct(&[]) + } +} + +impl<V> CharDataTable<V> { + /// 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<V: Copy> CharDataTable<V> { + /// Find the associated data for a character in this table. + pub fn find(&self, needle: char) -> Option<V> { + 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<V: Copy + Default> CharDataTable<V> { + /// 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<V>, usize); + +impl<'a, V: Copy> Iterator for CharDataTableIter<'a, V> { + type Item = (CharRange, V); + + fn next(&mut self) -> Option<Self::Item> { + 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<V> CharDataTable<V> { + /// Iterate over the entries in this table. Yields pairs `(CharRange, V)`. + pub fn iter(&self) -> CharDataTableIter<'_, V> { + CharDataTableIter(self, 0) + } +} |