Upgrade to Pro — share decks privately, control downloads, hide ads and more …

rust for web app

rust for web app

This presentation is #Zli_DeNA_LT .

poccariswet

January 22, 2020
Tweet

More Decks by poccariswet

Other Decks in Programming

Transcript

  1. Last time • APNG ライブラリの作成(rust) ◦ https://github.com/poccariswet/apng • APNG generator

    for web の作成 (rust, js) ◦ https://apng-maker.netlify.com • イマココ ◦ 複数のpngからAPNGを作ることはできた。じゃあ次は 0からAPNGを作ろう
  2. Last time • APNG ライブラリの作成(rust) ◦ https://github.com/poccariswet/apng • APNG maker

    for web の作成 (rust, js) ◦ https://apng-maker.netlify.com • イマココ ◦ 複数のpngからAPNGを作ることはできた。じゃあ次は 0からAPNGを作ろう
  3. Last time • APNG ライブラリの作成(rust) ◦ https://github.com/poccariswet/apng • APNG generator

    for web の作成 (rust, js) ◦ https://apng-maker.netlify.com • イマココ ◦ 複数のpngからAPNGを作ることはできた。じゃあ次は 0からAPNGを作ろう
  4. Last time • APNG ライブラリの作成(rust) ◦ https://github.com/poccariswet/apng • APNG generator

    for web の作成 (rust, js) ◦ https://apng-maker.netlify.com • イマココ ◦ 複数のpngからAPNGを作ることはできた。じゃあ次は 0からAPNGを作ろう
  5. • wasmとjsのインターフェース • rustのメソッド、構造体を jsのクラスに • wasm とjs間 のinterface ◦

    js-sys ◦ web-sys ◦ console_error_panic_hook • 最近、pull requestした wasm-bindgen
  6. state management • Arc/Rc : 共有スマートポインタ (Rcはシングルスレッド) ◦ 複数のデータや状態を共有 •

    RefCell : 内部可変性コンテナ ◦ 実行時に精査される可変借用を許可する、 RefCellが不変でもRefCell内の値を可変化する let state: Rc<RefCell<state::State>> = Rc::new(RefCell::new(state::State::new(canvas_w, canvas_h))); これで複数のオブジェクト間での状態の共有ができる https://github.com/poccariswet/drawasm/blob/master/src/lib.rs#L60-L61
  7. EventListener let picked_color = Closure::wrap(Box::new(move |e: Event| { let target

    = e.target().unwrap().dyn_into::<HtmlInputElement>().unwrap(); let color = target.value(); state.borrow_mut().set_color(color) }) as Box<dyn FnMut(_)>); input.add_event_listener_with_callback("change", picked_color.as_ref().unchecked_ref())?; picked_color.forget(); //⚠注意点 • jsでのEventListenerのClosureを作る ◦ Closure::wrap: rustのクロージャをラップして、 JSでもrustのクロー ジャを使用できるようにする。 https://github.com/poccariswet/drawasm/blob/master/src/toolbar.rs#L177-L183
  8. EventListener • Box::newでヒープメモリに割り当てる ◦ Js側(browser)とClosureを共有するため https://github.com/poccariswet/drawasm/blob/master/src/toolbar.rs#L177-L183 let picked_color = Closure::wrap(Box::new(move

    |e: Event| { let target = e.target().unwrap().dyn_into::<HtmlInputElement>().unwrap(); let color = target.value(); state.borrow_mut().set_color(color) }) as Box<dyn FnMut(_)>); input.add_event_listener_with_callback("change", picked_color.as_ref().unchecked_ref())?; picked_color.forget(); //⚠注意点
  9. EventListener (point!) • forget() : 意図的なメモリリーク(Dropしない) ◦ スコープを抜けても定義した Closureがdropしないので、EventListenerとして利用 可能

    ◦ このクロージャをシークして、プログラム全体の期間中有効にする https://github.com/poccariswet/drawasm/blob/master/src/toolbar.rs#L177-L183 let picked_color = Closure::wrap(Box::new(move |e: Event| { let target = e.target().unwrap().dyn_into::<HtmlInputElement>().unwrap(); let color = target.value(); state.borrow_mut().set_color(color) }) as Box<dyn FnMut(_)>); input.add_event_listener_with_callback("change", picked_color.as_ref().unchecked_ref())?; picked_color.forget(); //⚠注意点
  10. APNG generate • 自作したAPNGエンコーダーで、stateに保存されている PNGデータをAPNGにエンコードする • エンコード後のbufferを Blob::new_with_u8_array_sequence_and_options  で Blobに変

    換 • js側(browser) でも相互作用できるようにUint8Array型 に変換して線形メモリ(linear memory) へビューする。 • open_with_url() で次タブで開く https://github.com/poccariswet/drawasm/blob/master/src/generate.rs#L149-L159
  11. APNG generate https://github.com/poccariswet/drawasm/blob/master/src/generate.rs#L149-L159 let b = js_sys::Uint8Array::new(&unsafe { js_sys::Uint8Array::view(&buf) }.into());

    let array = js_sys::Array::new(); array.push(&b.buffer()); let blob = Blob::new_with_u8_array_sequence_and_options( &array, BlobPropertyBag::new().type_("image/png"), ) .unwrap(); let url = Url::create_object_url_with_blob(&blob).unwrap(); let window = window().unwrap(); window.open_with_url(&url).unwrap(); • js側(browser) でも相互作用できるようにUint8Array型に変 換して線形メモリ(linear memory) へビューする。 • open_with_url() で次タブで開く