1#![forbid(unsafe_code)]
2
3extern crate ternary_tree;
4extern crate js_sys;
5
6use wasm_bindgen::prelude::*;
7use ternary_tree::{TstIterator, TstCompleteIterator, TstNeighborIterator, TstCrosswordIterator};
8
9
10#[wasm_bindgen]
11pub struct Tst {
12
13 tree: ternary_tree::Tst<JsValue>
14}
15
16#[wasm_bindgen]
17#[derive(PartialEq)]
18pub enum Direction { Forward, Backward }
19
20
21#[wasm_bindgen]
22impl Tst {
23
24 pub fn new() -> Self {
25
26 Tst { tree: ternary_tree::Tst::new() }
27 }
28
29 pub fn insert(&mut self, key: &str, value: JsValue) -> JsValue {
30
31 match self.tree.insert(key, value) {
32
33 None => JsValue::null(), Some(value) => value
34 }
35 }
36
37 pub fn get(&self, key: &str) -> JsValue {
38
39 match self.tree.get(key) {
40
41 None => JsValue::null(), Some(value) => value.clone()
42 }
43 }
44
45 pub fn remove(&mut self, key: &str) -> JsValue {
46
47 match self.tree.remove(key) {
48
49 None => JsValue::null(), Some(value) => value.clone()
50 }
51 }
52
53 pub fn count(&self) -> usize {
54
55 self.tree.len()
56 }
57
58 pub fn clear(&mut self) {
59
60 self.tree.clear()
61 }
62
63 pub fn pretty_print(&self) -> String {
64
65 let mut w = Vec::new();
66
67 self.tree.pretty_print(&mut w);
68
69 match String::from_utf8(w) {
70
71 Ok(s) => s,
72 Err(_) => String::new()
73 }
74 }
75
76 pub fn visit(&self, callback: &js_sys::Function, direction: Direction) {
77
78 let mut it = self.tree.iter();
79 let this = JsValue::NULL;
80 let next_fn = if direction == Direction::Forward { TstIterator::<JsValue>::next } else { TstIterator::<JsValue>::next_back };
81 let key_fn = if direction == Direction::Forward { TstIterator::<JsValue>::current_key } else { TstIterator::<JsValue>::current_key_back };
82
83 while let Some(value) = (next_fn)(&mut it) {
84
85 let key = JsValue::from((key_fn)(&mut it));
86 let should_break = match callback.call2(&this, &key, value) {
87
88 Ok(res) => res.is_truthy(),
89 Err(_) => true
90 };
91
92 if should_break {
93
94 break;
95 }
96 }
97 }
98
99 pub fn complete(&self, prefix: &str, callback: &js_sys::Function, direction: Direction) {
100
101 let mut it = self.tree.iter_complete(prefix);
102 let this = JsValue::NULL;
103 let next_fn = if direction == Direction::Forward { TstCompleteIterator::<JsValue>::next } else { TstCompleteIterator::<JsValue>::next_back };
104 let key_fn = if direction == Direction::Forward { TstCompleteIterator::<JsValue>::current_key } else { TstCompleteIterator::<JsValue>::current_key_back };
105
106 while let Some(value) = (next_fn)(&mut it) {
107
108 let key = JsValue::from((key_fn)(&mut it));
109 let res = callback.call2(&this, &key, value);
110
111 let should_break = match res {
112
113 Ok(val) => val.is_truthy(),
114 Err(_) => true
115 };
116
117 if should_break {
118
119 break;
120 }
121 }
122 }
123
124 pub fn neighbor(&self, neighbor_key: &str, range: usize, callback: &js_sys::Function, direction: Direction) {
125
126 let mut it = self.tree.iter_neighbor(neighbor_key, range);
127 let this = JsValue::NULL;
128 let next_fn = if direction == Direction::Forward { TstNeighborIterator::<JsValue>::next } else { TstNeighborIterator::<JsValue>::next_back };
129 let key_fn = if direction == Direction::Forward { TstNeighborIterator::<JsValue>::current_key } else { TstNeighborIterator::<JsValue>::current_key_back };
130
131 while let Some(value) = (next_fn)(&mut it) {
132
133 let key = JsValue::from((key_fn)(&mut it));
134 let res = callback.call2(&this, &key, value);
135
136 let should_break = match res {
137
138 Ok(val) => val.is_truthy(),
139 Err(_) => true
140 };
141
142 if should_break {
143
144 break;
145 }
146 }
147 }
148
149 pub fn crossword(&self, pattern: &str, joker: char, callback: &js_sys::Function, direction: Direction) {
150
151 let mut it = self.tree.iter_crossword(pattern, joker);
152 let this = JsValue::NULL;
153 let next_fn = if direction == Direction::Forward { TstCrosswordIterator::<JsValue>::next } else { TstCrosswordIterator::<JsValue>::next_back };
154 let key_fn = if direction == Direction::Forward { TstCrosswordIterator::<JsValue>::current_key } else { TstCrosswordIterator::<JsValue>::current_key_back };
155
156 while let Some(value) = (next_fn)(&mut it) {
157
158 let key = JsValue::from((key_fn)(&mut it));
159 let res = callback.call2(&this, &key, value);
160
161 let should_break = match res {
162
163 Ok(val) => val.is_truthy(),
164 Err(_) => true
165 };
166
167 if should_break {
168
169 break;
170 }
171 }
172 }
173}