Skip to main content

zerodds_ast/
kind.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! Node kind discriminators.
4//!
5//! The tag numbers are part of the snapshot format (spec §9) — never
6//! renumber an existing variant, only append.
7
8use zerodds_ast_core::NodeKindTag;
9
10/// Every kind of node the model holds. Spec §3.
11///
12/// Exhaustive on purpose. An adapter presenting the model to another
13/// system has to name every kind; with a catch-all arm a kind added here
14/// would become a construct that system can never see, and nothing would
15/// say so. Adding a variant is a compile error at every such consumer,
16/// which is the point.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
18pub enum NodeKind {
19    /// A namespace. Spec §3.1.
20    Module,
21    /// A named type. Spec §3.2.
22    Type,
23    /// A field of an aggregate. Spec §3.3.
24    Member,
25    /// One `case` of a union. Spec §3.3.
26    Case,
27    /// One enumerator. Spec §3.3.
28    Enumerator,
29    /// One bitmask bit. Spec §3.3.
30    BitValue,
31    /// One bitset field. Spec §3.3.
32    Bitfield,
33    /// A named constant. Spec §3.5.
34    Const,
35    /// One node of a constant expression tree. Spec §3.5.
36    ConstExpr,
37    /// An interface or component form. Spec §3.4.
38    Interface,
39    /// An operation. Spec §3.4.
40    Operation,
41    /// An operation parameter. Spec §3.4.
42    Param,
43    /// An interface attribute. Spec §3.4.
44    Attribute,
45    /// An exception. Spec §3.4.
46    Exception,
47    /// An `@annotation` declaration. Spec §3.6.
48    AnnotationDef,
49    /// A member of an annotation declaration. Spec §3.6.
50    AnnotationMember,
51    /// A DDS domain. Spec §3.7.
52    Domain,
53    /// A topic. Spec §3.7.
54    Topic,
55    /// A QoS profile. Spec §3.7.
56    QosProfile,
57    /// A domain participant. Spec §3.7.
58    Participant,
59    /// A reader or writer endpoint. Spec §3.7.
60    Endpoint,
61    /// A deployment library. Spec §3.7.
62    Library,
63}
64
65impl NodeKind {
66    /// Every kind, in tag order. Lets a conformance test assert that the
67    /// tag mapping is total and collision-free.
68    pub const ALL: [Self; 22] = [
69        Self::Module,
70        Self::Type,
71        Self::Member,
72        Self::Case,
73        Self::Enumerator,
74        Self::BitValue,
75        Self::Bitfield,
76        Self::Const,
77        Self::ConstExpr,
78        Self::Interface,
79        Self::Operation,
80        Self::Param,
81        Self::Attribute,
82        Self::Exception,
83        Self::AnnotationDef,
84        Self::AnnotationMember,
85        Self::Domain,
86        Self::Topic,
87        Self::QosProfile,
88        Self::Participant,
89        Self::Endpoint,
90        Self::Library,
91    ];
92
93    /// Wire tag for changesets and snapshots.
94    #[must_use]
95    pub const fn tag(self) -> NodeKindTag {
96        NodeKindTag(match self {
97            Self::Module => 1,
98            Self::Type => 2,
99            Self::Member => 3,
100            Self::Case => 4,
101            Self::Enumerator => 5,
102            Self::BitValue => 6,
103            Self::Bitfield => 7,
104            Self::Const => 8,
105            Self::ConstExpr => 9,
106            Self::Interface => 10,
107            Self::Operation => 11,
108            Self::Param => 12,
109            Self::Attribute => 13,
110            Self::Exception => 14,
111            Self::AnnotationDef => 15,
112            Self::AnnotationMember => 16,
113            Self::Domain => 17,
114            Self::Topic => 18,
115            Self::QosProfile => 19,
116            Self::Participant => 20,
117            Self::Endpoint => 21,
118            Self::Library => 22,
119        })
120    }
121
122    /// Inverse of [`NodeKind::tag`].
123    #[must_use]
124    pub const fn from_tag(tag: NodeKindTag) -> Option<Self> {
125        Some(match tag.0 {
126            1 => Self::Module,
127            2 => Self::Type,
128            3 => Self::Member,
129            4 => Self::Case,
130            5 => Self::Enumerator,
131            6 => Self::BitValue,
132            7 => Self::Bitfield,
133            8 => Self::Const,
134            9 => Self::ConstExpr,
135            10 => Self::Interface,
136            11 => Self::Operation,
137            12 => Self::Param,
138            13 => Self::Attribute,
139            14 => Self::Exception,
140            15 => Self::AnnotationDef,
141            16 => Self::AnnotationMember,
142            17 => Self::Domain,
143            18 => Self::Topic,
144            19 => Self::QosProfile,
145            20 => Self::Participant,
146            21 => Self::Endpoint,
147            22 => Self::Library,
148            _ => return None,
149        })
150    }
151
152    /// Short name, for diagnostics and `BreakCause::KindMismatch`.
153    #[must_use]
154    pub const fn as_str(self) -> &'static str {
155        match self {
156            Self::Module => "module",
157            Self::Type => "type",
158            Self::Member => "member",
159            Self::Case => "case",
160            Self::Enumerator => "enumerator",
161            Self::BitValue => "bit value",
162            Self::Bitfield => "bitfield",
163            Self::Const => "constant",
164            Self::ConstExpr => "constant expression",
165            Self::Interface => "interface",
166            Self::Operation => "operation",
167            Self::Param => "parameter",
168            Self::Attribute => "attribute",
169            Self::Exception => "exception",
170            Self::AnnotationDef => "annotation",
171            Self::AnnotationMember => "annotation member",
172            Self::Domain => "domain",
173            Self::Topic => "topic",
174            Self::QosProfile => "QoS profile",
175            Self::Participant => "participant",
176            Self::Endpoint => "endpoint",
177            Self::Library => "library",
178        }
179    }
180}