zerodds_ast/facet/corba.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! CORBA and component-model information. Spec §4.2.
4
5use crate::facet::applied::AppliedArgument;
6use crate::node::constant::ConstExprNode;
7use crate::node::interface::InterfaceNode;
8use crate::node::type_::TypeNode;
9use alloc::string::String;
10use alloc::vec::Vec;
11use zerodds_ast_core::{Id, Ref, RepositoryId};
12
13/// How a repository identifier was arrived at.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum RepositoryIdOrigin {
16 /// Derived from the scoped name by the default rule.
17 Derived,
18 /// Influenced by `#pragma prefix`.
19 PragmaPrefix,
20 /// Influenced by `#pragma version`.
21 PragmaVersion,
22 /// Set outright by `#pragma ID`.
23 PragmaId,
24}
25
26/// The role a declaration plays in the CORBA component model.
27///
28/// Carried here rather than as core node kinds, so that CCM support does
29/// not widen the type space every consumer has to match on. Spec §3.4.
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub enum ComponentRole {
32 /// `provides` — a facet the component offers.
33 Facet {
34 /// Port name.
35 name: String,
36 /// Interface offered.
37 interface: Ref<InterfaceNode>,
38 },
39 /// `uses` — a receptacle the component consumes.
40 Receptacle {
41 /// Port name.
42 name: String,
43 /// Interface consumed.
44 interface: Ref<InterfaceNode>,
45 /// Whether the receptacle accepts multiple connections.
46 multiple: bool,
47 },
48 /// `publishes` or `emits` — an event source.
49 EventSource {
50 /// Port name.
51 name: String,
52 /// Event type.
53 event: Ref<TypeNode>,
54 /// `publishes` when true, `emits` when false.
55 publisher: bool,
56 },
57 /// `consumes` — an event sink.
58 EventSink {
59 /// Port name.
60 name: String,
61 /// Event type.
62 event: Ref<TypeNode>,
63 },
64 /// A `home` factory operation.
65 HomeFactory,
66 /// A `home` finder operation.
67 HomeFinder,
68 /// A member of a `porttype` declaration.
69 PortTypeRole,
70 /// A member of a `connector` declaration.
71 ConnectorRole,
72}
73
74/// Whether a valuetype state member is `public` or `private`.
75///
76/// IDL 4.2 §7.4.4, rule (106): a state member is written with one of the
77/// two keywords and there is no third option, so the model records which
78/// one rather than reconstructing it. CCM 4.0 §6.7.2 forbids a private
79/// state member in a primary-key valuetype, which is a rule that cannot
80/// be checked at all if the keyword is dropped at lowering.
81///
82/// Here rather than on [`crate::MemberNode`]: DDS-XTypes has no
83/// valuetypes and so no visibility, and a struct member has none either.
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
85pub enum StateVisibility {
86 /// `public` — part of the marshalled state and readable.
87 Public,
88 /// `private` — part of the marshalled state, not readable.
89 Private,
90}
91
92impl StateVisibility {
93 /// Both forms rule (106) defines.
94 pub const ALL: [Self; 2] = [Self::Public, Self::Private];
95
96 /// Source spelling.
97 #[must_use]
98 pub const fn as_str(self) -> &'static str {
99 match self {
100 Self::Public => "public",
101 Self::Private => "private",
102 }
103 }
104}
105
106/// Kind of a template module formal parameter. IDL 4.2 §7.4.15.
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
108pub enum TemplateParamKind {
109 /// `typename`
110 TypeName,
111 /// `const <type>`
112 Const,
113 /// `sequence`
114 Sequence,
115 /// `interface`
116 Interface,
117 /// `valuetype`
118 ValueType,
119 /// `eventtype`
120 EventType,
121 /// `struct`
122 Struct,
123 /// `union`
124 Union,
125 /// `exception`
126 Exception,
127 /// `enum`
128 Enum,
129}
130
131impl TemplateParamKind {
132 /// Every kind IDL 4.2 §7.4.15 defines, in specification order.
133 ///
134 /// The order is the snapshot's tag numbering, so a kind is appended
135 /// rather than inserted.
136 pub const ALL: [Self; 10] = [
137 Self::TypeName,
138 Self::Const,
139 Self::Sequence,
140 Self::Interface,
141 Self::ValueType,
142 Self::EventType,
143 Self::Struct,
144 Self::Union,
145 Self::Exception,
146 Self::Enum,
147 ];
148}
149
150/// One formal parameter of a template module.
151#[derive(Debug, Clone, PartialEq, Eq)]
152pub struct TemplateParam {
153 /// Parameter name.
154 pub name: String,
155 /// What kind of entity it stands for.
156 pub kind: TemplateParamKind,
157 /// Constraining type, for `const` and constrained parameters.
158 pub constraint: Option<Ref<TypeNode>>,
159}
160
161/// One actual argument of a template module instantiation.
162#[derive(Debug, Clone, PartialEq, Eq)]
163pub enum TemplateArg {
164 /// A type argument.
165 Type(Ref<TypeNode>),
166 /// A constant argument.
167 Const(Id<ConstExprNode>),
168}
169
170/// CORBA information attached to a node. Spec §4.2.
171#[derive(Debug, Clone, Default, PartialEq, Eq)]
172pub struct CorbaFacet {
173 /// Repository identifier.
174 pub repository_id: Option<RepositoryId>,
175 /// How that identifier was arrived at.
176 pub repository_id_origin: Option<RepositoryIdOrigin>,
177 /// Component-model role, for CCM declarations.
178 pub component_role: Option<ComponentRole>,
179 /// Interfaces named by a `supports` clause.
180 ///
181 /// A `component`, `home` or `connector` writes two inheritance
182 /// clauses — `: Base` and `supports I1, I2` — and they mean different
183 /// things: CCM 4.0 §6.3.2 adds `Components::CCMObject` only when
184 /// there is no base, and adds every supported interface on top of
185 /// whichever base applies. Merging both into
186 /// [`crate::InterfaceNode::bases`] would make the two
187 /// indistinguishable and the §6.3.2 mapping unwritable.
188 ///
189 /// A valuetype's `supports` lives in
190 /// [`crate::TypeKind::Valuetype::supported`]; this is the interface
191 /// side of the same clause.
192 pub supports: Vec<Ref<InterfaceNode>>,
193 /// `public` or `private`, on a valuetype state member.
194 pub state_visibility: Option<StateVisibility>,
195 /// Whether the declaration was written `eventtype` rather than
196 /// `valuetype`. IDL 4.2 §7.4.7, rule (166).
197 ///
198 /// The two lower to the same kind of node — an eventtype is a
199 /// valuetype with an extra rule attached — and the keyword is the
200 /// only thing that tells them apart. CCM 4.0 §6.6.1.1 maps an
201 /// eventtype onto a valuetype deriving from
202 /// `Components::EventBase` plus a `<E>Consumer` interface, and maps
203 /// a plain valuetype onto neither, so dropping the keyword makes the
204 /// clause unapplicable.
205 pub is_event_type: bool,
206 /// Formal parameters, on a template module.
207 pub template_params: Vec<TemplateParam>,
208 /// Actual arguments, on a template module instantiation.
209 pub template_args: Vec<TemplateArg>,
210 /// Mapping hint for a `native` declaration.
211 pub native_mapping: Option<String>,
212 /// `@service`, marking an interface as a service. IDL 4.2 §8.3.4.
213 pub is_service: bool,
214 /// The arguments written on that `@service`, in source order.
215 ///
216 /// Kept whole rather than folded into one named field because the two
217 /// specifications that read this annotation disagree about what its
218 /// argument means: IDL 4.2 §8.3.4 declares it `string platform
219 /// default "*"`, and DDS-RPC 1.0 §7.3 reads a service name from the
220 /// same place. Choosing one here would make the other unwritable.
221 ///
222 /// Empty for the bare `@service`. Before this field existed the
223 /// arguments were discarded on the way in, which made `@service` and
224 /// `@service(name = "X")` indistinguishable to every consumer.
225 pub service_arguments: Vec<AppliedArgument>,
226 /// `@ami`, requesting the asynchronous method invocation mapping.
227 /// IDL 4.2 §8.3.5.
228 pub is_ami: bool,
229 /// What a `home` manages, and the key it does so by.
230 /// IDL 4.2 §7.4.9.
231 pub manages: Option<HomeManages>,
232 /// `import` directives, as written. IDL 4.2 §7.4.13.
233 pub imports: Vec<String>,
234 /// `typeid` and `typeprefix` directives, as written. IDL 4.2 §7.4.14.
235 ///
236 /// The directives leave no declaration of their own: `typeid` writes a
237 /// repository id onto its target and `typeprefix` seeds one, so the
238 /// target nodes carry no mark that the file used one. DDS-RPC 1.0
239 /// §7.3.1.1 removes `<type_id_dcl>` and `<type_prefix_dcl>` from the
240 /// service-definition grammar, so the RPC layer has to be able to see
241 /// that a service definition used one. Kept on the root module
242 /// because the directives are file-scoped.
243 pub repository_directives: Vec<String>,
244}
245
246/// A home's `manages X primarykey K` clause.
247#[derive(Debug, Clone, PartialEq, Eq)]
248pub struct HomeManages {
249 /// The component the home manages.
250 pub component: Ref<InterfaceNode>,
251 /// The primary key type, when one was named.
252 pub primary_key: Option<Ref<TypeNode>>,
253}