Skip to main content

ens_normalize/
lib.rs

1mod nf;
2mod spec;
3mod utils;
4
5pub use nf::{nfc, nfd};
6pub use spec::{
7    Label, Token, TokenizeOptions, ens_beautify, ens_emoji, ens_normalize, ens_normalize_fragment,
8    ens_split, ens_tokenize, ens_tokenize_with_options, is_combining_mark, should_escape,
9};
10pub use utils::{EnsError, Result, explode_cp, quote_cp, safe_str_from_cps, str_from_cps};
11
12pub fn normalize(name: &str) -> Result<String> {
13    ens_normalize(name)
14}
15
16#[cfg(feature = "wasm")]
17mod wasm {
18    use crate::{EnsError, Token};
19    use serde_json::{Value, json};
20    use wasm_bindgen::prelude::*;
21
22    fn js_error(err: EnsError) -> JsValue {
23        JsValue::from_str(err.message())
24    }
25
26    fn to_js<T: serde::Serialize>(value: &T) -> std::result::Result<JsValue, JsValue> {
27        let serializer = serde_wasm_bindgen::Serializer::new().serialize_maps_as_objects(true);
28        value
29            .serialize(&serializer)
30            .map_err(|err| JsValue::from_str(&err.to_string()))
31    }
32
33    fn token_to_value(token: &Token) -> Value {
34        match token {
35            Token::Stop { cp } => json!({ "type": "stop", "cp": cp }),
36            Token::Disallowed { cp } => json!({ "type": "disallowed", "cp": cp }),
37            Token::Ignored { cp } => json!({ "type": "ignored", "cp": cp }),
38            Token::Valid { cps } => json!({ "type": "valid", "cps": cps }),
39            Token::Mapped { cp, cps } => json!({ "type": "mapped", "cp": cp, "cps": cps }),
40            Token::Emoji { input, cps, emoji } => {
41                json!({ "type": "emoji", "input": input, "cps": cps, "emoji": emoji })
42            }
43            Token::Nfc {
44                input,
45                tokens0,
46                cps,
47                tokens,
48            } => json!({
49                "type": "nfc",
50                "input": input,
51                "tokens0": tokens0.iter().map(token_to_value).collect::<Vec<_>>(),
52                "cps": cps,
53                "tokens": tokens.iter().map(token_to_value).collect::<Vec<_>>()
54            }),
55        }
56    }
57
58    #[wasm_bindgen(js_name = ens_normalize)]
59    pub fn ens_normalize_js(name: &str) -> std::result::Result<String, JsValue> {
60        crate::ens_normalize(name).map_err(js_error)
61    }
62
63    #[wasm_bindgen(js_name = ens_beautify)]
64    pub fn ens_beautify_js(name: &str) -> std::result::Result<String, JsValue> {
65        crate::ens_beautify(name).map_err(js_error)
66    }
67
68    #[wasm_bindgen(js_name = ens_normalize_fragment)]
69    pub fn ens_normalize_fragment_js(
70        fragment: &str,
71        decompose: bool,
72    ) -> std::result::Result<String, JsValue> {
73        crate::ens_normalize_fragment(fragment, decompose).map_err(js_error)
74    }
75
76    #[wasm_bindgen(js_name = ens_tokenize)]
77    pub fn ens_tokenize_js(name: &str) -> std::result::Result<JsValue, JsValue> {
78        let tokens = crate::ens_tokenize(name)
79            .iter()
80            .map(token_to_value)
81            .collect::<Vec<_>>();
82        to_js(&tokens)
83    }
84
85    #[wasm_bindgen(js_name = ens_emoji)]
86    pub fn ens_emoji_js() -> std::result::Result<JsValue, JsValue> {
87        to_js(&crate::ens_emoji())
88    }
89
90    #[wasm_bindgen(js_name = nfc)]
91    pub fn nfc_js(cps: JsValue) -> std::result::Result<JsValue, JsValue> {
92        let cps: Vec<u32> = serde_wasm_bindgen::from_value(cps)
93            .map_err(|err| JsValue::from_str(&err.to_string()))?;
94        to_js(&crate::nfc(&cps))
95    }
96
97    #[wasm_bindgen(js_name = nfd)]
98    pub fn nfd_js(cps: JsValue) -> std::result::Result<JsValue, JsValue> {
99        let cps: Vec<u32> = serde_wasm_bindgen::from_value(cps)
100            .map_err(|err| JsValue::from_str(&err.to_string()))?;
101        to_js(&crate::nfd(&cps))
102    }
103}