1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum Site {
4 Module,
6 Struct,
8 Union,
10 Enum,
12 Bitset,
14 Bitmask,
16 Typedef,
18 Native,
20 Constant,
22 Exception,
24 Member,
26 UnionMember,
28 Enumerator,
30 BitmaskValue,
32 Interface,
34 Operation,
36 Parameter,
38 Attribute,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum ArgumentShape {
45 Marker,
47 Value,
49 OptionalValue,
51 String(&'static [&'static str]),
53 OptionalString(&'static [&'static str]),
55 Lifecycle,
57 Version,
59 ApiKey,
61 Http,
63 Named {
65 required: &'static [&'static str],
67 optional: &'static [&'static str],
69 },
70 Values,
72 Cors,
74 Deprecated,
76 Grammar,
78}
79
80#[derive(Debug, Clone, Copy)]
82pub struct AnnotationDefinition {
83 pub name: &'static str,
85 pub kind: AnnotationKind,
87 pub sites: &'static [Site],
89 pub arguments: ArgumentShape,
91}
92
93impl AnnotationDefinition {
94 pub fn lookup(name: &str) -> Option<&'static Self> {
96 BUILTIN_ANNOTATIONS
97 .iter()
98 .find(|entry| entry.name.eq_ignore_ascii_case(name))
99 }
100
101 pub fn allows(&self, site: Site) -> bool {
103 self.sites.is_empty() || self.sites.contains(&site)
104 }
105
106 pub fn is_passthrough(name: &str) -> bool {
108 let name = name.to_ascii_lowercase();
109 ["rust-", "rust_", "ts-", "ts_"]
110 .iter()
111 .any(|prefix| name.starts_with(prefix))
112 }
113}
114
115macro_rules! annotations {
116 ($($kind:ident, $name:literal, $sites:expr, $args:expr;)+) => {
117 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
119 pub enum AnnotationKind {
120 $(#[doc = concat!("The `@", $name, "` annotation.")] $kind,)+
121 }
122 pub const BUILTIN_ANNOTATIONS: &[AnnotationDefinition] = &[
124 $(AnnotationDefinition { name: $name, kind: AnnotationKind::$kind,
125 sites: $sites, arguments: $args },)+
126 ];
127 };
128}
129
130use ArgumentShape::*;
131use Site::*;
132
133const TYPES: &[Site] = &[
134 Struct, Union, Enum, Bitset, Bitmask, Typedef, Native, Exception,
135];
136const FIELDS: &[Site] = &[Member, UnionMember, Parameter];
137const SECURITY: &[Site] = &[Interface, Operation, Attribute];
138const LIFECYCLE: &[Site] = &[
139 Module,
140 Struct,
141 Union,
142 Enum,
143 Bitset,
144 Bitmask,
145 Typedef,
146 Native,
147 Exception,
148 Member,
149 UnionMember,
150 Enumerator,
151 BitmaskValue,
152 Interface,
153 Operation,
154 Parameter,
155 Attribute,
156];
157
158annotations! {
159 Id, "id", &[Member, UnionMember], Grammar;
160 AutoId, "autoid", &[Module, Struct, Union, Exception], Grammar;
161 Optional, "optional", FIELDS, OptionalValue;
162 Position, "position", &[BitmaskValue], Grammar;
163 Value, "value", &[Enumerator], Grammar;
164 Extensibility, "extensibility", TYPES, Grammar;
165 Final, "final", TYPES, Marker;
166 Appendable, "appendable", TYPES, Marker;
167 Mutable, "mutable", TYPES, Marker;
168 Key, "key", &[Member, UnionMember], OptionalValue;
169 MustUnderstand, "must_understand", &[Member, UnionMember], OptionalValue;
170 DefaultLiteral, "default_literal", &[Enumerator], Marker;
171 Default, "default", FIELDS, Value;
172 Range, "range", FIELDS, Named { required: &["min", "max"], optional: &[] };
173 Min, "min", FIELDS, Value;
174 Max, "max", FIELDS, Value;
175 Unit, "unit", FIELDS, Value;
176 BitBound, "bit_bound", &[Enum, Bitmask], Value;
177 External, "external", FIELDS, OptionalValue;
178 Nested, "nested", TYPES, OptionalValue;
179 Verbatim, "verbatim", &[], Grammar;
180 Service, "service", &[Interface], Grammar;
181 Oneway, "oneway", &[Operation], OptionalValue;
182 Ami, "ami", &[Interface, Operation], OptionalValue;
183 HashId, "hashid", &[Member, UnionMember], OptionalValue;
184 DefaultNested, "default_nested", &[Module], OptionalValue;
185 IgnoreLiteralNames, "ignore_literal_names", &[Enum], OptionalValue;
186 TryConstruct, "try_construct", FIELDS, Grammar;
187 NonSerialized, "non_serialized", FIELDS, OptionalValue;
188 DataRepresentation, "data_representation", TYPES, Grammar;
189 Topic, "topic", &[Struct, Union], Grammar;
190 Choice, "choice", &[Union], Marker;
191 Empty, "empty", &[Struct], Marker;
192 DdsService, "dds_service", &[Interface], Marker;
193 DdsRequestTopic, "dds_request_topic", &[Operation], Grammar;
194 DdsReplyTopic, "dds_reply_topic", &[Operation], Grammar;
195 Rename, "rename", &[], String(&["name"]);
196 Name, "name", &[], String(&["name"]);
197 RenameAll, "rename_all", &[Struct, Union, Enum, Bitmask, Exception, Interface], String(&["rule"]);
198 Skip, "skip", &[Member, UnionMember, Enumerator, BitmaskValue, Parameter], Marker;
199 OmitEmpty, "omitempty", &[Member], Marker;
200 Doc, "doc", &[], String(&["text", "doc"]);
201 Derive, "derive", TYPES, Values;
202 Rust, "rust", &[], Value;
203 Version, "version", &[Enum], Version;
204 Added, "added", LIFECYCLE, Lifecycle;
205 Removed, "removed", LIFECYCLE, Lifecycle;
206 Http, "http", &[Exception, Union], Http;
207 Get, "get", &[Operation], OptionalString(&["path"]);
208 Post, "post", &[Operation], OptionalString(&["path"]);
209 Put, "put", &[Operation], OptionalString(&["path"]);
210 Patch, "patch", &[Operation], OptionalString(&["path"]);
211 Delete, "delete", &[Operation], OptionalString(&["path"]);
212 Head, "head", &[Operation], OptionalString(&["path"]);
213 Options, "options", &[Operation], OptionalString(&["path"]);
214 Path, "path", &[Interface, Operation, Parameter], OptionalString(&["name", "path"]);
215 Query, "query", &[Parameter], OptionalString(&["name"]);
216 Header, "header", &[Parameter, Member], OptionalString(&["name"]);
217 Cookie, "cookie", &[Parameter, Member], OptionalString(&["name"]);
218 Body, "body", &[Parameter, Member], OptionalString(&[]);
219 Flatten, "flatten", &[Member, Parameter], Marker;
220 HttpBasic, "http_basic", SECURITY, OptionalString(&["realm"]);
221 HttpBearer, "http_bearer", SECURITY, Marker;
222 ApiKey, "api_key", SECURITY, ApiKey;
223 NoSecurity, "no_security", SECURITY, Marker;
224 Request, "request", &[Interface, Operation], String(&["format"]);
225 Response, "response", &[Interface, Operation], String(&["format"]);
226 ServerStream, "server_stream", &[Operation, Attribute], Marker;
227 ClientStream, "client_stream", &[Operation], Marker;
228 BidiStream, "bidi_stream", &[Operation], Marker;
229 StreamCodec, "stream_codec", &[Operation], OptionalString(&[]);
230 Upgrade, "upgrade", &[Operation], Named { required: &["protocol"], optional: &["codec", "subprotocol", "heartbeat", "max_message"] };
231 Deprecated, "deprecated", SECURITY, Deprecated;
232 Cors, "cors", &[Interface, Operation], Cors;
233}
234
235impl AnnotationKind {
236 pub fn from_name(name: &str) -> Option<Self> {
238 AnnotationDefinition::lookup(name).map(|entry| entry.kind)
239 }
240
241 pub fn is_lifecycle(self) -> bool {
243 matches!(self, Self::Version | Self::Added | Self::Removed)
244 }
245}