ion/object/
map.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use std::ops::{Deref, DerefMut};
8
9use mozjs::jsapi::{
10	IsMapObject, JSObject, MapClear, MapDelete, MapEntries, MapForEach, MapGet, MapHas, MapKeys, MapSet, MapSize,
11	MapValues, NewMapObject,
12};
13
14use crate::conversions::ToValue as _;
15use crate::{Context, Function, Local, Object, Value};
16
17pub struct Map<'m> {
18	map: Local<'m, *mut JSObject>,
19}
20
21impl<'m> Map<'m> {
22	/// Creates a new empty [Map].
23	pub fn new(cx: &'m Context) -> Map<'m> {
24		Map {
25			map: cx.root(unsafe { NewMapObject(cx.as_ptr()) }),
26		}
27	}
28
29	/// Creates a [Map] from an [Object].
30	///
31	/// Returns [None] if the object is not a map.
32	pub fn from(cx: &Context, object: Local<'m, *mut JSObject>) -> Option<Map<'m>> {
33		Map::is_map(cx, &object).then_some(Map { map: object })
34	}
35
36	/// Creates a [Map] from an [Object].
37	///
38	/// ### Safety
39	/// Object must be a map.
40	pub unsafe fn from_unchecked(object: Local<'m, *mut JSObject>) -> Map<'m> {
41		Map { map: object }
42	}
43
44	/// Returns the size of the [Map].
45	pub fn size(&self, cx: &Context) -> u32 {
46		unsafe { MapSize(cx.as_ptr(), self.handle().into()) }
47	}
48
49	/// Checks if the [Map] contains the given key.
50	pub fn has(&self, cx: &Context, key: &Value) -> bool {
51		let mut has = false;
52		unsafe { MapHas(cx.as_ptr(), self.handle().into(), key.handle().into(), &raw mut has) && has }
53	}
54
55	/// Returns the value of the [Map] at the given key.
56	pub fn get<'cx>(&self, cx: &'cx Context, key: &Value) -> Option<Value<'cx>> {
57		self.has(cx, key).then(|| {
58			let mut rval = Value::undefined(cx);
59			unsafe {
60				MapGet(
61					cx.as_ptr(),
62					self.handle().into(),
63					key.handle().into(),
64					rval.handle_mut().into(),
65				);
66			}
67			rval
68		})
69	}
70
71	/// Sets the value of the [Map] at the given key.
72	pub fn set(&self, cx: &Context, key: &Value, value: &Value) -> bool {
73		unsafe {
74			MapSet(
75				cx.as_ptr(),
76				self.handle().into(),
77				key.handle().into(),
78				value.handle().into(),
79			)
80		}
81	}
82
83	/// Deletes the value of the [Map] at the given key.
84	pub fn delete(&self, cx: &Context, key: &Value) -> bool {
85		let mut rval = false;
86		unsafe { MapDelete(cx.as_ptr(), self.handle().into(), key.handle().into(), &raw mut rval) && rval }
87	}
88
89	/// Clears the contents of the [Map].
90	pub fn clear(&self, cx: &Context) -> bool {
91		unsafe { MapClear(cx.as_ptr(), self.handle().into()) }
92	}
93
94	/// Returns an Iterator over the keys of the [Map].
95	pub fn keys<'cx>(&self, cx: &'cx Context) -> Object<'cx> {
96		let mut keys = Value::undefined(cx);
97		unsafe {
98			MapKeys(cx.as_ptr(), self.handle().into(), keys.handle_mut().into());
99		}
100		keys.to_object(cx)
101	}
102
103	/// Returns an Iterator over the values of the [Map].
104	pub fn values<'cx>(&self, cx: &'cx Context) -> Object<'cx> {
105		let mut values = Value::undefined(cx);
106		unsafe {
107			MapValues(cx.as_ptr(), self.handle().into(), values.handle_mut().into());
108		}
109		values.to_object(cx)
110	}
111
112	/// Returns an Iterator over the entries of the [Map].
113	pub fn entries<'cx>(&self, cx: &'cx Context) -> Object<'cx> {
114		let mut entries = Value::undefined(cx);
115		unsafe {
116			MapEntries(cx.as_ptr(), self.handle().into(), entries.handle_mut().into());
117		}
118		entries.to_object(cx)
119	}
120
121	/// Runs the given callback for each entry in the [Map].
122	pub fn for_each(&self, cx: &Context, callback: &Function, this: &Object) -> bool {
123		unsafe {
124			MapForEach(
125				cx.as_ptr(),
126				self.handle().into(),
127				callback.as_value(cx).handle().into(),
128				this.as_value(cx).handle().into(),
129			)
130		}
131	}
132
133	/// Checks if the object is a map.
134	pub fn is_map(cx: &Context, object: &Local<*mut JSObject>) -> bool {
135		let mut map = false;
136		unsafe { IsMapObject(cx.as_ptr(), object.handle().into(), &raw mut map) && map }
137	}
138}
139
140impl<'m> Deref for Map<'m> {
141	type Target = Local<'m, *mut JSObject>;
142
143	fn deref(&self) -> &Self::Target {
144		&self.map
145	}
146}
147
148impl DerefMut for Map<'_> {
149	fn deref_mut(&mut self) -> &mut Self::Target {
150		&mut self.map
151	}
152}