mod atom_tables;
#[cfg(target_arch = "x86_64")]
mod avx;
#[cfg(target_arch = "aarch64")]
mod neon;
mod tables;
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
mod wasm;
use atom_tables::ATOM_TABLES;
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Atom {
Letter = 0, NumWord = 1, NumOther = 2, Newline = 3, Space = 4, WsOther = 5, Mark = 6, Connector = 7, Punct = 8, Apostrophe = 9, SymOther = 10, NumericOther = 11, Control = 12, Sentinel = 13, MultiByte = 14, Cont = 15, AlphaSymMark = 0x16, Zwj = 0x26, UpperLetter = 0x10,
LowerLetter = 0x20,
HanLetter = 0x30,
HanNum = 0x31,
HanSym = 0x3A,
}
impl Atom {
#[inline]
pub const fn bit(self) -> u16 {
1u16 << (self as u16)
}
}
#[inline]
pub const fn in_mask(tag: u8, mask: u16) -> bool {
mask & (1u16 << (tag & 0x0F)) != 0
}
#[inline(always)]
pub const fn char_len(b: u8) -> usize {
if b < 0x80 {
1
} else if b < 0xE0 {
2
} else if b < 0xF0 {
3
} else {
4
}
}
pub mod mask {
use super::Atom::*;
pub const WORD: u16 = Letter.bit() | NumWord.bit() | Mark.bit() | Connector.bit();
pub const WS: u16 = Newline.bit() | Space.bit() | WsOther.bit();
pub const LETTER: u16 = Letter.bit();
pub const NUMBER: u16 = NumWord.bit() | NumOther.bit();
pub const NUMERIC: u16 = NumWord.bit() | NumOther.bit() | NumericOther.bit();
pub const PUNCT: u16 = Connector.bit() | Punct.bit() | Apostrophe.bit();
pub const NOT_WS_L_N: u16 = Mark.bit()
| Connector.bit()
| Punct.bit()
| Apostrophe.bit()
| SymOther.bit()
| Control.bit()
| NumericOther.bit();
pub const PUNCT_SYM: u16 = Connector.bit() | Punct.bit() | Apostrophe.bit() | SymOther.bit();
pub const LETTER_MARK: u16 = Letter.bit() | Mark.bit();
}
pub const CONT: u8 = Atom::Cont as u8;
pub const MB: u8 = Atom::MultiByte as u8;
#[inline]
pub fn classify(text: &[u8], tags: &mut [u8]) {
assert!(
tags.len() >= text.len(),
"bitcannon::classify: `tags` shorter than `text`"
);
#[cfg(target_arch = "aarch64")]
unsafe {
neon::classify_neon(text, tags)
}
#[cfg(target_arch = "x86_64")]
avx::dispatch(text, tags);
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
unsafe {
wasm::classify_wasm(text, tags)
}
#[cfg(not(any(
target_arch = "aarch64",
target_arch = "x86_64",
all(target_arch = "wasm32", target_feature = "simd128")
)))]
classify_scalar(text, tags);
}
#[doc(hidden)]
pub fn classify_scalar(text: &[u8], tags: &mut [u8]) {
let n = text.len();
let mut i = 0;
while i < n {
let b = text[i];
if b & 0xC0 == 0x80 {
tags[i] = CONT; i += 1;
continue;
}
tags[i] = ATOM_TABLES.classify_char(text, i);
let w = char_len(b);
let mut j = 1;
while j < w && i + j < n {
tags[i + j] = CONT;
j += 1;
}
i += w;
}
}