1#![allow(clippy::transmute_ptr_to_ref)]
2
3use std::iter::FusedIterator;
4use std::mem::transmute;
5use std::ops::Index;
6
7#[derive(Debug)]
13#[repr(transparent)]
14pub struct CaptureTreeNode {
15 raw: onig_sys::OnigCaptureTreeNode,
16}
17
18impl CaptureTreeNode {
19 pub fn group(&self) -> usize {
21 self.raw.group as usize
22 }
23
24 pub fn pos(&self) -> (usize, usize) {
26 (self.raw.beg as usize, self.raw.end as usize)
27 }
28
29 pub fn len(&self) -> usize {
31 self.raw.num_childs as usize
32 }
33
34 pub fn is_empty(&self) -> bool {
36 self.len() == 0
37 }
38
39 pub fn children(&self) -> CaptureTreeNodeIter<'_> {
41 CaptureTreeNodeIter { idx: 0, node: self }
42 }
43}
44
45impl Index<usize> for CaptureTreeNode {
46 type Output = CaptureTreeNode;
47
48 fn index(&self, index: usize) -> &CaptureTreeNode {
49 if index >= self.len() {
50 panic!("capture tree node index overflow")
51 }
52 unsafe { transmute(*self.raw.childs.add(index)) }
53 }
54}
55
56#[derive(Debug)]
58pub struct CaptureTreeNodeIter<'t> {
59 idx: usize,
60 node: &'t CaptureTreeNode,
61}
62
63impl<'t> Iterator for CaptureTreeNodeIter<'t> {
64 type Item = &'t CaptureTreeNode;
65
66 fn next(&mut self) -> Option<&'t CaptureTreeNode> {
67 if self.idx < self.node.len() {
68 self.idx += 1;
69 Some(&self.node[self.idx - 1])
70 } else {
71 None
72 }
73 }
74
75 fn size_hint(&self) -> (usize, Option<usize>) {
76 let size = self.node.len();
77 (size, Some(size))
78 }
79
80 fn count(self) -> usize {
81 self.node.len()
82 }
83}
84
85impl<'t> FusedIterator for CaptureTreeNodeIter<'t> {}
86
87impl<'t> ExactSizeIterator for CaptureTreeNodeIter<'t> {}
88
89#[cfg(test)]
90mod tests {
91 use super::super::*;
92
93 #[test]
94 fn test_regex_search_with_region_tree() {
95 let mut region = Region::new();
96 let mut syntax = Syntax::ruby().clone();
97 syntax.enable_operators(SyntaxOperator::SYNTAX_OPERATOR_ATMARK_CAPTURE_HISTORY);
98
99 let regex = Regex::with_options(
100 "(?@a+(?@b+))|(?@c+(?@d+))",
101 RegexOptions::REGEX_OPTION_NONE,
102 &syntax,
103 )
104 .unwrap();
105
106 let r = regex.search_with_options(
107 "- cd aaabbb -",
108 0,
109 13,
110 SearchOptions::SEARCH_OPTION_NONE,
111 Some(&mut region),
112 );
113
114 assert_eq!(r, Some(2));
115 assert_eq!(region.len(), 5);
116
117 let tree = region.tree().unwrap();
118
119 assert_eq!(tree.len(), 1);
120 assert_eq!(tree.group(), 0);
121 assert_eq!(tree.pos(), (2, 4));
122
123 assert_eq!(tree[0].len(), 1);
124 assert_eq!(tree[0].group(), 3);
125 assert_eq!(tree[0].pos(), (2, 4));
126
127 assert_eq!(tree[0][0].len(), 0);
128 assert_eq!(tree[0][0].group(), 4);
129 assert_eq!(tree[0][0].pos(), (3, 4));
130 }
131}