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