Rust wasm-bindgen 结构体中包含字符串

8

我试图导出以下结构体:

#[wasm_bindgen]
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum TokenType {
    KeywordLiteral,
    NumberLiteral,
    Operator,
    Separator,
    StringLiteral,
}

#[wasm_bindgen]
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct Token {
    pub typ: TokenType,
    pub val: String,
}

但我得到的是:

error[E0277]: the trait bound `token::TokenType: std::marker::Copy` is not satisfied
  --> src\tokenizer\token.rs:17:14
   |
14 | #[wasm_bindgen]
   | --------------- required by this bound in `__wbg_get_token_typ::assert_copy`
...
17 |     pub typ: TokenType,
   |              ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `token::TokenType`

以及:

error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
  --> src\tokenizer\token.rs:18:14
   |
14 | #[wasm_bindgen]
   | --------------- required by this bound in `__wbg_get_token_val::assert_copy`
...
18 |     pub val: String,

我可以给TokenType添加#[derive(Copy)],但无法给String添加。

我是Rust的新手,所以需要帮助。感谢您的支持。

1个回答

12
根据wasm-bindgen#1985,为了使自动生成的访问器正常工作,结构体的公共字段必须是Copy类型。您可以将字段设置为私有,或者用#[wasm_bindgen(skip)]进行注释,然后直接实现getter和setter。在wasm-bindgen文档中提供了一个示例example provided来说明如何编写这些内容。
#[wasm_bindgen]
pub struct Baz {
    field: i32,
}

#[wasm_bindgen]
impl Baz {
    #[wasm_bindgen(constructor)]
    pub fn new(field: i32) -> Baz {
        Baz { field }
    }

    #[wasm_bindgen(getter)]
    pub fn field(&self) -> i32 {
        self.field
    }

    #[wasm_bindgen(setter)]
    pub fn set_field(&mut self, field: i32) {
        self.field = field;
    }
}

当wasm和js共享对象时,js对象仅包含指向wasm运行时内存中结构体的指针。当您从JS访问字段时,它会通过定义的属性进行访问,该属性调用函数请求wasm代码的属性值(可以将wasm内存视为UInt8Array位)。
要求对象为Copy可能是为了避免在自动生成这些getter和setter时出现意外情况。如果您手动实现它们,则可以在JS中具有相同的行为,并能够控制在rust侧设置的内容。

所以在结构体中简单地拥有一个String是不可能的吗? - Elias
那将如何编译成 TypeScript? - Elias
我编辑了答案以澄清。你可以在结构体中使用字符串,但如果你想使用自动生成的访问器,这些字符串就不能是pub - Mathieu Rene
那么你是在告诉我,我可以有一个getter和setter,但不能直接将String暴露给JavaScript? - Elias
向量不受支持,但 Box<[JsValue]> 是支持的,您可以使用 Vec::into_boxed_slice 将其从 Vec<JsValue> 转换过来,您可以通过类似 .map(JsValue::from) 的方式使用 wasm-bindgen 生成的 From impl 获取它。 - Mathieu Rene
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接