1#[cfg(test)]
2mod test;
3
4use crate::error::Error;
5use crate::Options;
6use aldrin_parser::{ast, Parsed, Schema};
7use diffy::Patch;
8use heck::ToUpperCamelCase;
9use std::fmt::Write;
10use std::fs;
11use std::path::Path;
12
13const BOOL: &str = "::std::primitive::bool";
14const BOX: &str = "::std::boxed::Box";
15const CLONE: &str = "::std::clone::Clone";
16const DEBUG: &str = "::std::fmt::Debug";
17const DEFAULT: &str = "::std::default::Default";
18const F32: &str = "::std::primitive::f32";
19const F64: &str = "::std::primitive::f64";
20const HASH_MAP: &str = "::std::collections::HashMap";
21const HASH_SET: &str = "::std::collections::HashSet";
22const I16: &str = "::std::primitive::i16";
23const I32: &str = "::std::primitive::i32";
24const I64: &str = "::std::primitive::i64";
25const I8: &str = "::std::primitive::i8";
26const OK: &str = "::std::result::Result::Ok";
27const OPTION: &str = "::std::option::Option";
28const RESULT: &str = "::std::result::Result";
29const STR: &str = "::std::primitive::str";
30const STRING: &str = "::std::string::String";
31const U16: &str = "::std::primitive::u16";
32const U32: &str = "::std::primitive::u32";
33const U64: &str = "::std::primitive::u64";
34const U8: &str = "::std::primitive::u8";
35const VEC: &str = "::std::vec::Vec";
36
37#[derive(Debug, Clone)]
38#[non_exhaustive]
39pub struct RustOptions<'a> {
40 pub patches: Vec<&'a Path>,
41 pub introspection_if: Option<&'a str>,
42 pub krate: &'a str,
43}
44
45impl RustOptions<'_> {
46 pub fn new() -> Self {
47 RustOptions {
48 patches: Vec::new(),
49 introspection_if: None,
50 krate: "::aldrin",
51 }
52 }
53}
54
55impl Default for RustOptions<'_> {
56 fn default() -> Self {
57 RustOptions::new()
58 }
59}
60
61#[derive(Debug, Clone)]
62pub struct RustOutput {
63 pub module_name: String,
64 pub module_content: String,
65}
66
67pub(crate) fn generate(
68 parsed: &Parsed,
69 options: &Options,
70 rust_options: &RustOptions,
71) -> Result<RustOutput, Error> {
72 let schema = parsed.main_schema();
73
74 let generator = RustGenerator {
75 schema,
76 options,
77 rust_options,
78 output: RustOutput {
79 module_name: schema.name().to_owned(),
80 module_content: String::new(),
81 },
82 };
83
84 generator.generate()
85}
86
87struct RustGenerator<'a> {
88 schema: &'a Schema,
89 options: &'a Options,
90 rust_options: &'a RustOptions<'a>,
91 output: RustOutput,
92}
93
94macro_rules! code {
95 ($this:expr, $arg:literal) => {
96 write!($this.output.module_content, $arg).unwrap()
97 };
98}
99
100macro_rules! codeln {
101 ($this:expr) => {
102 writeln!($this.output.module_content).unwrap()
103 };
104
105 ($this:expr, $arg:literal) => {
106 writeln!($this.output.module_content, $arg).unwrap()
107 };
108}
109
110#[rustfmt::skip::macros(code, codeln)]
111impl RustGenerator<'_> {
112 fn generate(mut self) -> Result<RustOutput, Error> {
113 for def in self.schema.definitions() {
114 self.definition(def);
115 }
116
117 if self.options.introspection {
118 let krate = self.rust_options.krate;
119
120 if let Some(feature) = self.rust_options.introspection_if {
121 codeln!(self, "#[cfg(feature = \"{feature}\")]");
122 }
123
124 codeln!(self, "pub fn register_introspection(client: &{krate}::Handle) -> {RESULT}<(), {krate}::Error> {{");
125
126 for def in self.schema.definitions() {
127 self.register_introspection(def);
128 }
129
130 codeln!(self, " {OK}(())");
131 codeln!(self, "}}");
132 }
133
134 for patch in &self.rust_options.patches {
135 self.patch(patch)?;
136 }
137
138 Ok(self.output)
139 }
140
141 fn patch(&mut self, patch: &Path) -> Result<(), Error> {
142 let patch = fs::read_to_string(patch)?;
143 let patch = Patch::from_str(&patch)?;
144 self.output.module_content = diffy::apply(&self.output.module_content, &patch)?;
145 Ok(())
146 }
147
148 fn definition(&mut self, def: &ast::Definition) {
149 match def {
150 ast::Definition::Struct(d) => self.struct_def(
151 d.name().value(),
152 Some(d.attributes()),
153 d.fields(),
154 d.fallback(),
155 ),
156
157 ast::Definition::Enum(e) => self.enum_def(
158 e.name().value(),
159 Some(e.attributes()),
160 e.variants(),
161 e.fallback(),
162 ),
163
164 ast::Definition::Service(s) => self.service_def(s),
165 ast::Definition::Const(c) => self.const_def(c),
166 }
167 }
168
169 fn struct_def(
170 &mut self,
171 name: &str,
172 attrs: Option<&[ast::Attribute]>,
173 fields: &[ast::StructField],
174 fallback: Option<&ast::Ident>,
175 ) {
176 let krate = self.rust_options.krate;
177 let ident = format!("r#{name}");
178 let attrs = attrs
179 .map(RustAttributes::parse)
180 .unwrap_or_else(RustAttributes::new);
181 let num_required_fields = fields.iter().filter(|&f| f.required()).count();
182 let has_required_fields = num_required_fields > 0;
183 let schema_name = self.schema.name();
184 let additional_derives = attrs.additional_derives();
185
186 let derive_default = if has_required_fields {
187 String::new()
188 } else {
189 format!(", {DEFAULT}")
190 };
191
192 let derive_introspectable =
193 if self.options.introspection && self.rust_options.introspection_if.is_none() {
194 format!(", {krate}::Introspectable")
195 } else {
196 String::new()
197 };
198
199 codeln!(self, "#[derive({DEBUG}, {CLONE}{derive_default}, {krate}::Serialize, {krate}::Deserialize, {krate}::AsSerializeArg{derive_introspectable}{additional_derives})]");
200
201 if self.options.introspection {
202 if let Some(feature) = self.rust_options.introspection_if {
203 codeln!(self, "#[cfg_attr(feature = \"{feature}\", derive({krate}::Introspectable))]");
204 }
205 }
206
207 codeln!(self, "#[aldrin(crate = \"{krate}::core\", schema = \"{schema_name}\")]");
208 codeln!(self, "pub struct {ident} {{");
209 let mut first = true;
210 for field in fields {
211 let id = field.id().value();
212 let ident = format!("r#{}", field.name().value());
213 let ty = self.type_name(field.field_type());
214
215 if first {
216 first = false;
217 } else {
218 codeln!(self);
219 }
220
221 if field.required() {
222 codeln!(self, " #[aldrin(id = {id})]");
223 codeln!(self, " pub {ident}: {ty},");
224 } else {
225 codeln!(self, " #[aldrin(id = {id}, optional)]");
226 codeln!(self, " pub {ident}: {OPTION}<{ty}>,");
227 }
228 }
229 if let Some(fallback) = fallback {
230 if !first {
231 codeln!(self);
232 }
233
234 let ident = format!("r#{}", fallback.value());
235 codeln!(self, " #[aldrin(fallback)]");
236 codeln!(self, " pub {ident}: {krate}::core::UnknownFields,");
237 }
238 codeln!(self, "}}");
239 codeln!(self);
240
241 if !has_required_fields {
242 codeln!(self, "impl {ident} {{");
243 codeln!(self, " pub fn new() -> Self {{");
244 codeln!(self, " <Self as {DEFAULT}>::default()");
245 codeln!(self, " }}");
246 codeln!(self, "}}");
247 codeln!(self);
248 }
249 }
250
251 fn enum_def(
252 &mut self,
253 name: &str,
254 attrs: Option<&[ast::Attribute]>,
255 vars: &[ast::EnumVariant],
256 fallback: Option<&ast::Ident>,
257 ) {
258 let ident = format!("r#{name}");
259 let krate = &self.rust_options.krate;
260 let schema_name = self.schema.name();
261
262 let attrs = attrs
263 .map(RustAttributes::parse)
264 .unwrap_or_else(RustAttributes::new);
265 let additional_derives = attrs.additional_derives();
266
267 let derive_introspectable =
268 if self.options.introspection && self.rust_options.introspection_if.is_none() {
269 format!(", {krate}::Introspectable")
270 } else {
271 String::new()
272 };
273
274 codeln!(self, "#[derive({DEBUG}, {CLONE}, {krate}::Serialize, {krate}::Deserialize, {krate}::AsSerializeArg{derive_introspectable}{additional_derives})]");
275
276 if self.options.introspection {
277 if let Some(feature) = self.rust_options.introspection_if {
278 codeln!(self, "#[cfg_attr(feature = \"{feature}\", derive({krate}::Introspectable))]");
279 }
280 }
281
282 codeln!(self, "#[aldrin(crate = \"{krate}::core\", schema = \"{schema_name}\")]");
283 codeln!(self, "pub enum {ident} {{");
284 let mut first = true;
285 for var in vars {
286 let id = var.id().value();
287 let ident = format!("r#{}", var.name().value());
288
289 if first {
290 first = false;
291 } else {
292 codeln!(self);
293 }
294
295 codeln!(self, " #[aldrin(id = {id})]");
296 if let Some(ty) = var.variant_type() {
297 let ty = self.type_name(ty);
298 codeln!(self, " {ident}({ty}),");
299 } else {
300 codeln!(self, " {ident},");
301 }
302 }
303 if let Some(fallback) = fallback {
304 if !first {
305 codeln!(self);
306 }
307
308 let ident = format!("r#{}", fallback.value());
309 codeln!(self, " #[aldrin(fallback)]");
310 codeln!(self, " {ident}({krate}::core::UnknownVariant),");
311 }
312 codeln!(self, "}}");
313 codeln!(self);
314 }
315
316 fn service_def(&mut self, svc: &ast::ServiceDef) {
317 if !self.options.client && !self.options.server {
318 return;
319 }
320
321 let krate = self.rust_options.krate;
322 let schema = self.schema.name();
323 let svc_name = svc.name().value();
324 let ident = format!("r#{svc_name}");
325 let uuid = svc.uuid().value();
326 let version = svc.version().value();
327
328 codeln!(self, "{krate}::service! {{");
329
330 code!(self, " #[aldrin(crate = \"{krate}\", schema = \"{schema}\"");
331
332 if !self.options.client {
333 code!(self, ", no_client");
334 }
335
336 if !self.options.server {
337 code!(self, ", no_server");
338 }
339
340 if self.options.introspection {
341 code!(self, ", introspection");
342 }
343
344 if let Some(feature) = self.rust_options.introspection_if {
345 code!(self, ", introspection_if = \"{feature}\"");
346 }
347
348 codeln!(self, ")]");
349
350 codeln!(self, " pub service {ident} {{");
351 codeln!(self, " uuid = {krate}::core::ServiceUuid({krate}::private::uuid::uuid!(\"{uuid}\"));");
352 codeln!(self, " version = {version};");
353
354 for item in svc.items() {
355 codeln!(self);
356
357 match item {
358 ast::ServiceItem::Function(func) => {
359 let name = func.name().value();
360 let ident = format!("r#{name}");
361 let id = func.id().value();
362
363 code!(self, " fn {ident} @ {id}");
364
365 if let (None, Some(ok), None) = (func.args(), func.ok(), func.err()) {
366 let ty = self.function_ok_type_name(svc_name, name, ok, true);
367 codeln!(self, " = {ty};");
368 } else if func.args().is_some() || func.ok().is_some() || func.err().is_some() {
369 codeln!(self, " {{");
370
371 if let Some(args) = func.args() {
372 let ty = self.function_args_type_name(svc_name, name, args, true);
373 codeln!(self, " args = {ty};");
374 }
375
376 if let Some(ok) = func.ok() {
377 let ty = self.function_ok_type_name(svc_name, name, ok, true);
378 codeln!(self, " ok = {ty};");
379 }
380
381 if let Some(err) = func.err() {
382 let ty = self.function_err_type_name(svc_name, name, err, true);
383 codeln!(self, " err = {ty};");
384 }
385
386 codeln!(self, " }}");
387 } else {
388 codeln!(self, ";");
389 }
390 }
391
392 ast::ServiceItem::Event(ev) => {
393 let name = ev.name().value();
394 let ident = format!("r#{name}");
395 let id = ev.id().value();
396
397 code!(self, " event {ident} @ {id}");
398
399 if let Some(ty) = ev.event_type() {
400 let ty = self.event_variant_type(svc_name, name, ty, true);
401 code!(self, " = {ty}");
402 }
403
404 codeln!(self, ";");
405 }
406 }
407 }
408
409 if let Some(fallback) = svc.function_fallback() {
410 let name = fallback.name().value();
411 let ident = format!("r#{name}");
412
413 codeln!(self);
414 codeln!(self, " fn {ident} = {krate}::UnknownCall;");
415 }
416
417 if let Some(fallback) = svc.event_fallback() {
418 let name = fallback.name().value();
419 let ident = format!("r#{name}");
420
421 codeln!(self);
422 codeln!(self, " event {ident} = {krate}::UnknownEvent;");
423 }
424
425 codeln!(self, " }}");
426 codeln!(self, "}}");
427 codeln!(self);
428
429 for item in svc.items() {
430 match item {
431 ast::ServiceItem::Function(func) => {
432 let func_name = func.name().value();
433
434 if let Some(args) = func.args() {
435 match args.part_type() {
436 ast::TypeNameOrInline::Struct(s) => self.struct_def(
437 &self.function_args_type_name(svc_name, func_name, args, false),
438 None,
439 s.fields(),
440 s.fallback(),
441 ),
442
443 ast::TypeNameOrInline::Enum(e) => self.enum_def(
444 &self.function_args_type_name(svc_name, func_name, args, false),
445 None,
446 e.variants(),
447 e.fallback(),
448 ),
449
450 ast::TypeNameOrInline::TypeName(_) => {}
451 }
452 }
453
454 if let Some(ok) = func.ok() {
455 match ok.part_type() {
456 ast::TypeNameOrInline::Struct(s) => self.struct_def(
457 &self.function_ok_type_name(svc_name, func_name, ok, false),
458 None,
459 s.fields(),
460 s.fallback(),
461 ),
462
463 ast::TypeNameOrInline::Enum(e) => self.enum_def(
464 &self.function_ok_type_name(svc_name, func_name, ok, false),
465 None,
466 e.variants(),
467 e.fallback(),
468 ),
469
470 ast::TypeNameOrInline::TypeName(_) => {}
471 }
472 }
473
474 if let Some(err) = func.err() {
475 match err.part_type() {
476 ast::TypeNameOrInline::Struct(s) => self.struct_def(
477 &self.function_err_type_name(svc_name, func_name, err, false),
478 None,
479 s.fields(),
480 s.fallback(),
481 ),
482
483 ast::TypeNameOrInline::Enum(e) => self.enum_def(
484 &self.function_err_type_name(svc_name, func_name, err, false),
485 None,
486 e.variants(),
487 e.fallback(),
488 ),
489
490 ast::TypeNameOrInline::TypeName(_) => {}
491 }
492 }
493 }
494
495 ast::ServiceItem::Event(ev) => {
496 if let Some(ty) = ev.event_type() {
497 let ev_name = ev.name().value();
498
499 match ty {
500 ast::TypeNameOrInline::Struct(s) => self.struct_def(
501 &self.event_variant_type(svc_name, ev_name, ty, false),
502 None,
503 s.fields(),
504 s.fallback(),
505 ),
506
507 ast::TypeNameOrInline::Enum(e) => self.enum_def(
508 &self.event_variant_type(svc_name, ev_name, ty, false),
509 None,
510 e.variants(),
511 e.fallback(),
512 ),
513
514 ast::TypeNameOrInline::TypeName(_) => {}
515 }
516 }
517 }
518 }
519 }
520 }
521
522 fn const_def(&mut self, const_def: &ast::ConstDef) {
523 let krate = self.rust_options.krate;
524 let name = const_def.name().value();
525
526 match const_def.value() {
527 ast::ConstValue::U8(v) => {
528 let val = v.value();
529 codeln!(self, "pub const {name}: {U8} = {val};");
530 }
531
532 ast::ConstValue::I8(v) => {
533 let val = v.value();
534 codeln!(self, "pub const {name}: {I8} = {val};");
535 }
536
537 ast::ConstValue::U16(v) => {
538 let val = v.value();
539 codeln!(self, "pub const {name}: {U16} = {val};");
540 }
541
542 ast::ConstValue::I16(v) => {
543 let val = v.value();
544 codeln!(self, "pub const {name}: {I16} = {val};");
545 }
546
547 ast::ConstValue::U32(v) => {
548 let val = v.value();
549 codeln!(self, "pub const {name}: {U32} = {val};");
550 }
551
552 ast::ConstValue::I32(v) => {
553 let val = v.value();
554 codeln!(self, "pub const {name}: {I32} = {val};");
555 }
556
557 ast::ConstValue::U64(v) => {
558 let val = v.value();
559 codeln!(self, "pub const {name}: {U64} = {val};");
560 }
561
562 ast::ConstValue::I64(v) => {
563 let val = v.value();
564 codeln!(self, "pub const {name}: {I64} = {val};");
565 }
566
567 ast::ConstValue::String(v) => {
568 let val = v.value();
569 codeln!(self, "pub const {name}: &{STR} = \"{val}\";");
570 }
571
572 ast::ConstValue::Uuid(v) => {
573 let val = v.value();
574 codeln!(self, "pub const {name}: {krate}::private::uuid::Uuid = {krate}::private::uuid::uuid!(\"{val}\");");
575 }
576 };
577
578 codeln!(self);
579 }
580
581 fn register_introspection(&mut self, def: &ast::Definition) {
582 match def {
583 ast::Definition::Struct(d) => {
584 let ident = format!("r#{}", d.name().value());
585 codeln!(self, " client.register_introspection::<{ident}>()?;");
586 }
587
588 ast::Definition::Enum(e) => {
589 let ident = format!("r#{}", e.name().value());
590 codeln!(self, " client.register_introspection::<{ident}>()?;");
591 }
592
593 ast::Definition::Service(s) => {
594 if self.options.client || self.options.server {
595 let ident = format!("r#{}", s.name().value());
596 codeln!(self, " client.register_introspection::<{ident}Introspection>()?;");
597 }
598 }
599
600 ast::Definition::Const(_) => {}
601 }
602 }
603
604 fn type_name(&self, ty: &ast::TypeName) -> String {
605 let krate = self.rust_options.krate;
606
607 match ty.kind() {
608 ast::TypeNameKind::Bool => BOOL.to_owned(),
609 ast::TypeNameKind::U8 => U8.to_owned(),
610 ast::TypeNameKind::I8 => I8.to_owned(),
611 ast::TypeNameKind::U16 => U16.to_owned(),
612 ast::TypeNameKind::I16 => I16.to_owned(),
613 ast::TypeNameKind::U32 => U32.to_owned(),
614 ast::TypeNameKind::I32 => I32.to_owned(),
615 ast::TypeNameKind::U64 => U64.to_owned(),
616 ast::TypeNameKind::I64 => I64.to_owned(),
617 ast::TypeNameKind::F32 => F32.to_owned(),
618 ast::TypeNameKind::F64 => F64.to_owned(),
619 ast::TypeNameKind::String => STRING.to_owned(),
620 ast::TypeNameKind::Uuid => format!("{krate}::private::uuid::Uuid"),
621 ast::TypeNameKind::ObjectId => format!("{krate}::core::ObjectId"),
622 ast::TypeNameKind::ServiceId => format!("{krate}::core::ServiceId"),
623 ast::TypeNameKind::Value => format!("{krate}::core::SerializedValue"),
624 ast::TypeNameKind::Option(ty) => format!("{OPTION}<{}>", self.type_name(ty)),
625 ast::TypeNameKind::Box(ty) => format!("{BOX}<{}>", self.type_name(ty)),
626
627 ast::TypeNameKind::Vec(ty) => match ty.kind() {
628 ast::TypeNameKind::U8 => format!("{krate}::core::Bytes"),
629 _ => format!("{VEC}<{}>", self.type_name(ty)),
630 },
631
632 ast::TypeNameKind::Bytes => format!("{krate}::core::Bytes"),
633
634 ast::TypeNameKind::Map(k, v) => format!(
635 "{HASH_MAP}<{}, {}>",
636 self.key_type_name(k),
637 self.type_name(v)
638 ),
639
640 ast::TypeNameKind::Set(ty) => format!("{HASH_SET}<{}>", self.key_type_name(ty)),
641
642 ast::TypeNameKind::Sender(ty) => {
643 format!("{krate}::UnboundSender<{}>", self.type_name(ty))
644 }
645
646 ast::TypeNameKind::Receiver(ty) => {
647 format!("{krate}::UnboundReceiver<{}>", self.type_name(ty))
648 }
649
650 ast::TypeNameKind::Lifetime => format!("{krate}::LifetimeId"),
651 ast::TypeNameKind::Unit => "()".to_owned(),
652
653 ast::TypeNameKind::Result(ok, err) => {
654 format!("{RESULT}<{}, {}>", self.type_name(ok), self.type_name(err))
655 }
656
657 ast::TypeNameKind::Array(ty, len) => self.array_name(ty, len),
658 ast::TypeNameKind::Ref(ty) => self.named_ref_name(ty),
659 }
660 }
661
662 fn array_name(&self, ty: &ast::TypeName, len: &ast::ArrayLen) -> String {
663 match len.value() {
664 ast::ArrayLenValue::Literal(len) => {
665 format!("[{}; {}usize]", self.type_name(ty), len.value())
666 }
667
668 ast::ArrayLenValue::Ref(named_ref) => {
669 format!(
670 "[{}; {} as usize]",
671 self.type_name(ty),
672 self.named_ref_name(named_ref)
673 )
674 }
675 }
676 }
677
678 fn named_ref_name(&self, ty: &ast::NamedRef) -> String {
679 match ty.kind() {
680 ast::NamedRefKind::Intern(ty) => format!("r#{}", ty.value().to_owned()),
681 ast::NamedRefKind::Extern(m, ty) => format!("super::r#{}::r#{}", m.value(), ty.value()),
682 }
683 }
684
685 fn function_args_type_name(
686 &self,
687 svc_name: &str,
688 func_name: &str,
689 part: &ast::FunctionPart,
690 raw: bool,
691 ) -> String {
692 match part.part_type() {
693 ast::TypeNameOrInline::TypeName(ty) => self.type_name(ty),
694
695 ast::TypeNameOrInline::Struct(_) | ast::TypeNameOrInline::Enum(_) => {
696 if raw {
697 format!("r#{svc_name}{}Args", func_name.to_upper_camel_case())
698 } else {
699 format!("{svc_name}{}Args", func_name.to_upper_camel_case())
700 }
701 }
702 }
703 }
704
705 fn function_ok_type_name(
706 &self,
707 svc_name: &str,
708 func_name: &str,
709 part: &ast::FunctionPart,
710 raw: bool,
711 ) -> String {
712 match part.part_type() {
713 ast::TypeNameOrInline::TypeName(ty) => self.type_name(ty),
714
715 ast::TypeNameOrInline::Struct(_) | ast::TypeNameOrInline::Enum(_) => {
716 if raw {
717 format!("r#{svc_name}{}Ok", func_name.to_upper_camel_case())
718 } else {
719 format!("{svc_name}{}Ok", func_name.to_upper_camel_case())
720 }
721 }
722 }
723 }
724
725 fn function_err_type_name(
726 &self,
727 svc_name: &str,
728 func_name: &str,
729 part: &ast::FunctionPart,
730 raw: bool,
731 ) -> String {
732 match part.part_type() {
733 ast::TypeNameOrInline::TypeName(ty) => self.type_name(ty),
734
735 ast::TypeNameOrInline::Struct(_) | ast::TypeNameOrInline::Enum(_) => {
736 if raw {
737 format!("r#{svc_name}{}Error", func_name.to_upper_camel_case())
738 } else {
739 format!("{svc_name}{}Error", func_name.to_upper_camel_case())
740 }
741 }
742 }
743 }
744
745 fn event_variant_type(
746 &self,
747 svc_name: &str,
748 ev_name: &str,
749 ev_type: &ast::TypeNameOrInline,
750 raw: bool,
751 ) -> String {
752 match ev_type {
753 ast::TypeNameOrInline::TypeName(ty) => self.type_name(ty),
754
755 ast::TypeNameOrInline::Struct(_) | ast::TypeNameOrInline::Enum(_) => {
756 if raw {
757 format!("r#{svc_name}{}Event", service_event_variant(ev_name))
758 } else {
759 format!("{svc_name}{}Event", service_event_variant(ev_name))
760 }
761 }
762 }
763 }
764
765 fn key_type_name(&self, ty: &ast::KeyTypeName) -> String {
766 let krate = self.rust_options.krate;
767
768 match ty.kind() {
769 ast::KeyTypeNameKind::U8 => U8.to_owned(),
770 ast::KeyTypeNameKind::I8 => I8.to_owned(),
771 ast::KeyTypeNameKind::U16 => U16.to_owned(),
772 ast::KeyTypeNameKind::I16 => I16.to_owned(),
773 ast::KeyTypeNameKind::U32 => U32.to_owned(),
774 ast::KeyTypeNameKind::I32 => I32.to_owned(),
775 ast::KeyTypeNameKind::U64 => U64.to_owned(),
776 ast::KeyTypeNameKind::I64 => I64.to_owned(),
777 ast::KeyTypeNameKind::String => STRING.to_owned(),
778 ast::KeyTypeNameKind::Uuid => format!("{krate}::private::uuid::Uuid"),
779 }
780 }
781}
782
783fn service_event_variant(ev_name: &str) -> String {
784 ev_name.to_upper_camel_case()
785}
786
787struct RustAttributes {
788 impl_copy: bool,
789 impl_partial_eq: bool,
790 impl_eq: bool,
791 impl_partial_ord: bool,
792 impl_ord: bool,
793 impl_hash: bool,
794}
795
796impl RustAttributes {
797 fn new() -> Self {
798 Self {
799 impl_copy: false,
800 impl_partial_eq: false,
801 impl_eq: false,
802 impl_partial_ord: false,
803 impl_ord: false,
804 impl_hash: false,
805 }
806 }
807
808 fn parse(attrs: &[ast::Attribute]) -> Self {
809 let mut res = Self::new();
810
811 for attr in attrs {
812 if attr.name().value() != "rust" {
813 continue;
814 }
815
816 for opt in attr.options() {
817 match opt.value() {
818 "impl_copy" => res.impl_copy = true,
819 "impl_partial_eq" => res.impl_partial_eq = true,
820 "impl_eq" => res.impl_eq = true,
821 "impl_partial_ord" => res.impl_partial_ord = true,
822 "impl_ord" => res.impl_ord = true,
823 "impl_hash" => res.impl_hash = true,
824 _ => {}
825 }
826 }
827 }
828
829 res
830 }
831
832 fn additional_derives(&self) -> String {
833 let mut derives = String::new();
834
835 if self.impl_copy {
836 derives.push_str(", ::std::marker::Copy");
837 }
838
839 if self.impl_partial_eq {
840 derives.push_str(", ::std::cmp::PartialEq");
841 }
842
843 if self.impl_eq {
844 derives.push_str(", ::std::cmp::Eq");
845 }
846
847 if self.impl_partial_ord {
848 derives.push_str(", ::std::cmp::PartialOrd");
849 }
850
851 if self.impl_ord {
852 derives.push_str(", ::std::cmp::Ord");
853 }
854
855 if self.impl_hash {
856 derives.push_str(", ::std::hash::Hash");
857 }
858
859 derives
860 }
861}