Skip to main content

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}