Как сравнить значения двух JsValues ​​в коде Rust?

В 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 --chrome о нет partialeq за 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()),
    );

1 ответ

Пытаться Object::is(&first, &second) из js_sys.

Вы можете использовать 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);
}

Пожалуйста, используйте свой собственный алгоритм сортировки. Я взял значения отсортированными для сравнения, если они не отсортированы, вы можете увидеть ошибку утверждения.

Если я правильно понимаю, вы не должны их сравнивать. Они не реализуют Eq или же PartialEqи поэтому вы не можете сравнивать их срезы или массивы.

На самом деле они даже не живут внутри Rust, а просто являются указателями на внешние значения.

Вы, вероятно, не можете сортировать их, потому что они не реализуют Ord,

Идиоматический способ сделать это - преобразовать их в примитивы Rust, используя as_f64 методы, а затем делать все, что вам нужно.

Было бы проще, если бы у вас был 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);
Другие вопросы по тегам