#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Layer {
Auto = 0,
Phrase = 1,
Zigen = 2,
Jianma3 = 3,
Jianma2 = 4,
Jianma1 = 5,
}
pub const LAYER_COUNT: usize = 6;
pub const LAYER_BASE: [u64; LAYER_COUNT] = [
100_000, 400_000, 500_000, 600_000, 800_000, 1_000_000, ];
#[allow(dead_code)] pub const DEFAULT_LAYER_PREFS: [f64; LAYER_COUNT] = [
0.7, 1.0, 1.0, 1.0, 1.0, 1.0, ];
#[allow(dead_code)] impl Layer {
pub const fn from_u8(b: u8) -> Option<Self> {
match b {
0 => Some(Self::Auto),
1 => Some(Self::Phrase),
2 => Some(Self::Zigen),
3 => Some(Self::Jianma3),
4 => Some(Self::Jianma2),
5 => Some(Self::Jianma1),
_ => None,
}
}
pub const fn as_u8(self) -> u8 {
self as u8
}
pub const fn as_index(self) -> usize {
self as usize
}
pub const fn base(self) -> u64 {
LAYER_BASE[self as usize]
}
}
const FREQ_MASK: u64 = 0x00FF_FFFF_FFFF_FFFF;
#[allow(dead_code)] pub const fn pack(layer: Layer, freq_score: u64) -> u64 {
((layer as u64) << 56) | (freq_score & FREQ_MASK)
}
#[allow(dead_code)] pub const fn unpack(packed: u64) -> (Layer, u64) {
let layer_byte = (packed >> 56) as u8;
let freq = packed & FREQ_MASK;
let layer = match Layer::from_u8(layer_byte) {
Some(l) => l,
None => Layer::Auto,
};
(layer, freq)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pack_unpack_roundtrip() {
for &l in &[
Layer::Jianma1,
Layer::Jianma2,
Layer::Jianma3,
Layer::Zigen,
Layer::Phrase,
Layer::Auto,
] {
for &f in &[0u64, 1, 1234, FREQ_MASK] {
let p = pack(l, f);
let (lu, fu) = unpack(p);
assert_eq!(lu, l);
assert_eq!(fu, f);
}
}
}
#[test]
fn freq_overflow_is_truncated() {
let p = pack(Layer::Phrase, FREQ_MASK + 1);
let (l, f) = unpack(p);
assert_eq!(l, Layer::Phrase);
assert_eq!(f, 0);
}
#[test]
fn layer_base_strict_ascending() {
for w in LAYER_BASE.windows(2) {
assert!(w[0] < w[1], "LAYER_BASE must be strictly ascending (Auto = lowest priority)");
}
}
#[test]
fn packed_u64_orders_by_priority() {
let auto = pack(Layer::Auto, FREQ_MASK);
let phrase = pack(Layer::Phrase, 0);
assert!(phrase > auto, "Phrase + 0 freq must beat Auto + max freq");
let jm1 = pack(Layer::Jianma1, 0);
let jm2 = pack(Layer::Jianma2, FREQ_MASK);
assert!(jm1 > jm2);
}
}