1#![allow(clippy::transmute_ptr_to_ptr)]
2#![allow(clippy::transmute_ptr_to_ref)]
3
4use super::{MetaCharType, RegexOptions, SyntaxBehavior, SyntaxOperator};
5use std::mem::transmute;
6
7#[derive(Copy, Clone)]
13pub enum MetaChar {
14 Character(char),
16 Ineffective,
18}
19
20#[derive(Debug, Clone, Copy)]
30#[repr(transparent)]
31pub struct Syntax {
32 raw: onig_sys::OnigSyntaxType,
33}
34
35impl Syntax {
36 pub fn python() -> &'static Syntax {
38 unsafe { transmute(&onig_sys::OnigSyntaxPython) }
39 }
40 pub fn asis() -> &'static Syntax {
42 unsafe { transmute(&onig_sys::OnigSyntaxASIS) }
43 }
44
45 pub fn posix_basic() -> &'static Syntax {
47 unsafe { transmute(&onig_sys::OnigSyntaxPosixBasic) }
48 }
49
50 pub fn posix_extended() -> &'static Syntax {
52 unsafe { transmute(&onig_sys::OnigSyntaxPosixExtended) }
53 }
54
55 pub fn emacs() -> &'static Syntax {
57 unsafe { transmute(&onig_sys::OnigSyntaxEmacs) }
58 }
59
60 pub fn grep() -> &'static Syntax {
62 unsafe { transmute(&onig_sys::OnigSyntaxGrep) }
63 }
64
65 pub fn gnu_regex() -> &'static Syntax {
67 unsafe { transmute(&onig_sys::OnigSyntaxGnuRegex) }
68 }
69
70 pub fn java() -> &'static Syntax {
72 unsafe { transmute(&onig_sys::OnigSyntaxJava) }
73 }
74
75 pub fn perl() -> &'static Syntax {
77 unsafe { transmute(&onig_sys::OnigSyntaxPerl) }
78 }
79
80 pub fn perl_ng() -> &'static Syntax {
82 unsafe { transmute(&onig_sys::OnigSyntaxPerl_NG) }
83 }
84
85 pub fn ruby() -> &'static Syntax {
87 unsafe { transmute(&onig_sys::OnigSyntaxRuby) }
88 }
89
90 pub fn oniguruma() -> &'static Syntax {
92 unsafe { transmute(&onig_sys::OnigSyntaxOniguruma) }
93 }
94
95 pub fn default() -> &'static Syntax {
97 unsafe { transmute(onig_sys::OnigDefaultSyntax) }
98 }
99
100 pub fn operators(&self) -> SyntaxOperator {
102 SyntaxOperator::from_bits_truncate(self.operators_bits())
103 }
104
105 fn operators_bits(&self) -> u64 {
107 unsafe {
108 let op = onig_sys::onig_get_syntax_op(self.raw_mut());
109 let op2 = onig_sys::onig_get_syntax_op2(self.raw_mut());
110 u64::from(op) + (u64::from(op2) << 32)
111 }
112 }
113
114 pub fn set_operators(&mut self, operators: SyntaxOperator) {
116 self.set_operators_bits(operators.bits())
117 }
118
119 fn set_operators_bits(&mut self, operators_bits: u64) {
121 let op = operators_bits as onig_sys::OnigSyntaxOp;
122 let op2 = (operators_bits >> 32) as onig_sys::OnigSyntaxOp2;
123 unsafe {
124 onig_sys::onig_set_syntax_op(&mut self.raw, op);
125 onig_sys::onig_set_syntax_op2(&mut self.raw, op2)
126 }
127 }
128
129 pub fn enable_operators(&mut self, operators: SyntaxOperator) {
134 let operators = self.operators_bits() | operators.bits();
135 self.set_operators_bits(operators)
136 }
137
138 pub fn disable_operators(&mut self, operators: SyntaxOperator) {
143 let operators = self.operators_bits() & !operators.bits();
144 self.set_operators_bits(operators)
145 }
146
147 pub fn behavior(&self) -> SyntaxBehavior {
149 SyntaxBehavior::from_bits_truncate(unsafe {
150 onig_sys::onig_get_syntax_behavior(self.raw_mut())
151 })
152 }
153
154 pub fn set_behavior(&mut self, behavior: SyntaxBehavior) {
156 let behavior = behavior.bits() as onig_sys::OnigSyntaxBehavior;
157 unsafe {
158 onig_sys::onig_set_syntax_behavior(&mut self.raw, behavior);
159 }
160 }
161
162 pub fn enable_behavior(&mut self, behavior: SyntaxBehavior) {
164 let behavior = self.behavior() | behavior;
165 self.set_behavior(behavior)
166 }
167
168 pub fn disable_behavior(&mut self, behavior: SyntaxBehavior) {
170 let behavior = self.behavior() & !behavior;
171 self.set_behavior(behavior)
172 }
173
174 pub fn options(&self) -> RegexOptions {
176 RegexOptions::from_bits_truncate(unsafe {
177 onig_sys::onig_get_syntax_options(self.raw_mut())
178 })
179 }
180
181 pub fn set_options(&mut self, options: RegexOptions) {
183 let options = options.bits() as onig_sys::OnigOptionType;
184 unsafe {
185 onig_sys::onig_set_syntax_options(&mut self.raw, options);
186 }
187 }
188
189 pub fn set_meta_char(&mut self, what: MetaCharType, meta: MetaChar) {
195 let what = what.bits();
196 let code = match meta {
197 MetaChar::Ineffective => onig_sys::ONIG_INEFFECTIVE_META_CHAR,
198 MetaChar::Character(char) => char as u32,
199 };
200 unsafe {
201 onig_sys::onig_set_meta_char(&mut self.raw, what, code);
202 }
203 }
204
205 fn raw_mut(&self) -> *mut onig_sys::OnigSyntaxType {
206 &self.raw as *const onig_sys::OnigSyntaxType as *mut onig_sys::OnigSyntaxType
207 }
208}
209
210#[cfg(test)]
211mod test {
212 use super::*;
213
214 #[test]
215 fn round_trip_bits() {
216 let mut syn = Syntax::python().clone();
217 syn.enable_operators(SyntaxOperator::SYNTAX_OPERATOR_ESC_X_BRACE_HEX8);
218 assert_ne!(Syntax::python().raw, syn.raw);
219 syn.disable_operators(SyntaxOperator::SYNTAX_OPERATOR_ESC_X_BRACE_HEX8);
220 assert_eq!(Syntax::python().raw, syn.raw);
221 }
222}