#![warn(missing_docs)]
#[cfg(any(feature = "wasm", feature = "icu4c"))]
use core::ops::RangeInclusive;
#[cfg(any(feature = "wasm", feature = "icu4c"))]
use icu_collections::codepointtrie::CodePointTrie;
#[cfg(any(feature = "wasm", feature = "icu4c"))]
use icu_collections::codepointtrie::TrieType;
#[cfg(any(feature = "wasm", feature = "icu4c"))]
use icu_collections::codepointtrie::TrieValue;
#[cfg(feature = "wasm")]
mod wasm;
#[cfg(feature = "icu4c")]
mod native;
#[cfg(feature = "wasm")]
use wasm::Builder;
#[cfg(all(feature = "icu4c", not(feature = "wasm")))]
use native::Builder;
#[allow(clippy::exhaustive_structs)]
#[derive(Debug)]
#[cfg(any(feature = "wasm", feature = "icu4c"))]
pub struct CodePointTrieBuilder<T: TrieValue> {
inner: Builder<T>,
trie_type: TrieType,
default_value: T,
}
#[cfg(any(feature = "wasm", feature = "icu4c"))]
impl<T: TrieValue> CodePointTrieBuilder<T> {
pub fn new(default_value: T, error_value: T, trie_type: TrieType) -> Self {
Self {
inner: Builder::create(default_value, error_value),
trie_type,
default_value,
}
}
#[cfg(any(feature = "wasm", feature = "icu4c"))]
pub fn set_value(&mut self, cp: u32, value: T) {
if value == self.default_value || cp > char::MAX as u32 {
return;
}
self.inner.set_value(cp, value);
}
#[cfg(any(feature = "wasm", feature = "icu4c"))]
pub fn set_range_value(&mut self, cps: RangeInclusive<u32>, value: T) {
if value == self.default_value {
return;
}
self.inner.set_range_value(
(*cps.start()).min(char::MAX as u32)..=(*cps.end()).min(char::MAX as u32),
value,
);
}
#[cfg(any(feature = "wasm", feature = "icu4c"))]
pub fn build(self) -> CodePointTrie<'static, T> {
let width = match size_of::<T::ULE>() {
1 => 2, 2 => 0, 3 | 4 => 1, other => panic!("Don't know how to make trie with width {other}"),
};
self.inner.build(self.trie_type, width)
}
}
#[test]
#[cfg(any(feature = "wasm", feature = "icu4c"))]
fn test_cpt_builder() {
let mut builder = CodePointTrieBuilder::new(100, 0xFFF, TrieType::Fast);
for (cp, value) in (0..100)
.map(|x| x / 10)
.chain((100..0x100).map(|_| 100))
.chain((0x100..0x200).map(|x| x % 16))
.enumerate()
{
builder.set_value(cp as u32, value);
}
let cpt = builder.build();
assert_eq!(cpt.get32(0), 0);
assert_eq!(cpt.get32(10), 1);
assert_eq!(cpt.get32(20), 2);
assert_eq!(cpt.get32(21), 2);
assert_eq!(cpt.get32(99), 9);
assert_eq!(cpt.get32(0x101), 0x1);
assert_eq!(cpt.get32(0x102), 0x2);
assert_eq!(cpt.get32(0x105), 0x5);
assert_eq!(cpt.get32(0x125), 0x5);
assert_eq!(cpt.get32(0x135), 0x5);
assert_eq!(cpt.get32(0x13F), 0xF);
assert_eq!(cpt.get32(0x300), 100);
}