1#[cfg(test)]
2mod test;
3
4pub mod names;
5
6use crate::error::Error;
7use crate::Options;
8use aldrin_parser::{ast, LinkResolver, Parser, ResolvedLink, Schema};
9use comrak::nodes::NodeValue;
10use comrak::options::BrokenLinkReference;
11use comrak::{Arena, Options as ComrakOptions, ResolvedReference};
12use diffy::Patch;
13use std::fmt::Write;
14use std::fs;
15use std::path::Path;
16use std::sync::Arc;
17
18const BOOL: &str = "::std::primitive::bool";
19const BOX: &str = "::std::boxed::Box";
20const CLONE: &str = "::std::clone::Clone";
21const DEBUG: &str = "::std::fmt::Debug";
22const DEFAULT: &str = "::std::default::Default";
23const EQ: &str = "::std::cmp::Eq";
24const F32: &str = "::std::primitive::f32";
25const F64: &str = "::std::primitive::f64";
26const HASH: &str = "::std::hash::Hash";
27const HASH_MAP: &str = "::std::collections::HashMap";
28const HASH_SET: &str = "::std::collections::HashSet";
29const I16: &str = "::std::primitive::i16";
30const I32: &str = "::std::primitive::i32";
31const I64: &str = "::std::primitive::i64";
32const I8: &str = "::std::primitive::i8";
33const OK: &str = "::std::result::Result::Ok";
34const OPTION: &str = "::std::option::Option";
35const ORD: &str = "::std::cmp::Ord";
36const PARTIAL_EQ: &str = "::std::cmp::PartialEq";
37const PARTIAL_ORD: &str = "::std::cmp::PartialOrd";
38const RESULT: &str = "::std::result::Result";
39const STR: &str = "::std::primitive::str";
40const STRING: &str = "::std::string::String";
41const U16: &str = "::std::primitive::u16";
42const U32: &str = "::std::primitive::u32";
43const U64: &str = "::std::primitive::u64";
44const U8: &str = "::std::primitive::u8";
45const VEC: &str = "::std::vec::Vec";
46
47#[derive(Debug, Clone)]
48#[non_exhaustive]
49pub struct RustOptions<'a> {
50 pub patches: Vec<&'a Path>,
51 pub introspection_if: Option<&'a str>,
52 pub krate: Option<&'a str>,
53}
54
55impl<'a> RustOptions<'a> {
56 pub fn new() -> Self {
57 RustOptions {
58 patches: Vec::new(),
59 introspection_if: None,
60 krate: None,
61 }
62 }
63
64 pub fn krate_or_default(&self) -> &'a str {
65 self.krate.unwrap_or("::aldrin")
66 }
67}
68
69impl Default for RustOptions<'_> {
70 fn default() -> Self {
71 RustOptions::new()
72 }
73}
74
75#[derive(Debug, Clone)]
76pub struct RustOutput {
77 pub module_name: String,
78 pub module_content: String,
79}
80
81pub(crate) fn generate(
82 parser: &Parser,
83 options: &Options,
84 rust_options: &RustOptions,
85) -> Result<RustOutput, Error> {
86 let schema = parser.main_schema();
87
88 let generator = RustGenerator {
89 parser,
90 schema,
91 options,
92 rust_options,
93 output: RustOutput {
94 module_name: schema.name().to_owned(),
95 module_content: String::new(),
96 },
97 };
98
99 generator.generate()
100}
101
102struct RustGenerator<'a> {
103 parser: &'a Parser,
104 schema: &'a Schema,
105 options: &'a Options,
106 rust_options: &'a RustOptions<'a>,
107 output: RustOutput,
108}
109
110macro_rules! code {
111 ($this:expr, $arg:literal) => {
112 write!($this.output.module_content, $arg).unwrap()
113 };
114}
115
116macro_rules! codeln {
117 ($this:expr) => {
118 writeln!($this.output.module_content).unwrap()
119 };
120
121 ($this:expr, $arg:literal) => {
122 writeln!($this.output.module_content, $arg).unwrap()
123 };
124}
125
126#[rustfmt::skip::macros(code, codeln)]
127impl RustGenerator<'_> {
128 fn generate(mut self) -> Result<RustOutput, Error> {
129 let (doc, _) = self.doc_string_inner(self.schema.doc(), 0);
130 if !doc.is_empty() {
131 codeln!(self, "{doc}");
132 }
133
134 for def in self.schema.definitions() {
135 self.definition(def);
136 }
137
138 if self.options.introspection {
139 let krate = self.rust_options.krate_or_default();
140 let name = names::register_introspection(self.schema.name());
141
142 if let Some(feature) = self.rust_options.introspection_if {
143 codeln!(self, "#[cfg(feature = \"{feature}\")]");
144 }
145
146 codeln!(self, "pub fn {name}(client: &{krate}::Handle) -> {RESULT}<(), {krate}::Error> {{");
147
148 for def in self.schema.definitions() {
149 self.register_introspection(def);
150 }
151
152 codeln!(self, " {OK}(())");
153 codeln!(self, "}}");
154 }
155
156 for patch in &self.rust_options.patches {
157 self.patch(patch)?;
158 }
159
160 Ok(self.output)
161 }
162
163 fn patch(&mut self, patch: &Path) -> Result<(), Error> {
164 let patch = fs::read_to_string(patch)?;
165 let patch = Patch::from_str(&patch)?;
166 self.output.module_content = diffy::apply(&self.output.module_content, &patch)?;
167 Ok(())
168 }
169
170 fn definition(&mut self, def: &ast::Definition) {
171 match def {
172 ast::Definition::Struct(d) => self.struct_def(
173 d.name().value(),
174 d.doc(),
175 d.attributes(),
176 d.fields(),
177 d.fallback(),
178 ),
179
180 ast::Definition::Enum(e) => self.enum_def(
181 e.name().value(),
182 e.doc(),
183 e.attributes(),
184 e.variants(),
185 e.fallback(),
186 ),
187
188 ast::Definition::Service(s) => self.service_def(s),
189 ast::Definition::Const(c) => self.const_def(c),
190 ast::Definition::Newtype(n) => self.newtype_def(n),
191 }
192 }
193
194 fn struct_def(
195 &mut self,
196 name: &str,
197 doc: &[ast::DocString],
198 attrs: &[ast::Attribute],
199 fields: &[ast::StructField],
200 fallback: Option<&ast::StructFallback>,
201 ) {
202 let krate = self.rust_options.krate_or_default();
203 let ident = format!("r#{name}");
204 let attrs = RustAttributes::parse(attrs);
205 let num_required_fields = fields.iter().filter(|&f| f.required()).count();
206 let has_required_fields = num_required_fields > 0;
207 let schema_name = self.schema.name();
208 let additional_derives = attrs.additional_derives();
209
210 let (doc_comment, doc_alt) = self.doc_string(doc, 0);
211 code!(self, "{doc_comment}");
212
213 code!(self, "#[derive({DEBUG}, {CLONE}");
214
215 if !has_required_fields {
216 code!(self, ", {DEFAULT}");
217 }
218
219 code!(self, ", {krate}::Tag, {krate}::PrimaryTag, {krate}::RefType, {krate}::Serialize, {krate}::Deserialize");
220
221 if self.options.introspection && self.rust_options.introspection_if.is_none() {
222 code!(self, ", {krate}::Introspectable");
223 }
224
225 codeln!(self, "{additional_derives})]");
226
227 if self.options.introspection {
228 if let Some(feature) = self.rust_options.introspection_if {
229 codeln!(self, "#[cfg_attr(feature = \"{feature}\", derive({krate}::Introspectable))]");
230 }
231 }
232
233 code!(self, "#[aldrin(");
234 if let Some(krate) = self.rust_options.krate {
235 code!(self, "crate = {krate}::core, ");
236 }
237 codeln!(self, "schema = \"{schema_name}\", ref_type)]");
238
239 if doc_alt && self.options.introspection {
240 for doc in doc {
241 let doc = doc.value_inner();
242 codeln!(self, "#[aldrin(doc = \"{doc}\")]");
243 }
244 }
245
246 codeln!(self, "pub struct {ident} {{");
247 let mut first = true;
248 for field in fields {
249 let id = field.id().value();
250 let ident = format!("r#{}", field.name().value());
251 let ty = self.type_name(field.field_type());
252
253 if first {
254 first = false;
255 } else {
256 codeln!(self);
257 }
258
259 let (doc_comment, doc_alt) = self.doc_string(field.doc(), 4);
260 code!(self, "{doc_comment}");
261
262 if field.required() {
263 codeln!(self, " #[aldrin(id = {id})]");
264 } else {
265 codeln!(self, " #[aldrin(id = {id}, optional)]");
266 }
267
268 if doc_alt && self.options.introspection {
269 for doc in field.doc() {
270 let doc = doc.value_inner();
271 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
272 }
273 }
274
275 if field.required() {
276 codeln!(self, " pub {ident}: {ty},");
277 } else {
278 codeln!(self, " pub {ident}: {OPTION}<{ty}>,");
279 }
280 }
281 if let Some(fallback) = fallback {
282 if !first {
283 codeln!(self);
284 }
285
286 let (doc_comment, doc_alt) = self.doc_string(fallback.doc(), 4);
287 code!(self, "{doc_comment}");
288
289 codeln!(self, " #[aldrin(fallback)]");
290
291 if doc_alt && self.options.introspection {
292 for doc in fallback.doc() {
293 let doc = doc.value_inner();
294 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
295 }
296 }
297
298 let ident = format!("r#{}", fallback.name().value());
299 codeln!(self, " pub {ident}: {krate}::core::UnknownFields,");
300 }
301 codeln!(self, "}}");
302 codeln!(self);
303
304 if !has_required_fields {
305 codeln!(self, "impl {ident} {{");
306 codeln!(self, " pub fn new() -> Self {{");
307 codeln!(self, " <Self as {DEFAULT}>::default()");
308 codeln!(self, " }}");
309 codeln!(self, "}}");
310 codeln!(self);
311 }
312 }
313
314 fn enum_def(
315 &mut self,
316 name: &str,
317 doc: &[ast::DocString],
318 attrs: &[ast::Attribute],
319 vars: &[ast::EnumVariant],
320 fallback: Option<&ast::EnumFallback>,
321 ) {
322 let ident = format!("r#{name}");
323 let krate = &self.rust_options.krate_or_default();
324 let schema_name = self.schema.name();
325 let attrs = RustAttributes::parse(attrs);
326 let additional_derives = attrs.additional_derives();
327
328 let (doc_comment, doc_alt) = self.doc_string(doc, 0);
329 code!(self, "{doc_comment}");
330
331 code!(self, "#[derive({DEBUG}, {CLONE}");
332 code!(self, ", {krate}::Tag, {krate}::PrimaryTag, {krate}::RefType, {krate}::Serialize, {krate}::Deserialize");
333
334 if self.options.introspection && self.rust_options.introspection_if.is_none() {
335 code!(self, ", {krate}::Introspectable");
336 }
337
338 codeln!(self, "{additional_derives})]");
339
340 if self.options.introspection {
341 if let Some(feature) = self.rust_options.introspection_if {
342 codeln!(self, "#[cfg_attr(feature = \"{feature}\", derive({krate}::Introspectable))]");
343 }
344 }
345
346 code!(self, "#[aldrin(");
347 if let Some(krate) = self.rust_options.krate {
348 code!(self, "crate = {krate}::core, ");
349 }
350 codeln!(self, "schema = \"{schema_name}\", ref_type)]");
351
352 if doc_alt && self.options.introspection {
353 for doc in doc {
354 let doc = doc.value_inner();
355 codeln!(self, "#[aldrin(doc = \"{doc}\")]");
356 }
357 }
358
359 codeln!(self, "pub enum {ident} {{");
360 let mut first = true;
361 for var in vars {
362 let id = var.id().value();
363 let ident = format!("r#{}", var.name().value());
364
365 if first {
366 first = false;
367 } else {
368 codeln!(self);
369 }
370
371 let (doc_comment, doc_alt) = self.doc_string(var.doc(), 4);
372 code!(self, "{doc_comment}");
373
374 codeln!(self, " #[aldrin(id = {id})]");
375
376 if doc_alt && self.options.introspection {
377 for doc in var.doc() {
378 let doc = doc.value_inner();
379 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
380 }
381 }
382
383 if let Some(ty) = var.variant_type() {
384 let ty = self.type_name(ty);
385 codeln!(self, " {ident}({ty}),");
386 } else {
387 codeln!(self, " {ident},");
388 }
389 }
390 if let Some(fallback) = fallback {
391 if !first {
392 codeln!(self);
393 }
394
395 let (doc_comment, doc_alt) = self.doc_string(fallback.doc(), 4);
396 code!(self, "{doc_comment}");
397
398 codeln!(self, " #[aldrin(fallback)]");
399
400 if doc_alt && self.options.introspection {
401 for doc in fallback.doc() {
402 let doc = doc.value_inner();
403 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
404 }
405 }
406
407 let ident = format!("r#{}", fallback.name().value());
408 codeln!(self, " {ident}({krate}::core::UnknownVariant),");
409 }
410 codeln!(self, "}}");
411 codeln!(self);
412 }
413
414 fn service_def(&mut self, svc: &ast::ServiceDef) {
415 if !self.options.client && !self.options.server {
416 return;
417 }
418
419 let krate = self.rust_options.krate_or_default();
420 let schema = self.schema.name();
421 let svc_name = svc.name().value();
422 let ident = format!("r#{svc_name}");
423 let uuid = svc.uuid().value();
424 let version = svc.version().value();
425
426 codeln!(self, "{krate}::service! {{");
427
428 let (doc_comment, doc_alt) = self.doc_string(svc.doc(), 4);
429 code!(self, "{doc_comment}");
430
431 code!(self, " #[aldrin(");
432
433 if let Some(krate) = self.rust_options.krate {
434 code!(self, "crate = {krate}, ");
435 }
436
437 code!(self, "schema = \"{schema}\"");
438
439 if !self.options.client {
440 code!(self, ", client = false");
441 }
442
443 if !self.options.server {
444 code!(self, ", server = false");
445 }
446
447 if self.options.introspection {
448 code!(self, ", introspection");
449 }
450
451 if let Some(feature) = self.rust_options.introspection_if {
452 code!(self, ", introspection_if = \"{feature}\"");
453 }
454
455 codeln!(self, ")]");
456
457 if doc_alt && self.options.introspection {
458 for doc in svc.doc() {
459 let doc = doc.value_inner();
460 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
461 }
462 }
463
464 codeln!(self, " pub service {ident} {{");
465 codeln!(self, " uuid = {krate}::core::ServiceUuid({krate}::private::uuid::uuid!(\"{uuid}\"));");
466 codeln!(self, " version = {version};");
467
468 for item in svc.items() {
469 codeln!(self);
470
471 match item {
472 ast::ServiceItem::Function(func) => {
473 let name = func.name().value();
474 let ident = format!("r#{name}");
475 let id = func.id().value();
476
477 let (doc_comment, doc_alt) = self.doc_string(func.doc(), 8);
478 code!(self, "{doc_comment}");
479
480 if doc_alt && self.options.introspection {
481 for doc in func.doc() {
482 let doc = doc.value_inner();
483 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
484 }
485 }
486
487 code!(self, " fn {ident} @ {id}");
488
489 if let (None, Some(ok), None) = (func.args(), func.ok(), func.err()) {
490 let ty = self.function_ok_type_name(svc_name, name, ok, true);
491 codeln!(self, " = {ty};");
492 } else if func.args().is_some() || func.ok().is_some() || func.err().is_some() {
493 codeln!(self, " {{");
494
495 if let Some(args) = func.args() {
496 let ty = self.function_args_type_name(svc_name, name, args, true);
497 codeln!(self, " args = {ty};");
498 }
499
500 if let Some(ok) = func.ok() {
501 let ty = self.function_ok_type_name(svc_name, name, ok, true);
502 codeln!(self, " ok = {ty};");
503 }
504
505 if let Some(err) = func.err() {
506 let ty = self.function_err_type_name(svc_name, name, err, true);
507 codeln!(self, " err = {ty};");
508 }
509
510 codeln!(self, " }}");
511 } else {
512 codeln!(self, ";");
513 }
514 }
515
516 ast::ServiceItem::Event(ev) => {
517 let name = ev.name().value();
518 let ident = format!("r#{name}");
519 let id = ev.id().value();
520
521 let (doc_comment, doc_alt) = self.doc_string(ev.doc(), 8);
522 code!(self, "{doc_comment}");
523
524 if doc_alt && self.options.introspection {
525 for doc in ev.doc() {
526 let doc = doc.value_inner();
527 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
528 }
529 }
530
531 code!(self, " event {ident} @ {id}");
532
533 if let Some(ty) = ev.event_type() {
534 let ty = self.event_args_type_name(svc_name, name, ty, true);
535 code!(self, " = {ty}");
536 }
537
538 codeln!(self, ";");
539 }
540 }
541 }
542
543 if let Some(fallback) = svc.function_fallback() {
544 let name = fallback.name().value();
545 let ident = format!("r#{name}");
546
547 codeln!(self);
548
549 let (doc_comment, doc_alt) = self.doc_string(fallback.doc(), 8);
550 code!(self, "{doc_comment}");
551
552 if doc_alt && self.options.introspection {
553 for doc in fallback.doc() {
554 let doc = doc.value_inner();
555 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
556 }
557 }
558
559 codeln!(self, " fn {ident} = {krate}::UnknownCall;");
560 }
561
562 if let Some(fallback) = svc.event_fallback() {
563 let name = fallback.name().value();
564 let ident = format!("r#{name}");
565
566 codeln!(self);
567
568 let (doc_comment, doc_alt) = self.doc_string(fallback.doc(), 8);
569 code!(self, "{doc_comment}");
570
571 if doc_alt && self.options.introspection {
572 for doc in fallback.doc() {
573 let doc = doc.value_inner();
574 codeln!(self, " #[aldrin(doc = \"{doc}\")]");
575 }
576 }
577
578 codeln!(self, " event {ident} = {krate}::UnknownEvent;");
579 }
580
581 codeln!(self, " }}");
582 codeln!(self, "}}");
583 codeln!(self);
584
585 for item in svc.items() {
586 match item {
587 ast::ServiceItem::Function(func) => {
588 let func_name = func.name().value();
589
590 if let Some(args) = func.args() {
591 match args.part_type() {
592 ast::TypeNameOrInline::Struct(s) => self.struct_def(
593 &self.function_args_type_name(svc_name, func_name, args, false),
594 s.doc(),
595 s.attributes(),
596 s.fields(),
597 s.fallback(),
598 ),
599
600 ast::TypeNameOrInline::Enum(e) => self.enum_def(
601 &self.function_args_type_name(svc_name, func_name, args, false),
602 e.doc(),
603 e.attributes(),
604 e.variants(),
605 e.fallback(),
606 ),
607
608 ast::TypeNameOrInline::TypeName(_) => {}
609 }
610 }
611
612 if let Some(ok) = func.ok() {
613 match ok.part_type() {
614 ast::TypeNameOrInline::Struct(s) => self.struct_def(
615 &self.function_ok_type_name(svc_name, func_name, ok, false),
616 s.doc(),
617 s.attributes(),
618 s.fields(),
619 s.fallback(),
620 ),
621
622 ast::TypeNameOrInline::Enum(e) => self.enum_def(
623 &self.function_ok_type_name(svc_name, func_name, ok, false),
624 e.doc(),
625 e.attributes(),
626 e.variants(),
627 e.fallback(),
628 ),
629
630 ast::TypeNameOrInline::TypeName(_) => {}
631 }
632 }
633
634 if let Some(err) = func.err() {
635 match err.part_type() {
636 ast::TypeNameOrInline::Struct(s) => self.struct_def(
637 &self.function_err_type_name(svc_name, func_name, err, false),
638 s.doc(),
639 s.attributes(),
640 s.fields(),
641 s.fallback(),
642 ),
643
644 ast::TypeNameOrInline::Enum(e) => self.enum_def(
645 &self.function_err_type_name(svc_name, func_name, err, false),
646 e.doc(),
647 e.attributes(),
648 e.variants(),
649 e.fallback(),
650 ),
651
652 ast::TypeNameOrInline::TypeName(_) => {}
653 }
654 }
655 }
656
657 ast::ServiceItem::Event(ev) => {
658 if let Some(ty) = ev.event_type() {
659 let ev_name = ev.name().value();
660
661 match ty {
662 ast::TypeNameOrInline::Struct(s) => self.struct_def(
663 &self.event_args_type_name(svc_name, ev_name, ty, false),
664 s.doc(),
665 s.attributes(),
666 s.fields(),
667 s.fallback(),
668 ),
669
670 ast::TypeNameOrInline::Enum(e) => self.enum_def(
671 &self.event_args_type_name(svc_name, ev_name, ty, false),
672 e.doc(),
673 e.attributes(),
674 e.variants(),
675 e.fallback(),
676 ),
677
678 ast::TypeNameOrInline::TypeName(_) => {}
679 }
680 }
681 }
682 }
683 }
684 }
685
686 fn const_def(&mut self, const_def: &ast::ConstDef) {
687 let krate = self.rust_options.krate_or_default();
688 let name = const_def.name().value();
689
690 let (doc_comment, _) = self.doc_string(const_def.doc(), 0);
691 code!(self, "{doc_comment}");
692
693 match const_def.value() {
694 ast::ConstValue::U8(v) => {
695 let val = v.value();
696 codeln!(self, "pub const {name}: {U8} = {val};");
697 }
698
699 ast::ConstValue::I8(v) => {
700 let val = v.value();
701 codeln!(self, "pub const {name}: {I8} = {val};");
702 }
703
704 ast::ConstValue::U16(v) => {
705 let val = v.value();
706 codeln!(self, "pub const {name}: {U16} = {val};");
707 }
708
709 ast::ConstValue::I16(v) => {
710 let val = v.value();
711 codeln!(self, "pub const {name}: {I16} = {val};");
712 }
713
714 ast::ConstValue::U32(v) => {
715 let val = v.value();
716 codeln!(self, "pub const {name}: {U32} = {val};");
717 }
718
719 ast::ConstValue::I32(v) => {
720 let val = v.value();
721 codeln!(self, "pub const {name}: {I32} = {val};");
722 }
723
724 ast::ConstValue::U64(v) => {
725 let val = v.value();
726 codeln!(self, "pub const {name}: {U64} = {val};");
727 }
728
729 ast::ConstValue::I64(v) => {
730 let val = v.value();
731 codeln!(self, "pub const {name}: {I64} = {val};");
732 }
733
734 ast::ConstValue::String(v) => {
735 let val = v.value();
736 codeln!(self, "pub const {name}: &{STR} = {val};");
737 }
738
739 ast::ConstValue::Uuid(v) => {
740 let val = v.value();
741 codeln!(self, "pub const {name}: {krate}::private::uuid::Uuid = {krate}::private::uuid::uuid!(\"{val}\");");
742 }
743 };
744
745 codeln!(self);
746 }
747
748 fn newtype_def(&mut self, newtype_def: &ast::NewtypeDef) {
749 let krate = self.rust_options.krate_or_default();
750 let name = newtype_def.name().value();
751 let ident = format!("r#{name}");
752 let ty = self.type_name(newtype_def.target_type());
753 let schema_name = self.schema.name();
754 let additional_derives =
755 RustAttributes::parse(newtype_def.attributes()).additional_derives();
756 let (is_key_type, derive_default) =
757 self.newtype_properties(self.schema, newtype_def.target_type());
758
759 let (doc_comment, doc_alt) = self.doc_string(newtype_def.doc(), 0);
760 code!(self, "{doc_comment}");
761
762 code!(self, "#[derive({DEBUG}, {CLONE}");
763
764 if derive_default {
765 code!(self, ", {DEFAULT}");
766 }
767
768 if is_key_type {
769 code!(self, ", {PARTIAL_EQ}, {EQ}, {PARTIAL_ORD}, {ORD}, {HASH}");
770 }
771
772 code!(self, ", {krate}::Tag, {krate}::PrimaryTag, {krate}::RefType, {krate}::Serialize, {krate}::Deserialize");
773
774 if self.options.introspection && self.rust_options.introspection_if.is_none() {
775 code!(self, ", {krate}::Introspectable");
776 }
777
778 if is_key_type {
779 code!(self, ", {krate}::KeyTag, {krate}::PrimaryKeyTag, {krate}::SerializeKey, {krate}::DeserializeKey");
780 }
781
782 codeln!(self, "{additional_derives})]");
783
784 if self.options.introspection {
785 if let Some(feature) = self.rust_options.introspection_if {
786 codeln!(self, "#[cfg_attr(feature = \"{feature}\", derive({krate}::Introspectable))]");
787 }
788 }
789
790 code!(self, "#[aldrin(");
791 if let Some(krate) = self.rust_options.krate {
792 code!(self, "crate = {krate}::core, ");
793 }
794 codeln!(self, "newtype, schema = \"{schema_name}\", ref_type)]");
795
796 if doc_alt && self.options.introspection {
797 for doc in newtype_def.doc() {
798 let doc = doc.value_inner();
799 codeln!(self, "#[aldrin(doc = \"{doc}\")]");
800 }
801 }
802
803 codeln!(self, "pub struct {ident}(pub {ty});");
804 codeln!(self);
805 }
806
807 fn register_introspection(&mut self, def: &ast::Definition) {
808 match def {
809 def @ (ast::Definition::Struct(_)
810 | ast::Definition::Enum(_)
811 | ast::Definition::Newtype(_)) => {
812 let ident = format!("r#{}", def.name().value());
813 codeln!(self, " client.register_introspection::<{ident}>()?;");
814 }
815
816 ast::Definition::Service(s) => {
817 if self.options.client || self.options.server {
818 let ident = format!("r#{}", s.name().value());
819 codeln!(self, " client.register_introspection::<{ident}Introspection>()?;");
820 }
821 }
822
823 ast::Definition::Const(_) => {}
824 }
825 }
826
827 fn type_name(&self, ty: &ast::TypeName) -> String {
828 let krate = self.rust_options.krate_or_default();
829
830 match ty.kind() {
831 ast::TypeNameKind::Bool => BOOL.to_owned(),
832 ast::TypeNameKind::U8 => U8.to_owned(),
833 ast::TypeNameKind::I8 => I8.to_owned(),
834 ast::TypeNameKind::U16 => U16.to_owned(),
835 ast::TypeNameKind::I16 => I16.to_owned(),
836 ast::TypeNameKind::U32 => U32.to_owned(),
837 ast::TypeNameKind::I32 => I32.to_owned(),
838 ast::TypeNameKind::U64 => U64.to_owned(),
839 ast::TypeNameKind::I64 => I64.to_owned(),
840 ast::TypeNameKind::F32 => F32.to_owned(),
841 ast::TypeNameKind::F64 => F64.to_owned(),
842 ast::TypeNameKind::String => STRING.to_owned(),
843 ast::TypeNameKind::Uuid => format!("{krate}::private::uuid::Uuid"),
844 ast::TypeNameKind::ObjectId => format!("{krate}::core::ObjectId"),
845 ast::TypeNameKind::ServiceId => format!("{krate}::core::ServiceId"),
846 ast::TypeNameKind::Value => format!("{krate}::core::SerializedValue"),
847 ast::TypeNameKind::Option(ty) => format!("{OPTION}<{}>", self.type_name(ty)),
848 ast::TypeNameKind::Box(ty) => format!("{BOX}<{}>", self.type_name(ty)),
849
850 ast::TypeNameKind::Vec(ty) => match ty.kind() {
851 ast::TypeNameKind::U8 => format!("{krate}::core::Bytes"),
852 _ => format!("{VEC}<{}>", self.type_name(ty)),
853 },
854
855 ast::TypeNameKind::Bytes => format!("{krate}::core::Bytes"),
856
857 ast::TypeNameKind::Map(k, v) => {
858 format!("{HASH_MAP}<{}, {}>", self.type_name(k), self.type_name(v))
859 }
860
861 ast::TypeNameKind::Set(ty) => format!("{HASH_SET}<{}>", self.type_name(ty)),
862
863 ast::TypeNameKind::Sender(ty) => {
864 format!("{krate}::UnboundSender<{}>", self.type_name(ty))
865 }
866
867 ast::TypeNameKind::Receiver(ty) => {
868 format!("{krate}::UnboundReceiver<{}>", self.type_name(ty))
869 }
870
871 ast::TypeNameKind::Lifetime => format!("{krate}::LifetimeId"),
872 ast::TypeNameKind::Unit => "()".to_owned(),
873
874 ast::TypeNameKind::Result(ok, err) => {
875 format!("{RESULT}<{}, {}>", self.type_name(ok), self.type_name(err))
876 }
877
878 ast::TypeNameKind::Array(ty, len) => self.array_name(ty, len),
879 ast::TypeNameKind::Ref(ty) => self.named_ref_name(ty),
880 }
881 }
882
883 fn array_name(&self, ty: &ast::TypeName, len: &ast::ArrayLen) -> String {
884 match len.value() {
885 ast::ArrayLenValue::Literal(len) => {
886 format!("[{}; {}usize]", self.type_name(ty), len.value())
887 }
888
889 ast::ArrayLenValue::Ref(named_ref) => {
890 format!(
891 "[{}; {} as usize]",
892 self.type_name(ty),
893 self.named_ref_name(named_ref)
894 )
895 }
896 }
897 }
898
899 fn named_ref_name(&self, ty: &ast::NamedRef) -> String {
900 match ty.kind() {
901 ast::NamedRefKind::Intern(ty) => format!("r#{}", ty.value()),
902 ast::NamedRefKind::Extern(m, ty) => format!("super::r#{}::r#{}", m.value(), ty.value()),
903 }
904 }
905
906 fn function_args_type_name(
907 &self,
908 svc_name: &str,
909 func_name: &str,
910 part: &ast::FunctionPart,
911 raw: bool,
912 ) -> String {
913 match part.part_type() {
914 ast::TypeNameOrInline::TypeName(ty) => self.type_name(ty),
915
916 ast::TypeNameOrInline::Struct(_) | ast::TypeNameOrInline::Enum(_) => {
917 if raw {
918 format!("r#{}", names::function_args(svc_name, func_name))
919 } else {
920 names::function_args(svc_name, func_name)
921 }
922 }
923 }
924 }
925
926 fn function_ok_type_name(
927 &self,
928 svc_name: &str,
929 func_name: &str,
930 part: &ast::FunctionPart,
931 raw: bool,
932 ) -> String {
933 match part.part_type() {
934 ast::TypeNameOrInline::TypeName(ty) => self.type_name(ty),
935
936 ast::TypeNameOrInline::Struct(_) | ast::TypeNameOrInline::Enum(_) => {
937 if raw {
938 format!("r#{}", names::function_ok(svc_name, func_name))
939 } else {
940 names::function_ok(svc_name, func_name)
941 }
942 }
943 }
944 }
945
946 fn function_err_type_name(
947 &self,
948 svc_name: &str,
949 func_name: &str,
950 part: &ast::FunctionPart,
951 raw: bool,
952 ) -> String {
953 match part.part_type() {
954 ast::TypeNameOrInline::TypeName(ty) => self.type_name(ty),
955
956 ast::TypeNameOrInline::Struct(_) | ast::TypeNameOrInline::Enum(_) => {
957 if raw {
958 format!("r#{}", names::function_err(svc_name, func_name))
959 } else {
960 names::function_err(svc_name, func_name)
961 }
962 }
963 }
964 }
965
966 fn event_args_type_name(
967 &self,
968 svc_name: &str,
969 ev_name: &str,
970 ev_type: &ast::TypeNameOrInline,
971 raw: bool,
972 ) -> String {
973 match ev_type {
974 ast::TypeNameOrInline::TypeName(ty) => self.type_name(ty),
975
976 ast::TypeNameOrInline::Struct(_) | ast::TypeNameOrInline::Enum(_) => {
977 if raw {
978 format!("r#{}", names::event_args(svc_name, ev_name))
979 } else {
980 names::event_args(svc_name, ev_name)
981 }
982 }
983 }
984 }
985
986 fn newtype_properties(&self, schema: &Schema, ty: &ast::TypeName) -> (bool, bool) {
987 match ty.kind() {
988 ast::TypeNameKind::U8
989 | ast::TypeNameKind::I8
990 | ast::TypeNameKind::U16
991 | ast::TypeNameKind::I16
992 | ast::TypeNameKind::U32
993 | ast::TypeNameKind::I32
994 | ast::TypeNameKind::U64
995 | ast::TypeNameKind::I64
996 | ast::TypeNameKind::String
997 | ast::TypeNameKind::Uuid => (true, false),
998
999 ast::TypeNameKind::Bool
1000 | ast::TypeNameKind::F32
1001 | ast::TypeNameKind::F64
1002 | ast::TypeNameKind::ObjectId
1003 | ast::TypeNameKind::ServiceId
1004 | ast::TypeNameKind::Value
1005 | ast::TypeNameKind::Option(_)
1006 | ast::TypeNameKind::Box(_)
1007 | ast::TypeNameKind::Vec(_)
1008 | ast::TypeNameKind::Bytes
1009 | ast::TypeNameKind::Map(_, _)
1010 | ast::TypeNameKind::Set(_)
1011 | ast::TypeNameKind::Sender(_)
1012 | ast::TypeNameKind::Receiver(_)
1013 | ast::TypeNameKind::Lifetime
1014 | ast::TypeNameKind::Unit
1015 | ast::TypeNameKind::Result(_, _)
1016 | ast::TypeNameKind::Array(_, _) => (false, false),
1017
1018 ast::TypeNameKind::Ref(ty) => {
1019 let (schema, name) = match ty.kind() {
1020 ast::NamedRefKind::Intern(name) => (schema, name.value()),
1021
1022 ast::NamedRefKind::Extern(schema, name) => {
1023 if let Some(schema) = self.parser.get_schema(schema.value()) {
1024 (schema, name.value())
1025 } else {
1026 return (false, false);
1027 }
1028 }
1029 };
1030
1031 let Some(def) = schema
1032 .definitions()
1033 .iter()
1034 .find(|def| def.name().value() == name)
1035 else {
1036 return (false, false);
1037 };
1038
1039 match def {
1040 ast::Definition::Struct(struct_def) => {
1041 let has_required_fields =
1042 struct_def.fields().iter().any(ast::StructField::required);
1043
1044 (false, !has_required_fields)
1045 }
1046
1047 ast::Definition::Newtype(newtype_def) => {
1048 self.newtype_properties(schema, newtype_def.target_type())
1049 }
1050
1051 ast::Definition::Enum(_)
1052 | ast::Definition::Service(_)
1053 | ast::Definition::Const(_) => (false, false),
1054 }
1055 }
1056 }
1057 }
1058
1059 fn doc_string(&self, doc: &[ast::DocString], indent: usize) -> (String, bool) {
1060 self.doc_string_impl(doc, indent, "///")
1061 }
1062
1063 fn doc_string_inner(&self, doc: &[ast::DocString], indent: usize) -> (String, bool) {
1064 self.doc_string_impl(doc, indent, "//!")
1065 }
1066
1067 fn doc_string_impl(
1068 &self,
1069 doc: &[ast::DocString],
1070 indent: usize,
1071 style: &'static str,
1072 ) -> (String, bool) {
1073 const INDENT: &str = " ";
1074
1075 debug_assert!(indent <= INDENT.len());
1076
1077 if doc.is_empty() {
1078 return (String::new(), false);
1079 }
1080
1081 let mut orig = String::new();
1082
1083 for doc in doc {
1084 orig.push_str(doc.value_inner());
1085 orig.push('\n');
1086 }
1087
1088 let with_links = self.rewrite_doc_links(&orig);
1089 let mut doc_string = String::new();
1090
1091 for line in with_links.lines() {
1092 doc_string.push_str(&INDENT[..indent]);
1093 doc_string.push_str(style);
1094
1095 if !line.is_empty() {
1096 doc_string.push(' ');
1097 doc_string.push_str(line);
1098 }
1099
1100 doc_string.push('\n');
1101 }
1102
1103 (doc_string, orig != with_links)
1104 }
1105
1106 fn rewrite_doc_links(&self, doc: &str) -> String {
1107 let resolver = LinkResolver::new(self.parser, self.schema);
1108
1109 let mut options = ComrakOptions::default();
1110 options.extension.footnotes = true;
1111 options.extension.strikethrough = true;
1112 options.extension.table = true;
1113 options.extension.tasklist = true;
1114 options.parse.smart = true;
1115
1116 options.parse.broken_link_callback = Some(Arc::new(move |link: BrokenLinkReference| {
1117 resolver
1118 .convert_broken_link_if_valid(link.original)
1119 .map(|link| ResolvedReference {
1120 url: link.to_owned(),
1121 title: String::new(),
1122 })
1123 }));
1124
1125 let arena = Arena::new();
1126 let root = comrak::parse_document(&arena, doc, &options);
1127
1128 for node in root.descendants() {
1129 let mut data = node.data.borrow_mut();
1130
1131 if let NodeValue::Link(ref mut link) = data.value {
1132 if let Some(new_link) = self.rewrite_doc_link(&link.url, resolver) {
1133 link.url = new_link;
1134 }
1135 }
1136 }
1137
1138 let mut doc_string = String::new();
1139 comrak::format_commonmark(root, &options, &mut doc_string).unwrap();
1140 doc_string
1141 }
1142
1143 fn rewrite_doc_link(&self, link: &str, resolver: LinkResolver<'_>) -> Option<String> {
1144 let Ok(resolved) = resolver.resolve(link) else {
1145 return None;
1146 };
1147
1148 match resolved {
1149 ResolvedLink::Foreign => None,
1150
1151 ResolvedLink::Schema(schema) => {
1152 if schema.name() == resolver.schema().name() {
1153 Some("self".to_owned())
1154 } else {
1155 Some(format!("super::{}", schema.name()))
1156 }
1157 }
1158
1159 ResolvedLink::Struct(schema, struct_def) => Some(Self::doc_link_components(
1160 schema,
1161 resolver,
1162 &[struct_def.name().value()],
1163 )),
1164
1165 ResolvedLink::Field(schema, struct_def, field) => Some(Self::doc_link_components(
1166 schema,
1167 resolver,
1168 &[struct_def.name().value(), field.name().value()],
1169 )),
1170
1171 ResolvedLink::FallbackField(schema, struct_def, fallback) => {
1172 Some(Self::doc_link_components(
1173 schema,
1174 resolver,
1175 &[struct_def.name().value(), fallback.name().value()],
1176 ))
1177 }
1178
1179 ResolvedLink::Enum(schema, enum_def) => Some(Self::doc_link_components(
1180 schema,
1181 resolver,
1182 &[enum_def.name().value()],
1183 )),
1184
1185 ResolvedLink::Variant(schema, enum_def, var) => Some(Self::doc_link_components(
1186 schema,
1187 resolver,
1188 &[enum_def.name().value(), var.name().value()],
1189 )),
1190
1191 ResolvedLink::FallbackVariant(schema, enum_def, fallback) => {
1192 Some(Self::doc_link_components(
1193 schema,
1194 resolver,
1195 &[enum_def.name().value(), fallback.name().value()],
1196 ))
1197 }
1198
1199 ResolvedLink::Service(schema, svc) => {
1200 if self.options.client {
1201 Some(Self::doc_link_components(
1202 schema,
1203 resolver,
1204 &[&names::service_proxy(svc.name().value())],
1205 ))
1206 } else if self.options.server {
1207 Some(Self::doc_link_components(
1208 schema,
1209 resolver,
1210 &[svc.name().value()],
1211 ))
1212 } else {
1213 None
1214 }
1215 }
1216
1217 ResolvedLink::Function(schema, svc, func) => {
1218 if self.options.client {
1219 Some(Self::doc_link_components(
1220 schema,
1221 resolver,
1222 &[
1223 &names::service_proxy(svc.name().value()),
1224 func.name().value(),
1225 ],
1226 ))
1227 } else if self.options.server {
1228 Some(Self::doc_link_components(
1229 schema,
1230 resolver,
1231 &[
1232 &names::service_call(svc.name().value()),
1233 &names::function_variant(func.name().value()),
1234 ],
1235 ))
1236 } else {
1237 None
1238 }
1239 }
1240
1241 ResolvedLink::FunctionArgsStruct(schema, svc, func, _, _) => {
1242 if self.options.client || self.options.server {
1243 Some(Self::doc_link_components(
1244 schema,
1245 resolver,
1246 &[&names::function_args(
1247 svc.name().value(),
1248 func.name().value(),
1249 )],
1250 ))
1251 } else {
1252 None
1253 }
1254 }
1255
1256 ResolvedLink::FunctionArgsField(schema, svc, func, _, _, field) => {
1257 if self.options.client || self.options.server {
1258 Some(Self::doc_link_components(
1259 schema,
1260 resolver,
1261 &[
1262 &names::function_args(svc.name().value(), func.name().value()),
1263 field.name().value(),
1264 ],
1265 ))
1266 } else {
1267 None
1268 }
1269 }
1270
1271 ResolvedLink::FunctionArgsFallbackField(schema, svc, func, _, _, fallback) => {
1272 if self.options.client || self.options.server {
1273 Some(Self::doc_link_components(
1274 schema,
1275 resolver,
1276 &[
1277 &names::function_args(svc.name().value(), func.name().value()),
1278 fallback.name().value(),
1279 ],
1280 ))
1281 } else {
1282 None
1283 }
1284 }
1285
1286 ResolvedLink::FunctionArgsEnum(schema, svc, func, _, _) => {
1287 if self.options.client || self.options.server {
1288 Some(Self::doc_link_components(
1289 schema,
1290 resolver,
1291 &[&names::function_args(
1292 svc.name().value(),
1293 func.name().value(),
1294 )],
1295 ))
1296 } else {
1297 None
1298 }
1299 }
1300
1301 ResolvedLink::FunctionArgsVariant(schema, svc, func, _, _, var) => {
1302 if self.options.client || self.options.server {
1303 Some(Self::doc_link_components(
1304 schema,
1305 resolver,
1306 &[
1307 &names::function_args(svc.name().value(), func.name().value()),
1308 var.name().value(),
1309 ],
1310 ))
1311 } else {
1312 None
1313 }
1314 }
1315
1316 ResolvedLink::FunctionArgsFallbackVariant(schema, svc, func, _, _, fallback) => {
1317 if self.options.client || self.options.server {
1318 Some(Self::doc_link_components(
1319 schema,
1320 resolver,
1321 &[
1322 &names::function_args(svc.name().value(), func.name().value()),
1323 fallback.name().value(),
1324 ],
1325 ))
1326 } else {
1327 None
1328 }
1329 }
1330
1331 ResolvedLink::FunctionOkStruct(schema, svc, func, _, _) => {
1332 if self.options.client || self.options.server {
1333 Some(Self::doc_link_components(
1334 schema,
1335 resolver,
1336 &[&names::function_ok(svc.name().value(), func.name().value())],
1337 ))
1338 } else {
1339 None
1340 }
1341 }
1342
1343 ResolvedLink::FunctionOkField(schema, svc, func, _, _, field) => {
1344 if self.options.client || self.options.server {
1345 Some(Self::doc_link_components(
1346 schema,
1347 resolver,
1348 &[
1349 &names::function_ok(svc.name().value(), func.name().value()),
1350 field.name().value(),
1351 ],
1352 ))
1353 } else {
1354 None
1355 }
1356 }
1357
1358 ResolvedLink::FunctionOkFallbackField(schema, svc, func, _, _, fallback) => {
1359 if self.options.client || self.options.server {
1360 Some(Self::doc_link_components(
1361 schema,
1362 resolver,
1363 &[
1364 &names::function_ok(svc.name().value(), func.name().value()),
1365 fallback.name().value(),
1366 ],
1367 ))
1368 } else {
1369 None
1370 }
1371 }
1372
1373 ResolvedLink::FunctionOkEnum(schema, svc, func, _, _) => {
1374 if self.options.client || self.options.server {
1375 Some(Self::doc_link_components(
1376 schema,
1377 resolver,
1378 &[&names::function_ok(svc.name().value(), func.name().value())],
1379 ))
1380 } else {
1381 None
1382 }
1383 }
1384
1385 ResolvedLink::FunctionOkVariant(schema, svc, func, _, _, var) => {
1386 if self.options.client || self.options.server {
1387 Some(Self::doc_link_components(
1388 schema,
1389 resolver,
1390 &[
1391 &names::function_ok(svc.name().value(), func.name().value()),
1392 var.name().value(),
1393 ],
1394 ))
1395 } else {
1396 None
1397 }
1398 }
1399
1400 ResolvedLink::FunctionOkFallbackVariant(schema, svc, func, _, _, fallback) => {
1401 if self.options.client || self.options.server {
1402 Some(Self::doc_link_components(
1403 schema,
1404 resolver,
1405 &[
1406 &names::function_ok(svc.name().value(), func.name().value()),
1407 fallback.name().value(),
1408 ],
1409 ))
1410 } else {
1411 None
1412 }
1413 }
1414
1415 ResolvedLink::FunctionErrStruct(schema, svc, func, _, _) => {
1416 if self.options.client || self.options.server {
1417 Some(Self::doc_link_components(
1418 schema,
1419 resolver,
1420 &[&names::function_err(
1421 svc.name().value(),
1422 func.name().value(),
1423 )],
1424 ))
1425 } else {
1426 None
1427 }
1428 }
1429
1430 ResolvedLink::FunctionErrField(schema, svc, func, _, _, field) => {
1431 if self.options.client || self.options.server {
1432 Some(Self::doc_link_components(
1433 schema,
1434 resolver,
1435 &[
1436 &names::function_err(svc.name().value(), func.name().value()),
1437 field.name().value(),
1438 ],
1439 ))
1440 } else {
1441 None
1442 }
1443 }
1444
1445 ResolvedLink::FunctionErrFallbackField(schema, svc, func, _, _, fallback) => {
1446 if self.options.client || self.options.server {
1447 Some(Self::doc_link_components(
1448 schema,
1449 resolver,
1450 &[
1451 &names::function_err(svc.name().value(), func.name().value()),
1452 fallback.name().value(),
1453 ],
1454 ))
1455 } else {
1456 None
1457 }
1458 }
1459
1460 ResolvedLink::FunctionErrEnum(schema, svc, func, _, _) => {
1461 if self.options.client || self.options.server {
1462 Some(Self::doc_link_components(
1463 schema,
1464 resolver,
1465 &[&names::function_err(
1466 svc.name().value(),
1467 func.name().value(),
1468 )],
1469 ))
1470 } else {
1471 None
1472 }
1473 }
1474
1475 ResolvedLink::FunctionErrVariant(schema, svc, func, _, _, var) => {
1476 if self.options.client || self.options.server {
1477 Some(Self::doc_link_components(
1478 schema,
1479 resolver,
1480 &[
1481 &names::function_err(svc.name().value(), func.name().value()),
1482 var.name().value(),
1483 ],
1484 ))
1485 } else {
1486 None
1487 }
1488 }
1489
1490 ResolvedLink::FunctionErrFallbackVariant(schema, svc, func, _, _, fallback) => {
1491 if self.options.client || self.options.server {
1492 Some(Self::doc_link_components(
1493 schema,
1494 resolver,
1495 &[
1496 &names::function_err(svc.name().value(), func.name().value()),
1497 fallback.name().value(),
1498 ],
1499 ))
1500 } else {
1501 None
1502 }
1503 }
1504
1505 ResolvedLink::FunctionFallback(schema, svc, fallback) => {
1506 if self.options.server {
1507 Some(Self::doc_link_components(
1508 schema,
1509 resolver,
1510 &[
1511 &names::service_call(svc.name().value()),
1512 &names::function_variant(fallback.name().value()),
1513 ],
1514 ))
1515 } else {
1516 None
1517 }
1518 }
1519
1520 ResolvedLink::Event(schema, svc, ev) => {
1521 if self.options.client {
1522 Some(Self::doc_link_components(
1523 schema,
1524 resolver,
1525 &[
1526 &names::service_event(svc.name().value()),
1527 &names::event_variant(ev.name().value()),
1528 ],
1529 ))
1530 } else if self.options.server {
1531 Some(Self::doc_link_components(
1532 schema,
1533 resolver,
1534 &[svc.name().value(), ev.name().value()],
1535 ))
1536 } else {
1537 None
1538 }
1539 }
1540
1541 ResolvedLink::EventStruct(schema, svc, ev, _) => {
1542 if self.options.client || self.options.server {
1543 Some(Self::doc_link_components(
1544 schema,
1545 resolver,
1546 &[&names::event_args(svc.name().value(), ev.name().value())],
1547 ))
1548 } else {
1549 None
1550 }
1551 }
1552
1553 ResolvedLink::EventField(schema, svc, ev, _, field) => {
1554 if self.options.client || self.options.server {
1555 Some(Self::doc_link_components(
1556 schema,
1557 resolver,
1558 &[
1559 &names::event_args(svc.name().value(), ev.name().value()),
1560 field.name().value(),
1561 ],
1562 ))
1563 } else {
1564 None
1565 }
1566 }
1567
1568 ResolvedLink::EventFallbackField(schema, svc, ev, _, fallback) => {
1569 if self.options.client || self.options.server {
1570 Some(Self::doc_link_components(
1571 schema,
1572 resolver,
1573 &[
1574 &names::event_args(svc.name().value(), ev.name().value()),
1575 fallback.name().value(),
1576 ],
1577 ))
1578 } else {
1579 None
1580 }
1581 }
1582
1583 ResolvedLink::EventEnum(schema, svc, ev, _) => {
1584 if self.options.client || self.options.server {
1585 Some(Self::doc_link_components(
1586 schema,
1587 resolver,
1588 &[&names::event_args(svc.name().value(), ev.name().value())],
1589 ))
1590 } else {
1591 None
1592 }
1593 }
1594
1595 ResolvedLink::EventVariant(schema, svc, ev, _, var) => {
1596 if self.options.client || self.options.server {
1597 Some(Self::doc_link_components(
1598 schema,
1599 resolver,
1600 &[
1601 &names::event_args(svc.name().value(), ev.name().value()),
1602 var.name().value(),
1603 ],
1604 ))
1605 } else {
1606 None
1607 }
1608 }
1609
1610 ResolvedLink::EventFallbackVariant(schema, svc, ev, _, fallback) => {
1611 if self.options.client || self.options.server {
1612 Some(Self::doc_link_components(
1613 schema,
1614 resolver,
1615 &[
1616 &names::event_args(svc.name().value(), ev.name().value()),
1617 fallback.name().value(),
1618 ],
1619 ))
1620 } else {
1621 None
1622 }
1623 }
1624
1625 ResolvedLink::EventFallback(schema, svc, fallback) => {
1626 if self.options.client {
1627 Some(Self::doc_link_components(
1628 schema,
1629 resolver,
1630 &[
1631 &names::service_event(svc.name().value()),
1632 &names::event_variant(fallback.name().value()),
1633 ],
1634 ))
1635 } else {
1636 None
1637 }
1638 }
1639
1640 ResolvedLink::Const(schema, const_def) => Some(Self::doc_link_components(
1641 schema,
1642 resolver,
1643 &[const_def.name().value()],
1644 )),
1645
1646 ResolvedLink::Newtype(schema, newtype) => Some(Self::doc_link_components(
1647 schema,
1648 resolver,
1649 &[newtype.name().value()],
1650 )),
1651 }
1652 }
1653
1654 fn doc_link_base(schema: &Schema, resolver: LinkResolver) -> String {
1655 if schema.name() == resolver.schema().name() {
1656 String::new()
1657 } else {
1658 format!("super::{}::", schema.name())
1659 }
1660 }
1661
1662 fn doc_link_components(schema: &Schema, resolver: LinkResolver, components: &[&str]) -> String {
1663 let mut link = Self::doc_link_base(schema, resolver);
1664
1665 for (i, component) in components.iter().enumerate() {
1666 if i > 0 {
1667 link.push_str("::");
1668 }
1669
1670 link.push_str(component);
1671 }
1672
1673 link
1674 }
1675}
1676
1677struct RustAttributes {
1678 impl_copy: bool,
1679 impl_partial_eq: bool,
1680 impl_eq: bool,
1681 impl_partial_ord: bool,
1682 impl_ord: bool,
1683 impl_hash: bool,
1684}
1685
1686impl RustAttributes {
1687 fn new() -> Self {
1688 Self {
1689 impl_copy: false,
1690 impl_partial_eq: false,
1691 impl_eq: false,
1692 impl_partial_ord: false,
1693 impl_ord: false,
1694 impl_hash: false,
1695 }
1696 }
1697
1698 fn parse(attrs: &[ast::Attribute]) -> Self {
1699 let mut res = Self::new();
1700
1701 for attr in attrs {
1702 if attr.name().value() != "rust" {
1703 continue;
1704 }
1705
1706 for opt in attr.options() {
1707 match opt.value() {
1708 "impl_copy" => res.impl_copy = true,
1709 "impl_partial_eq" => res.impl_partial_eq = true,
1710 "impl_eq" => res.impl_eq = true,
1711 "impl_partial_ord" => res.impl_partial_ord = true,
1712 "impl_ord" => res.impl_ord = true,
1713 "impl_hash" => res.impl_hash = true,
1714 _ => {}
1715 }
1716 }
1717 }
1718
1719 res
1720 }
1721
1722 fn additional_derives(&self) -> String {
1723 let mut derives = String::new();
1724
1725 if self.impl_copy {
1726 derives.push_str(", ::std::marker::Copy");
1727 }
1728
1729 if self.impl_partial_eq {
1730 derives.push_str(", ");
1731 derives.push_str(PARTIAL_EQ);
1732 }
1733
1734 if self.impl_eq {
1735 derives.push_str(", ");
1736 derives.push_str(EQ);
1737 }
1738
1739 if self.impl_partial_ord {
1740 derives.push_str(", ");
1741 derives.push_str(PARTIAL_ORD);
1742 }
1743
1744 if self.impl_ord {
1745 derives.push_str(", ");
1746 derives.push_str(ORD);
1747 }
1748
1749 if self.impl_hash {
1750 derives.push_str(", ");
1751 derives.push_str(HASH);
1752 }
1753
1754 derives
1755 }
1756}