1pub mod walker;
2
3#[cfg(feature = "psql")]
4pub mod psql;
5
6#[cfg(feature = "async-psql")]
7pub mod async_psql;
8
9#[cfg(any(feature = "psql", feature = "async-psql"))]
10pub(crate) mod shared_psql;
11
12use crate::gen::Generator;
13use crate::model::rust::{DataEnum, Field};
14use crate::model::rust::{EncodingOrdering, PlainEnum};
15use crate::model::Model;
16use crate::model::Rust;
17use crate::model::RustType;
18use crate::model::TagProperty;
19use crate::model::{Definition, Tag, Type as AsnType, Type};
20use codegen::Block;
21use codegen::Enum;
22use codegen::Impl;
23use codegen::Scope;
24use codegen::Struct;
25use std::borrow::Cow;
26use std::convert::Infallible;
27use std::fmt::Display;
28
29#[cfg(feature = "psql")]
30use self::psql::PsqlInserter;
31
32#[cfg(feature = "async-psql")]
33use self::async_psql::AsyncPsqlInserter;
34
35const KEYWORDS: [&str; 9] = [
36 "use", "mod", "const", "type", "pub", "enum", "struct", "impl", "trait",
37];
38
39pub trait GeneratorSupplement<T> {
40 fn add_imports(&self, scope: &mut Scope);
41 fn impl_supplement(&self, scope: &mut Scope, definition: &Definition<T>);
42 fn extend_impl_of_struct(&self, _name: &str, _impl_scope: &mut Impl, _fields: &[Field]) {}
43 fn extend_impl_of_enum(&self, _name: &str, _impl_scope: &mut Impl, _enumeration: &PlainEnum) {}
44 fn extend_impl_of_data_enum(
45 &self,
46 _name: &str,
47 _impl_scope: &mut Impl,
48 _enumeration: &DataEnum,
49 ) {
50 }
51 fn extend_impl_of_tuple(&self, _name: &str, _impl_scope: &mut Impl, _definition: &RustType) {}
52}
53
54#[allow(clippy::module_name_repetitions)]
55#[derive(Debug)]
56pub struct RustCodeGenerator {
57 models: Vec<Model<Rust>>,
58 global_derives: Vec<String>,
59 direct_field_access: bool,
60 getter_and_setter: bool,
61}
62
63impl From<Model<Rust>> for RustCodeGenerator {
64 fn from(model: Model<Rust>) -> Self {
65 let mut gen = Self::default();
66 gen.add_model(model);
67 gen
68 }
69}
70
71impl Default for RustCodeGenerator {
72 fn default() -> Self {
73 RustCodeGenerator {
74 models: Default::default(),
75 global_derives: Vec::default(),
76 direct_field_access: true,
77 getter_and_setter: false,
78 }
79 }
80}
81
82impl Generator<Rust> for RustCodeGenerator {
83 type Error = Infallible;
84
85 fn add_model(&mut self, model: Model<Rust>) {
86 self.models.push(model);
87 }
88
89 fn models(&self) -> &[Model<Rust>] {
90 &self.models[..]
91 }
92
93 fn models_mut(&mut self) -> &mut [Model<Rust>] {
94 &mut self.models[..]
95 }
96
97 fn to_string(&self) -> Result<Vec<(String, String)>, Self::Error> {
98 Ok(self.to_string_with_generators(&[
99 #[cfg(feature = "psql")]
100 &PsqlInserter,
101 #[cfg(feature = "async-psql")]
102 &AsyncPsqlInserter,
103 ]))
104 }
105}
106
107impl RustCodeGenerator {
108 pub fn add_global_derive<I: Into<String>>(&mut self, derive: I) {
109 self.global_derives.push(derive.into());
110 }
111
112 pub fn without_additional_global_derives(mut self) -> Self {
113 self.global_derives.clear();
114 self
115 }
116
117 pub const fn fields_are_pub(&self) -> bool {
118 self.direct_field_access
119 }
120
121 pub fn set_fields_pub(&mut self, allow: bool) {
122 self.direct_field_access = allow;
123 }
124
125 pub const fn fields_have_getter_and_setter(&self) -> bool {
126 self.getter_and_setter
127 }
128
129 pub fn set_fields_have_getter_and_setter(&mut self, allow: bool) {
130 self.getter_and_setter = allow;
131 }
132
133 pub fn to_string_without_generators(&self) -> Vec<(String, String)> {
134 self.to_string_with_generators(&[])
135 }
136
137 pub fn to_string_with_generators(
138 &self,
139 generators: &[&dyn GeneratorSupplement<Rust>],
140 ) -> Vec<(String, String)> {
141 let mut files = Vec::new();
142 for model in &self.models {
143 files.push(self.model_to_file(model, generators));
144 }
145 files
146 }
147
148 pub fn model_to_file(
149 &self,
150 model: &Model<Rust>,
151 generators: &[&dyn GeneratorSupplement<Rust>],
152 ) -> (String, String) {
153 let file = {
154 let mut string = Self::rust_module_name(&model.name);
155 string.push_str(".rs");
156 string
157 };
158
159 let mut scope = Scope::new();
160 generators.iter().for_each(|g| g.add_imports(&mut scope));
161
162 scope.import("asn1rs::prelude", "*");
163 for import in &model.imports {
164 let from = format!("super::{}", &Self::rust_module_name(&import.from));
165 for what in &import.what {
166 scope.import(&from, what);
167 }
168 }
169
170 for vref in &model.value_references {
171 scope.raw(&Self::fmt_const(
172 &vref.name,
173 &vref.role,
174 &vref.value.as_rust_const_literal(true),
175 0,
176 ));
177 }
178
179 for definition in &model.definitions {
180 self.add_definition(&mut scope, definition);
181 Self::impl_definition(&mut scope, definition, generators, self.getter_and_setter);
182
183 generators
184 .iter()
185 .for_each(|g| g.impl_supplement(&mut scope, definition));
186 }
187
188 (file, scope.to_string())
189 }
190
191 fn fmt_const(name: &str, r#type: &RustType, value: &impl Display, indent: usize) -> String {
192 format!(
193 "{}pub const {}: {} = {};",
194 " ".repeat(indent),
195 name,
196 r#type.to_const_lit_string(),
197 if let RustType::Complex(..) = r#type {
198 format!("{}::new({})", r#type.to_const_lit_string(), value)
199 } else {
200 value.to_string()
201 }
202 )
203 }
204
205 pub fn add_definition(&self, scope: &mut Scope, Definition(name, rust): &Definition<Rust>) {
206 match rust {
207 Rust::Struct {
208 fields,
209 tag,
210 extension_after,
211 ordering,
212 } => {
213 scope.raw(&Self::asn_attribute(
214 match ordering {
215 EncodingOrdering::Keep => "sequence",
216 EncodingOrdering::Sort => "set",
217 },
218 *tag,
219 extension_after.map(|index| fields[index].name().to_string()),
220 &[],
221 ));
222 Self::add_struct(
223 self.new_struct(scope, name),
224 name,
225 fields,
226 self.direct_field_access,
227 )
228 }
229 Rust::Enum(plain) => {
230 scope.raw(&Self::asn_attribute(
231 "enumerated",
232 plain.tag(),
233 plain.extension_after_variant().cloned(),
234 &[],
235 ));
236 Self::add_enum(
237 self.new_enum(scope, name, true).derive("Default"),
238 name,
239 plain,
240 )
241 }
242 Rust::DataEnum(data) => {
243 scope.raw(&Self::asn_attribute(
244 "choice",
245 data.tag(),
246 data.extension_after_variant().map(|v| v.name().to_string()),
247 &[],
248 ));
249 Self::add_data_enum(self.new_enum(scope, name, false), name, data)
250 }
251 Rust::TupleStruct {
252 r#type,
253 tag,
254 constants,
255 } => {
256 scope.raw(&Self::asn_attribute("transparent", *tag, None, &[]));
257 Self::add_tuple_struct(
258 self.new_struct(scope, name),
259 name,
260 r#type,
261 self.direct_field_access,
262 None,
263 &constants[..],
264 )
265 }
266 }
267 }
268
269 fn add_struct(str_ct: &mut Struct, _name: &str, fields: &[Field], pub_access: bool) {
270 for field in fields {
271 str_ct.field(
272 &format!(
273 "{} {}{}",
274 Self::asn_attribute(
275 Self::asn_attribute_type(&field.r#type().clone().into_asn()),
276 field.tag(),
277 None,
278 field.constants(),
279 ),
280 if pub_access { "pub " } else { "" },
281 Self::rust_field_name(field.name(), true),
282 ),
283 field.r#type().to_string(),
284 );
285 }
286 }
287
288 fn add_enum(en_m: &mut Enum, _name: &str, rust_enum: &PlainEnum) {
289 for (index, variant) in rust_enum.variants().enumerate() {
290 let name = Self::rust_variant_name(variant);
291 let name = if index == 0 {
292 format!("#[default] {name}")
293 } else {
294 name
295 };
296 en_m.new_variant(&name);
297 }
298 }
299
300 fn add_data_enum(en_m: &mut Enum, _name: &str, enumeration: &DataEnum) {
301 for variant in enumeration.variants() {
302 en_m.new_variant(&format!(
303 "{} {}({})",
304 Self::asn_attribute(
305 Self::asn_attribute_type(&variant.r#type().clone().into_asn()),
306 variant.tag(),
307 None,
308 &[],
309 ),
310 Self::rust_variant_name(variant.name()),
311 variant.r#type().to_string(),
312 ));
313 }
314 }
315
316 fn add_tuple_struct(
317 str_ct: &mut Struct,
318 _name: &str,
319 inner: &RustType,
320 pub_access: bool,
321 tag: Option<Tag>,
322 constants: &[(String, String)],
323 ) {
324 str_ct.tuple_field(format!(
325 "{} {}{}",
326 Self::asn_attribute(
327 Self::asn_attribute_type(&inner.clone().into_asn()),
328 tag,
329 None,
330 constants,
331 ),
332 if pub_access { "pub " } else { "" },
333 inner.to_string(),
334 ));
335 }
336
337 fn asn_attribute<T: ToString>(
338 r#type: T,
339 tag: Option<Tag>,
340 extensible_after: Option<String>,
341 constants: &[(String, String)],
342 ) -> String {
343 format!(
344 "#[asn({})]",
345 vec![
346 Some(r#type.to_string()),
347 tag.map(Self::asn_attribute_tag),
348 extensible_after.map(Self::asn_attribute_extensible_after),
349 if constants.is_empty() {
350 None
351 } else {
352 Some(format!(
353 "const({})",
354 constants
355 .iter()
356 .map(|(name, value)| format!("{}({})", name, value))
357 .collect::<Vec<_>>()
358 .join(", ")
359 ))
360 }
361 ]
362 .into_iter()
363 .flatten()
364 .collect::<Vec<_>>()
365 .join(", ")
366 )
367 }
368
369 fn asn_attribute_type(r#type: &AsnType) -> String {
370 let (name, parameters) = match r#type {
371 Type::Boolean => (Cow::Borrowed("boolean"), Vec::default()),
372 Type::Integer(integer) => (
373 Cow::Borrowed("integer"),
374 vec![format!(
375 "{}..{}{}",
376 integer
377 .range
378 .min()
379 .as_ref()
380 .map(ToString::to_string)
381 .unwrap_or_else(|| "min".to_string()),
382 integer
383 .range
384 .max()
385 .as_ref()
386 .map(ToString::to_string)
387 .unwrap_or_else(|| "max".to_string()),
388 if integer.range.extensible() {
389 ",..."
390 } else {
391 ""
392 }
393 )],
394 ),
395 Type::String(size, charset) => (
396 Cow::Owned(format!("{:?}string", charset).to_lowercase()),
397 vec![size.to_constraint_string()]
398 .into_iter()
399 .flatten()
400 .collect(),
401 ),
402 Type::OctetString(size) => (
403 Cow::Borrowed("octet_string"),
404 vec![size.to_constraint_string()]
405 .into_iter()
406 .flatten()
407 .collect(),
408 ),
409 Type::BitString(bitstring) => (
410 Cow::Borrowed("bit_string"),
411 vec![vec![bitstring.size.to_constraint_string()]
412 .into_iter()
413 .flatten()
414 .collect()],
415 ),
416 Type::Null => (Cow::Borrowed("null"), Vec::default()),
417 Type::Optional(inner) => (
418 Cow::Borrowed("optional"),
419 vec![Self::asn_attribute_type(inner)],
420 ),
421 Type::Default(inner, default) => (
422 Cow::Borrowed("default"),
423 vec![
424 Self::asn_attribute_type(inner),
425 default.as_rust_const_literal(true).to_string(),
426 ],
427 ),
428 Type::SequenceOf(inner, size) => (
429 Cow::Borrowed("sequence_of"),
430 vec![
431 size.to_constraint_string(),
432 Some(Self::asn_attribute_type(inner)),
433 ]
434 .into_iter()
435 .flatten()
436 .collect(),
437 ),
438 Type::SetOf(inner, size) => (
439 Cow::Borrowed("set_of"),
440 vec![
441 size.to_constraint_string(),
442 Some(Self::asn_attribute_type(inner)),
443 ]
444 .into_iter()
445 .flatten()
446 .collect(),
447 ),
448
449 Type::Sequence(_) => (Cow::Borrowed("sequence"), Vec::default()),
450 Type::Set(_) => (Cow::Borrowed("set"), Vec::default()),
451 Type::Enumerated(_) => (Cow::Borrowed("enumerated"), Vec::default()),
452 Type::Choice(_) => (Cow::Borrowed("choice"), Vec::default()),
453 Type::TypeReference(inner, tag) => (
454 Cow::Borrowed("complex"),
455 vec![Some(inner.clone()), (*tag).map(Self::asn_attribute_tag)]
456 .into_iter()
457 .flatten()
458 .collect(),
459 ),
460 };
461 if parameters.is_empty() {
462 name.into_owned()
463 } else {
464 format!("{}({})", name, parameters.join(", "))
465 }
466 }
467
468 fn asn_attribute_tag(tag: Tag) -> String {
469 match tag {
470 Tag::Universal(t) => format!("tag(UNIVERSAL({}))", t),
471 Tag::Application(t) => format!("tag(APPLICATION({}))", t),
472 Tag::Private(t) => format!("tag(PRIVATE({}))", t),
473 Tag::ContextSpecific(t) => format!("tag({})", t),
474 }
475 }
476
477 fn asn_attribute_extensible_after(variant: String) -> String {
478 format!("extensible_after({})", variant)
479 }
480
481 fn impl_definition(
482 scope: &mut Scope,
483 Definition(name, rust): &Definition<Rust>,
484 generators: &[&dyn GeneratorSupplement<Rust>],
485 getter_and_setter: bool,
486 ) {
487 match rust {
488 Rust::Struct {
489 fields,
490 tag: _,
491 extension_after: _,
492 ordering: _,
493 } => {
494 Self::impl_consts(
495 scope,
496 name,
497 fields
498 .iter()
499 .map(|f| (f.name_type.0.as_str(), &f.name_type.1, &f.constants[..])),
500 );
501 let implementation = Self::impl_struct(scope, name, fields, getter_and_setter);
502 for g in generators {
503 g.extend_impl_of_struct(name, implementation, fields);
504 }
505 }
506 Rust::Enum(r_enum) => {
507 let implementation = Self::impl_enum(scope, name, r_enum);
508 for g in generators {
509 g.extend_impl_of_enum(name, implementation, r_enum);
510 }
511 }
512 Rust::DataEnum(enumeration) => {
513 let implementation = Self::impl_data_enum(scope, name, enumeration);
514 for g in generators {
515 g.extend_impl_of_data_enum(name, implementation, enumeration);
516 }
517 Self::impl_data_enum_default(scope, name, enumeration);
518 }
519 Rust::TupleStruct {
520 r#type: inner,
521 tag: _,
522 constants,
523 } => {
524 Self::impl_consts(scope, name, Some(("", inner, &constants[..])).into_iter());
525 let implementation = Self::impl_tuple_struct(scope, name, inner);
526 for g in generators {
527 g.extend_impl_of_tuple(name, implementation, inner);
528 }
529 Self::impl_tuple_struct_const_new(scope, name, inner);
530 Self::impl_tuple_struct_deref(scope, name, inner);
531 Self::impl_tuple_struct_deref_mut(scope, name, inner);
532 Self::impl_tuple_struct_from(scope, name, inner);
533 }
534 }
535 }
536
537 fn impl_tuple_struct_const_new(scope: &mut Scope, name: &str, rust: &RustType) {
538 scope
539 .new_impl(name)
540 .new_fn("new")
541 .vis("pub const")
542 .arg("value", rust.to_string())
543 .ret("Self")
544 .line("Self(value)");
545 }
546
547 fn impl_tuple_struct_deref(scope: &mut Scope, name: &str, rust: &RustType) {
548 scope
549 .new_impl(name)
550 .impl_trait("::core::ops::Deref")
551 .associate_type("Target", rust.to_string())
552 .new_fn("deref")
553 .arg_ref_self()
554 .ret(&format!("&{}", rust.to_string()))
555 .line("&self.0".to_string());
556 }
557
558 fn impl_tuple_struct_deref_mut(scope: &mut Scope, name: &str, rust: &RustType) {
559 scope
560 .new_impl(name)
561 .impl_trait("::core::ops::DerefMut")
562 .new_fn("deref_mut")
563 .arg_mut_self()
564 .ret(&format!("&mut {}", rust.to_string()))
565 .line("&mut self.0".to_string());
566 }
567
568 fn impl_tuple_struct_from(scope: &mut Scope, name: &str, rust: &RustType) {
569 scope
570 .new_impl(name)
571 .impl_trait(format!("::core::convert::From<{}>", rust.to_string()))
572 .new_fn("from")
573 .arg("value", &rust.to_string())
574 .ret("Self")
575 .line("Self(value)");
576 scope
577 .new_impl(&rust.to_string())
578 .impl_trait(format!("::core::convert::From<{}>", name))
579 .new_fn("from")
580 .arg("value", name)
581 .ret("Self")
582 .line("value.0");
583 }
584
585 fn impl_tuple_struct<'a>(scope: &'a mut Scope, name: &str, rust: &RustType) -> &'a mut Impl {
586 let implementation = scope.new_impl(name);
587 Self::add_min_max_fn_if_applicable(implementation, None, rust);
588 implementation
589 }
590
591 fn impl_struct<'a>(
592 scope: &'a mut Scope,
593 name: &str,
594 fields: &[Field],
595 getter_and_setter: bool,
596 ) -> &'a mut Impl {
597 let implementation = scope.new_impl(name);
598
599 for field in fields {
600 if getter_and_setter {
601 Self::impl_struct_field_get(implementation, field.name(), field.r#type());
602 Self::impl_struct_field_get_mut(implementation, field.name(), field.r#type());
603 Self::impl_struct_field_set(implementation, field.name(), field.r#type());
604 }
605
606 Self::add_min_max_fn_if_applicable(implementation, Some(field.name()), field.r#type());
607 }
608 implementation
609 }
610
611 fn impl_consts<'a>(
612 scope: &mut Scope,
613 name: &str,
614 fields: impl Iterator<Item = (&'a str, &'a RustType, &'a [(String, String)])>,
615 ) {
616 let mut found_consts = false;
617 for (field, r#type, constants) in fields {
618 if !found_consts && !constants.is_empty() {
619 scope.raw(&format!("impl {} {{", name));
620 found_consts = true;
621 }
622 for (name, value) in constants {
623 scope.raw(&Self::fmt_const(
624 &if field.is_empty() {
625 Cow::Borrowed(name)
626 } else {
627 Cow::Owned(format!("{}_{}", field.to_uppercase(), name))
628 },
629 r#type,
630 value,
631 1,
632 ));
633 }
634 }
635 if found_consts {
636 scope.raw("}");
637 }
638 }
639
640 fn impl_struct_field_get(implementation: &mut Impl, field_name: &str, field_type: &RustType) {
641 implementation
642 .new_fn(&Self::rust_field_name(field_name, true))
643 .vis("pub")
644 .arg_ref_self()
645 .ret(format!("&{}", field_type.to_string()))
646 .line(format!("&self.{}", Self::rust_field_name(field_name, true)));
647 }
648
649 fn impl_struct_field_get_mut(
650 implementation: &mut Impl,
651 field_name: &str,
652 field_type: &RustType,
653 ) {
654 implementation
655 .new_fn(&format!("{}_mut", field_name))
656 .vis("pub")
657 .arg_mut_self()
658 .ret(format!("&mut {}", field_type.to_string()))
659 .line(format!(
660 "&mut self.{}",
661 Self::rust_field_name(field_name, true)
662 ));
663 }
664
665 fn impl_struct_field_set(implementation: &mut Impl, field_name: &str, field_type: &RustType) {
666 implementation
667 .new_fn(&format!("set_{}", field_name))
668 .vis("pub")
669 .arg_mut_self()
670 .arg("value", field_type.to_string())
671 .line(format!(
672 "self.{} = value;",
673 Self::rust_field_name(field_name, true)
674 ));
675 }
676
677 fn impl_enum<'a>(scope: &'a mut Scope, name: &str, r_enum: &PlainEnum) -> &'a mut Impl {
678 let implementation = scope.new_impl(name);
679
680 Self::impl_enum_value_fn(implementation, name, r_enum);
681 Self::impl_enum_values_fn(implementation, name, r_enum);
682 Self::impl_enum_value_index_fn(implementation, name, r_enum);
683 implementation
684 }
685
686 fn impl_enum_value_fn(implementation: &mut Impl, name: &str, r_enum: &PlainEnum) {
687 let value_fn = implementation
688 .new_fn("variant")
689 .vis("pub")
690 .arg("index", "usize")
691 .ret("Option<Self>");
692
693 let mut block_match = Block::new("match index");
694
695 for (index, variant) in r_enum.variants().enumerate() {
696 block_match.line(format!(
697 "{} => Some({}::{}),",
698 index,
699 name,
700 Self::rust_variant_name(variant)
701 ));
702 }
703 block_match.line("_ => None,");
704 value_fn.push_block(block_match);
705 }
706
707 fn impl_enum_values_fn(implementation: &mut Impl, name: &str, r_enum: &PlainEnum) {
708 let values_fn = implementation
709 .new_fn("variants")
710 .vis("pub const")
711 .ret(format!("[Self; {}]", r_enum.len()))
712 .line("[");
713
714 for variant in r_enum.variants() {
715 values_fn.line(format!("{}::{},", name, Self::rust_variant_name(variant)));
716 }
717 values_fn.line("]");
718 }
719
720 fn impl_enum_value_index_fn(implementation: &mut Impl, name: &str, r_enum: &PlainEnum) {
721 let ordinal_fn = implementation
722 .new_fn("value_index")
723 .arg_self()
724 .vis("pub")
725 .ret("usize");
726
727 let mut block = Block::new("match self");
728 r_enum
729 .variants()
730 .enumerate()
731 .for_each(|(ordinal, variant)| {
732 block.line(format!(
733 "{}::{} => {},",
734 name,
735 Self::rust_variant_name(variant),
736 ordinal
737 ));
738 });
739
740 ordinal_fn.push_block(block);
741 }
742
743 fn impl_data_enum<'a>(
744 scope: &'a mut Scope,
745 name: &str,
746 enumeration: &DataEnum,
747 ) -> &'a mut Impl {
748 let implementation = scope.new_impl(name);
749
750 Self::impl_data_enum_values_fn(implementation, name, enumeration);
751 Self::impl_data_enum_value_index_fn(implementation, name, enumeration);
752
753 for variant in enumeration.variants() {
754 let field_name = Self::rust_module_name(variant.name());
755 Self::add_min_max_fn_if_applicable(implementation, Some(&field_name), variant.r#type());
756 }
757
758 implementation
759 }
760
761 fn impl_data_enum_values_fn(implementation: &mut Impl, name: &str, enumeration: &DataEnum) {
762 let values_fn = implementation
763 .new_fn("variants")
764 .vis("pub")
765 .ret(format!("[Self; {}]", enumeration.len()))
766 .line("[");
767
768 for variant in enumeration.variants() {
769 values_fn.line(format!(
770 "{}::{}(Default::default()),",
771 name,
772 Self::rust_variant_name(variant.name())
773 ));
774 }
775 values_fn.line("]");
776 }
777
778 fn impl_data_enum_value_index_fn(
779 implementation: &mut Impl,
780 name: &str,
781 enumeration: &DataEnum,
782 ) {
783 let ordinal_fn = implementation
784 .new_fn("value_index")
785 .arg_ref_self()
786 .vis("pub")
787 .ret("usize");
788
789 let mut block = Block::new("match self");
790 enumeration
791 .variants()
792 .enumerate()
793 .for_each(|(ordinal, variant)| {
794 block.line(format!(
795 "{}::{}(_) => {},",
796 name,
797 Self::rust_variant_name(variant.name()),
798 ordinal
799 ));
800 });
801
802 ordinal_fn.push_block(block);
803 }
804
805 fn impl_data_enum_default(scope: &mut Scope, name: &str, enumeration: &DataEnum) {
806 scope
807 .new_impl(name)
808 .impl_trait("Default")
809 .new_fn("default")
810 .ret(name as &str)
811 .line(format!(
812 "{}::{}(Default::default())",
813 name,
814 Self::rust_variant_name(enumeration.variants().next().unwrap().name())
815 ));
816 }
817
818 fn add_min_max_fn_if_applicable(
819 implementation: &mut Impl,
820 field_name: Option<&str>,
821 field_type: &RustType,
822 ) {
823 let prefix = if let Some(field_name) = field_name {
824 format!("{}_", field_name)
825 } else {
826 "value_".to_string()
827 };
828 if let Some(range) = field_type.integer_range_str() {
829 implementation
830 .new_fn(&format!("{}min", prefix))
831 .vis("pub const")
832 .ret(&field_type.to_inner_type_string())
833 .line(&Self::format_number_nicely(range.min()));
834 implementation
835 .new_fn(&format!("{}max", prefix))
836 .vis("pub const")
837 .ret(&field_type.to_inner_type_string())
838 .line(&Self::format_number_nicely(range.max()));
839 }
840 }
841
842 fn format_number_nicely(string: &str) -> String {
843 let mut out = String::with_capacity(string.len() * 2);
844 let mut pos = (3 - string.len() % 3) % 3;
845 for char in string.chars() {
846 out.push(char);
847 pos = (pos + 1) % 3;
848 if pos == 0 && char.is_numeric() {
849 out.push('_');
850 }
851 }
852 let len = out.len();
853 out.remove(len - 1);
854 out
855 }
856
857 pub fn rust_field_name(name: &str, check_for_keywords: bool) -> String {
858 let mut name = name.replace('-', "_");
859 if check_for_keywords {
860 for keyword in &KEYWORDS {
861 if keyword.eq(&name) {
862 name.push('_');
863 return name;
864 }
865 }
866 }
867 name
868 }
869
870 pub fn rust_variant_name(name: &str) -> String {
871 let mut out = String::new();
872 let mut next_upper = true;
873 for c in name.chars() {
874 if next_upper {
875 out.push_str(&c.to_uppercase().to_string());
876 next_upper = false;
877 } else if c == '-' || c == '_' {
878 next_upper = true;
879 } else {
880 out.push(c);
881 }
882 }
883 out
884 }
885
886 pub fn rust_module_name(name: &str) -> String {
887 let mut out = String::new();
888 let mut prev_lowered = false;
889 let mut chars = name.chars().peekable();
890 while let Some(c) = chars.next() {
891 let mut lowered = false;
892 if c.is_uppercase() {
893 if !out.is_empty() {
894 if !prev_lowered {
895 out.push('_');
896 } else if let Some(next) = chars.peek() {
897 if next.is_lowercase() {
898 out.push('_');
899 }
900 }
901 }
902 lowered = true;
903 out.push_str(&c.to_lowercase().to_string());
904 } else if c == '-' {
905 out.push('_');
906 } else {
907 out.push(c);
908 }
909 prev_lowered = lowered;
910 }
911 out
912 }
913
914 fn new_struct<'a>(&self, scope: &'a mut Scope, name: &str) -> &'a mut Struct {
915 let str_ct = scope
916 .new_struct(name)
917 .vis("pub")
918 .derive("Default")
919 .derive("Debug")
920 .derive("Clone")
921 .derive("PartialEq")
922 .derive("Hash");
923 self.global_derives.iter().for_each(|derive| {
924 str_ct.derive(derive);
925 });
926 str_ct
927 }
928
929 fn new_enum<'a>(&self, scope: &'a mut Scope, name: &str, c_enum: bool) -> &'a mut Enum {
930 let en_m = scope
931 .new_enum(name)
932 .vis("pub")
933 .derive("Debug")
934 .derive("Clone")
935 .derive("PartialEq")
936 .derive("Hash");
937 if c_enum {
938 en_m.derive("Copy").derive("PartialOrd").derive("Eq");
939 }
940 self.global_derives.iter().for_each(|derive| {
941 en_m.derive(derive);
942 });
943 en_m
944 }
945}
946
947#[cfg(test)]
948pub(crate) mod tests {
949 use super::*;
950 use crate::gen::rust::walker::tests::assert_starts_with_lines;
951 use crate::parser::Tokenizer;
952
953 #[test]
954 pub fn test_integer_struct_constants() {
955 let model = Model::try_from(Tokenizer::default().parse(
956 r#"BasicInteger DEFINITIONS AUTOMATIC TAGS ::=
957 BEGIN
958
959 MyStruct ::= SEQUENCE {
960 item INTEGER { apple(8), banana(9) } (0..255)
961 }
962
963 END
964 "#,
965 ))
966 .unwrap()
967 .try_resolve()
968 .unwrap()
969 .to_rust();
970
971 let (_file_name, file_content) = RustCodeGenerator::from(model)
972 .without_additional_global_derives()
973 .to_string_without_generators()
974 .into_iter()
975 .next()
976 .unwrap();
977
978 assert_starts_with_lines(
979 r#"
980 use asn1rs::prelude::*;
981
982 #[asn(sequence)]
983 #[derive(Default, Debug, Clone, PartialEq, Hash)]
984 pub struct MyStruct {
985 #[asn(integer(0..255), const(APPLE(8), BANANA(9)))] pub item: u8,
986 }
987
988 impl MyStruct {
989 pub const ITEM_APPLE: u8 = 8;
990 pub const ITEM_BANANA: u8 = 9;
991 }
992
993 "#,
994 &file_content,
995 );
996 }
997
998 #[test]
999 pub fn test_integer_tuple_constants() {
1000 let model = Model::try_from(Tokenizer::default().parse(
1001 r#"BasicInteger DEFINITIONS AUTOMATIC TAGS ::=
1002 BEGIN
1003
1004 MyTuple ::= INTEGER { abc(8), bernd(9) } (0..255)
1005
1006 END
1007 "#,
1008 ))
1009 .unwrap()
1010 .try_resolve()
1011 .unwrap()
1012 .to_rust();
1013
1014 let (_file_name, file_content) = RustCodeGenerator::from(model)
1015 .without_additional_global_derives()
1016 .to_string_without_generators()
1017 .into_iter()
1018 .next()
1019 .unwrap();
1020
1021 assert_starts_with_lines(
1022 r#"
1023 use asn1rs::prelude::*;
1024
1025 #[asn(transparent)]
1026 #[derive(Default, Debug, Clone, PartialEq, Hash)]
1027 pub struct MyTuple(#[asn(integer(0..255), const(ABC(8), BERND(9)))] pub u8);
1028
1029 impl MyTuple {
1030 pub const ABC: u8 = 8;
1031 pub const BERND: u8 = 9;
1032 }
1033
1034 "#,
1035 &file_content,
1036 );
1037 }
1038}