wasm_quicksort_example/
lib.rs1mod utils;
2
3use serde::{Deserialize, Serialize};
4use serde_json::{from_str, to_string};
5use tsify::Tsify;
6use wasm_bindgen::prelude::*;
7
8#[derive(Clone, Deserialize, Serialize, Tsify)]
14#[tsify(into_wasm_abi, from_wasm_abi)]
15#[serde(untagged)]
16pub enum Sortable {
17 Strings(Vec<String>),
18 Numbers(Vec<f64>),
19}
20
21fn quicksort_interface(s: Sortable) -> Sortable {
23 match s {
24 Sortable::Strings(mut v) => {
25 qsort(&mut v);
26 Sortable::Strings(v)
27 }
28 Sortable::Numbers(mut v) => {
29 qsort(&mut v);
30 Sortable::Numbers(v)
31 }
32 }
33}
34
35#[wasm_bindgen]
40pub fn quicksort(vec: String) -> Result<JsValue, JsError> {
41 let vec: Sortable = from_str(&vec).map_err(|e| JsError::new(&format!("{}", e)))?;
42 let res = to_string(&quicksort_interface(vec)).map_err(|e| JsError::new(&format!("{}", e)))?;
43 Ok(res.into())
44}
45
46fn qsort<T: PartialEq + PartialOrd>(arr: &mut [T]) {
51 let len = arr.len();
52 _quicksort(arr, 0, (len - 1) as isize);
53}
54
55fn _quicksort<T: PartialEq + PartialOrd>(arr: &mut [T], low: isize, high: isize) {
56 if low < high {
57 let p = partition(arr, low, high);
58 _quicksort(arr, low, p - 1);
59 _quicksort(arr, p + 1, high);
60 }
61}
62
63fn partition<T: PartialEq + PartialOrd>(arr: &mut [T], low: isize, high: isize) -> isize {
64 let pivot = high as usize;
65 let mut store_index = low - 1;
66 let mut last_index = high;
67
68 loop {
69 store_index += 1;
70 while arr[store_index as usize] < arr[pivot] {
71 store_index += 1;
72 }
73 last_index -= 1;
74 while last_index >= 0 && arr[last_index as usize] > arr[pivot] {
75 last_index -= 1;
76 }
77 if store_index >= last_index {
78 break;
79 } else {
80 arr.swap(store_index as usize, last_index as usize);
81 }
82 }
83 arr.swap(store_index as usize, pivot);
84 store_index
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_qsort() {
93 let expected = vec![
94 "A".to_string(),
95 "B".to_string(),
96 "C".to_string(),
97 "D".to_string(),
98 ];
99
100 let mut unsort1 = vec![
101 "B".to_string(),
102 "A".to_string(),
103 "C".to_string(),
104 "D".to_string(),
105 ];
106
107 let mut unsort2 = vec![
108 "D".to_string(),
109 "C".to_string(),
110 "B".to_string(),
111 "A".to_string(),
112 ];
113
114 let mut unsort3 = vec![
115 "C".to_string(),
116 "B".to_string(),
117 "D".to_string(),
118 "A".to_string(),
119 ];
120
121 assert_eq!(&expected, &expected);
123 assert_ne!(&expected, &unsort1);
124 assert_ne!(&expected, &unsort2);
125 assert_ne!(&expected, &unsort3);
126
127 qsort(&mut unsort1);
128 qsort(&mut unsort2);
129 qsort(&mut unsort3);
130
131 assert_eq!(&expected, &unsort1);
132 assert_eq!(&expected, &unsort2);
133 assert_eq!(&expected, &unsort3);
134
135 let expected = [1, 2, 3];
136 let mut unsort1 = [3, 2, 1];
137 let mut unsort2 = [2, 3, 1];
138
139 assert_eq!(&expected, &expected);
141 assert_ne!(&expected, &unsort1);
142 assert_ne!(&expected, &unsort2);
143
144 qsort(&mut unsort1);
145 qsort(&mut unsort2);
146
147 assert_eq!(&expected, &unsort1);
148 assert_eq!(&expected, &unsort2);
149 }
150}