1use wasm_bindgen::prelude::*;
2use serde::{Deserialize, Serialize};
3use serde_wasm_bindgen::{from_value, to_value};
4
5#[derive(Serialize, Deserialize)]
8pub struct U128Wrapper {
9 value: u128,
10}
11
12#[wasm_bindgen]
21pub fn most_significant_bit(input: &JsValue) -> Result<JsValue, JsValue> {
22 let wrapper: U128Wrapper = from_value(input.clone()).map_err(|e| JsValue::from_str(&format!("Invalid input: {}", e)))?;
23 let value = wrapper.value;
24
25 if value == 0 {
26 return Err(JsValue::from_str("Input must be greater than 0"));
27 }
28
29 let mut x = value;
30 let mut r: u8 = 0;
31
32 if x >= 0x10000000000000000 {
33 x >>= 64;
34 r += 64;
35 }
36 if x >= 0x100000000 {
37 x >>= 32;
38 r += 32;
39 }
40 if x >= 0x10000 {
41 x >>= 16;
42 r += 16;
43 }
44 if x >= 0x100 {
45 x >>= 8;
46 r += 8;
47 }
48 if x >= 0x10 {
49 x >>= 4;
50 r += 4;
51 }
52 if x >= 0x4 {
53 x >>= 2;
54 r += 2;
55 }
56 if x >= 0x2 {
57 r += 1;
58 }
59
60 to_value(&r).map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
61}
62
63#[wasm_bindgen]
72pub fn least_significant_bit(input: &JsValue) -> Result<JsValue, JsValue> {
73 let wrapper: U128Wrapper = from_value(input.clone()).map_err(|e| JsValue::from_str(&format!("Invalid input: {}", e)))?;
74 let value = wrapper.value;
75
76 if value == 0 {
77 return Err(JsValue::from_str("Input must be greater than 0"));
78 }
79
80 let mut x = value;
81 let mut r: u8 = 127;
82
83 if x & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF > 0 {
84 r -= 64;
85 } else {
86 x >>= 64;
87 }
88 if x & 0xFFFFFFFF > 0 {
89 r -= 32;
90 } else {
91 x >>= 32;
92 }
93 if x & 0xFFFF > 0 {
94 r -= 16;
95 } else {
96 x >>= 16;
97 }
98 if x & 0xFF > 0 {
99 r -= 8;
100 } else {
101 x >>= 8;
102 }
103 if x & 0xF > 0 {
104 r -= 4;
105 } else {
106 x >>= 4;
107 }
108 if x & 0x3 > 0 {
109 r -= 2;
110 } else {
111 x >>= 2;
112 }
113 if x & 0x1 > 0 {
114 r -= 1;
115 }
116
117 to_value(&r).map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use serde_wasm_bindgen::to_value;
124
125 #[test]
126 fn test_most_significant_bit() {
127 let input = U128Wrapper { value: 128 };
128 let input_js = to_value(&input).unwrap();
129 assert_eq!(most_significant_bit(&input_js).unwrap(), JsValue::from(7));
130 }
131
132 #[test]
133 fn test_least_significant_bit() {
134 let input = U128Wrapper { value: 16 };
135 let input_js = to_value(&input).unwrap();
136 assert_eq!(least_significant_bit(&input_js).unwrap(), JsValue::from(4));
137 }
138
139 #[test]
140 fn test_invalid_input() {
141 let input = U128Wrapper { value: 0 };
142 let input_js = to_value(&input).unwrap();
143 assert!(most_significant_bit(&input_js).is_err());
144 assert!(least_significant_bit(&input_js).is_err());
145 }
146}