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

时间:2015-07-28 19:23:23

标签: string rust utf-16

对于大多数程序,最好use UTF-8 internally,并在必要时转换为其他编码。但就我而言,我想编写一个Javascript解释器,只存储UTF-16字符串(或u16数组)更简单,因为

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

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

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

    此外,我的字符串将始终是不可变的,位于Rc之后,并且从包含指向所有字符串的弱指针的数据结构中引用(实现string interning)。这可能是相关的:或许最好将Rc<Utf16Str>作为字符串类型,其中Utf16Str是未确定的字符串类型(可以定义为struct Utf16Str([u16]))。这样可以避免在访问字符串时遵循两个指针,但我不知道如何使用unsized类型实例化Rc

    鉴于上述要求,仅使用防锈编码非常不方便,因为它会处理所有非UTF-8编码as vectors of u8

    另外,我不确定using the std library是否可以帮助我。我查看了Utf16Units,它只是一个迭代器,而不是一个正确的字符串类型。 (另外,我知道OsString无效 - 我不在Windows上,甚至没有实现Index<usize>

1 个答案:

答案 0 :(得分:5)

由于这里有多个问题,我会尝试单独回答:

我认为您想要的类型是[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>>是安全且容易的。