1use crate::context::Context;
10use crate::data::Metadata;
11use crate::schema::{SchemaModule, SchemaNode};
12use crate::utils::Binding;
13use bitflags::bitflags;
14use libyang2_sys as ffi;
15
16#[doc(hidden)]
18pub trait NodeIterable<'a>: Sized + Clone + PartialEq + Binding<'a> {
19 fn parent(&self) -> Option<Self>;
21
22 fn next_sibling(&self) -> Option<Self>;
24
25 fn first_child(&self) -> Option<Self>;
27}
28
29#[derive(Debug)]
31pub struct Siblings<'a, T>
32where
33 T: NodeIterable<'a>,
34{
35 next: Option<T>,
36 _marker: std::marker::PhantomData<&'a T>,
37}
38
39#[derive(Debug)]
41pub struct Ancestors<'a, T>
42where
43 T: NodeIterable<'a>,
44{
45 next: Option<T>,
46 _marker: std::marker::PhantomData<&'a T>,
47}
48
49#[derive(Debug)]
54pub struct Traverse<'a, T>
55where
56 T: NodeIterable<'a>,
57{
58 start: T,
59 next: Option<T>,
60 _marker: std::marker::PhantomData<&'a T>,
61}
62
63#[derive(Debug)]
65pub struct Getnext<'a> {
66 flags: IterSchemaFlags,
67 last: Option<SchemaNode<'a>>,
68 parent: Option<SchemaNode<'a>>,
69 module: Option<SchemaModule<'a>>,
70}
71
72bitflags! {
73 #[derive(Debug)]
75 pub struct IterSchemaFlags: u32 {
76 const WITH_CHOICE = ffi::LYS_GETNEXT_WITHCHOICE;
78 const NO_CHOICE = ffi::LYS_GETNEXT_NOCHOICE;
80 const WITH_CASE = ffi::LYS_GETNEXT_WITHCASE;
82 const INTO_NP_CONT = ffi::LYS_GETNEXT_INTONPCONT;
85 const OUTPUT = ffi::LYS_GETNEXT_OUTPUT;
88 }
89}
90
91#[derive(Debug)]
95pub struct Set<'a, T>
96where
97 T: NodeIterable<'a>,
98{
99 container: &'a T::Container,
100 slice: &'a [*mut T::CType],
101}
102
103#[derive(Debug)]
108pub struct Array<'a, S: Binding<'a>> {
109 context: &'a Context,
110 raw: *mut S::CType,
111 ptr_size: usize,
112 count: usize,
113}
114
115#[derive(Debug)]
117pub struct SchemaModules<'a> {
118 context: &'a Context,
119 index: u32,
120}
121
122#[derive(Debug)]
124pub struct MetadataList<'a, 'b> {
125 next: Option<Metadata<'a, 'b>>,
126}
127
128impl<'a, T> Siblings<'a, T>
131where
132 T: NodeIterable<'a>,
133{
134 pub fn new(next: Option<T>) -> Siblings<'a, T> {
135 Siblings {
136 next,
137 _marker: std::marker::PhantomData,
138 }
139 }
140}
141
142impl<'a, T> Iterator for Siblings<'a, T>
143where
144 T: NodeIterable<'a>,
145{
146 type Item = T;
147
148 fn next(&mut self) -> Option<T> {
149 let ret = self.next.clone();
150 if let Some(next) = &self.next {
151 self.next = next.next_sibling();
152 }
153 ret
154 }
155}
156
157impl<'a, T> Ancestors<'a, T>
160where
161 T: NodeIterable<'a>,
162{
163 pub fn new(next: Option<T>) -> Ancestors<'a, T> {
164 Ancestors {
165 next,
166 _marker: std::marker::PhantomData,
167 }
168 }
169}
170
171impl<'a, T> Iterator for Ancestors<'a, T>
172where
173 T: NodeIterable<'a>,
174{
175 type Item = T;
176
177 fn next(&mut self) -> Option<T> {
178 let node = self.next.clone();
179 if let Some(next) = &self.next {
180 self.next = next.parent();
181 }
182 node
183 }
184}
185
186impl<'a, T> Traverse<'a, T>
189where
190 T: NodeIterable<'a>,
191{
192 pub fn new(start: T) -> Traverse<'a, T> {
193 let next = start.clone();
194
195 Traverse {
196 start,
197 next: Some(next),
198 _marker: std::marker::PhantomData,
199 }
200 }
201}
202
203impl<'a, T> Iterator for Traverse<'a, T>
204where
205 T: NodeIterable<'a>,
206{
207 type Item = T;
208
209 fn next(&mut self) -> Option<T> {
210 let ret = self.next.clone();
211
212 if let Some(elem) = &mut self.next {
213 let mut next_elem = elem.first_child();
215 if next_elem.is_none() {
216 if *elem == self.start {
218 self.next = None;
219 return ret;
220 }
221
222 next_elem = elem.next_sibling();
224 }
225
226 while next_elem.is_none() {
227 *elem = elem.parent().unwrap();
229
230 if *elem == self.start {
232 self.next = None;
233 return ret;
234 }
235 next_elem = elem.next_sibling();
236 }
237
238 *elem = next_elem.unwrap();
239 }
240
241 ret
242 }
243}
244
245impl<'a> Getnext<'a> {
248 pub fn new(
249 flags: IterSchemaFlags,
250 parent: Option<SchemaNode<'a>>,
251 module: Option<SchemaModule<'a>>,
252 ) -> Getnext<'a> {
253 Getnext {
254 flags,
255 last: None,
256 parent,
257 module,
258 }
259 }
260}
261
262impl<'a> Iterator for Getnext<'a> {
263 type Item = SchemaNode<'a>;
264
265 fn next(&mut self) -> Option<SchemaNode<'a>> {
266 let last = self.last.take();
267 let parent = self.parent.clone();
268 let module = self.module.clone();
269
270 let last_raw =
271 last.map(|snode| snode.raw as _).unwrap_or(std::ptr::null());
272 let parent_raw = parent
273 .as_ref()
274 .map(|snode| snode.raw as _)
275 .unwrap_or(std::ptr::null());
276 let module_raw = module
277 .as_ref()
278 .map(|smodule| unsafe { (*smodule.raw).compiled } as _)
279 .unwrap_or(std::ptr::null());
280 let next = unsafe {
281 ffi::lys_getnext(
282 last_raw,
283 parent_raw,
284 module_raw,
285 self.flags.bits(),
286 )
287 };
288
289 let context = parent
290 .map(|snode| snode.context)
291 .or(module.map(|smodule| smodule.context))
292 .unwrap();
293 let next = unsafe { SchemaNode::from_raw_opt(context, next as *mut _) };
294 self.last = next.clone();
295 next
296 }
297}
298
299impl<'a, T> Set<'a, T>
302where
303 T: NodeIterable<'a>,
304{
305 pub fn new(
306 container: &'a T::Container,
307 slice: &'a [*mut T::CType],
308 ) -> Set<'a, T> {
309 Set { container, slice }
310 }
311}
312
313impl<'a, T> Iterator for Set<'a, T>
314where
315 T: NodeIterable<'a>,
316{
317 type Item = T;
318
319 fn next(&mut self) -> Option<T> {
320 if !self.slice.is_empty() {
321 let dnode =
322 Some(unsafe { T::from_raw(self.container, self.slice[0]) });
323 self.slice = &self.slice[1..];
324 dnode
325 } else {
326 None
327 }
328 }
329
330 fn size_hint(&self) -> (usize, Option<usize>) {
331 (0, Some(self.slice.len()))
332 }
333}
334
335unsafe impl<'a, T> Send for Set<'a, T> where T: NodeIterable<'a> {}
336unsafe impl<'a, T> Sync for Set<'a, T> where T: NodeIterable<'a> {}
337
338impl<'a, S> Array<'a, S>
341where
342 S: Binding<'a>,
343{
344 pub fn new(
345 context: &'a Context,
346 raw: *mut S::CType,
347 ptr_size: usize,
348 ) -> Array<'a, S> {
349 let count = if raw.is_null() {
352 0
353 } else {
354 unsafe { (raw as *const usize).offset(-1).read() }
355 };
356
357 Array {
358 context,
359 raw,
360 ptr_size,
361 count,
362 }
363 }
364}
365
366impl<'a, S> Iterator for Array<'a, S>
367where
368 S: Binding<'a, Container = Context>,
369{
370 type Item = S;
371
372 fn next(&mut self) -> Option<S> {
373 if self.count > 0 {
374 let next = unsafe { S::from_raw_opt(self.context, self.raw) };
375 self.count -= 1;
376 self.raw = (self.raw as usize + self.ptr_size) as *mut S::CType;
377 next
378 } else {
379 None
380 }
381 }
382
383 fn size_hint(&self) -> (usize, Option<usize>) {
384 (0, Some(self.count))
385 }
386}
387
388unsafe impl<'a, S> Send for Array<'a, S> where S: NodeIterable<'a> {}
389unsafe impl<'a, S> Sync for Array<'a, S> where S: NodeIterable<'a> {}
390
391impl<'a> SchemaModules<'a> {
394 pub fn new(context: &'a Context, skip_internal: bool) -> SchemaModules<'a> {
395 let index = if skip_internal {
396 context.internal_module_count()
397 } else {
398 0
399 };
400 SchemaModules { context, index }
401 }
402}
403
404impl<'a> Iterator for SchemaModules<'a> {
405 type Item = SchemaModule<'a>;
406
407 fn next(&mut self) -> Option<SchemaModule<'a>> {
408 let rmodule = unsafe {
409 ffi::ly_ctx_get_module_iter(self.context.raw, &mut self.index)
410 };
411 unsafe { SchemaModule::from_raw_opt(self.context, rmodule as *mut _) }
412 }
413}
414
415impl<'a, 'b> MetadataList<'a, 'b> {
418 pub fn new(next: Option<Metadata<'a, 'b>>) -> MetadataList<'a, 'b> {
419 MetadataList { next }
420 }
421}
422
423impl<'a, 'b> Iterator for MetadataList<'a, 'b> {
424 type Item = Metadata<'a, 'b>;
425
426 fn next(&mut self) -> Option<Metadata<'a, 'b>> {
427 let meta = self.next.clone();
428 if let Some(next) = &self.next {
429 self.next = next.next();
430 }
431 meta
432 }
433}