如何在Rust代码中比较两个JsValues的值?

时间:2019-03-14 21:50:56

标签: unit-testing rust webassembly wasm-bindgen

在JavaScript中,我可以这样做:

JSON.stringify([1,2,3]) ===  JSON.stringify([1,2,3]) // true

在Rust编译成Wasm的过程中,我尝试过类似的操作:

#[wasm_bindgen_test]
fn test_algo() {
    let js_array_to_sort = Array::of3(&JsValue::from(1), &JsValue::from(3), &JsValue::from(2));
    let js_array_after_sort = Array::of3(&JsValue::from(1), &JsValue::from(2), &JsValue::from(3));
    let array = JsValue::from(&js_array_to_sort);

    assert_eq!(
        JSON::stringify(BubbleSort::sort(SortArray::new(array))).unwrap(),
        JSON::stringify(JsValue::from(&js_array_after_sort)).unwrap(),
    );
}

由于wasm-pack test --chromepartialeq出现了一些关于JsString没有JSON::stringify的错误-

 error[E0277]: can't compare `js_sys::JsString` with `js_sys::JsString`
    --> src/algorithms/bubble.rs:36:5
     |
  36 | /     assert_eq!(
  37 | |         JSON::stringify(&BubbleSort::sort(SortArray::new(array))).unwrap(),
  38 | |         JSON::stringify(&JsValue::from(&js_array_after_sort)).unwrap(),
  39 | |     );
     | |______^ no implementation for `js_sys::JsString == js_sys::JsString`
     |
     = help: the trait `std::cmp::PartialEq` is not implemented for `js_sys::JsString`

如果我尝试转换为字符串并以其他方式进行比较(例如直接与JsString方法进行比较),则总是会遇到相同的编译错误。

如果我尝试直接比较此数组,那么我在JavaScript中的行为与此类似:

JsValue([1,2,3]) == JsValue([1,2,3]) // false

Cargo.toml中,我有:

[dependencies]
wasm-bindgen = "0.2.39"
js-sys = "0.3.16"
wasm-bindgen-test = "0.2.39"

我如何进行这种比较?

编辑。

我想出了类似的方法来通过此测试:

  assert_eq!(
        String::from(JSON::stringify(&BubbleSort::sort(SortArray::new(array))).unwrap()),
        String::from(JSON::stringify(&JsValue::from(&js_array_after_sort)).unwrap()),
    );

2 个答案:

答案 0 :(得分:1)

如果我的理解正确,则不应将它们进行比较。它们没有实现EqPartialEq,因此您不能比较它们的切片或数组。

实际上,它们甚至不存在于Rust中,而只是外部值的索引。

您可能也无法对它们进行排序,因为它们没有实现Ord

惯用的方法是使用as_f64方法将其转换为Rust原语,然后执行所需的任何操作。

如果您有一个TypedArray,可以很容易地将其转换为vec,则会更容易。

let js_array_to_sort = Array::of3(&JsValue::from(1), &JsValue::from(3), &JsValue::from(2));

let rust_vec = js_array_to_sort
    .values().into_iter()
    .map(|js_val|
        js_val.as_f64().unwrap() as i64
    )
    .collect::<Vec<i64>>();

let mut sorted_rust_vec = rust_vec.clone();
sorted_rust_vec.sort();

dbg!(sorted_rust_vec == rust_vec);

答案 1 :(得分:1)

尝试从js_sys访问Object::is(&first, &second)

您可以使用JSON::stringify(...),然后以与JavaScript相似的方式进行比较

#[wasm_bindgen_test]
fn test_algo() {
    let js_array_to_sort = Array::of3(&JsValue::from(1), &JsValue::from(2), &JsValue::from(3));
    let js_array_after_sort = Array::of3(&JsValue::from(1), &JsValue::from(2), &JsValue::from(3));
    let to_array = JsValue::from(&js_array_to_sort);
    let from_array = JsValue::from(&js_array_after_sort);
    let to_str: JsString = JSON::stringify(&to_array).unwrap();
    let from_str: JsString = JSON::stringify(&from_array).unwrap();
    assert_eq!(to_str == from_str, true);
    assert_eq!(Object::is(&to_str, &from_str), true);
}

请使用您自己的排序算法。我将这些值按排序进行比较,如果未排序则可以看到断言错误。