是否有一个带有UTF-16字符串类型的Rust库?(用于编写Javascript解释器)



对于大多数程序,最好在内部使用UTF-8,必要时转换为其他编码。但是在我的情况下,我想编写一个Javascript解释器,并且只存储UTF-16字符串(或u16数组)要简单得多,因为

  1. 我需要单独处理16位代码单元(这通常是一个坏主意,但Javascript需要这样做)。这意味着我需要它来实现Index<usize>

  2. 我需要存储未配对的代理,即格式错误的UTF-16字符串(因此,ECMAScript字符串在技术上被定义为u16数组,通常表示UTF-16字符串)。有一种名为WTF-8的编码可以在UTF-8中存储未配对的代理,但我不想使用这样的编码。

我想用所有或最常用的方法拥有通常的拥有/借用类型(如String/strCString/CStr)。我不想滚动我自己的字符串类型(如果我可以避免的话)。

此外,我的字符串将始终是不可变的,在Rc后面,并从包含弱指针的数据结构引用到所有字符串(实现字符串实习)。这可能是相关的:也许将Rc<Utf16Str>作为字符串类型会更好,其中Utf16Str是未大小的字符串类型(可以定义为struct Utf16Str([u16]))。这将避免在访问字符串时跟随两个指针,但我不知道如何实例化具有unsize类型的Rc

考虑到上述要求,仅仅使用rust编码是非常不方便的,因为它将所有非utf -8编码视为u8的向量。

另外,我不确定使用std库是否会对我有所帮助。我查看了Utf16Units,它只是一个迭代器,而不是一个合适的字符串类型。(另外,我知道OsString没有帮助-我不在Windows上,它甚至没有实现Index<usize>)

由于这里有多个问题,我将尝试分别回答:


我认为你需要的类型是[u16]Vec<u16>

默认的字符串类型strString[u8]Vec<u8>的包装(严格来说,str不是原始的,但足够接近)。使用单独的类型是为了保持底层字节在UTF-8中格式良好的不变性。

类似地,您可以使用Utf16StrUtf16String类型包裹[u16]Vec<u16>,以保留在UTF-16中格式良好的不变量,即没有未配对的代理。

但是正如您在问题中注意到的,JavaScript字符串可以包含未配对的代理。这是因为JavaScript字符串不是严格的UTF-16,它们实际上是u16的任意序列,没有额外的不变量。

没有不变量需要维护,我不认为包装类型有那么大的用处。


rust-encoding支持基于字节的UTF-16-LE和UTF-16-BE。您可能需要基于u16的UTF-16。

std::str::Utf16Units确实不是字符串类型。它是一个由str::utf16_units()方法返回的迭代器,它将Rust字符串转换为UTF-16(不是LE或BE)。例如,您可以在该迭代器上使用.collect()来获得Vec<u16>


获取Rc<[u16]>的唯一安全方法是强制Rc<[u16; N]>,其大小在编译时已知,这显然是不切实际的。我不推荐不安全的方法:分配内存,给它写一个头,希望能匹配RcBox的内存表示,然后转换。

如果你要使用原始内存分配,最好使用你自己的类型,这样你就可以使用它的私有字段。卷须是这样做的:https://github.com/servo/tendril/blob/master/src/buf32.rs

或者,如果你愿意承担额外的间接成本,Rc<Vec<u16>>是安全的,更容易。

最新更新