作者:Timothy McCallum Second State 核心开发
这篇文章详细解释了 WASM 中如何实现字符串,文章有点长,建议收藏后慢慢读~
字符串的重要性
计算机程序只用数字就可以成功执行。 然而,为了方便人机交互,人类可读的字符和文字是必需的。 当我们思考人类如何与 Web 上的应用程序进行交互时,情况尤其如此。 绝佳的例子是,人们在访问Web 时选择使用域名,而非数字 IP 地址。
正如本文的标题所宣称的,我们将讨论 WebAssembly (Wasm)中的字符串。 WASM是最近我们看到的最令人兴奋的计算机编程技术之一。 Wasm 是一种接近机器的、支持多平台的、低级的、类汇编语言(Reiser and bl ser,2017) ,它从一开始就是第一个实现形式语义学的主流编程语言(Rossberg et al. ,2018)。
WebAssembly 中的字符串
有趣的是,WebAssembly 代码中没有本地字符串。 更具体地说,Wasm 没有字符串数据类型。
Wasm的MVP(只支持wasm32)有一个ILP32数据模型,目前提供以下4种数据类型,分别是:
- i32,一个32位的整数(相当于 c + + 的带符号 long int)
- i64,一个64位的整数(相当于 c + + 的带符号 long int)
- f32,32位浮点数(相当于 c + + 的浮点数)
- f64,64位浮点数(相当于 c + + 的 double)
虽然我们很快就会开始讨论在浏览器中使用 Wasm,但关键是要始终记住,从根本上讲,Wasm 的执行是用堆栈机器来定义的。 其基本想法是,每种类型的指令都会将一定数量的 i32、 i64、 f32、 f64值从堆栈中推入或弹出(MDN Web Docs ——理解 WebbAssembly 文本格式,2020)。
正如我们所看到的,上面的四种数据类型都属于数字。 那么,如果是这种情况,我们如何在 WebAssembly (Wasm)中促成(facilitate)字符串呢?
WebAssembly 中的字符串ーー怎样解决?
现在,可以将高级值(如字符串)转换为一组数字。 如果实现了这一点,那么我们就可以在函数之间来回传递这些数字集(代表字符串)。
然而,这里有几个问题。
对于一般的高级编码来说,总是需要这种常量的显式编码 / 解码是很麻烦的,因此这不是一个很好的长期解决方案。
此外,事实证明,这种方法目前在 Wasm 实际上不可能实现。 原因是,尽管 Wasm 函数可以接受函数中的许多值(作为参数) ,但是目前 Wasm 函数只能返回一个值。而Wasm会有很多信息。
现在,让我们通过看看 Rust 中的字符串的工作机制,来讲一下基础知识。
Rust字符串
字符串
Rust中的String 可以被认为是一个保证了拥有良好的 UTF-8 Vec(Blandy and Orendorff,2017)。
& str
Rust 中的 &str
是对其他人拥有的一组 UTF-8文本的引用。&str
是一个宽指针(fat pointer),包含实际数据的地址及其长度。 您可以将 &str
看作是一个保证包含格式良好的 UTF-8的 &[u8]
(Blandy and Orendorff,2017)。
编译时的字符串——存储在可执行文件中
字符串文本是一个指预先分配的文本的 &st
r,通常与程序机器代码一起存储在只读内存文档中; 程序开始执行时创建字节,一直到程序结束。 因此,修改 &str
是不可能的(Blandy 和 Orendorff,2017)。
&str
可以引用任何字符串的任何片段,因此使用 &str
作为函数参数的一部分是合适的; 调用者可以传递 String
或 &str
(Klabnik 和 Nichols,2019)。
像这样的代码这样:
fn my_function(the_string: &str) -> &str {
// code ...
}
运行时的字符串ー在运行时分配和释放
可以在运行时使用 String
创建新字符串。 可以使用以下方法将字符串文本转换为 String
。To String ()
和 String::from
做同样的事情,因此您选择哪个只是风格上的区别(Klabnik 和 Nichols,2019)。
let s = "the string literal".to_string();
let s = String::from("the string literal");
将字符串转换为数字
下面的 Rust 代码获取字符串 hello
并将其转换为字节,然后将该字符串的两个版本输出到终端。
fn main() {
let s: String = String::from("hello");
println!("String: {:?}", &s);
println!("Bytes: {:?}", &s.as_bytes());
}
输出
String: "hello"
Bytes: [104, 101, 108, 108, 111]
Wasm 的“ Hello World! ”例子
有了所有这些信息,我们如何为 Web 用 Wasm 编写“ Hello World! ” ? 例如,我们如何在用户界面和 Wasm 执行环境之间来回传递字符串?
问题的核心是… WebAssembly 需要很好地使用 JavaScript… 我们需要使用Javascript并将 JavaScript 对象传递到 WebAssembly,但 WebAssembly 根本不支持这一点。 目前,WebAssembly 只支持整数和浮点数(Williams,2019)。
将 JavaScript 对象硬塞进 u32以便用于 Wasm,需要费些力气。
摔跤图案,看起来很像甲壳类动物。
这是个巧合吗? 我不这么认为。