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

dar*_*que 7 string utf-16 rust

对于大多数程序,最好在内部使用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是未定义的字符串类型(可以定义为just struct Utf16Str([u16])).这样可以避免在访问字符串时遵循两个指针,但我不知道如何Rc使用unsized类型实例化.

鉴于上述要求,仅使用防锈编码非常不方便,因为它将所有非UTF-8编码视为矢量u8.

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

Sim*_*pin 7

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


我认为您想要的类型是[u16]Vec<u16>

默认的字符串类型strString是环绕[u8]和的包装Vec<u8>(从技术上讲,str它不是原始的,但足够接近)。具有单独类型的目的是要保持不变,即底层字节在UTF-8格式正确

类似地,您可能拥有Utf16StrUtf16String包装类型,[u16]并且Vec<u16>保留了格式良好的UTF-16不变式,即没有不成对的代理。

但是,正如您在问题中指出的那样,JavaScript字符串可以包含未配对的代理。这是因为JavaScript字符串严格来说不是UTF-16,它们实际上是任意序列,u16没有附加的不变性。

无需维护不变性,我认为包装器类型并没有那么有用。


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

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


唯一安全的获取方法是在编译时Rc<[u16]>强制确定Rc<[u16; N]>其大小,这显然是不切实际的。我不建议这种不安全的方法:分配内存,向其中写入一个希望与的内存表示形式匹配的标头RcBox,然后进行转换。

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

或者,如果您愿意承担额外的间接费用,那将Rc<Vec<u16>>是安全且容易得多的。