Search code examples
rustwebassemblydenowasm-bindgen

WASM & Deno / Extract and manipulate Array of Date


I try to extract and manipulate an array of date in a function in WASM project for Deno

The rust function doesn't compile. How to manipulate Date and convert it ?

Does someone have a repository/link with examples of Rust + Deno library ?

Cargo.toml

[dependencies]
wasm-bindgen = "=0.2.87"
time = { version = "0.3", features = ["parsing", "macros"] }
js-sys = "0.3.64"

mod.ts

import { instantiate } from "./lib/rs_lib.generated.js";

const { DateArrayToString } = await instantiate();

console.log(DateArrayToString( [new Date(2015, 11, 1 ), new Date(2016, 7, 1 ), new Date(2016, 7, 19 )]))

lib.rs

use wasm_bindgen::prelude::*;

use js_sys::Array;
use js_sys::Date;

#[wasm_bindgen]
pub fn DateArrayToString(arr:Array) -> JsString {
    let result : JsString;
    for i in 0..arr.length() {
        // problem is here
        let d : Date = arr.get(i).as_ref();
        // Concat
        result = result.concat(d.to_string());
    }
    return result;
}

Solution

  • There are multiple issues with your current implementation. The compile error you are facing at the moment is because the types do not match.

    You can fix this by casting the JsValue to a js_sys::Date like so:

    let d : Date = arr.get(i).into();
    

    This will lead you to another compile error, because result is possibly uninitialized. This can be fixed like so:

    let result: JsString = JsString::from("");
    

    Then you need to make result mutable because it is overwritten in the loop:

    let mut result: JsString = JsString::from("");
    

    And lastly you need to borrow, because the concat method expects to borrow its parameter:

    result = result.concat(&d.to_string());
    

    Thereby the full fixed code with minimal changes would look like this:

    use wasm_bindgen::prelude::*;
    
    use js_sys::Array;
    use js_sys::JsString;
    use js_sys::Date;
    
    #[wasm_bindgen]
    pub fn DateArrayToString(arr:Array) -> JsString {
        let mut result : JsString = JsString::from("");
        for i in 0..arr.length() {
            // problem is here
            let d : Date = arr.get(i).into();
            // Concat
            result = result.concat(&d.to_string());
        }
        return result;
    }
    

    However this is unneccessarily complex and violates some common rust standards, which is why I would advise to aim for something like the code posted below.

    Improved code:

    use js_sys::{Array, Date, JsString};
    use wasm_bindgen::prelude::*;
    
    #[wasm_bindgen(js_name = DateArrayToString)]
    pub fn date_array_to_string(arr: Array) -> JsString {
        let mut result = JsString::from("");
        for date_value in arr.values() {
            let d: Date = date_value.expect("Some error occured.").into();
            result = result.concat(&d.to_string());
        }
    
        result
    }