quickjs_runtime/quickjs_utils/sets.rs
1//! Set utils, these methods can be used to manage Set objects from rust
2//! see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Sap) for more on Sets
3
4use crate::jsutils::JsError;
5use crate::quickjs_utils::class_ids::JS_CLASS_SET;
6use crate::quickjs_utils::objects::construct_object;
7use crate::quickjs_utils::{functions, get_constructor, iterators, objects, primitives};
8use crate::quickjsrealmadapter::QuickJsRealmAdapter;
9use crate::quickjsvalueadapter::QuickJsValueAdapter;
10use libquickjs_sys as q;
11use libquickjs_sys::JS_GetClassID;
12
13/// create new instance of Set
14/// # Example
15/// ```rust
16/// use quickjs_runtime::builder::QuickJsRuntimeBuilder;
17/// use quickjs_runtime::quickjsvalueadapter::QuickJsValueAdapter;
18/// use quickjs_runtime::quickjs_utils::sets::new_set_q;
19///
20/// let rt = QuickJsRuntimeBuilder::new().build();
21/// rt.exe_rt_task_in_event_loop(|q_js_rt| {
22/// let q_ctx = q_js_rt.get_main_realm();
23/// let my_set: QuickJsValueAdapter = new_set_q(q_ctx).ok().unwrap();
24/// });
25/// ```
26pub fn new_set_q(q_ctx: &QuickJsRealmAdapter) -> Result<QuickJsValueAdapter, JsError> {
27 unsafe { new_set(q_ctx.context) }
28}
29
30/// create new instance of Set
31/// # Safety
32/// please ensure the passed JSContext is still valid
33pub unsafe fn new_set(ctx: *mut q::JSContext) -> Result<QuickJsValueAdapter, JsError> {
34 let map_constructor = get_constructor(ctx, "Set")?;
35 construct_object(ctx, &map_constructor, &[])
36}
37
38/// see if a JSValueRef is an instance of Set
39pub fn is_set_q(obj: &QuickJsValueAdapter) -> bool {
40 unsafe { is_set(obj) }
41}
42
43/// see if a JSValueRef is an instance of Set
44/// # Safety
45/// please ensure the passed JSContext is still valid
46pub unsafe fn is_set(obj: &QuickJsValueAdapter) -> bool {
47 JS_GetClassID(*obj.borrow_value()) == JS_CLASS_SET
48}
49
50/// add a value to the Set
51/// # Example
52/// ```rust
53/// use quickjs_runtime::builder::QuickJsRuntimeBuilder;
54/// use quickjs_runtime::quickjsvalueadapter::QuickJsValueAdapter;
55/// use quickjs_runtime::quickjs_utils::primitives;
56/// use quickjs_runtime::quickjs_utils::sets::{new_set_q, add_q};
57///
58/// let rt = QuickJsRuntimeBuilder::new().build();
59/// rt.exe_rt_task_in_event_loop(|q_js_rt| {
60/// let q_ctx = q_js_rt.get_main_realm();
61/// let my_set: QuickJsValueAdapter = new_set_q(q_ctx).ok().unwrap();
62/// let value = primitives::from_i32(23);
63/// add_q(q_ctx, &my_set, value).ok().unwrap();
64/// });
65/// ```
66pub fn add_q(
67 q_ctx: &QuickJsRealmAdapter,
68 set: &QuickJsValueAdapter,
69 val: QuickJsValueAdapter,
70) -> Result<QuickJsValueAdapter, JsError> {
71 unsafe { add(q_ctx.context, set, val) }
72}
73
74/// add a value to a Set
75/// # Safety
76/// please ensure the passed JSContext is still valid
77pub unsafe fn add(
78 ctx: *mut q::JSContext,
79 set: &QuickJsValueAdapter,
80 val: QuickJsValueAdapter,
81) -> Result<QuickJsValueAdapter, JsError> {
82 functions::invoke_member_function(ctx, set, "add", &[val])
83}
84
85/// delete a value from a set
86/// # Example
87/// ```rust
88/// use quickjs_runtime::builder::QuickJsRuntimeBuilder;
89/// use quickjs_runtime::quickjsvalueadapter::QuickJsValueAdapter;
90/// use quickjs_runtime::quickjs_utils::primitives;
91/// use quickjs_runtime::quickjs_utils::sets::{add_q, new_set_q, delete_q};
92///
93/// let rt = QuickJsRuntimeBuilder::new().build();
94/// rt.exe_rt_task_in_event_loop(|q_js_rt| {
95/// let q_ctx = q_js_rt.get_main_realm();
96/// let my_set: QuickJsValueAdapter = new_set_q(q_ctx).ok().unwrap();
97/// let value = primitives::from_i32(23);
98/// add_q(q_ctx, &my_set, value.clone()).ok().unwrap();
99/// delete_q(q_ctx, &my_set, value).ok().unwrap();
100/// });
101/// ```
102pub fn delete_q(
103 q_ctx: &QuickJsRealmAdapter,
104 set: &QuickJsValueAdapter,
105 value: QuickJsValueAdapter,
106) -> Result<bool, JsError> {
107 unsafe { delete(q_ctx.context, set, value) }
108}
109
110/// delete a value from a set
111/// # Safety
112/// please ensure the passed JSContext is still valid
113pub unsafe fn delete(
114 ctx: *mut q::JSContext,
115 set: &QuickJsValueAdapter,
116 value: QuickJsValueAdapter,
117) -> Result<bool, JsError> {
118 let res = functions::invoke_member_function(ctx, set, "delete", &[value])?;
119 primitives::to_bool(&res)
120}
121
122/// check whether a Set has a certain value
123/// # Example
124/// ```rust
125/// use quickjs_runtime::builder::QuickJsRuntimeBuilder;
126/// use quickjs_runtime::quickjsvalueadapter::QuickJsValueAdapter;
127/// use quickjs_runtime::quickjs_utils::primitives;
128/// use quickjs_runtime::quickjs_utils::sets::{new_set_q, add_q, has_q};
129///
130/// let rt = QuickJsRuntimeBuilder::new().build();
131/// rt.exe_rt_task_in_event_loop(|q_js_rt| {
132/// let q_ctx = q_js_rt.get_main_realm();
133/// let my_set: QuickJsValueAdapter = new_set_q(q_ctx).ok().unwrap();
134/// let value = primitives::from_i32(23);
135/// add_q(q_ctx, &my_set, value.clone()).ok().unwrap();
136/// let bln_has = has_q(q_ctx, &my_set, value).ok().unwrap();
137/// assert!(bln_has);
138/// });
139/// ```
140pub fn has_q(
141 q_ctx: &QuickJsRealmAdapter,
142 set: &QuickJsValueAdapter,
143 key: QuickJsValueAdapter,
144) -> Result<bool, JsError> {
145 unsafe { has(q_ctx.context, set, key) }
146}
147
148/// check whether a Set has a value
149/// # Safety
150/// please ensure the passed JSContext is still valid
151pub unsafe fn has(
152 ctx: *mut q::JSContext,
153 set: &QuickJsValueAdapter,
154 key: QuickJsValueAdapter,
155) -> Result<bool, JsError> {
156 let res = functions::invoke_member_function(ctx, set, "has", &[key])?;
157 primitives::to_bool(&res)
158}
159
160/// get the number of entries in a Set
161/// # Example
162/// ```rust
163/// use quickjs_runtime::builder::QuickJsRuntimeBuilder;
164/// use quickjs_runtime::quickjsvalueadapter::QuickJsValueAdapter;
165/// use quickjs_runtime::quickjs_utils::primitives;
166/// use quickjs_runtime::quickjs_utils::sets::{add_q, new_set_q, size_q};
167///
168/// let rt = QuickJsRuntimeBuilder::new().build();
169/// rt.exe_rt_task_in_event_loop(|q_js_rt| {
170/// let q_ctx = q_js_rt.get_main_realm();
171/// let my_set: QuickJsValueAdapter = new_set_q(q_ctx).ok().unwrap();
172/// let value = primitives::from_i32(23);
173/// add_q(q_ctx, &my_set, value).ok().unwrap();
174/// let i_size = size_q(q_ctx, &my_set).ok().unwrap();
175/// assert_eq!(i_size, 1);
176/// });
177/// ```
178pub fn size_q(q_ctx: &QuickJsRealmAdapter, set: &QuickJsValueAdapter) -> Result<i32, JsError> {
179 unsafe { size(q_ctx.context, set) }
180}
181
182/// get the number of entries in a Set
183/// # Safety
184/// please ensure the passed JSContext is still valid
185pub unsafe fn size(ctx: *mut q::JSContext, set: &QuickJsValueAdapter) -> Result<i32, JsError> {
186 let res = objects::get_property(ctx, set, "size")?;
187 primitives::to_i32(&res)
188}
189
190/// remove all entries from a Set
191/// # Example
192/// ```rust
193/// use quickjs_runtime::builder::QuickJsRuntimeBuilder;
194/// use quickjs_runtime::quickjsvalueadapter::QuickJsValueAdapter;
195/// use quickjs_runtime::quickjs_utils::primitives;
196/// use quickjs_runtime::quickjs_utils::sets::{size_q, clear_q, add_q, new_set_q};
197///
198/// let rt = QuickJsRuntimeBuilder::new().build();
199/// rt.exe_rt_task_in_event_loop(|q_js_rt| {
200/// let q_ctx = q_js_rt.get_main_realm();
201/// let my_set: QuickJsValueAdapter = new_set_q(q_ctx).ok().unwrap();
202/// let value = primitives::from_i32(23);
203/// add_q(q_ctx, &my_set, value).ok().unwrap();
204/// clear_q(q_ctx, &my_set).ok().unwrap();
205/// let i_size = size_q(q_ctx, &my_set).ok().unwrap();
206/// assert_eq!(i_size, 0);
207/// });
208/// ```
209pub fn clear_q(q_ctx: &QuickJsRealmAdapter, map: &QuickJsValueAdapter) -> Result<(), JsError> {
210 unsafe { clear(q_ctx.context, map) }
211}
212
213/// remove all entries from a Set
214/// # Safety
215/// please ensure the passed JSContext is still valid
216pub unsafe fn clear(ctx: *mut q::JSContext, set: &QuickJsValueAdapter) -> Result<(), JsError> {
217 let _ = functions::invoke_member_function(ctx, set, "clear", &[])?;
218 Ok(())
219}
220
221/// iterate over all values of a Set
222/// # Example
223/// ```rust
224/// use quickjs_runtime::builder::QuickJsRuntimeBuilder;
225/// use quickjs_runtime::quickjsvalueadapter::QuickJsValueAdapter;
226/// use quickjs_runtime::quickjs_utils::primitives;
227/// use quickjs_runtime::quickjs_utils::sets::{new_set_q, add_q, values_q};
228///
229/// let rt = QuickJsRuntimeBuilder::new().build();
230/// rt.exe_rt_task_in_event_loop(|q_js_rt| {
231/// let q_ctx = q_js_rt.get_main_realm();
232/// let my_set: QuickJsValueAdapter = new_set_q(q_ctx).ok().unwrap();
233/// let value = primitives::from_i32(23);
234/// add_q(q_ctx, &my_set, value).ok().unwrap();
235/// let mapped_values = values_q(q_ctx, &my_set, |value| {Ok(123)}).ok().unwrap();
236/// assert_eq!(mapped_values.len(), 1);
237/// });
238/// ```
239pub fn values_q<C: Fn(QuickJsValueAdapter) -> Result<R, JsError>, R>(
240 q_ctx: &QuickJsRealmAdapter,
241 set: &QuickJsValueAdapter,
242 consumer_producer: C,
243) -> Result<Vec<R>, JsError> {
244 unsafe { values(q_ctx.context, set, consumer_producer) }
245}
246
247/// iterate over all values of a Set
248/// # Safety
249/// please ensure the passed JSContext is still valid
250pub unsafe fn values<C: Fn(QuickJsValueAdapter) -> Result<R, JsError>, R>(
251 ctx: *mut q::JSContext,
252 set: &QuickJsValueAdapter,
253 consumer_producer: C,
254) -> Result<Vec<R>, JsError> {
255 let iter_ref = functions::invoke_member_function(ctx, set, "values", &[])?;
256
257 iterators::iterate(ctx, &iter_ref, consumer_producer)
258}