Skip to content
This repository has been archived by the owner on Mar 9, 2023. It is now read-only.

Commit

Permalink
Get the WASM bindings working end-to-end using Serde, but by awkwardl…
Browse files Browse the repository at this point in the history
…y forcing
  • Loading branch information
dabreegster committed Mar 21, 2022
1 parent 098d9b7 commit c3e4504
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 4 deletions.
13 changes: 13 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,16 @@ trunk serve
- The web demo is updated with every push on `main`, [see Workflow](./.github/workflows/web.yml)
- The html website is part of the rest implementation at [`/rust/osm2lanes-web` ](./rust/osm2lanes-web)

### JS bindings

You can call the Rust library in JavaScript through WASM bindings.

```shell
cd rust/osm2lanes
wasm-pack build --dev --target web -- --features wasm
cd ../../web
ln -s ../rust/osm2lanes/pkg/ .
./serve_locally.py
```

Then open the link in your web browser and click a road.
10 changes: 7 additions & 3 deletions rust/osm2lanes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,29 @@ authors = [
]
license = "Apache 2.0"

[lib]
crate-type = ["cdylib", "lib"]
bench = false

[dependencies]
celes = "2.1"
console_error_panic_hook = { version = "0.1.7", optional = true }
log = "0.4"
reqwest = { version = "0.11", optional = true, features = ["blocking", "json"] }
serde = { version = "1", features = ["derive"] }
serde_yaml = "0.8"
wasm-bindgen = { version = "0.2.79", optional = true, features = ["serde-serialize"] }

[features]
overpass = ["reqwest", "reqwest/blocking", "reqwest/json"]
tests = []
wasm = ["console_error_panic_hook", "wasm-bindgen"]

[dev-dependencies]
assert-json-diff = "2.0"
criterion = { version = "0.3", features = ["html_reports"] }
serde_json = "1"

[lib]
bench = false

[[bench]]
name = "benchmark_slice_all_same"
harness = false
Expand Down
5 changes: 5 additions & 0 deletions rust/osm2lanes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ pub use transform::{lanes_to_tags, tags_to_lanes, LanesToTagsConfig, TagsToLanes

#[cfg(feature = "tests")]
pub mod test;

#[cfg(target_arch = "wasm32")]
mod wasm;
#[cfg(target_arch = "wasm32")]
pub use wasm::*;
39 changes: 39 additions & 0 deletions rust/osm2lanes/src/wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;

use crate::tag::{Tags, TagsWrite};
use crate::{tags_to_lanes, DrivingSide, Locale, TagsToLanesConfig};

#[derive(Serialize, Deserialize)]
pub struct Input {
key_values: HashMap<String, String>,
drive_on_right: bool,
}

#[wasm_bindgen]
pub fn js_tags_to_lanes(val: &JsValue) -> JsValue {
console_error_panic_hook::set_once();

let input: Input = val.into_serde().unwrap();

let mut config = TagsToLanesConfig::default();
config.error_on_warnings = false;
config.include_separators = true;

let locale = Locale::builder()
.driving_side(if input.drive_on_right {
DrivingSide::Right
} else {
DrivingSide::Left
})
.build();

let mut tags = Tags::default();
for (key, value) in input.key_values {
tags.checked_insert(key, value).unwrap();
}
let lanes = tags_to_lanes(&tags, &locale, &config).unwrap();
JsValue::from_serde(&lanes).unwrap()
}
17 changes: 16 additions & 1 deletion web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@
<textarea id="input" rows="10" cols="80" disabled>Input</textarea>
<textarea id="output" rows="10" cols="80" disabled>Output</textarea>

<script>
<script type="module">
import init, { js_tags_to_lanes } from "./pkg/osm2lanes.js";

await init();

mapboxgl.accessToken =
"pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw";
const map = new mapboxgl.Map({
Expand Down Expand Up @@ -113,6 +117,17 @@

// Add the first feature to the map
map.getSource("road").setData(geojson["features"][0]);

const input = {
key_values: geojson["features"][0]["properties"],
drive_on_right: true,
};
let lanes = js_tags_to_lanes(input);
document.getElementById("output").innerText = JSON.stringify(
lanes,
null,
2
);
}

map.on("click", (e) => {
Expand Down

0 comments on commit c3e4504

Please sign in to comment.