最近我正在活跃开发和频繁发布 loneoutpost/core-extra
包,这是我针对 core
包 API 的应用过程中遇到的个别问题,给出的高度试验性的一些修补。
不稳定,随时变更,但会尽最大努力维护文档,欢迎使用、关注和PR!
- Mooncakes.io 文档页面:
https://mooncakes.io/docs/#/loneoutpost/core-extra/ - GitHub 仓库:
https://github.com/lone-outpost-oss/mbt-core-extra
一个应用例
MoonBit的内部字符串编码是UTF-16:
- 大多数字符占用一个WORD(字,即16位),但是……
- 对于emoji等落在
U+10000
以上,一个字放不下的字符,就要占用一个DWORD(双字,即32位)[1]。但在目前的工具链中,无论是用
[]
运算符还是用String::get(self, idx)
方法拿取一个Char
,都只会固定读取位于idx
位置的一个WORD。如果这个位置的恰好是一个DWORD字符就会被截断,从而拿到一个无效的Char
值。
loneoutpost/core-extra/string
提供了临时性的修补函数get_valid_char_at(str: String, idx_word: Int)
。它与原来的get
函数行为一致,仍然是读取idx
位置的一个WORD,只是能够正确读取前后邻接的WORD,从而保证即使落在DWORD字符上,拿到的Char
类型值是完整无截断的。利用它写一个遍历字符的代码:
let str = "\u{6708}\u{1f430}\u{5154}" // 月🐰兔 let mut i = 0 while i < str.length() { let (ch, ty) = get_valid_char_at(str, i) println(ch) // advance by 2 words on a surrogate pair i += if ty != Utf16WordType::BMP { 1 } else { 2 } } // output: 月 🐰 兔
就是surrogate pair。 ↩︎