Skip to main content

zerodds_idl_parse/
dialect.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! Which dialect the parser accepts. Spec §3.5.
4//!
5//! Strict OMG IDL 4.2 by default. A vendor flag admits that vendor's
6//! extensions, and a construct admitted only by a flag records which
7//! one — so a later validation against `Profile::Idl42Core` can say
8//! that the file is not portable and why.
9
10/// The set of dialects a parse accepts.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
12pub struct Dialect {
13    /// RTI Connext extensions: `keylist`.
14    pub rti: bool,
15    /// Cyclone DDS extensions.
16    pub cyclone: bool,
17    /// eProsima Fast DDS extensions.
18    pub fast_dds: bool,
19    /// OpenDDS extensions.
20    pub open_dds: bool,
21    /// ROS 2 dialect: admits unqualified member types that differ only in case
22    /// from the member name (e.g., `Pose pose;`).
23    pub ros2: bool,
24}
25
26impl Dialect {
27    /// OMG IDL 4.2 and nothing else.
28    ///
29    /// The default, because a file that parses under it is one every
30    /// other vendor's compiler also reads.
31    pub const STRICT: Self = Self {
32        rti: false,
33        cyclone: false,
34        fast_dds: false,
35        open_dds: false,
36        ros2: false,
37    };
38
39    /// Every vendor dialect at once.
40    pub const ALL_VENDORS: Self = Self {
41        rti: true,
42        cyclone: true,
43        fast_dds: true,
44        open_dds: true,
45        ros2: false,
46    };
47
48    /// Whether any vendor extension is admitted.
49    #[must_use]
50    pub const fn any_vendor(self) -> bool {
51        self.rti || self.cyclone || self.fast_dds || self.open_dds || self.ros2
52    }
53
54    /// The name of the flag that admits a construct, for a diagnostic
55    /// that has to say what made a file unportable.
56    #[must_use]
57    pub const fn flag_name(admitted_by: VendorFlag) -> &'static str {
58        match admitted_by {
59            VendorFlag::Rti => "rti",
60            VendorFlag::Cyclone => "cyclone",
61            VendorFlag::FastDds => "fast_dds",
62            VendorFlag::OpenDds => "open_dds",
63            VendorFlag::Ros2 => "ros2",
64        }
65    }
66
67    /// Whether this dialect admits `flag`.
68    #[must_use]
69    pub const fn admits(self, flag: VendorFlag) -> bool {
70        match flag {
71            VendorFlag::Rti => self.rti,
72            VendorFlag::Cyclone => self.cyclone,
73            VendorFlag::FastDds => self.fast_dds,
74            VendorFlag::OpenDds => self.open_dds,
75            VendorFlag::Ros2 => self.ros2,
76        }
77    }
78}
79
80/// One vendor flag, for naming which admitted a construct.
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
82pub enum VendorFlag {
83    /// RTI Connext.
84    Rti,
85    /// Cyclone DDS.
86    Cyclone,
87    /// Fast DDS.
88    FastDds,
89    /// OpenDDS.
90    OpenDds,
91    /// ROS 2 dialect.
92    Ros2,
93}
94
95impl VendorFlag {
96    /// Every flag, so a test can assert the set is complete.
97    pub const ALL: [Self; 5] = [
98        Self::Rti,
99        Self::Cyclone,
100        Self::FastDds,
101        Self::OpenDds,
102        Self::Ros2,
103    ];
104}