ion/
flags.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::fmt::{Display, Formatter};
8use std::{fmt, str};
9
10use arrayvec::ArrayVec;
11use bitflags::{Flags as _, bitflags};
12use mozjs::jsapi::{
13	JSITER_FORAWAITOF, JSITER_HIDDEN, JSITER_OWNONLY, JSITER_PRIVATE, JSITER_SYMBOLS, JSITER_SYMBOLSONLY,
14	JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_RESOLVING, RegExpFlag_DotAll, RegExpFlag_Global,
15	RegExpFlag_HasIndices, RegExpFlag_IgnoreCase, RegExpFlag_Multiline, RegExpFlag_Sticky, RegExpFlag_Unicode,
16	RegExpFlags as REFlags,
17};
18
19bitflags! {
20	/// Represents the flags of properties on an [Object](crate::Object)
21	#[derive(Clone, Copy, Debug)]
22	pub struct PropertyFlags: u16 {
23		/// Allows enumeration through `Object.keys()`, `for...in` and other functions.
24		/// See [Enumerability of Properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties#traversing_object_properties).
25		const ENUMERATE = JSPROP_ENUMERATE as u16;
26		/// Prevents reassignment of the property.
27		const READ_ONLY = JSPROP_READONLY as u16;
28		/// Prevents deletion and attribute modification of the property.
29		const PERMANENT = JSPROP_PERMANENT as u16;
30		const RESOLVING = JSPROP_RESOLVING as u16;
31
32		const CONSTANT = PropertyFlags::READ_ONLY.bits() | PropertyFlags::PERMANENT.bits();
33		const CONSTANT_ENUMERATED = PropertyFlags::CONSTANT.bits() | PropertyFlags::ENUMERATE.bits();
34	}
35}
36
37bitflags! {
38	/// Represents the flags when iterating over an [Object](crate::Object).
39	#[derive(Clone, Copy, Debug, Default)]
40	pub struct IteratorFlags: u32 {
41		/// Allows iterating over private properties.
42		const PRIVATE = JSITER_PRIVATE;
43		/// Disallows iterating over inherited properties.
44		const OWN_ONLY = JSITER_OWNONLY;
45		/// Allows iteration over non-enumerable properties.
46		const HIDDEN = JSITER_HIDDEN;
47		/// Allows iteration over symbol keys.
48		const SYMBOLS = JSITER_SYMBOLS;
49		/// Disallows iteration over string keys.
50		const SYMBOLS_ONLY = JSITER_SYMBOLSONLY;
51		/// Iteration over async iterable objects and async generators.
52		const FOR_AWAIT_OF = JSITER_FORAWAITOF;
53	}
54}
55
56bitflags! {
57	/// Represents the flags of a [RegExp](crate::RegExp) object.
58	/// See [Advanced searching with flags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#advanced_searching_with_flags)
59	#[derive(Clone, Copy, Debug, Eq, PartialEq)]
60	pub struct RegExpFlags: u8 {
61		/// Determines if indices are generated for matches. Represents `d` flag.
62		/// See [hasIndices](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/hasIndices).
63		const HAS_INDICES = RegExpFlag_HasIndices;
64		/// Determines if search is global. Represents `g` flag.
65		/// See [global](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/global).
66		const GLOBAL = RegExpFlag_Global;
67		/// Determines if search ignores case. Represents `i` flag.
68		/// See [ignoreCase](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/ignoreCase).
69		const IGNORE_CASE = RegExpFlag_IgnoreCase;
70		/// Determines if `^` and `$` match newline characters. Represents `m` flag.
71		/// See [multiline](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/multiline).
72		const MULTILINE = RegExpFlag_Multiline;
73		/// Determines if `.` matches newline characters. Represents `s` flag.
74		/// See [dotAll](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/dotAll).
75		const DOT_ALL = RegExpFlag_DotAll;
76		/// Determines if pattern uses unicode semantics. Represents `u` flag.
77		/// See [unicode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode).
78		const UNICODE = RegExpFlag_Unicode;
79		/// Determines if search is continued from current index. Represents `y` flag.
80		/// See [sticky](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky).
81		const STICKY = RegExpFlag_Sticky;
82	}
83}
84
85impl Display for RegExpFlags {
86	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
87		let mut flags = ArrayVec::<_, 8>::new();
88		for flag in RegExpFlags::FLAGS {
89			if self.contains(*flag.value()) {
90				match *flag.value() {
91					RegExpFlags::HAS_INDICES => flags.push(b'd'),
92					RegExpFlags::GLOBAL => flags.push(b'g'),
93					RegExpFlags::IGNORE_CASE => flags.push(b'i'),
94					RegExpFlags::MULTILINE => flags.push(b'm'),
95					RegExpFlags::DOT_ALL => flags.push(b's'),
96					RegExpFlags::UNICODE => flags.push(b'u'),
97					RegExpFlags::STICKY => flags.push(b'y'),
98					_ => (),
99				}
100			}
101		}
102		flags.sort_unstable();
103		f.write_str(unsafe { str::from_utf8_unchecked(&flags) })
104	}
105}
106
107impl From<RegExpFlags> for REFlags {
108	fn from(flags: RegExpFlags) -> Self {
109		REFlags { flags_: flags.bits() }
110	}
111}
112
113impl From<REFlags> for RegExpFlags {
114	fn from(flags: REFlags) -> RegExpFlags {
115		RegExpFlags::from_bits_retain(flags.flags_)
116	}
117}