25次发布
0.10.0 | 2024年2月7日 |
---|---|
0.9.0 | 2023年3月14日 |
0.8.0 | 2023年2月23日 |
0.6.0 | 2022年9月20日 |
0.4.0 | 2022年7月26日 |
#244 在 算法
每月 25 次下载
435KB
857 行
feruca – Rust中的Unicode Collation
feruca是Unicode Collation Algorithm在Rust中的基本实现。它与Unicode版本15.1保持一致(相应地,CLDR版本44;见下文)。该库的名称是Ferris 🦀和UCA的混成词。
此库中未直接使用unsafe
:#![forbid(unsafe_code)]
。它依赖于经过良好验证的bstr来接受输入(形式为&str
或&[u8]
),进行UTF-8验证,并生成Unicode标量值的列表,然后可以对这些值进行排序处理。该理念是对于可能不是完全合法的UTF-8输入保持容忍。
在将feruca描述为“基本实现”时,我有几个想法。首先,该库的性能可能仍然可以进一步提高——特别是在与官方的C实现,来自icu4c的ucol
相比,它非常优化。我不再运行针对该实现的基准测试,但feruca始终运行较慢,我猜测它现在仍然如此(尽管可能不是非常严重)。我现在所进行基准测试的是来自icu4x项目的较新的第一方实现,该实现也是用Rust编写的。与icu4x collator相比,feruca的性能可高达3-4倍——而功能集却小得多。作为一个独立开发者,我的首要任务是生产一个相对简陋的实现,该实现可以顺利通过官方UCA兼容性测试,以及通用区域数据存储库(CLDR)的“根排序顺序”测试。
第二,对定制的支持最小(到目前为止)。您可以在两个字符权重表中选择:默认Unicode排序元素表(DUCET)或CLDR的变体。然后,CLDR表成为基于语言/区域设置的实际排序定制的起点。我只添加了一个定制,旨在与阿拉伯语脚本语言一起使用。它将阿拉伯语脚本中的字母移动到拉丁字母之前。这对于我处理波斯语和阿拉伯语文本的工作已经足够了。未修改的CLDR表——即根排序顺序——对几种其他语言来说都是即插即用的。我确实计划添加更多定制,但这将是一个渐进的过程,由需求驱动。现实中,feruca永远不会像ICU那样提供全面、灵活的定制支持。我的感觉是,需要更简单、API更简单、依赖树更小等不复杂的解决方案(如果您对此有任何想法,我很乐意听听)。
除了区域设置定制之外,您还可以在处理可变权重字符时选择“非可忽略”和“移位”策略——后者是默认选项。还有一项选项,在两个字符串产生相同的UCA排序键的情况下,使用字节值比较作为“决胜者”。
第三,这个库实际上只有一个公共方法,属于一个结构体Collator
,名为collate
,用于设置选项。 collate
接受两个字符串引用或字节切片,并返回一个Ordering
值。它旨在作为比较器传递给标准库方法sort_by
(或sort_unstable_by
)。下面是“用法示例”。
对于许多人和使用场景,没有指定区域设置,UCA排序将无法正常工作!然而,再次强调CLDR根排序顺序的实用性是很重要的。在定义Collator
时,您可以设置默认选项(见下文),这些选项表示使用具有“移位”策略的CLDR表。我认为这是一个好起点。
用法示例
use feruca::Collator;
fn main() {
let mut uca = [
"چنگیز",
"Éloi",
"Ötzi",
"Melissa",
"صدام",
"Mélissa",
"Overton",
"Elrond",
];
let mut naive = uca;
naive.sort_unstable();
let mut collator = Collator::default();
uca.sort_unstable_by(|a, b| collator.collate(a, b));
for item in uca {
println!("{item}");
}
// Éloi
// Elrond
// Melissa
// Mélissa
// Ötzi
// Overton
// چنگیز
// صدام
println!(); // Empty line for clarity
for item in naive {
println!("{item}");
}
// Elrond
// Melissa
// Mélissa
// Overton
// Éloi
// Ötzi
// صدام
// چنگیز
}
一致性
可以使用命令cargo test --release
运行UCA一致性测试。请注意,由于这个库依赖于bstr
进行UTF-8验证,所以任何在collate
方法的输入中发现的代理代码点将被转换为标准的“替换字符”,U+FFFD
。UCA的一致性实现明确允许采取这种方法。这意味着,在一致性测试中,需要跳过数千行中的几行。如果您查看测试模块中的conformance
函数,您会看到任何包含代理代码点的行都会被跳过。
二进制编码
feruca包含的二进制文件表示Unicode数据的哈希表。它们在单独的存储库中生成,即feruca-mapper,并使用bincode进行序列化。如果您愿意,您可以自己重新构建它们。
许可
在test-data
目录中的文本文件受Unicode许可协议的保护。其他一切都是MIT许可。
依赖项
~1–1.3MB
~24K SLoC