1use bitflags::bitflags;
10use num_derive::FromPrimitive;
11use num_traits::FromPrimitive;
12use std::ffi::CString;
13use std::mem;
14use std::os::raw::{c_char, c_void};
15use std::os::unix::io::AsRawFd;
16use std::slice;
17
18use crate::context::Context;
19use crate::data::DataTree;
20use crate::error::{Error, Result};
21use crate::iter::{
22 Ancestors, Array, Getnext, IterSchemaFlags, NodeIterable, Set, Siblings,
23 Traverse,
24};
25use crate::utils::*;
26use libyang2_sys as ffi;
27
28#[derive(Clone, Debug)]
30pub struct SchemaModule<'a> {
31 pub(crate) context: &'a Context,
32 pub(crate) raw: *mut ffi::lys_module,
33}
34
35#[allow(clippy::upper_case_acronyms)]
37#[repr(u32)]
38#[derive(Clone, Copy, Debug, PartialEq)]
39pub enum SchemaInputFormat {
40 YANG = ffi::LYS_INFORMAT::LYS_IN_YANG,
41 YIN = ffi::LYS_INFORMAT::LYS_IN_YIN,
42}
43
44#[allow(clippy::upper_case_acronyms)]
46#[repr(u32)]
47#[derive(Clone, Copy, Debug, PartialEq)]
48pub enum SchemaOutputFormat {
49 YANG = ffi::LYS_OUTFORMAT::LYS_OUT_YANG,
50 YIN = ffi::LYS_OUTFORMAT::LYS_OUT_YIN,
51 TREE = ffi::LYS_OUTFORMAT::LYS_OUT_TREE,
52}
53
54#[allow(clippy::upper_case_acronyms)]
56#[repr(u32)]
57#[derive(Clone, Copy, Debug, PartialEq)]
58pub enum SchemaPathFormat {
59 LOG = ffi::LYSC_PATH_TYPE::LYSC_PATH_LOG,
61 DATA = ffi::LYSC_PATH_TYPE::LYSC_PATH_DATA,
64}
65
66bitflags! {
67 pub struct SchemaPrinterFlags: u32 {
69 const SHRINK = ffi::LYS_PRINT_SHRINK;
71 const NO_SUBSTMT = ffi::LYS_PRINT_NO_SUBSTMT;
74 }
75}
76
77#[derive(Clone, Debug)]
79pub struct SchemaNode<'a> {
80 pub(crate) context: &'a Context,
81 pub(crate) raw: *mut ffi::lysc_node,
82 kind: SchemaNodeKind,
83}
84
85#[derive(Clone, Copy, Debug, PartialEq)]
87pub enum SchemaNodeKind {
88 Container,
89 Case,
90 Choice,
91 Leaf,
92 LeafList,
93 List,
94 AnyData,
95 Rpc,
96 Input,
97 Output,
98 Action,
99 Notification,
100}
101
102#[derive(Clone, Debug)]
104pub struct SchemaStmtMust<'a> {
105 raw: *mut ffi::lysc_must,
106 _marker: std::marker::PhantomData<&'a Context>,
107}
108
109#[derive(Clone, Debug)]
111pub struct SchemaStmtWhen<'a> {
112 raw: *mut ffi::lysc_when,
113 _marker: std::marker::PhantomData<&'a Context>,
114}
115
116#[derive(Clone, Debug)]
118pub struct SchemaLeafType<'a> {
119 context: &'a Context,
120 raw: *mut ffi::lysc_type,
121}
122
123#[derive(Clone, Debug)]
125pub struct SchemaExtInstance<'a> {
126 context: &'a Context,
127 raw: *mut ffi::lysc_ext_instance,
128}
129
130#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
132pub enum DataValueType {
133 Unknown = 0,
134 Binary = 1,
135 Uint8 = 2,
136 Uint16 = 3,
137 Uint32 = 4,
138 Uint64 = 5,
139 String = 6,
140 Bits = 7,
141 Bool = 8,
142 Dec64 = 9,
143 Empty = 10,
144 Enum = 11,
145 IdentityRef = 12,
146 InstanceId = 13,
147 LeafRef = 14,
148 Union = 15,
149 Int8 = 16,
150 Int16 = 17,
151 Int32 = 18,
152 Int64 = 19,
153}
154
155#[derive(Clone, Debug, PartialEq)]
157pub enum DataValue {
158 Uint8(u8),
159 Uint16(u16),
160 Uint32(u32),
161 Uint64(u64),
162 Bool(bool),
163 Empty,
164 Int8(i8),
165 Int16(i16),
166 Int32(i32),
167 Int64(i64),
168 Other(String),
169}
170
171impl<'a> SchemaModule<'a> {
174 pub fn as_raw(&self) -> *mut ffi::lys_module {
177 self.raw
178 }
179
180 pub fn name(&self) -> &str {
182 char_ptr_to_str(unsafe { (*self.raw).name })
183 }
184
185 pub fn revision(&self) -> Option<&str> {
187 char_ptr_to_opt_str(unsafe { (*self.raw).revision })
188 }
189
190 pub fn namespace(&self) -> &str {
192 char_ptr_to_str(unsafe { (*self.raw).ns })
193 }
194
195 pub fn prefix(&self) -> &str {
197 char_ptr_to_str(unsafe { (*self.raw).prefix })
198 }
199
200 pub fn filepath(&self) -> Option<&str> {
202 char_ptr_to_opt_str(unsafe { (*self.raw).filepath })
203 }
204
205 pub fn organization(&self) -> Option<&str> {
207 char_ptr_to_opt_str(unsafe { (*self.raw).org })
208 }
209
210 pub fn contact(&self) -> Option<&str> {
212 char_ptr_to_opt_str(unsafe { (*self.raw).contact })
213 }
214
215 pub fn description(&self) -> Option<&str> {
217 char_ptr_to_opt_str(unsafe { (*self.raw).dsc })
218 }
219
220 pub fn reference(&self) -> Option<&str> {
222 char_ptr_to_opt_str(unsafe { (*self.raw).ref_ })
223 }
224
225 pub fn set_implemented(&self) -> Result<()> {
227 let ret =
228 unsafe { ffi::lys_set_implemented(self.raw, std::ptr::null_mut()) };
229 if ret != ffi::LY_ERR::LY_SUCCESS {
230 return Err(Error::new(self.context));
231 }
232
233 Ok(())
234 }
235
236 pub fn is_implemented(&self) -> bool {
238 unsafe { (*self.raw).implemented != 0 }
239 }
240
241 pub fn feature_value(&self, feature: &str) -> Result<bool> {
243 let feature = CString::new(feature).unwrap();
244 let ret = unsafe { ffi::lys_feature_value(self.raw, feature.as_ptr()) };
245 match ret {
246 ffi::LY_ERR::LY_SUCCESS => Ok(true),
247 ffi::LY_ERR::LY_ENOT => Ok(false),
248 _ => Err(Error::new(self.context)),
249 }
250 }
251
252 pub fn print_file<F: AsRawFd>(
254 &self,
255 fd: F,
256 format: SchemaOutputFormat,
257 options: SchemaPrinterFlags,
258 ) -> Result<()> {
259 let ret = unsafe {
260 ffi::lys_print_fd(
261 fd.as_raw_fd(),
262 self.raw,
263 format as u32,
264 options.bits(),
265 )
266 };
267 if ret != ffi::LY_ERR::LY_SUCCESS {
268 return Err(Error::new(self.context));
269 }
270
271 Ok(())
272 }
273
274 pub fn print_string(
276 &self,
277 format: SchemaOutputFormat,
278 options: SchemaPrinterFlags,
279 ) -> Result<String> {
280 let mut cstr = std::ptr::null_mut();
281 let cstr_ptr = &mut cstr;
282
283 let ret = unsafe {
284 ffi::lys_print_mem(
285 cstr_ptr,
286 self.raw,
287 format as u32,
288 options.bits(),
289 )
290 };
291 if ret != ffi::LY_ERR::LY_SUCCESS {
292 return Err(Error::new(self.context));
293 }
294
295 Ok(char_ptr_to_string(cstr))
296 }
297
298 pub fn data(&self) -> Siblings<'a, SchemaNode<'a>> {
300 let compiled = unsafe { (*self.raw).compiled };
301 let rdata = if compiled.is_null() {
302 std::ptr::null()
303 } else {
304 unsafe { (*compiled).data }
305 };
306 let data =
307 unsafe { SchemaNode::from_raw_opt(self.context, rdata as *mut _) };
308 Siblings::new(data)
309 }
310
311 pub fn rpcs(&self) -> Siblings<'a, SchemaNode<'a>> {
313 let compiled = unsafe { (*self.raw).compiled };
314 let rdata = if compiled.is_null() {
315 std::ptr::null()
316 } else {
317 unsafe { (*compiled).rpcs }
318 };
319 let rpcs =
320 unsafe { SchemaNode::from_raw_opt(self.context, rdata as *mut _) };
321 Siblings::new(rpcs)
322 }
323
324 pub fn notifications(&self) -> Siblings<'a, SchemaNode<'a>> {
326 let compiled = unsafe { (*self.raw).compiled };
327 let rdata = if compiled.is_null() {
328 std::ptr::null()
329 } else {
330 unsafe { (*compiled).notifs }
331 };
332 let notifications =
333 unsafe { SchemaNode::from_raw_opt(self.context, rdata as *mut _) };
334 Siblings::new(notifications)
335 }
336
337 pub fn extensions(&self) -> impl Iterator<Item = SchemaExtInstance<'a>> {
339 let compiled = unsafe { (*self.raw).compiled };
340 let array = unsafe { (*compiled).exts };
341 let ptr_size = mem::size_of::<ffi::lysc_ext_instance>();
342 Array::new(self.context, array as *mut _, ptr_size)
343 }
344
345 pub fn top_level_nodes(
348 &self,
349 flags: IterSchemaFlags,
350 ) -> impl Iterator<Item = SchemaNode<'a>> {
351 Getnext::new(flags, None, Some(self.clone()))
352 }
353
354 pub fn traverse(&self) -> impl Iterator<Item = SchemaNode<'a>> {
360 let data = self.data().flat_map(|snode| snode.traverse());
361 let rpcs = self.rpcs().flat_map(|snode| snode.traverse());
362 let notifications =
363 self.notifications().flat_map(|snode| snode.traverse());
364 data.chain(rpcs).chain(notifications)
365 }
366}
367
368unsafe impl<'a> Binding<'a> for SchemaModule<'a> {
369 type CType = ffi::lys_module;
370 type Container = Context;
371
372 unsafe fn from_raw(
373 context: &'a Context,
374 raw: *mut ffi::lys_module,
375 ) -> SchemaModule<'a> {
376 SchemaModule { context, raw }
377 }
378}
379
380impl PartialEq for SchemaModule<'_> {
381 fn eq(&self, other: &SchemaModule<'_>) -> bool {
382 self.raw == other.raw
383 }
384}
385
386unsafe impl Send for SchemaModule<'_> {}
387unsafe impl Sync for SchemaModule<'_> {}
388
389impl<'a> SchemaNode<'a> {
392 pub fn as_raw(&self) -> *mut ffi::lysc_node {
395 self.raw
396 }
397
398 #[doc(hidden)]
399 fn check_flag(&self, flag: u32) -> bool {
400 let flags = unsafe { (*self.raw).flags } as u32;
401 flags & flag != 0
402 }
403
404 pub fn module(&self) -> SchemaModule<'_> {
406 let module = unsafe { (*self.raw).module };
407 unsafe { SchemaModule::from_raw(self.context, module) }
408 }
409
410 pub fn kind(&self) -> SchemaNodeKind {
412 self.kind
413 }
414
415 pub fn name(&self) -> &str {
417 char_ptr_to_str(unsafe { (*self.raw).name })
418 }
419
420 pub fn description(&self) -> Option<&str> {
422 char_ptr_to_opt_str(unsafe { (*self.raw).dsc })
423 }
424
425 pub fn reference(&self) -> Option<&str> {
427 char_ptr_to_opt_str(unsafe { (*self.raw).ref_ })
428 }
429
430 pub fn path(&self, format: SchemaPathFormat) -> String {
432 let buf = std::mem::MaybeUninit::<[c_char; 4096]>::uninit();
433 let mut buf = unsafe { buf.assume_init() };
434
435 let ret = unsafe {
436 ffi::lysc_path(self.raw, format as u32, buf.as_mut_ptr(), buf.len())
437 };
438 if ret.is_null() {
439 panic!("Failed to generate path of the schema node");
440 }
441
442 char_ptr_to_string(buf.as_ptr())
443 }
444
445 pub fn find_xpath(&self, xpath: &str) -> Result<Set<'_, SchemaNode<'_>>> {
447 let xpath = CString::new(xpath).unwrap();
448 let mut set = std::ptr::null_mut();
449 let set_ptr = &mut set;
450 let options = 0u32;
451
452 let ret = unsafe {
453 ffi::lys_find_xpath(
454 std::ptr::null(),
455 self.raw,
456 xpath.as_ptr(),
457 options,
458 set_ptr,
459 )
460 };
461 if ret != ffi::LY_ERR::LY_SUCCESS {
462 return Err(Error::new(self.context));
463 }
464
465 let rnodes_count = unsafe { (*set).count } as usize;
466 let slice = if rnodes_count == 0 {
467 &[]
468 } else {
469 let rnodes = unsafe { (*set).__bindgen_anon_1.snodes };
470 unsafe { slice::from_raw_parts(rnodes, rnodes_count) }
471 };
472
473 Ok(Set::new(self.context, slice))
474 }
475
476 pub fn find_path(&self, path: &str) -> Result<SchemaNode<'_>> {
478 let path = CString::new(path).unwrap();
479
480 let rnode = unsafe {
481 ffi::lys_find_path(std::ptr::null(), self.raw, path.as_ptr(), 0)
482 };
483 if rnode.is_null() {
484 return Err(Error::new(self.context));
485 }
486
487 Ok(unsafe { SchemaNode::from_raw(self.context, rnode as *mut _) })
488 }
489
490 pub fn is_config(&self) -> bool {
492 match self.kind {
493 SchemaNodeKind::Container
494 | SchemaNodeKind::Case
495 | SchemaNodeKind::Choice
496 | SchemaNodeKind::Leaf
497 | SchemaNodeKind::LeafList
498 | SchemaNodeKind::List
499 | SchemaNodeKind::AnyData => self.check_flag(ffi::LYS_CONFIG_W),
500 _ => false,
501 }
502 }
503
504 pub fn is_state(&self) -> bool {
506 match self.kind {
507 SchemaNodeKind::Container
508 | SchemaNodeKind::Case
509 | SchemaNodeKind::Choice
510 | SchemaNodeKind::Leaf
511 | SchemaNodeKind::LeafList
512 | SchemaNodeKind::List
513 | SchemaNodeKind::AnyData => self.check_flag(ffi::LYS_CONFIG_R),
514 _ => false,
515 }
516 }
517
518 pub fn is_status_current(&self) -> bool {
520 self.check_flag(ffi::LYS_STATUS_CURR)
521 }
522
523 pub fn is_status_deprecated(&self) -> bool {
525 self.check_flag(ffi::LYS_STATUS_DEPRC)
526 }
527
528 pub fn is_status_obsolete(&self) -> bool {
530 self.check_flag(ffi::LYS_STATUS_OBSLT)
531 }
532
533 pub fn is_mandatory(&self) -> bool {
535 match self.kind {
536 SchemaNodeKind::Container
537 | SchemaNodeKind::Choice
538 | SchemaNodeKind::Leaf
539 | SchemaNodeKind::LeafList
540 | SchemaNodeKind::List
541 | SchemaNodeKind::AnyData => self.check_flag(ffi::LYS_MAND_TRUE),
542 _ => false,
543 }
544 }
545
546 pub fn is_np_container(&self) -> bool {
548 match self.kind {
549 SchemaNodeKind::Container => !self.check_flag(ffi::LYS_PRESENCE),
550 _ => false,
551 }
552 }
553
554 pub fn is_list_key(&self) -> bool {
556 match self.kind {
557 SchemaNodeKind::Leaf => self.check_flag(ffi::LYS_KEY),
558 _ => false,
559 }
560 }
561
562 pub fn is_keyless_list(&self) -> bool {
564 match self.kind {
565 SchemaNodeKind::List => self.check_flag(ffi::LYS_KEYLESS),
566 _ => false,
567 }
568 }
569
570 pub fn is_user_ordered(&self) -> bool {
572 match self.kind {
573 SchemaNodeKind::LeafList | SchemaNodeKind::List => {
574 self.check_flag(ffi::LYS_ORDBY_USER)
575 }
576 _ => false,
577 }
578 }
579
580 pub fn is_schema_only(&self) -> bool {
583 matches!(self.kind(), SchemaNodeKind::Choice | SchemaNodeKind::Case)
584 }
585
586 pub fn is_within_input(&self) -> bool {
588 match self.kind {
589 SchemaNodeKind::Container
590 | SchemaNodeKind::Case
591 | SchemaNodeKind::Choice
592 | SchemaNodeKind::Leaf
593 | SchemaNodeKind::LeafList
594 | SchemaNodeKind::List
595 | SchemaNodeKind::AnyData => self.check_flag(ffi::LYS_IS_INPUT),
596 _ => false,
597 }
598 }
599
600 pub fn is_within_output(&self) -> bool {
602 match self.kind {
603 SchemaNodeKind::Container
604 | SchemaNodeKind::Case
605 | SchemaNodeKind::Choice
606 | SchemaNodeKind::Leaf
607 | SchemaNodeKind::LeafList
608 | SchemaNodeKind::List
609 | SchemaNodeKind::AnyData => self.check_flag(ffi::LYS_IS_OUTPUT),
610 _ => false,
611 }
612 }
613
614 pub fn is_within_notification(&self) -> bool {
616 match self.kind {
617 SchemaNodeKind::Container
618 | SchemaNodeKind::Case
619 | SchemaNodeKind::Choice
620 | SchemaNodeKind::Leaf
621 | SchemaNodeKind::LeafList
622 | SchemaNodeKind::List
623 | SchemaNodeKind::AnyData => self.check_flag(ffi::LYS_IS_NOTIF),
624 _ => false,
625 }
626 }
627
628 pub fn has_default(&self) -> bool {
630 match self.kind {
631 SchemaNodeKind::Case
632 | SchemaNodeKind::Leaf
633 | SchemaNodeKind::LeafList => self.check_flag(ffi::LYS_SET_DFLT),
634 _ => false,
635 }
636 }
637
638 pub fn default_value_canonical(&self) -> Option<&str> {
640 let default = unsafe {
641 match self.kind() {
642 SchemaNodeKind::Leaf => {
643 let rvalue =
644 (*(self.raw as *const ffi::lysc_node_leaf)).dflt;
645 let mut canonical = (*rvalue)._canonical;
646 if canonical.is_null() {
647 canonical = ffi::lyd_value_get_canonical(
648 self.context.raw,
649 rvalue,
650 )
651 }
652 canonical
653 }
654 _ => return None,
655 }
656 };
657
658 char_ptr_to_opt_str(default)
659 }
660
661 pub fn default_value(&self) -> Option<DataValue> {
663 match self.kind() {
664 SchemaNodeKind::Leaf => {
665 let default = unsafe {
666 let rvalue =
667 (*(self.raw as *const ffi::lysc_node_leaf)).dflt;
668 if rvalue.is_null() {
669 return None;
670 }
671 DataValue::from_raw(self.context, rvalue)
672 };
673 Some(default)
674 }
675 _ => None,
676 }
677 }
678
679 pub fn default_case(&self) -> Option<SchemaNode<'_>> {
681 let default = unsafe {
682 match self.kind() {
683 SchemaNodeKind::Choice => {
684 (*(self.raw as *mut ffi::lysc_node_choice)).dflt
685 }
686 _ => return None,
687 }
688 };
689
690 unsafe { SchemaNode::from_raw_opt(self.context, default as *mut _) }
691 }
692
693 pub fn leaf_type(&self) -> Option<SchemaLeafType<'_>> {
697 let raw = unsafe {
698 match self.kind() {
699 SchemaNodeKind::Leaf => {
700 (*(self.raw as *mut ffi::lysc_node_leaf)).type_
701 }
702 SchemaNodeKind::LeafList => {
703 (*(self.raw as *mut ffi::lysc_node_leaflist)).type_
704 }
705 _ => return None,
706 }
707 };
708 let ltype = unsafe { SchemaLeafType::from_raw(self.context, raw) };
709 Some(ltype)
710 }
711
712 pub fn units(&self) -> Option<&str> {
714 let units = unsafe {
715 match self.kind() {
716 SchemaNodeKind::Leaf => {
717 (*(self.raw as *mut ffi::lysc_node_leaf)).units
718 }
719 SchemaNodeKind::LeafList => {
720 (*(self.raw as *mut ffi::lysc_node_leaflist)).units
721 }
722 _ => return None,
723 }
724 };
725
726 char_ptr_to_opt_str(units)
727 }
728
729 pub fn min_elements(&self) -> Option<u32> {
731 let min = unsafe {
732 match self.kind() {
733 SchemaNodeKind::LeafList => {
734 (*(self.raw as *mut ffi::lysc_node_leaflist)).min
735 }
736 SchemaNodeKind::List => {
737 (*(self.raw as *mut ffi::lysc_node_list)).min
738 }
739 _ => return None,
740 }
741 };
742
743 if min != 0 {
744 Some(min)
745 } else {
746 None
747 }
748 }
749
750 pub fn max_elements(&self) -> Option<u32> {
752 let max = unsafe {
753 match self.kind() {
754 SchemaNodeKind::LeafList => {
755 (*(self.raw as *mut ffi::lysc_node_leaflist)).max
756 }
757 SchemaNodeKind::List => {
758 (*(self.raw as *mut ffi::lysc_node_list)).max
759 }
760 _ => return None,
761 }
762 };
763 if max != u32::MAX {
764 Some(max)
765 } else {
766 None
767 }
768 }
769
770 pub fn musts(&self) -> Option<Array<'_, SchemaStmtMust<'_>>> {
772 let array = unsafe { ffi::lysc_node_musts(self.raw) };
773 let ptr_size = mem::size_of::<ffi::lysc_must>();
774 Some(Array::new(self.context, array as *mut _, ptr_size))
775 }
776
777 pub fn whens(&self) -> Array<'_, SchemaStmtWhen<'_>> {
779 let array = unsafe { ffi::lysc_node_when(self.raw) };
780 let ptr_size = mem::size_of::<ffi::lysc_when>();
781 Array::new(self.context, array as *mut _, ptr_size)
782 }
783
784 pub fn actions(&self) -> impl Iterator<Item = SchemaNode<'a>> + 'a {
786 let rnode = unsafe {
787 match self.kind {
788 SchemaNodeKind::Container => {
789 (*(self.raw as *mut ffi::lysc_node_container)).actions
790 }
791 SchemaNodeKind::List => {
792 (*(self.raw as *mut ffi::lysc_node_list)).actions
793 }
794 _ => std::ptr::null_mut(),
795 }
796 };
797
798 let node =
799 unsafe { SchemaNode::from_raw_opt(self.context, rnode as *mut _) };
800 Siblings::new(node)
801 }
802
803 pub fn notifications(&self) -> impl Iterator<Item = SchemaNode<'a>> + 'a {
805 let rnode = unsafe {
806 match self.kind {
807 SchemaNodeKind::Container => {
808 (*(self.raw as *mut ffi::lysc_node_container)).notifs
809 }
810 SchemaNodeKind::List => {
811 (*(self.raw as *mut ffi::lysc_node_list)).notifs
812 }
813 _ => std::ptr::null_mut(),
814 }
815 };
816
817 let node =
818 unsafe { SchemaNode::from_raw_opt(self.context, rnode as *mut _) };
819 Siblings::new(node)
820 }
821
822 pub fn input(
826 &self,
827 ) -> Option<(Siblings<'_, SchemaNode<'_>>, Array<'_, SchemaStmtMust<'_>>)>
828 {
829 match self.kind {
830 SchemaNodeKind::Rpc | SchemaNodeKind::Action => {
831 let raw = self.raw as *mut ffi::lysc_node_action;
832 let input = unsafe { (*raw).input };
833 let rnode = input.child;
834 let rmusts = input.musts;
835
836 let node =
837 unsafe { SchemaNode::from_raw_opt(self.context, rnode) };
838 let nodes = Siblings::new(node);
839 let ptr_size = mem::size_of::<ffi::lysc_must>();
840 let musts = Array::new(self.context, rmusts, ptr_size);
841 Some((nodes, musts))
842 }
843 _ => None,
844 }
845 }
846
847 pub fn output(
851 &self,
852 ) -> Option<(Siblings<'_, SchemaNode<'_>>, Array<'_, SchemaStmtMust<'_>>)>
853 {
854 match self.kind {
855 SchemaNodeKind::Rpc | SchemaNodeKind::Action => {
856 let raw = self.raw as *mut ffi::lysc_node_action;
857 let output = unsafe { (*raw).output };
858 let rnode = output.child;
859 let rmusts = output.musts;
860
861 let node =
862 unsafe { SchemaNode::from_raw_opt(self.context, rnode) };
863 let nodes = Siblings::new(node);
864 let ptr_size = mem::size_of::<ffi::lysc_must>();
865 let musts = Array::new(self.context, rmusts, ptr_size);
866 Some((nodes, musts))
867 }
868 _ => None,
869 }
870 }
871
872 pub fn ancestors(&self) -> Ancestors<'a, SchemaNode<'a>> {
874 let parent = self.parent();
875 Ancestors::new(parent)
876 }
877
878 pub fn inclusive_ancestors(&self) -> Ancestors<'a, SchemaNode<'a>> {
880 Ancestors::new(Some(self.clone()))
881 }
882
883 pub fn siblings(&self) -> Siblings<'a, SchemaNode<'a>> {
885 let sibling = self.next_sibling();
886 Siblings::new(sibling)
887 }
888
889 pub fn inclusive_siblings(&self) -> Siblings<'a, SchemaNode<'a>> {
891 Siblings::new(Some(self.clone()))
892 }
893
894 pub fn children(&self) -> Siblings<'a, SchemaNode<'a>> {
897 let child = self.first_child();
898 Siblings::new(child)
899 }
900
901 pub fn all_children(&self) -> impl Iterator<Item = SchemaNode<'a>> {
904 let child = self.first_child();
905 Siblings::new(child)
906 .chain(self.actions())
907 .chain(self.notifications())
908 }
909
910 pub fn children2(
913 &self,
914 flags: IterSchemaFlags,
915 ) -> impl Iterator<Item = SchemaNode<'a>> {
916 Getnext::new(flags, Some(self.clone()), None)
917 }
918
919 pub fn traverse(&self) -> Traverse<'a, SchemaNode<'a>> {
922 Traverse::new(self.clone())
923 }
924
925 pub fn list_keys(&self) -> impl Iterator<Item = SchemaNode<'a>> {
927 self.children().filter(|snode| snode.is_list_key())
928 }
929
930 pub unsafe fn set_private(&self, ptr: *mut c_void) {
936 (*self.raw).priv_ = ptr;
937 }
938
939 pub fn get_private(&self) -> Option<*mut c_void> {
941 let priv_ = unsafe { (*self.raw).priv_ };
942 if priv_.is_null() {
943 None
944 } else {
945 Some(priv_)
946 }
947 }
948}
949
950unsafe impl<'a> Binding<'a> for SchemaNode<'a> {
951 type CType = ffi::lysc_node;
952 type Container = Context;
953
954 unsafe fn from_raw(
955 context: &'a Context,
956 raw: *mut ffi::lysc_node,
957 ) -> SchemaNode<'a> {
958 let nodetype = unsafe { (*raw).nodetype } as u32;
959 let kind = match nodetype {
960 ffi::LYS_CONTAINER => SchemaNodeKind::Container,
961 ffi::LYS_CASE => SchemaNodeKind::Case,
962 ffi::LYS_CHOICE => SchemaNodeKind::Choice,
963 ffi::LYS_LEAF => SchemaNodeKind::Leaf,
964 ffi::LYS_LEAFLIST => SchemaNodeKind::LeafList,
965 ffi::LYS_LIST => SchemaNodeKind::List,
966 ffi::LYS_ANYDATA => SchemaNodeKind::AnyData,
967 ffi::LYS_ACTION => SchemaNodeKind::Action,
968 ffi::LYS_RPC => SchemaNodeKind::Rpc,
969 ffi::LYS_INPUT => SchemaNodeKind::Input,
970 ffi::LYS_OUTPUT => SchemaNodeKind::Output,
971 ffi::LYS_NOTIF => SchemaNodeKind::Notification,
972 _ => panic!("unknown node type"),
973 };
974 SchemaNode { context, raw, kind }
975 }
976}
977
978impl<'a> NodeIterable<'a> for SchemaNode<'a> {
979 fn parent(&self) -> Option<SchemaNode<'a>> {
980 let rparent = unsafe { (*self.raw).parent };
981 unsafe { SchemaNode::from_raw_opt(self.context, rparent) }
982 }
983
984 fn next_sibling(&self) -> Option<SchemaNode<'a>> {
985 let rnext = unsafe { (*self.raw).next };
986 unsafe { SchemaNode::from_raw_opt(self.context, rnext) }
987 }
988
989 fn first_child(&self) -> Option<SchemaNode<'a>> {
990 let rchild = unsafe { ffi::lysc_node_child(&*self.raw) };
991 unsafe { SchemaNode::from_raw_opt(self.context, rchild as *mut _) }
992 }
993}
994
995impl PartialEq for SchemaNode<'_> {
996 fn eq(&self, other: &SchemaNode<'_>) -> bool {
997 self.raw == other.raw
998 }
999}
1000
1001unsafe impl Send for SchemaNode<'_> {}
1002unsafe impl Sync for SchemaNode<'_> {}
1003
1004impl SchemaStmtMust<'_> {
1007 pub fn as_raw(&self) -> *mut ffi::lysc_must {
1012 self.raw
1013 }
1014
1015 pub fn description(&self) -> Option<&str> {
1017 char_ptr_to_opt_str(unsafe { (*self.raw).dsc })
1018 }
1019
1020 pub fn reference(&self) -> Option<&str> {
1022 char_ptr_to_opt_str(unsafe { (*self.raw).ref_ })
1023 }
1024
1025 pub fn error_msg(&self) -> Option<&str> {
1027 char_ptr_to_opt_str(unsafe { (*self.raw).emsg })
1028 }
1029
1030 pub fn error_apptag(&self) -> Option<&str> {
1032 char_ptr_to_opt_str(unsafe { (*self.raw).eapptag })
1033 }
1034}
1035
1036unsafe impl<'a> Binding<'a> for SchemaStmtMust<'a> {
1037 type CType = ffi::lysc_must;
1038 type Container = Context;
1039
1040 unsafe fn from_raw(
1041 _context: &'a Context,
1042 raw: *mut ffi::lysc_must,
1043 ) -> SchemaStmtMust<'a> {
1044 SchemaStmtMust {
1045 raw,
1046 _marker: std::marker::PhantomData,
1047 }
1048 }
1049}
1050
1051unsafe impl Send for SchemaStmtMust<'_> {}
1052unsafe impl Sync for SchemaStmtMust<'_> {}
1053
1054impl SchemaStmtWhen<'_> {
1057 pub fn as_raw(&self) -> *mut ffi::lysc_when {
1062 self.raw
1063 }
1064
1065 pub fn description(&self) -> Option<&str> {
1067 char_ptr_to_opt_str(unsafe { (*self.raw).dsc })
1068 }
1069
1070 pub fn reference(&self) -> Option<&str> {
1072 char_ptr_to_opt_str(unsafe { (*self.raw).ref_ })
1073 }
1074}
1075
1076unsafe impl<'a> Binding<'a> for SchemaStmtWhen<'a> {
1077 type CType = *mut ffi::lysc_when;
1078 type Container = Context;
1079
1080 unsafe fn from_raw(
1081 _context: &'a Context,
1082 raw: *mut *mut ffi::lysc_when,
1083 ) -> SchemaStmtWhen<'a> {
1084 let raw = unsafe { *raw };
1085 SchemaStmtWhen {
1086 raw,
1087 _marker: std::marker::PhantomData,
1088 }
1089 }
1090}
1091
1092unsafe impl Send for SchemaStmtWhen<'_> {}
1093unsafe impl Sync for SchemaStmtWhen<'_> {}
1094
1095impl SchemaLeafType<'_> {
1098 pub fn as_raw(&self) -> *mut ffi::lysc_type {
1101 self.raw
1102 }
1103
1104 pub fn base_type(&self) -> DataValueType {
1106 let base_type = unsafe { (*self.raw).basetype };
1107 DataValueType::from_u32(base_type).unwrap()
1108 }
1109
1110 pub fn typedef_name(&self) -> Option<String> {
1112 let typedef = unsafe { (*self.raw).name };
1113 char_ptr_to_opt_string(typedef)
1114 }
1115
1116 pub fn leafref_real_type(&self) -> Option<SchemaLeafType<'_>> {
1119 if self.base_type() != DataValueType::LeafRef {
1120 return None;
1121 }
1122
1123 let leafref = self.raw as *mut ffi::lysc_type_leafref;
1124 let real_type = unsafe { (*leafref).realtype };
1125 let ltype =
1126 unsafe { SchemaLeafType::from_raw(self.context, real_type) };
1127 Some(ltype)
1128 }
1129}
1130
1131unsafe impl<'a> Binding<'a> for SchemaLeafType<'a> {
1132 type CType = ffi::lysc_type;
1133 type Container = Context;
1134
1135 unsafe fn from_raw(
1136 context: &'a Context,
1137 raw: *mut ffi::lysc_type,
1138 ) -> SchemaLeafType<'a> {
1139 SchemaLeafType { context, raw }
1140 }
1141}
1142
1143unsafe impl Send for SchemaLeafType<'_> {}
1144unsafe impl Sync for SchemaLeafType<'_> {}
1145
1146impl<'a> SchemaExtInstance<'a> {
1149 pub fn as_raw(&self) -> *mut ffi::lysc_ext_instance {
1152 self.raw
1153 }
1154
1155 pub fn argument(&self) -> Option<String> {
1157 let argument = unsafe { (*self.raw).argument };
1158 char_ptr_to_opt_string(argument)
1159 }
1160
1161 pub fn new_path(
1176 &self,
1177 path: &str,
1178 value: Option<&str>,
1179 output: bool,
1180 ) -> Result<Option<DataTree<'a>>> {
1181 let path = CString::new(path).unwrap();
1182 let mut rnode = std::ptr::null_mut();
1183 let rnode_ptr = &mut rnode;
1184 let value_cstr;
1185
1186 let value_ptr = match value {
1187 Some(value) => {
1188 value_cstr = CString::new(value).unwrap();
1189 value_cstr.as_ptr()
1190 }
1191 None => std::ptr::null(),
1192 };
1193
1194 let mut options = ffi::LYD_NEW_PATH_UPDATE;
1195 if output {
1196 options |= ffi::LYD_NEW_VAL_OUTPUT;
1197 }
1198
1199 let ret = unsafe {
1200 ffi::lyd_new_ext_path(
1201 std::ptr::null_mut(),
1202 self.raw,
1203 path.as_ptr(),
1204 value_ptr as *const c_void,
1205 options,
1206 rnode_ptr,
1207 )
1208 };
1209 if ret != ffi::LY_ERR::LY_SUCCESS {
1210 return Err(Error::new(self.context));
1211 }
1212
1213 Ok(unsafe { DataTree::from_raw_opt(self.context, rnode) })
1214 }
1215
1216 pub fn new_inner(&self, name: &str) -> Result<DataTree<'a>> {
1221 let name_cstr = CString::new(name).unwrap();
1222 let mut rnode = std::ptr::null_mut();
1223 let rnode_ptr = &mut rnode;
1224
1225 let ret = unsafe {
1226 ffi::lyd_new_ext_inner(self.raw, name_cstr.as_ptr(), rnode_ptr)
1227 };
1228 if ret != ffi::LY_ERR::LY_SUCCESS {
1229 return Err(Error::new(self.context));
1230 }
1231
1232 Ok(unsafe { DataTree::from_raw(self.context, rnode) })
1233 }
1234}
1235
1236unsafe impl<'a> Binding<'a> for SchemaExtInstance<'a> {
1237 type CType = ffi::lysc_ext_instance;
1238 type Container = Context;
1239
1240 unsafe fn from_raw(
1241 context: &'a Context,
1242 raw: *mut ffi::lysc_ext_instance,
1243 ) -> SchemaExtInstance<'a> {
1244 SchemaExtInstance { context, raw }
1245 }
1246}
1247
1248unsafe impl Send for SchemaExtInstance<'_> {}
1249unsafe impl Sync for SchemaExtInstance<'_> {}
1250
1251impl DataValue {
1254 pub(crate) unsafe fn from_raw(
1255 context: &Context,
1256 raw: *const ffi::lyd_value,
1257 ) -> DataValue {
1258 let rtype = (*(*raw).realtype).basetype;
1259 match rtype {
1260 ffi::LY_DATA_TYPE::LY_TYPE_UINT8 => {
1261 let value = (*raw).__bindgen_anon_1.uint8;
1262 DataValue::Uint8(value)
1263 }
1264 ffi::LY_DATA_TYPE::LY_TYPE_UINT16 => {
1265 let value = (*raw).__bindgen_anon_1.uint16;
1266 DataValue::Uint16(value)
1267 }
1268 ffi::LY_DATA_TYPE::LY_TYPE_UINT32 => {
1269 let value = (*raw).__bindgen_anon_1.uint32;
1270 DataValue::Uint32(value)
1271 }
1272 ffi::LY_DATA_TYPE::LY_TYPE_UINT64 => {
1273 let value = (*raw).__bindgen_anon_1.uint64;
1274 DataValue::Uint64(value)
1275 }
1276 ffi::LY_DATA_TYPE::LY_TYPE_BOOL => {
1277 let value = (*raw).__bindgen_anon_1.boolean != 0;
1278 DataValue::Bool(value)
1279 }
1280 ffi::LY_DATA_TYPE::LY_TYPE_INT8 => {
1281 let value = (*raw).__bindgen_anon_1.int8;
1282 DataValue::Int8(value)
1283 }
1284 ffi::LY_DATA_TYPE::LY_TYPE_INT16 => {
1285 let value = (*raw).__bindgen_anon_1.int16;
1286 DataValue::Int16(value)
1287 }
1288 ffi::LY_DATA_TYPE::LY_TYPE_INT32 => {
1289 let value = (*raw).__bindgen_anon_1.int32;
1290 DataValue::Int32(value)
1291 }
1292 ffi::LY_DATA_TYPE::LY_TYPE_INT64 => {
1293 let value = (*raw).__bindgen_anon_1.int64;
1294 DataValue::Int64(value)
1295 }
1296 _ => {
1297 let mut canonical = (*raw)._canonical;
1298 if canonical.is_null() {
1299 canonical = ffi::lyd_value_get_canonical(context.raw, raw);
1300 }
1301 DataValue::Other(char_ptr_to_string(canonical))
1302 }
1303 }
1304 }
1305}