1use std::fmt;
12use std::marker::PhantomData;
13use std::ptr;
14
15use crate::types::{Access, BaseType, ByteOffset, Kind, Language, Span, Status};
16
17use super::capability::CapabilityData;
18use super::compliance::ComplianceData;
19use super::group::GroupData;
20use super::mib::Mib;
21use super::module::ModuleData;
22use super::node::NodeData;
23use super::notification::NotificationData;
24use super::object::ObjectData;
25use super::typedef::TypeData;
26use super::types::*;
27
28macro_rules! define_handle {
29 ($name:ident, $id:ident, $data:ident, $getter:ident) => {
30 #[derive(Clone, Copy)]
31 #[doc = concat!("Borrowed handle to a resolved [`", stringify!($data), "`].")]
32 pub struct $name<'a> {
37 pub(crate) mib: &'a Mib,
38 pub(crate) id: $id,
39 }
40
41 impl<'a> $name<'a> {
42 pub(crate) fn new(mib: &'a Mib, id: $id) -> Self {
43 Self { mib, id }
44 }
45
46 pub(crate) fn data(self) -> &'a $data {
47 self.mib.$getter(self.id)
48 }
49
50 pub fn id(self) -> $id {
55 self.id
56 }
57 }
58
59 impl PartialEq for $name<'_> {
60 fn eq(&self, other: &Self) -> bool {
61 self.id == other.id && ptr::eq(self.mib, other.mib)
62 }
63 }
64
65 impl Eq for $name<'_> {}
66
67 impl fmt::Debug for $name<'_> {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 f.debug_struct(stringify!($name))
70 .field("id", &self.id)
71 .field("name", &self.data().name())
72 .finish()
73 }
74 }
75 };
76}
77
78define_handle!(Module, ModuleId, ModuleData, module_data);
79define_handle!(Object, ObjectId, ObjectData, object_data);
80define_handle!(Type, TypeId, TypeData, type_data);
81define_handle!(
82 Notification,
83 NotificationId,
84 NotificationData,
85 notification_data
86);
87define_handle!(Group, GroupId, GroupData, group_data);
88define_handle!(Compliance, ComplianceId, ComplianceData, compliance_data);
89define_handle!(Capability, CapabilityId, CapabilityData, capability_data);
90
91#[derive(Clone, Copy)]
101pub struct Node<'a> {
102 pub(crate) mib: &'a Mib,
103 pub(crate) id: NodeId,
104}
105
106impl<'a> Node<'a> {
107 pub(crate) fn new(mib: &'a Mib, id: NodeId) -> Self {
108 Self { mib, id }
109 }
110
111 pub(crate) fn data(self) -> &'a NodeData {
112 self.mib.node_data(self.id)
113 }
114
115 pub fn id(self) -> NodeId {
117 self.id
118 }
119
120 pub fn arc(self) -> u32 {
122 self.data().arc()
123 }
124
125 pub fn name(self) -> &'a str {
127 self.data().name()
128 }
129
130 pub fn description(self) -> &'a str {
132 self.data().description()
133 }
134
135 pub fn reference(self) -> &'a str {
137 self.data().reference()
138 }
139
140 pub fn status(self) -> Option<Status> {
142 self.data().status()
143 }
144
145 pub fn kind(self) -> Kind {
147 self.data().kind()
148 }
149
150 pub fn span(self) -> Span {
152 self.data().span()
153 }
154
155 pub fn oid(self) -> &'a super::oid::Oid {
157 self.mib.tree().oid_of(self.id)
158 }
159
160 pub fn parent(self) -> Option<Node<'a>> {
162 self.data().parent().map(|id| Node::new(self.mib, id))
163 }
164
165 pub fn module(self) -> Option<Module<'a>> {
170 self.mib
171 .effective_module(self.id)
172 .map(|id| Module::new(self.mib, id))
173 }
174
175 pub fn object(self) -> Option<Object<'a>> {
177 self.data().object().map(|id| Object::new(self.mib, id))
178 }
179
180 pub fn notification(self) -> Option<Notification<'a>> {
182 self.data()
183 .notification()
184 .map(|id| Notification::new(self.mib, id))
185 }
186
187 pub fn group(self) -> Option<Group<'a>> {
189 self.data().group().map(|id| Group::new(self.mib, id))
190 }
191
192 pub fn compliance(self) -> Option<Compliance<'a>> {
194 self.data()
195 .compliance()
196 .map(|id| Compliance::new(self.mib, id))
197 }
198
199 pub fn capability(self) -> Option<Capability<'a>> {
201 self.data()
202 .capability()
203 .map(|id| Capability::new(self.mib, id))
204 }
205
206 pub fn children(self) -> impl Iterator<Item = Node<'a>> + 'a {
208 self.data()
209 .children()
210 .values()
211 .copied()
212 .map(|id| Node::new(self.mib, id))
213 }
214
215 pub fn subtree(self) -> impl Iterator<Item = Node<'a>> + 'a {
217 self.mib.subtree(self.id).map(|id| Node::new(self.mib, id))
218 }
219}
220
221impl PartialEq for Node<'_> {
222 fn eq(&self, other: &Self) -> bool {
223 self.id == other.id && ptr::eq(self.mib, other.mib)
224 }
225}
226
227impl Eq for Node<'_> {}
228
229impl fmt::Debug for Node<'_> {
230 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231 f.debug_struct("Node")
232 .field("id", &self.id)
233 .field("name", &self.data().name())
234 .field("kind", &self.data().kind())
235 .finish()
236 }
237}
238
239#[derive(Clone, Copy)]
246pub struct Index<'a> {
247 mib: &'a Mib,
248 row_id: ObjectId,
249 entry: &'a IndexEntry,
250}
251
252impl<'a> Index<'a> {
253 fn new(mib: &'a Mib, row_id: ObjectId, entry: &'a IndexEntry) -> Self {
254 Self { mib, row_id, entry }
255 }
256
257 pub fn row(self) -> Object<'a> {
259 Object::new(self.mib, self.row_id)
260 }
261
262 pub fn object(self) -> Option<Object<'a>> {
264 self.entry.object.map(|id| Object::new(self.mib, id))
265 }
266
267 pub fn name(self) -> &'a str {
272 &self.entry.name
273 }
274
275 pub fn ty(self) -> Option<Type<'a>> {
277 self.entry.type_id.map(|id| Type::new(self.mib, id))
278 }
279
280 pub fn implied(self) -> bool {
282 self.entry.implied
283 }
284
285 pub fn encoding(self) -> crate::types::IndexEncoding {
287 self.entry.encoding
288 }
289
290 pub fn fixed_size(self) -> (usize, bool) {
296 match self.entry.encoding {
297 crate::types::IndexEncoding::Integer => (1, true),
298 crate::types::IndexEncoding::IpAddress => (4, true),
299 crate::types::IndexEncoding::FixedString => {
300 if let Some(obj) = self.object() {
301 let sizes = obj.effective_sizes();
302 if super::types::is_fixed_size(sizes) {
303 return (sizes[0].min as usize, true);
304 }
305 }
306 (0, false)
307 }
308 _ => (0, false),
309 }
310 }
311
312 pub fn span(self) -> Span {
314 self.entry.span
315 }
316
317 pub fn entry(self) -> &'a IndexEntry {
321 self.entry
322 }
323}
324
325impl<'a> Module<'a> {
326 pub fn name(self) -> &'a str {
328 self.data().name()
329 }
330
331 pub fn language(self) -> Language {
333 self.data().language()
334 }
335
336 pub fn source_path(self) -> &'a str {
338 self.data().source_path()
339 }
340
341 pub fn organization(self) -> &'a str {
343 self.data().organization()
344 }
345
346 pub fn contact_info(self) -> &'a str {
348 self.data().contact_info()
349 }
350
351 pub fn description(self) -> &'a str {
353 self.data().description()
354 }
355
356 pub fn last_updated(self) -> &'a str {
358 self.data().last_updated()
359 }
360
361 pub fn revisions(self) -> &'a [super::types::Revision] {
363 self.data().revisions()
364 }
365
366 pub fn imports(self) -> &'a [super::types::Import] {
368 self.data().imports()
369 }
370
371 pub fn is_base(self) -> bool {
379 self.data().is_base()
380 }
381
382 pub fn oid(self) -> Option<&'a super::oid::Oid> {
384 self.data().oid()
385 }
386
387 pub fn line_col(self, offset: ByteOffset) -> (usize, usize) {
389 self.data().line_col(offset)
390 }
391
392 pub fn imports_symbol(self, name: &str) -> bool {
394 self.data().imports_symbol(name)
395 }
396
397 pub fn import_source(self, name: &str) -> Option<Module<'a>> {
399 self.data()
400 .import_source(name)
401 .map(|id| Module::new(self.mib, id))
402 }
403
404 pub fn object(self, name: &str) -> Option<Object<'a>> {
406 self.data()
407 .object_by_name(name)
408 .map(|id| Object::new(self.mib, id))
409 }
410
411 pub fn r#type(self, name: &str) -> Option<Type<'a>> {
413 self.data()
414 .type_by_name(name)
415 .map(|id| Type::new(self.mib, id))
416 }
417
418 pub fn node(self, name: &str) -> Option<Node<'a>> {
420 self.data()
421 .node_by_name(name)
422 .map(|id| Node::new(self.mib, id))
423 }
424
425 pub fn notification(self, name: &str) -> Option<Notification<'a>> {
427 self.data()
428 .notification_by_name(name)
429 .map(|id| Notification::new(self.mib, id))
430 }
431
432 pub fn group(self, name: &str) -> Option<Group<'a>> {
434 self.data()
435 .group_by_name(name)
436 .map(|id| Group::new(self.mib, id))
437 }
438
439 pub fn compliance(self, name: &str) -> Option<Compliance<'a>> {
441 self.data()
442 .compliance_by_name(name)
443 .map(|id| Compliance::new(self.mib, id))
444 }
445
446 pub fn capability(self, name: &str) -> Option<Capability<'a>> {
448 self.data()
449 .capability_by_name(name)
450 .map(|id| Capability::new(self.mib, id))
451 }
452
453 pub fn objects(self) -> impl Iterator<Item = Object<'a>> + 'a {
455 self.data()
456 .objects()
457 .iter()
458 .copied()
459 .map(|id| Object::new(self.mib, id))
460 }
461
462 pub fn types(self) -> impl Iterator<Item = Type<'a>> + 'a {
464 self.data()
465 .types()
466 .iter()
467 .copied()
468 .map(|id| Type::new(self.mib, id))
469 }
470
471 pub fn nodes(self) -> impl Iterator<Item = Node<'a>> + 'a {
473 self.data()
474 .nodes()
475 .iter()
476 .copied()
477 .map(|id| Node::new(self.mib, id))
478 }
479}
480
481impl<'a> Object<'a> {
482 pub fn name(self) -> &'a str {
484 self.data().name()
485 }
486
487 pub fn span(self) -> Span {
489 self.data().span()
490 }
491
492 pub fn module(self) -> Option<Module<'a>> {
494 self.data().module().map(|id| Module::new(self.mib, id))
495 }
496
497 pub fn node(self) -> Node<'a> {
504 Node::new(
505 self.mib,
506 self.data().node().expect("resolved object missing node"),
507 )
508 }
509
510 pub fn status(self) -> Status {
512 self.data().status()
513 }
514
515 pub fn description(self) -> &'a str {
517 self.data().description()
518 }
519
520 pub fn reference(self) -> &'a str {
522 self.data().reference()
523 }
524
525 pub fn ty(self) -> Option<Type<'a>> {
527 self.data().type_id().map(|id| Type::new(self.mib, id))
528 }
529
530 pub fn access(self) -> Access {
532 self.data().access()
533 }
534
535 pub fn units(self) -> &'a str {
537 self.data().units()
538 }
539
540 pub fn default_value(self) -> Option<&'a DefVal> {
542 self.data().default_value()
543 }
544
545 pub fn kind(self) -> Kind {
547 self.data().kind(self.mib.tree())
548 }
549
550 pub fn effective_display_hint(self) -> &'a str {
552 self.data().effective_display_hint()
553 }
554
555 pub fn effective_sizes(self) -> &'a [Range] {
557 self.data().effective_sizes()
558 }
559
560 pub fn effective_ranges(self) -> &'a [Range] {
562 self.data().effective_ranges()
563 }
564
565 pub fn effective_enums(self) -> &'a [NamedValue] {
567 self.data().effective_enums()
568 }
569
570 pub fn effective_bits(self) -> &'a [NamedValue] {
572 self.data().effective_bits()
573 }
574
575 pub fn parsed_display_hint(self) -> Option<super::display_hint::DisplayHint> {
581 let hint = self.data().effective_display_hint();
582 if hint.is_empty() {
583 return None;
584 }
585 super::display_hint::DisplayHint::parse(hint)
586 }
587
588 pub fn format_integer(
593 self,
594 value: i64,
595 hex_case: super::display_hint::HexCase,
596 ) -> Option<String> {
597 let hint = self.data().effective_display_hint();
598 if hint.is_empty() {
599 return None;
600 }
601 super::display_hint::format_integer(hint, value, hex_case)
602 }
603
604 pub fn scale_integer(self, value: i64) -> Option<f64> {
610 let hint = self.data().effective_display_hint();
611 if hint.is_empty() {
612 return None;
613 }
614 super::display_hint::scale_integer(hint, value)
615 }
616
617 pub fn format_octets(
622 self,
623 data: &[u8],
624 hex_case: super::display_hint::HexCase,
625 ) -> Option<String> {
626 let hint = self.data().effective_display_hint();
627 if hint.is_empty() {
628 return None;
629 }
630 super::display_hint::format_octets(hint, data, hex_case)
631 }
632
633 pub fn table(self) -> Option<Object<'a>> {
637 self.mib
638 .object_table(self.id)
639 .map(|id| Object::new(self.mib, id))
640 }
641
642 pub fn row(self) -> Option<Object<'a>> {
647 self.mib
648 .object_row(self.id)
649 .map(|id| Object::new(self.mib, id))
650 }
651
652 pub fn columns(self) -> impl Iterator<Item = Object<'a>> + 'a {
656 self.mib
657 .object_columns(self.id)
658 .into_iter()
659 .map(|id| Object::new(self.mib, id))
660 }
661
662 pub fn augments(self) -> Option<Object<'a>> {
664 self.data().augments().map(|id| Object::new(self.mib, id))
665 }
666
667 pub fn augmented_by(self) -> impl Iterator<Item = Object<'a>> + 'a {
669 self.data()
670 .augmented_by()
671 .iter()
672 .copied()
673 .map(|id| Object::new(self.mib, id))
674 }
675
676 pub fn index(self) -> impl Iterator<Item = Index<'a>> + 'a {
681 self.data()
682 .index()
683 .iter()
684 .map(move |entry| Index::new(self.mib, self.id, entry))
685 }
686
687 pub fn effective_indexes(self) -> impl Iterator<Item = Index<'a>> + 'a {
693 self.mib
694 .effective_indexes_source(self.id)
695 .into_iter()
696 .flat_map(move |id| {
697 self.mib
698 .object_data(id)
699 .index()
700 .iter()
701 .map(move |entry| Index::new(self.mib, self.id, entry))
702 })
703 }
704
705 pub fn is_table(self) -> bool {
707 self.mib.is_table(self.id)
708 }
709
710 pub fn is_row(self) -> bool {
712 self.mib.is_row(self.id)
713 }
714
715 pub fn is_column(self) -> bool {
717 self.mib.is_column(self.id)
718 }
719
720 pub fn is_scalar(self) -> bool {
722 self.mib.is_scalar(self.id)
723 }
724
725 pub fn is_index(self) -> bool {
727 self.mib.is_index(self.id)
728 }
729}
730
731impl<'a> Type<'a> {
732 pub fn name(self) -> &'a str {
734 self.data().name()
735 }
736
737 pub fn span(self) -> Span {
739 self.data().span()
740 }
741
742 pub fn syntax_span(self) -> Span {
744 self.data().syntax_span()
745 }
746
747 pub fn module(self) -> Option<Module<'a>> {
749 self.data().module().map(|id| Module::new(self.mib, id))
750 }
751
752 pub fn base(self) -> BaseType {
754 self.data().base()
755 }
756
757 pub fn parent(self) -> Option<Type<'a>> {
759 self.data().parent().map(|id| Type::new(self.mib, id))
760 }
761
762 pub fn status(self) -> Status {
764 self.data().status()
765 }
766
767 pub fn display_hint(self) -> &'a str {
769 self.data().display_hint()
770 }
771
772 pub fn description(self) -> &'a str {
774 self.data().description()
775 }
776
777 pub fn reference(self) -> &'a str {
779 self.data().reference()
780 }
781
782 pub fn sizes(self) -> &'a [Range] {
784 self.data().sizes()
785 }
786
787 pub fn ranges(self) -> &'a [Range] {
789 self.data().ranges()
790 }
791
792 pub fn enums(self) -> &'a [NamedValue] {
794 self.data().enums()
795 }
796
797 pub fn bits(self) -> &'a [NamedValue] {
799 self.data().bits()
800 }
801
802 pub fn is_textual_convention(self) -> bool {
804 self.data().is_textual_convention()
805 }
806
807 pub fn effective_tc(self) -> Option<Type<'a>> {
810 if self.data().is_textual_convention() {
811 return Some(self);
812 }
813 self.data()
814 .effective_tc_in_parents(self.mib.types_slice())
815 .map(|id| Type::new(self.mib, id))
816 }
817
818 pub fn effective_base(self) -> BaseType {
823 self.data().effective_base(self.mib.types_slice())
824 }
825
826 pub fn effective_display_hint(self) -> &'a str {
828 self.data().effective_display_hint(self.mib.types_slice())
829 }
830
831 pub fn parsed_display_hint(self) -> Option<super::display_hint::DisplayHint> {
837 let hint = self.data().effective_display_hint(self.mib.types_slice());
838 if hint.is_empty() {
839 return None;
840 }
841 super::display_hint::DisplayHint::parse(hint)
842 }
843
844 pub fn effective_sizes(self) -> &'a [Range] {
846 self.data().effective_sizes(self.mib.types_slice())
847 }
848
849 pub fn effective_ranges(self) -> &'a [Range] {
851 self.data().effective_ranges(self.mib.types_slice())
852 }
853
854 pub fn effective_enums(self) -> &'a [NamedValue] {
856 self.data().effective_enums(self.mib.types_slice())
857 }
858
859 pub fn effective_bits(self) -> &'a [NamedValue] {
861 self.data().effective_bits(self.mib.types_slice())
862 }
863
864 pub fn is_counter(self) -> bool {
866 self.data().is_counter(self.mib.types_slice())
867 }
868
869 pub fn is_gauge(self) -> bool {
871 self.data().is_gauge(self.mib.types_slice())
872 }
873
874 pub fn is_string(self) -> bool {
876 self.data().is_string(self.mib.types_slice())
877 }
878
879 pub fn is_enumeration(self) -> bool {
881 self.data().is_enumeration(self.mib.types_slice())
882 }
883
884 pub fn is_bits(self) -> bool {
886 self.data().is_bits(self.mib.types_slice())
887 }
888}
889
890macro_rules! entity_handle_impl {
891 ($name:ident) => {
892 impl<'a> $name<'a> {
893 pub fn name(self) -> &'a str {
895 self.data().name()
896 }
897
898 pub fn span(self) -> Span {
900 self.data().span()
901 }
902
903 pub fn module(self) -> Option<Module<'a>> {
905 self.data().module().map(|id| Module::new(self.mib, id))
906 }
907
908 pub fn node(self) -> Option<Node<'a>> {
910 self.data().node().map(|id| Node::new(self.mib, id))
911 }
912
913 pub fn status(self) -> Status {
915 self.data().status()
916 }
917
918 pub fn description(self) -> &'a str {
920 self.data().description()
921 }
922
923 pub fn reference(self) -> &'a str {
925 self.data().reference()
926 }
927
928 pub fn oid_refs(self) -> &'a [OidRef] {
930 self.data().oid_refs()
931 }
932 }
933 };
934}
935
936entity_handle_impl!(Notification);
937entity_handle_impl!(Group);
938entity_handle_impl!(Compliance);
939entity_handle_impl!(Capability);
940
941impl<'a> Notification<'a> {
942 pub fn objects(self) -> impl Iterator<Item = Object<'a>> + 'a {
944 self.data()
945 .objects()
946 .iter()
947 .copied()
948 .map(|id| Object::new(self.mib, id))
949 }
950
951 pub fn trap_info(self) -> Option<&'a TrapInfo> {
953 self.data().trap_info()
954 }
955}
956
957impl<'a> Group<'a> {
958 pub fn members(self) -> impl Iterator<Item = Node<'a>> + 'a {
960 self.data()
961 .members()
962 .iter()
963 .copied()
964 .map(|id| Node::new(self.mib, id))
965 }
966
967 pub fn is_notification_group(self) -> bool {
969 self.data().is_notification_group()
970 }
971}
972
973impl<'a> Compliance<'a> {
974 pub fn modules(self) -> &'a [ComplianceModule] {
976 self.data().modules()
977 }
978}
979
980impl<'a> Capability<'a> {
981 pub fn product_release(self) -> &'a str {
983 self.data().product_release()
984 }
985
986 pub fn supports(self) -> &'a [CapabilitiesModule] {
988 self.data().supports()
989 }
990}
991
992pub struct HandleIter<'a, H, I> {
998 mib: &'a Mib,
999 ids: I,
1000 _marker: PhantomData<H>,
1001}
1002
1003impl<'a, H, I> HandleIter<'a, H, I> {
1004 pub(crate) fn new(mib: &'a Mib, ids: I) -> Self {
1005 Self {
1006 mib,
1007 ids,
1008 _marker: PhantomData,
1009 }
1010 }
1011}
1012
1013impl<'a, I> Iterator for HandleIter<'a, Module<'a>, I>
1014where
1015 I: Iterator<Item = ModuleId>,
1016{
1017 type Item = Module<'a>;
1018
1019 fn next(&mut self) -> Option<Self::Item> {
1020 self.ids.next().map(|id| Module::new(self.mib, id))
1021 }
1022}
1023
1024impl<'a, I> Iterator for HandleIter<'a, Object<'a>, I>
1025where
1026 I: Iterator<Item = ObjectId>,
1027{
1028 type Item = Object<'a>;
1029
1030 fn next(&mut self) -> Option<Self::Item> {
1031 self.ids.next().map(|id| Object::new(self.mib, id))
1032 }
1033}
1034
1035impl<'a, I> Iterator for HandleIter<'a, Type<'a>, I>
1036where
1037 I: Iterator<Item = TypeId>,
1038{
1039 type Item = Type<'a>;
1040
1041 fn next(&mut self) -> Option<Self::Item> {
1042 self.ids.next().map(|id| Type::new(self.mib, id))
1043 }
1044}
1045
1046impl<'a, I> Iterator for HandleIter<'a, Node<'a>, I>
1047where
1048 I: Iterator<Item = NodeId>,
1049{
1050 type Item = Node<'a>;
1051
1052 fn next(&mut self) -> Option<Self::Item> {
1053 self.ids.next().map(|id| Node::new(self.mib, id))
1054 }
1055}
1056
1057impl<'a, I> Iterator for HandleIter<'a, Notification<'a>, I>
1058where
1059 I: Iterator<Item = NotificationId>,
1060{
1061 type Item = Notification<'a>;
1062
1063 fn next(&mut self) -> Option<Self::Item> {
1064 self.ids.next().map(|id| Notification::new(self.mib, id))
1065 }
1066}
1067
1068impl<'a, I> Iterator for HandleIter<'a, Group<'a>, I>
1069where
1070 I: Iterator<Item = GroupId>,
1071{
1072 type Item = Group<'a>;
1073
1074 fn next(&mut self) -> Option<Self::Item> {
1075 self.ids.next().map(|id| Group::new(self.mib, id))
1076 }
1077}
1078
1079impl<'a, I> Iterator for HandleIter<'a, Compliance<'a>, I>
1080where
1081 I: Iterator<Item = ComplianceId>,
1082{
1083 type Item = Compliance<'a>;
1084
1085 fn next(&mut self) -> Option<Self::Item> {
1086 self.ids.next().map(|id| Compliance::new(self.mib, id))
1087 }
1088}
1089
1090impl<'a, I> Iterator for HandleIter<'a, Capability<'a>, I>
1091where
1092 I: Iterator<Item = CapabilityId>,
1093{
1094 type Item = Capability<'a>;
1095
1096 fn next(&mut self) -> Option<Self::Item> {
1097 self.ids.next().map(|id| Capability::new(self.mib, id))
1098 }
1099}