Slide 1

Slide 1 text

rust for webapp(wasm) 2020/1/22

Slide 2

Slide 2 text

self introduction ● poccariswet ● 4nen ● skill golang, rust, video/live streaming ● like radio

Slide 3

Slide 3 text

contents ● 作ったやつ ○ 実装 ○ wasm-bindgen ○ ポイント ● 思ったこと ● 今後...

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

APNG ● Animated PNGの略 ● PNGファイルをアニメーション(連番画像)のように表現した画像のこと ● PNGフォーマットを拡張してできた画像のこと ○ acTL(Animation Controlチャンク) ○ fcTL(Frame Controlチャンク) ○ fdAT(Frame Dataチャンク)

Slide 7

Slide 7 text

APNG library https://qiita.com/poccariswet/items/677fda45f837f4d1dc3c https://github.com/poccariswet/apng

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

APNG maker https://github.com/poccariswet/apng-maker-wasm https://apng-maker.netlify.com/

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

drawasm ● rust (wasm) だけ ● 絵や文字を書いてAPNGを作れる ● APNGのframe speedの調整可能 https://drawasm.netlify.com/

Slide 12

Slide 12 text

drawasm https://drawasm.netlify.com/

Slide 13

Slide 13 text

drawasm import * as wasm from "drawing-wasm"; wasm.run(); ちなみに、jsを書いたのはこれだけ ...

Slide 14

Slide 14 text

Implementation ● state management ● EventListener ● APNG generate

Slide 15

Slide 15 text

● wasmとjsのインターフェース ● rustのメソッド、構造体を jsのクラスに ● wasm とjs間 のinterface ○ js-sys ○ web-sys ○ console_error_panic_hook ● 最近、pull requestした wasm-bindgen

Slide 16

Slide 16 text

state management ● Arc/Rc : 共有スマートポインタ (Rcはシングルスレッド) ○ 複数のデータや状態を共有 ● RefCell : 内部可変性コンテナ ○ 実行時に精査される可変借用を許可する、 RefCellが不変でもRefCell内の値を可変化する let state: Rc> = Rc::new(RefCell::new(state::State::new(canvas_w, canvas_h))); これで複数のオブジェクト間での状態の共有ができる https://github.com/poccariswet/drawasm/blob/master/src/lib.rs#L60-L61

Slide 17

Slide 17 text

EventListener let picked_color = Closure::wrap(Box::new(move |e: Event| { let target = e.target().unwrap().dyn_into::().unwrap(); let color = target.value(); state.borrow_mut().set_color(color) }) as Box); 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

Slide 18

Slide 18 text

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::().unwrap(); let color = target.value(); state.borrow_mut().set_color(color) }) as Box); input.add_event_listener_with_callback("change", picked_color.as_ref().unchecked_ref())?; picked_color.forget(); //⚠注意点

Slide 19

Slide 19 text

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::().unwrap(); let color = target.value(); state.borrow_mut().set_color(color) }) as Box); input.add_event_listener_with_callback("change", picked_color.as_ref().unchecked_ref())?; picked_color.forget(); //⚠注意点

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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() で次タブで開く

Slide 22

Slide 22 text

https://drawasm.netlify.com

Slide 23

Slide 23 text

● 思ったこと ○ mem::forget関数などのrust独自の面白い関数に出会えよかった ○ ある程度はjsでいい

Slide 24

Slide 24 text

● 今後 ○ 足りない機能の追加 ○ バグを取り除く ○ wasm-bindgenに恩返し(コントリビュート)

Slide 25

Slide 25 text

Thanks!!!