perspective_viewer/utils/number_format.rs
1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors. ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use std::sync::LazyLock;
14
15use js_sys::Intl;
16use perspective_js::json;
17use perspective_js::utils::global::navigator;
18use wasm_bindgen::JsValue;
19
20struct UnsafeNumberFormat(Intl::NumberFormat);
21
22// JavaScript does not allow threading, but we do not have a non-threadsafe
23// way to conveniently make lazy static caches of JavaScript ref values.
24unsafe impl Send for UnsafeNumberFormat {}
25unsafe impl Sync for UnsafeNumberFormat {}
26
27static NUMBER_FORMAT: LazyLock<UnsafeNumberFormat> = LazyLock::new(|| {
28 let locale = navigator().languages();
29 let opts = json!({});
30 let number_format = Intl::NumberFormat::new(&locale, &opts);
31 UnsafeNumberFormat(number_format)
32});
33
34impl UnsafeNumberFormat {}
35
36/// Trait for the [`u32::to_formatted_string`] method.
37#[extend::ext]
38pub impl u32 {
39 /// Format integers consistenly using the Browser's native `NumberFormat`.
40 fn to_formatted_string(&self) -> String {
41 NUMBER_FORMAT
42 .0
43 .format()
44 .call1(&NUMBER_FORMAT.0, &JsValue::from_f64(*self as f64))
45 .unwrap()
46 .as_string()
47 .unwrap()
48 }
49}