是否存在带有UTF-16字符串类型的Rust库? (旨在编写JavaScript解释器)

Is there a Rust library with an UTF-16 string type? (intended for writing a Javascript interpreter)

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

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

  • 我需要存储不成对的代理,即格式不正确的UTF-16字符串(因此,ECMAScript字符串在技术上被定义为u16的数组,通常表示UTF-16字符串)。有一种恰当地命名为WTF-8的编码可以将未配对的替代存储在UTF-8中,但是我不想使用类似的东西。

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

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

    鉴于上述要求,仅使用rust-encoding很不方便,因为它将所有非UTF-8编码都视为u8的向量。

    此外,我不确定是否完全可以使用std库在这里对我有所帮助。我调查了Utf16Units,它只是一个迭代器,而不是正确的字符串类型。 (此外,我知道OsString不能帮助您-我不在Windows上,并且甚至没有实现Index<usize>)


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

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

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

    类似地,您可以将Utf16StrUtf16String类型包裹在[u16]Vec<u16>周围,并保留格式良好的UTF-16不变式,即没有不成对的替代。

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

    由于不需要维护不变性,因此我认为package器类型没什么用。

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

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

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