[New-Mooncake] 新包 `loneoutpost/core-extra` 发布和交流

最近我正在活跃开发和频繁发布 loneoutpost/core-extra 包,这是我针对 core 包 API 的应用过程中遇到的个别问题,给出的高度试验性的一些修补。

不稳定,随时变更,但会尽最大努力维护文档,欢迎使用、关注和PR!

一个应用例

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: 月 🐰 兔

[^1]: 就是surrogate pair。

3 个赞