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}