Как сравнить значения двух 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);