1use crate::ast::*;
4use std::collections::{HashMap, HashSet};
5use std::fmt::Write;
6
7#[derive(Debug, Clone, Default, PartialEq, Eq)]
37pub enum StringTypeMode {
38 #[default]
41 Owned,
42 Borrowed,
46}
47
48#[derive(Debug, Clone, Default, PartialEq, Eq)]
59pub enum DeriveMode {
60 #[default]
67 FeatureGated,
68 Always,
73 Custom(String),
79}
80
81#[derive(Debug, Clone, Default)]
83pub struct CodeGenConfig {
84 pub module_path_prefix: Option<String>,
87 pub use_core: bool,
90 pub skip_imported_types: std::collections::HashSet<String>,
93 pub imported_type_lifetimes: std::collections::HashMap<String, String>,
97 pub string_type_mode: StringTypeMode,
102 pub any_as_raw_der: bool,
113 pub derive_mode: DeriveMode,
121 pub raw_der_fields: std::collections::HashSet<String>,
134 pub known_choice_types: std::collections::HashSet<String>,
149}
150
151impl CodeGenConfig {
152 pub fn with_lifetime(
154 mut self,
155 type_name: impl Into<String>,
156 lifetime: impl Into<String>,
157 ) -> Self {
158 self.imported_type_lifetimes
159 .insert(type_name.into(), lifetime.into());
160 self
161 }
162
163 pub fn with_x509_lifetimes(mut self) -> Self {
167 let skip_types = vec![
169 "AlgorithmIdentifier",
170 "SubjectPublicKeyInfo",
171 "TBSCertificate",
172 "Certificate",
173 "Validity", ];
175
176 let types_with_lifetimes = vec![
178 "AlgorithmIdentifier",
179 "SubjectPublicKeyInfo",
180 "TBSCertificate",
181 "Certificate",
182 ];
185
186 for type_name in skip_types {
187 self.skip_imported_types.insert(type_name.to_string());
188 }
189
190 for type_name in types_with_lifetimes {
191 self.imported_type_lifetimes
192 .insert(type_name.to_string(), "'a".to_string());
193 }
194
195 self
196 }
197}
198
199impl CodeGenConfig {
200 pub fn with_crate_imports() -> Self {
202 Self {
203 module_path_prefix: Some("crate".to_string()),
204 ..Default::default()
205 }
206 }
207
208 pub fn with_super_imports() -> Self {
210 Self {
211 module_path_prefix: Some("super".to_string()),
212 ..Default::default()
213 }
214 }
215
216 pub fn with_custom_prefix(prefix: impl Into<String>) -> Self {
218 Self {
219 module_path_prefix: Some(prefix.into()),
220 ..Default::default()
221 }
222 }
223}
224
225fn is_rust_keyword(s: &str) -> bool {
227 matches!(
228 s,
229 "as" | "break"
230 | "const"
231 | "continue"
232 | "crate"
233 | "else"
234 | "enum"
235 | "extern"
236 | "false"
237 | "fn"
238 | "for"
239 | "if"
240 | "impl"
241 | "in"
242 | "let"
243 | "loop"
244 | "match"
245 | "mod"
246 | "move"
247 | "mut"
248 | "pub"
249 | "ref"
250 | "return"
251 | "self"
252 | "Self"
253 | "static"
254 | "struct"
255 | "super"
256 | "trait"
257 | "true"
258 | "type"
259 | "unsafe"
260 | "use"
261 | "where"
262 | "while"
263 | "async"
264 | "await"
265 | "dyn"
266 | "abstract"
267 | "become"
268 | "box"
269 | "do"
270 | "final"
271 | "macro"
272 | "override"
273 | "priv"
274 | "typeof"
275 | "unsized"
276 | "virtual"
277 | "yield"
278 | "try"
279 )
280}
281
282fn escape_rust_keyword(s: String) -> String {
284 if is_rust_keyword(&s) {
285 format!("r#{}", s)
286 } else {
287 s
288 }
289}
290
291fn to_snake_case(s: &str) -> String {
293 let mut result = String::new();
294 let mut prev_lower = false;
295
296 for (i, ch) in s.chars().enumerate() {
297 if ch == '-' {
298 result.push('_');
299 prev_lower = false;
300 } else if ch.is_uppercase() {
301 if i > 0 && prev_lower {
302 result.push('_');
303 }
304 result.push(ch.to_ascii_lowercase());
305 prev_lower = false;
306 } else {
307 result.push(ch);
308 prev_lower = ch.is_lowercase();
309 }
310 }
311
312 escape_rust_keyword(result)
313}
314
315fn to_pascal_case(s: &str) -> String {
324 s.split('-').map(pascal_segment).collect()
325}
326
327fn pascal_segment(seg: &str) -> String {
329 if seg.is_empty() {
330 return String::new();
331 }
332 let all_caps = seg.chars().all(|c| !c.is_alphabetic() || c.is_uppercase());
335 let mut out = String::with_capacity(seg.len());
336 for (i, c) in seg.chars().enumerate() {
337 if i == 0 {
338 out.push(c.to_ascii_uppercase());
339 } else if all_caps && c.is_alphabetic() {
340 out.push(c.to_ascii_lowercase());
341 } else {
342 out.push(c);
343 }
344 }
345 out
346}
347
348fn to_screaming_snake_case(s: &str) -> String {
350 let mut result = String::new();
351 let mut prev_lower = false;
352
353 for (i, ch) in s.chars().enumerate() {
354 if ch == '-' {
355 result.push('_');
356 prev_lower = false;
357 } else if ch.is_ascii_uppercase() {
358 if i > 0 && prev_lower {
359 result.push('_');
360 }
361 result.push(ch);
362 prev_lower = false;
363 } else {
364 result.push(ch.to_ascii_uppercase());
365 prev_lower = true;
366 }
367 }
368
369 result
370}
371
372fn module_name_to_rust(s: &str) -> String {
374 to_snake_case(s)
377}
378
379pub struct CodeGenerator {
381 output: String,
382 config: CodeGenConfig,
383 pattern_counter: usize, imported_types: HashSet<String>, types_with_lifetimes: HashSet<String>, type_definitions: HashMap<String, Type>, }
388
389impl CodeGenerator {
390 pub fn new() -> Self {
391 Self {
392 output: String::new(),
393 config: CodeGenConfig::default(),
394 pattern_counter: 0,
395 imported_types: HashSet::new(),
396 types_with_lifetimes: HashSet::new(),
397 type_definitions: HashMap::new(),
398 }
399 }
400
401 pub fn with_config(config: CodeGenConfig) -> Self {
402 Self {
403 output: String::new(),
404 config,
405 pattern_counter: 0,
406 imported_types: HashSet::new(),
407 types_with_lifetimes: HashSet::new(),
408 type_definitions: HashMap::new(),
409 }
410 }
411
412 fn try_from_path(&self) -> &'static str {
418 "core"
419 }
420
421 fn derive_feature_name(&self) -> Option<&str> {
424 match &self.config.derive_mode {
425 DeriveMode::Always => None,
426 DeriveMode::FeatureGated => Some("derive"),
427 DeriveMode::Custom(name) => Some(name.as_str()),
428 }
429 }
430
431 fn derive_cfg_attr(&self, attr: &str) -> String {
437 match self.derive_feature_name() {
438 None => format!("#[{}]", attr),
439 Some(feat) => format!("#[cfg_attr(feature = \"{}\", {})]", feat, attr),
440 }
441 }
442
443 fn field_derive_cfg_attr(&self, attr: &str) -> String {
445 match self.derive_feature_name() {
446 None => format!(" #[{}]", attr),
447 Some(feat) => format!(" #[cfg_attr(feature = \"{}\", {})]", feat, attr),
448 }
449 }
450
451 fn has_pattern_constraints(&self, module: &Module) -> bool {
453 for def in &module.definitions {
454 if self.type_has_pattern(&def.ty) {
455 return true;
456 }
457 }
458 false
459 }
460
461 fn type_has_pattern(&self, ty: &Type) -> bool {
463 match ty {
464 Type::Constrained {
465 constraint,
466 base_type,
467 } => {
468 if let ConstraintSpec::Subtype(subtype) = &constraint.spec {
469 if self.constraint_has_pattern(subtype) {
470 return true;
471 }
472 }
473 self.type_has_pattern(base_type)
474 }
475 Type::Sequence(fields) | Type::Set(fields) => {
476 fields.iter().any(|f| self.type_has_pattern(&f.ty))
477 }
478 Type::Choice(variants) => variants.iter().any(|v| self.type_has_pattern(&v.ty)),
479 Type::SequenceOf(inner, _) | Type::SetOf(inner, _) => self.type_has_pattern(inner),
480 Type::Tagged { inner, .. } => self.type_has_pattern(inner),
481 _ => false,
482 }
483 }
484
485 fn constraint_has_pattern(&self, constraint: &SubtypeConstraint) -> bool {
487 match constraint {
488 SubtypeConstraint::Pattern(_) => true,
489 SubtypeConstraint::SizeConstraint(inner)
490 | SubtypeConstraint::InnerType(inner)
491 | SubtypeConstraint::Complement(inner) => self.constraint_has_pattern(inner),
492 SubtypeConstraint::Union(elements) | SubtypeConstraint::Intersection(elements) => {
493 elements.iter().any(|e| self.constraint_has_pattern(e))
494 }
495 _ => false,
496 }
497 }
498
499 pub fn generate_module(&mut self, module: &Module) -> Result<String, std::fmt::Error> {
501 writeln!(
503 &mut self.output,
504 "// Auto-generated from ASN.1 module: {}",
505 module.name
506 )?;
507 writeln!(&mut self.output)?;
508
509 if !module.exports.is_empty() {
511 writeln!(&mut self.output, "// EXPORTS:")?;
512 for export in &module.exports {
513 writeln!(&mut self.output, "// {}", export)?;
514 }
515 writeln!(&mut self.output)?;
516 }
517
518 if !module.imports.is_empty() {
520 writeln!(&mut self.output, "// IMPORTS:")?;
521 for import in &module.imports {
522 write!(&mut self.output, "// ")?;
523 for (i, symbol) in import.symbols.iter().enumerate() {
524 if i > 0 {
525 write!(&mut self.output, ", ")?;
526 }
527 write!(&mut self.output, "{}", symbol)?;
528 }
529 writeln!(&mut self.output, " FROM {}", import.module_name)?;
530 }
531 writeln!(&mut self.output)?;
532 }
533
534 writeln!(&mut self.output, "#[allow(unused_imports)]")?;
538 writeln!(&mut self.output, "use synta::types::string::*;")?;
539 writeln!(&mut self.output, "#[allow(unused_imports)]")?;
543 writeln!(
544 &mut self.output,
545 "use synta::{{Encode, Decode, Tagged, Encoder, Decoder, \
546 GeneralizedTime, ObjectIdentifier, UtcTime, \
547 Integer, Boolean, Enumerated, Null, Real, \
548 ExplicitTag, ImplicitTag, Element, RawDer, SetOf}};"
549 )?;
550 let derive_feat = self.derive_feature_name().map(str::to_owned);
551 if let Some(feat) = derive_feat {
552 writeln!(&mut self.output, "#[cfg(feature = \"{feat}\")]")?;
553 }
554 writeln!(&mut self.output, "#[allow(unused_imports)]")?;
555 writeln!(
556 &mut self.output,
557 "use synta_derive::{{Asn1Sequence, Asn1Choice, Asn1Set}};"
558 )?;
559
560 if self.has_pattern_constraints(module) {
562 writeln!(&mut self.output, "#[cfg(feature = \"regex\")]")?;
563 writeln!(&mut self.output, "use regex::Regex;")?;
564 writeln!(&mut self.output, "#[cfg(feature = \"regex\")]")?;
565 writeln!(&mut self.output, "use once_cell::sync::Lazy;")?;
566 }
567 writeln!(&mut self.output)?;
568
569 if let Some(ref prefix) = self.config.module_path_prefix {
571 if !module.imports.is_empty() {
572 for import in &module.imports {
573 let module_path = module_name_to_rust(&import.module_name);
574 write!(&mut self.output, "use {}::{}", prefix, module_path)?;
575
576 if import.symbols.len() == 1 {
577 writeln!(&mut self.output, "::{};", import.symbols[0])?;
578 } else {
579 write!(&mut self.output, "::{{")?;
580 for (i, symbol) in import.symbols.iter().enumerate() {
581 if i > 0 {
582 write!(&mut self.output, ", ")?;
583 }
584 write!(&mut self.output, "{}", symbol)?;
585 }
586 writeln!(&mut self.output, "}};")?;
587 }
588 }
589 writeln!(&mut self.output)?;
590 }
591 }
592
593 self.imported_types = module
595 .imports
596 .iter()
597 .flat_map(|import| import.symbols.iter())
598 .cloned()
599 .collect();
600
601 if !module.values.is_empty() {
603 writeln!(
604 &mut self.output,
605 "// ============================================================================"
606 )?;
607 writeln!(&mut self.output, "// Constants")?;
608 writeln!(
609 &mut self.output,
610 "// ============================================================================\n"
611 )?;
612
613 let oid_registry = self.build_oid_registry(&module.values);
615
616 for value_assignment in &module.values {
617 self.generate_value_assignment(value_assignment, &oid_registry)?;
618 }
619 writeln!(&mut self.output)?;
620 }
621
622 for def in &module.definitions {
624 let type_name = to_pascal_case(&def.name);
625 self.type_definitions.insert(type_name, def.ty.clone());
626 }
627
628 self.prescan_types_for_lifetimes(&module.definitions);
631
632 for def in &module.definitions {
634 if self.config.skip_imported_types.contains(&def.name) {
636 continue;
637 }
638
639 self.generate_definition(def)?;
640 writeln!(&mut self.output)?;
641 }
642
643 Ok(self.output.clone())
644 }
645
646 fn generate_definition(&mut self, def: &Definition) -> Result<(), std::fmt::Error> {
647 let type_name = to_pascal_case(&def.name);
648
649 match &def.ty {
650 Type::Sequence(fields) => {
651 self.generate_sequence_type(&type_name, fields)?;
652 }
653 Type::Set(fields) => {
654 self.generate_set_type(&type_name, fields)?;
655 }
656 Type::Choice(variants) => {
657 self.generate_choice_type(&type_name, variants)?;
658 }
659 Type::SequenceOf(inner, size_constraint) => {
660 self.generate_sequence_of_type(&type_name, inner, size_constraint.as_ref())?;
661 }
662 Type::SetOf(inner, size_constraint) => {
663 self.generate_set_of_type(&type_name, inner, size_constraint.as_ref())?;
664 }
665 Type::Constrained {
667 base_type,
668 constraint,
669 } => {
670 match (base_type.as_ref(), &constraint.spec) {
671 (
672 Type::Integer(_, named_numbers),
673 ConstraintSpec::Subtype(subtype_constraint),
674 ) => {
675 self.generate_constrained_integer(&type_name, subtype_constraint)?;
676
677 if !named_numbers.is_empty() {
679 let prim = Self::constrained_integer_rust_type(subtype_constraint);
680 writeln!(&mut self.output)?;
681 writeln!(&mut self.output, "impl {} {{", type_name)?;
682
683 for named_number in named_numbers {
684 let const_name = to_screaming_snake_case(&named_number.name);
685 writeln!(
686 &mut self.output,
687 " pub const {}: {} = {};",
688 const_name, prim, named_number.value
689 )?;
690 }
691
692 writeln!(&mut self.output, "}}")?;
693 }
694 }
695 (Type::IA5String(_), ConstraintSpec::Subtype(subtype_constraint)) => {
696 self.generate_constrained_string(
697 &type_name,
698 "IA5String",
699 subtype_constraint,
700 )?;
701 }
702 (Type::PrintableString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
703 self.generate_constrained_string(
704 &type_name,
705 "PrintableString",
706 subtype_constraint,
707 )?;
708 }
709 (Type::Utf8String(_), ConstraintSpec::Subtype(subtype_constraint)) => {
710 self.generate_constrained_string(
711 &type_name,
712 "Utf8String",
713 subtype_constraint,
714 )?;
715 }
716 (Type::TeletexString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
717 self.generate_constrained_string(
718 &type_name,
719 "TeletexString",
720 subtype_constraint,
721 )?;
722 }
723 (Type::UniversalString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
724 self.generate_constrained_string(
725 &type_name,
726 "UniversalString",
727 subtype_constraint,
728 )?;
729 }
730 (Type::BmpString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
731 self.generate_constrained_string(
732 &type_name,
733 "BmpString",
734 subtype_constraint,
735 )?;
736 }
737 (Type::GeneralString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
738 self.generate_constrained_string(
739 &type_name,
740 "GeneralString",
741 subtype_constraint,
742 )?;
743 }
744 (Type::NumericString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
745 self.generate_constrained_string(
746 &type_name,
747 "NumericString",
748 subtype_constraint,
749 )?;
750 }
751 (Type::VisibleString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
752 self.generate_constrained_string(
753 &type_name,
754 "VisibleString",
755 subtype_constraint,
756 )?;
757 }
758 (Type::OctetString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
759 self.generate_constrained_string(
760 &type_name,
761 "OctetString",
762 subtype_constraint,
763 )?;
764 }
765 (
766 Type::BitString(_),
767 ConstraintSpec::Subtype(SubtypeConstraint::NamedBitList(named_bits)),
768 ) => {
769 writeln!(&mut self.output, "pub type {} = BitString;", type_name)?;
771 self.generate_named_bit_constants(&type_name, named_bits)?;
772 }
773 (
774 Type::BitString(_),
775 ConstraintSpec::Subtype(SubtypeConstraint::Intersection(constraints)),
776 ) if constraints
777 .iter()
778 .any(|c| matches!(c, SubtypeConstraint::NamedBitList(_))) =>
779 {
780 let size_con = constraints
782 .iter()
783 .find(|c| matches!(c, SubtypeConstraint::SizeConstraint(_)));
784 let named_bits_opt = constraints.iter().find_map(|c| {
785 if let SubtypeConstraint::NamedBitList(bits) = c {
786 Some(bits)
787 } else {
788 None
789 }
790 });
791
792 if let Some(size_con) = size_con {
793 self.generate_constrained_string(&type_name, "BitString", size_con)?;
794 } else {
795 writeln!(&mut self.output, "pub type {} = BitString;", type_name)?;
796 }
797
798 if let Some(named_bits) = named_bits_opt {
799 self.generate_named_bit_constants(&type_name, named_bits)?;
800 }
801 }
802 (Type::BitString(_), ConstraintSpec::Subtype(subtype_constraint)) => {
803 self.generate_constrained_string(
804 &type_name,
805 "BitString",
806 subtype_constraint,
807 )?;
808 }
809 (Type::TypeRef(_), ConstraintSpec::Subtype(subtype_constraint)) => {
810 self.generate_subtype(&type_name, base_type, subtype_constraint)?;
812 }
813 _ => {
814 writeln!(
816 &mut self.output,
817 "// Constrained type (validation not yet implemented)"
818 )?;
819 let rust_type = self.rust_type(base_type);
820 self.generate_type_alias(&type_name, &rust_type, base_type)?;
821 }
822 }
823 }
824 Type::Integer(_, named_numbers) if !named_numbers.is_empty() => {
825 writeln!(&mut self.output, "pub type {} = Integer;", type_name)?;
829 self.generate_named_integer_constants(&type_name, named_numbers)?;
830 }
831 Type::Integer(Some(constraint), _) => {
832 let constraint_str = self.format_value_constraint(constraint);
834 writeln!(&mut self.output, "// Constraint: {}", constraint_str)?;
835 writeln!(&mut self.output, "pub type {} = Integer;", type_name)?;
836 }
837 Type::OctetString(Some(constraint))
838 | Type::BitString(Some(constraint))
839 | Type::Utf8String(Some(constraint))
840 | Type::PrintableString(Some(constraint))
841 | Type::IA5String(Some(constraint))
842 | Type::TeletexString(Some(constraint))
843 | Type::UniversalString(Some(constraint))
844 | Type::BmpString(Some(constraint))
845 | Type::GeneralString(Some(constraint))
846 | Type::NumericString(Some(constraint))
847 | Type::VisibleString(Some(constraint)) => {
848 let constraint_str = self.format_size_constraint(constraint);
850 writeln!(&mut self.output, "// Constraint: {}", constraint_str)?;
851 let rust_type = self.rust_type(&def.ty);
852 self.generate_type_alias(&type_name, &rust_type, &def.ty)?;
853 }
854 Type::Enumerated(named_values) => {
855 self.generate_enumerated_type(&type_name, named_values)?;
856 }
857 Type::Tagged { tag, inner } => {
858 let class_str = match tag.class {
860 TagClass::Application => "APPLICATION",
861 TagClass::Universal => "UNIVERSAL",
862 TagClass::Private => "PRIVATE",
863 TagClass::ContextSpecific => "CONTEXT",
864 };
865 let tagging_str = match tag.tagging {
866 Tagging::Explicit => "EXPLICIT",
867 Tagging::Implicit => "IMPLICIT",
868 };
869 writeln!(
870 &mut self.output,
871 "/// [{} {}] {} outer tag",
872 class_str, tag.number, tagging_str
873 )?;
874 let inner_def = Definition {
876 name: def.name.clone(),
877 ty: *inner.clone(),
878 };
879 self.generate_definition(&inner_def)?;
880 }
881 Type::Class(fields) => {
882 writeln!(
886 &mut self.output,
887 "// ASN.1 Information Object Class: {} (no Rust type generated)",
888 type_name
889 )?;
890 if !fields.is_empty() {
891 write!(&mut self.output, "// Fields:")?;
892 for field in fields {
893 write!(&mut self.output, " &{}", field.name)?;
894 if field.unique {
895 write!(&mut self.output, " UNIQUE")?;
896 }
897 if field.optional {
898 write!(&mut self.output, " OPTIONAL")?;
899 }
900 write!(&mut self.output, ";")?;
901 }
902 writeln!(&mut self.output)?;
903 }
904 }
905 _ => {
906 let rust_type = self.rust_type(&def.ty);
908 self.generate_type_alias(&type_name, &rust_type, &def.ty)?;
909 }
910 }
911
912 Ok(())
913 }
914
915 fn format_value_constraint(&self, constraint: &ValueConstraint) -> String {
916 match constraint {
917 ValueConstraint::Single(val) => format!("value = {}", val),
918 ValueConstraint::Range(min, max) => {
919 let min_str = min
920 .map(|v| v.to_string())
921 .unwrap_or_else(|| "MIN".to_string());
922 let max_str = max
923 .map(|v| v.to_string())
924 .unwrap_or_else(|| "MAX".to_string());
925 format!("{}..{}", min_str, max_str)
926 }
927 }
928 }
929
930 fn format_size_constraint(&self, constraint: &SizeConstraint) -> String {
931 match constraint {
932 SizeConstraint::Fixed(size) => format!("SIZE ({})", size),
933 SizeConstraint::Range(min, max) => {
934 let min_str = min
935 .map(|v| v.to_string())
936 .unwrap_or_else(|| "0".to_string());
937 let max_str = max
938 .map(|v| v.to_string())
939 .unwrap_or_else(|| "MAX".to_string());
940 format!("SIZE ({}..{})", min_str, max_str)
941 }
942 }
943 }
944
945 fn constrained_integer_rust_type(constraint: &SubtypeConstraint) -> &'static str {
958 let (lo, hi) = match constraint {
959 SubtypeConstraint::SingleValue(ConstraintValue::Integer(n)) => (*n, *n),
960 SubtypeConstraint::ValueRange {
961 min: ConstraintValue::Integer(lo),
962 max: ConstraintValue::Integer(hi),
963 } => (*lo, *hi),
964 _ => return "i64",
965 };
966 if lo >= 0 {
967 if hi <= u8::MAX as i64 {
969 "u8"
970 } else if hi <= u16::MAX as i64 {
971 "u16"
972 } else if hi <= u32::MAX as i64 {
973 "u32"
974 } else {
975 "u64"
976 }
977 } else {
978 if lo >= i8::MIN as i64 && hi <= i8::MAX as i64 {
980 "i8"
981 } else if lo >= i16::MIN as i64 && hi <= i16::MAX as i64 {
982 "i16"
983 } else if lo >= i32::MIN as i64 && hi <= i32::MAX as i64 {
984 "i32"
985 } else {
986 "i64"
987 }
988 }
989 }
990
991 fn generate_constraint_value_check(&self, var: &str, value: &ConstraintValue) -> String {
993 match value {
994 ConstraintValue::Integer(n) => format!("{} == {}", var, n),
995 ConstraintValue::Min => "true /* MIN */".to_string(),
996 ConstraintValue::Max => "true /* MAX */".to_string(),
997 ConstraintValue::NamedValue(name) => format!("{} == {} /* named value */", var, name),
998 }
999 }
1000
1001 fn generate_constraint_validation(&self, var: &str, constraint: &SubtypeConstraint) -> String {
1003 match constraint {
1004 SubtypeConstraint::SingleValue(val) => self.generate_constraint_value_check(var, val),
1005 SubtypeConstraint::ValueRange { min, max } => {
1006 if let (ConstraintValue::Integer(lo), ConstraintValue::Integer(hi)) = (min, max) {
1009 return format!("({}..={}).contains(&{})", lo, hi, var);
1010 }
1011 let mut parts: Vec<String> = Vec::new();
1012 match min {
1013 ConstraintValue::Integer(n) => parts.push(format!("{} >= {}", var, n)),
1014 ConstraintValue::Min => {}
1015 ConstraintValue::NamedValue(name) => parts.push(format!("{} >= {}", var, name)),
1016 ConstraintValue::Max => parts.push(format!("{} <= i64::MAX", var)),
1017 }
1018 match max {
1019 ConstraintValue::Integer(n) => parts.push(format!("{} <= {}", var, n)),
1020 ConstraintValue::Max => {}
1021 ConstraintValue::NamedValue(name) => parts.push(format!("{} <= {}", var, name)),
1022 ConstraintValue::Min => parts.push(format!("{} >= i64::MIN", var)),
1023 }
1024 if parts.is_empty() {
1025 "true".to_string()
1026 } else {
1027 format!("({})", parts.join(" && "))
1028 }
1029 }
1030 SubtypeConstraint::Union(elements) => {
1031 let checks: Vec<String> = elements
1032 .iter()
1033 .map(|e| self.generate_constraint_validation(var, e))
1034 .collect();
1035 format!("({})", checks.join(" || "))
1036 }
1037 SubtypeConstraint::Intersection(elements) => {
1038 let checks: Vec<String> = elements
1039 .iter()
1040 .map(|e| self.generate_constraint_validation(var, e))
1041 .collect();
1042 format!("({})", checks.join(" && "))
1043 }
1044 SubtypeConstraint::Complement(inner) => {
1045 let inner_check = self.generate_constraint_validation(var, inner);
1046 format!("!({})", inner_check)
1047 }
1048 _ => "true /* unsupported constraint */".to_string(),
1049 }
1050 }
1051
1052 fn generate_constraint_description(&self, constraint: &SubtypeConstraint) -> String {
1054 match constraint {
1055 SubtypeConstraint::SingleValue(ConstraintValue::Integer(n)) => {
1056 format!("must equal {}", n)
1057 }
1058 SubtypeConstraint::ValueRange { min, max } => {
1059 let min_str = match min {
1060 ConstraintValue::Integer(n) => n.to_string(),
1061 ConstraintValue::Min => "MIN".to_string(),
1062 ConstraintValue::NamedValue(n) => n.clone(),
1063 ConstraintValue::Max => "MAX".to_string(),
1064 };
1065 let max_str = match max {
1066 ConstraintValue::Integer(n) => n.to_string(),
1067 ConstraintValue::Max => "MAX".to_string(),
1068 ConstraintValue::NamedValue(n) => n.clone(),
1069 ConstraintValue::Min => "MIN".to_string(),
1070 };
1071 format!("must be in range {}..{}", min_str, max_str)
1072 }
1073 SubtypeConstraint::Union(elements) => {
1074 let descriptions: Vec<String> = elements
1075 .iter()
1076 .map(|e| self.generate_constraint_description(e))
1077 .collect();
1078 format!("must satisfy one of: {}", descriptions.join(", "))
1079 }
1080 SubtypeConstraint::Complement(inner) => {
1081 format!(
1082 "must not be {}",
1083 self.generate_constraint_description(inner)
1084 )
1085 }
1086 _ => "must satisfy constraint".to_string(),
1087 }
1088 }
1089
1090 fn generate_enumerated_type(
1092 &mut self,
1093 name: &str,
1094 named_values: &[NamedNumber],
1095 ) -> Result<(), std::fmt::Error> {
1096 writeln!(&mut self.output, "/// ENUMERATED")?;
1097 writeln!(
1098 &mut self.output,
1099 "#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]"
1100 )?;
1101 writeln!(&mut self.output, "#[repr(i64)]")?;
1102 writeln!(&mut self.output, "pub enum {} {{", name)?;
1103
1104 for nv in named_values {
1105 let variant_name = to_pascal_case(&nv.name);
1106 writeln!(&mut self.output, " {} = {},", variant_name, nv.value)?;
1107 }
1108
1109 writeln!(&mut self.output, "}}")?;
1110 writeln!(&mut self.output)?;
1111
1112 let try_from_path = self.try_from_path();
1114 writeln!(
1115 &mut self.output,
1116 "impl {}::convert::TryFrom<Integer> for {} {{",
1117 try_from_path, name
1118 )?;
1119 writeln!(&mut self.output, " type Error = &'static str;")?;
1120 writeln!(&mut self.output)?;
1121 writeln!(
1122 &mut self.output,
1123 " fn try_from(value: Integer) -> Result<Self, Self::Error> {{"
1124 )?;
1125 writeln!(
1126 &mut self.output,
1127 " let discriminant = value.as_i64().map_err(|_| \"ENUMERATED value out of i64 range\")?;"
1128 )?;
1129 writeln!(&mut self.output, " match discriminant {{")?;
1130
1131 for nv in named_values {
1132 let variant_name = to_pascal_case(&nv.name);
1133 writeln!(
1134 &mut self.output,
1135 " {} => Ok({}::{}),",
1136 nv.value, name, variant_name
1137 )?;
1138 }
1139
1140 writeln!(
1141 &mut self.output,
1142 " _ => Err(\"unknown ENUMERATED value\"),"
1143 )?;
1144 writeln!(&mut self.output, " }}")?;
1145 writeln!(&mut self.output, " }}")?;
1146 writeln!(&mut self.output, "}}")?;
1147 writeln!(&mut self.output)?;
1148
1149 writeln!(&mut self.output, "impl From<{}> for Integer {{", name)?;
1151 writeln!(&mut self.output, " fn from(value: {}) -> Self {{", name)?;
1152 writeln!(&mut self.output, " Integer::from(value as i64)")?;
1153 writeln!(&mut self.output, " }}")?;
1154 writeln!(&mut self.output, "}}")?;
1155 writeln!(&mut self.output)?;
1156
1157 writeln!(&mut self.output, "impl Encode for {} {{", name)?;
1161 writeln!(
1162 &mut self.output,
1163 " fn encode(&self, encoder: &mut Encoder) -> synta::Result<()> {{"
1164 )?;
1165 writeln!(
1166 &mut self.output,
1167 " let as_int = Integer::from(*self as i64);"
1168 )?;
1169 writeln!(
1170 &mut self.output,
1171 " let tag = synta::Tag::universal(synta::tag::TAG_ENUMERATED);"
1172 )?;
1173 writeln!(&mut self.output, " encoder.write_tag(tag)?;")?;
1174 writeln!(
1175 &mut self.output,
1176 " encoder.write_length(as_int.as_bytes().len())?;"
1177 )?;
1178 writeln!(
1179 &mut self.output,
1180 " encoder.write_bytes(as_int.as_bytes());"
1181 )?;
1182 writeln!(&mut self.output, " Ok(())")?;
1183 writeln!(&mut self.output, " }}")?;
1184 writeln!(
1185 &mut self.output,
1186 " fn encoded_len(&self) -> synta::Result<usize> {{"
1187 )?;
1188 writeln!(
1189 &mut self.output,
1190 " let as_int = Integer::from(*self as i64);"
1191 )?;
1192 writeln!(&mut self.output, " let tag_len = 1usize;")?;
1193 writeln!(
1194 &mut self.output,
1195 " let length = as_int.as_bytes().len();"
1196 )?;
1197 writeln!(
1198 &mut self.output,
1199 " let length_len = synta::Length::Definite(length).encoded_len()?;"
1200 )?;
1201 writeln!(
1202 &mut self.output,
1203 " Ok(tag_len + length_len + length)"
1204 )?;
1205 writeln!(&mut self.output, " }}")?;
1206 writeln!(&mut self.output, "}}")?;
1207 writeln!(&mut self.output)?;
1208
1209 writeln!(&mut self.output, "impl<'a> Decode<'a> for {} {{", name)?;
1210 writeln!(
1211 &mut self.output,
1212 " fn decode(decoder: &mut Decoder<'a>) -> synta::Result<Self> {{"
1213 )?;
1214 writeln!(&mut self.output, " let tag = decoder.read_tag()?;")?;
1215 writeln!(
1216 &mut self.output,
1217 " let expected = synta::Tag::universal(synta::tag::TAG_ENUMERATED);"
1218 )?;
1219 writeln!(&mut self.output, " if tag != expected {{")?;
1220 writeln!(
1221 &mut self.output,
1222 " return Err(synta::Error::UnexpectedTag {{"
1223 )?;
1224 writeln!(
1225 &mut self.output,
1226 " position: decoder.position(),"
1227 )?;
1228 writeln!(&mut self.output, " expected,")?;
1229 writeln!(&mut self.output, " actual: tag,")?;
1230 writeln!(&mut self.output, " }});")?;
1231 writeln!(&mut self.output, " }}")?;
1232 writeln!(
1233 &mut self.output,
1234 " let length = decoder.read_length()?;"
1235 )?;
1236 writeln!(&mut self.output, " let len = length.definite()?;")?;
1237 writeln!(
1238 &mut self.output,
1239 " let bytes = decoder.read_bytes(len)?;"
1240 )?;
1241 writeln!(
1242 &mut self.output,
1243 " let integer = Integer::from_bytes(bytes);"
1244 )?;
1245 writeln!(
1246 &mut self.output,
1247 " core::convert::TryFrom::try_from(integer)\
1248 .map_err(|_| synta::Error::LengthOverflow)"
1249 )?;
1250 writeln!(&mut self.output, " }}")?;
1251 writeln!(&mut self.output, "}}")?;
1252 writeln!(&mut self.output)?;
1253
1254 writeln!(&mut self.output, "impl Tagged for {} {{", name)?;
1255 writeln!(
1256 &mut self.output,
1257 " fn tag() -> synta::Tag {{ synta::Tag::universal(synta::tag::TAG_ENUMERATED) }}"
1258 )?;
1259 writeln!(&mut self.output, "}}")?;
1260
1261 self.generate_format_asn1_impl(name, false)?;
1262
1263 Ok(())
1264 }
1265
1266 fn generate_named_bit_constants(
1268 &mut self,
1269 name: &str,
1270 named_bits: &[NamedNumber],
1271 ) -> Result<(), std::fmt::Error> {
1272 if named_bits.is_empty() {
1273 return Ok(());
1274 }
1275
1276 writeln!(&mut self.output)?;
1277 writeln!(
1278 &mut self.output,
1279 "// Named bit positions for {} (defined as module-level constants to avoid orphan rule issues)",
1280 name
1281 )?;
1282
1283 for bit in named_bits {
1284 let const_name = to_screaming_snake_case(&bit.name);
1285 let full_const_name = format!("{}_{}", to_screaming_snake_case(name), const_name);
1286 writeln!(
1287 &mut self.output,
1288 "/// Bit position for `{}` in {}",
1289 bit.name, name
1290 )?;
1291 writeln!(
1292 &mut self.output,
1293 "pub const {}: usize = {};",
1294 full_const_name, bit.value
1295 )?;
1296 }
1297
1298 Ok(())
1299 }
1300
1301 fn generate_named_integer_constants(
1307 &mut self,
1308 name: &str,
1309 named_numbers: &[NamedNumber],
1310 ) -> Result<(), std::fmt::Error> {
1311 if named_numbers.is_empty() {
1312 return Ok(());
1313 }
1314
1315 writeln!(&mut self.output)?;
1316 writeln!(
1317 &mut self.output,
1318 "// Named values for {} (defined as module-level constants to avoid orphan rule issues)",
1319 name
1320 )?;
1321
1322 for num in named_numbers {
1323 let const_name = to_screaming_snake_case(&num.name);
1324 let full_const_name = format!("{}_{}", to_screaming_snake_case(name), const_name);
1325 writeln!(
1326 &mut self.output,
1327 "/// Named value `{}` for {}",
1328 num.name, name
1329 )?;
1330 writeln!(
1331 &mut self.output,
1332 "pub const {}: i64 = {};",
1333 full_const_name, num.value
1334 )?;
1335 }
1336
1337 Ok(())
1338 }
1339
1340 fn generate_constrained_integer(
1350 &mut self,
1351 name: &str,
1352 constraint: &SubtypeConstraint,
1353 ) -> Result<(), std::fmt::Error> {
1354 let prim = Self::constrained_integer_rust_type(constraint);
1355
1356 let constraint_display = self.format_constraint_display(constraint);
1358 writeln!(&mut self.output, "/// INTEGER ({})", constraint_display)?;
1359 writeln!(
1360 &mut self.output,
1361 "#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]"
1362 )?;
1363 writeln!(&mut self.output, "pub struct {}({});", name, prim)?;
1364 writeln!(&mut self.output)?;
1365
1366 writeln!(&mut self.output, "impl {} {{", name)?;
1368 writeln!(
1369 &mut self.output,
1370 " /// Create a new {} with validation",
1371 name
1372 )?;
1373 writeln!(
1374 &mut self.output,
1375 " pub fn new(value: {}) -> Result<Self, &'static str> {{",
1376 prim
1377 )?;
1378
1379 let validation = self.generate_constraint_validation("value", constraint);
1380 let description = self.generate_constraint_description(constraint);
1381
1382 writeln!(&mut self.output, " if {} {{", validation)?;
1383 writeln!(&mut self.output, " Ok({}(value))", name)?;
1384 writeln!(&mut self.output, " }} else {{")?;
1385 writeln!(&mut self.output, " Err(\"{}\")", description)?;
1386 writeln!(&mut self.output, " }}")?;
1387 writeln!(&mut self.output, " }}")?;
1388 writeln!(&mut self.output)?;
1389
1390 writeln!(
1392 &mut self.output,
1393 " /// Create without validation (use with caution)"
1394 )?;
1395 writeln!(
1396 &mut self.output,
1397 " pub const fn new_unchecked(value: {}) -> Self {{",
1398 prim
1399 )?;
1400 writeln!(&mut self.output, " {}(value)", name)?;
1401 writeln!(&mut self.output, " }}")?;
1402 writeln!(&mut self.output)?;
1403
1404 writeln!(&mut self.output, " /// Get the inner value")?;
1406 writeln!(
1407 &mut self.output,
1408 " pub const fn get(&self) -> {} {{",
1409 prim
1410 )?;
1411 writeln!(&mut self.output, " self.0")?;
1412 writeln!(&mut self.output, " }}")?;
1413 writeln!(&mut self.output)?;
1414
1415 writeln!(
1417 &mut self.output,
1418 " /// Consume and return the inner value"
1419 )?;
1420 writeln!(
1421 &mut self.output,
1422 " pub fn into_inner(self) -> {} {{",
1423 prim
1424 )?;
1425 writeln!(&mut self.output, " self.0")?;
1426 writeln!(&mut self.output, " }}")?;
1427 writeln!(&mut self.output, "}}")?;
1428 writeln!(&mut self.output)?;
1429
1430 let as_method = format!("as_{}", prim);
1434 let try_from_path = self.try_from_path();
1435 writeln!(
1436 &mut self.output,
1437 "impl {}::convert::TryFrom<Integer> for {} {{",
1438 try_from_path, name
1439 )?;
1440 writeln!(&mut self.output, " type Error = &'static str;")?;
1441 writeln!(&mut self.output)?;
1442 writeln!(
1443 &mut self.output,
1444 " fn try_from(value: Integer) -> Result<Self, Self::Error> {{"
1445 )?;
1446 writeln!(
1447 &mut self.output,
1448 " let n = value.{as_method}().map_err(|_| \"integer value out of {prim} range\")?;"
1449 )?;
1450 writeln!(&mut self.output, " Self::new(n)")?;
1451 writeln!(&mut self.output, " }}")?;
1452 writeln!(&mut self.output, "}}")?;
1453 writeln!(&mut self.output)?;
1454
1455 writeln!(&mut self.output, "impl Encode for {} {{", name)?;
1459 writeln!(
1460 &mut self.output,
1461 " fn encode(&self, encoder: &mut Encoder) -> synta::Result<()> {{"
1462 )?;
1463 writeln!(
1464 &mut self.output,
1465 " Integer::from(self.0).encode(encoder)"
1466 )?;
1467 writeln!(&mut self.output, " }}")?;
1468 writeln!(
1469 &mut self.output,
1470 " fn encoded_len(&self) -> synta::Result<usize> {{"
1471 )?;
1472 writeln!(
1473 &mut self.output,
1474 " Integer::from(self.0).encoded_len()"
1475 )?;
1476 writeln!(&mut self.output, " }}")?;
1477 writeln!(&mut self.output, "}}")?;
1478 writeln!(&mut self.output)?;
1479
1480 writeln!(&mut self.output, "impl<'a> Decode<'a> for {} {{", name)?;
1482 writeln!(
1483 &mut self.output,
1484 " fn decode(decoder: &mut Decoder<'a>) -> synta::Result<Self> {{"
1485 )?;
1486 writeln!(
1487 &mut self.output,
1488 " Integer::decode(decoder).and_then(|v| {{"
1489 )?;
1490 writeln!(
1491 &mut self.output,
1492 " let n = v.{as_method}().map_err(|_| synta::Error::LengthOverflow)?;"
1493 )?;
1494 writeln!(
1495 &mut self.output,
1496 " Self::new(n).map_err(|_| synta::Error::LengthOverflow)"
1497 )?;
1498 writeln!(&mut self.output, " }})")?;
1499 writeln!(&mut self.output, " }}")?;
1500 writeln!(&mut self.output, "}}")?;
1501 writeln!(&mut self.output)?;
1502
1503 writeln!(&mut self.output, "impl Tagged for {} {{", name)?;
1504 writeln!(
1505 &mut self.output,
1506 " fn tag() -> synta::Tag {{ Integer::tag() }}"
1507 )?;
1508 writeln!(&mut self.output, "}}")?;
1509
1510 self.generate_format_asn1_impl(name, false)?;
1511
1512 Ok(())
1513 }
1514
1515 fn generate_constrained_string(
1517 &mut self,
1518 name: &str,
1519 base_type: &str,
1520 constraint: &SubtypeConstraint,
1521 ) -> Result<(), std::fmt::Error> {
1522 let constraint_display = self.format_constraint_display(constraint);
1524 writeln!(
1525 &mut self.output,
1526 "/// {} ({})",
1527 base_type, constraint_display
1528 )?;
1529 writeln!(&mut self.output, "#[derive(Debug, Clone, PartialEq, Eq)]")?;
1530 writeln!(&mut self.output, "pub struct {}({});", name, base_type)?;
1531 writeln!(&mut self.output)?;
1532
1533 writeln!(&mut self.output, "impl {} {{", name)?;
1535 writeln!(
1536 &mut self.output,
1537 " /// Create a new {} with validation",
1538 name
1539 )?;
1540 writeln!(
1541 &mut self.output,
1542 " pub fn new(value: {}) -> Result<Self, &'static str> {{",
1543 base_type
1544 )?;
1545
1546 let validation_code = self.generate_string_validation("value", base_type, constraint);
1548 writeln!(&mut self.output, "{}", validation_code)?;
1549
1550 writeln!(&mut self.output, " }}")?;
1551 writeln!(&mut self.output)?;
1552
1553 writeln!(
1555 &mut self.output,
1556 " /// Create without validation (use with caution)"
1557 )?;
1558 writeln!(
1559 &mut self.output,
1560 " pub fn new_unchecked(value: {}) -> Self {{",
1561 base_type
1562 )?;
1563 writeln!(&mut self.output, " {}(value)", name)?;
1564 writeln!(&mut self.output, " }}")?;
1565 writeln!(&mut self.output)?;
1566
1567 writeln!(
1569 &mut self.output,
1570 " /// Get a reference to the inner value"
1571 )?;
1572 writeln!(
1573 &mut self.output,
1574 " pub fn get(&self) -> &{} {{",
1575 base_type
1576 )?;
1577 writeln!(&mut self.output, " &self.0")?;
1578 writeln!(&mut self.output, " }}")?;
1579 writeln!(&mut self.output)?;
1580
1581 if base_type != "OctetString" && base_type != "BitString" {
1583 writeln!(&mut self.output, " /// Get the string value")?;
1584 writeln!(&mut self.output, " pub fn as_str(&self) -> &str {{")?;
1585 writeln!(&mut self.output, " self.0.as_str()")?;
1586 writeln!(&mut self.output, " }}")?;
1587 writeln!(&mut self.output)?;
1588 }
1589
1590 writeln!(
1592 &mut self.output,
1593 " /// Consume and return the inner value"
1594 )?;
1595 writeln!(
1596 &mut self.output,
1597 " pub fn into_inner(self) -> {} {{",
1598 base_type
1599 )?;
1600 writeln!(&mut self.output, " self.0")?;
1601 writeln!(&mut self.output, " }}")?;
1602 writeln!(&mut self.output, "}}")?;
1603 writeln!(&mut self.output)?;
1604
1605 let try_from_path = self.try_from_path();
1607 writeln!(
1608 &mut self.output,
1609 "impl {}::convert::TryFrom<{}> for {} {{",
1610 try_from_path, base_type, name
1611 )?;
1612 writeln!(&mut self.output, " type Error = &'static str;")?;
1613 writeln!(&mut self.output)?;
1614 writeln!(
1615 &mut self.output,
1616 " fn try_from(value: {}) -> Result<Self, Self::Error> {{",
1617 base_type
1618 )?;
1619 writeln!(&mut self.output, " Self::new(value)")?;
1620 writeln!(&mut self.output, " }}")?;
1621 writeln!(&mut self.output, "}}")?;
1622 writeln!(&mut self.output)?;
1623
1624 writeln!(&mut self.output, "impl Encode for {} {{", name)?;
1627 writeln!(
1628 &mut self.output,
1629 " fn encode(&self, encoder: &mut Encoder) -> synta::Result<()> {{"
1630 )?;
1631 writeln!(&mut self.output, " self.0.encode(encoder)")?;
1632 writeln!(&mut self.output, " }}")?;
1633 writeln!(
1634 &mut self.output,
1635 " fn encoded_len(&self) -> synta::Result<usize> {{"
1636 )?;
1637 writeln!(&mut self.output, " self.0.encoded_len()")?;
1638 writeln!(&mut self.output, " }}")?;
1639 writeln!(&mut self.output, "}}")?;
1640 writeln!(&mut self.output)?;
1641
1642 writeln!(&mut self.output, "impl<'a> Decode<'a> for {} {{", name)?;
1643 writeln!(
1644 &mut self.output,
1645 " fn decode(decoder: &mut Decoder<'a>) -> synta::Result<Self> {{"
1646 )?;
1647 writeln!(
1648 &mut self.output,
1649 " {}::decode(decoder).and_then(|v| {{",
1650 base_type
1651 )?;
1652 writeln!(
1653 &mut self.output,
1654 " Self::new(v).map_err(|_| synta::Error::LengthOverflow)"
1655 )?;
1656 writeln!(&mut self.output, " }})")?;
1657 writeln!(&mut self.output, " }}")?;
1658 writeln!(&mut self.output, "}}")?;
1659 writeln!(&mut self.output)?;
1660
1661 writeln!(&mut self.output, "impl Tagged for {} {{", name)?;
1662 writeln!(
1663 &mut self.output,
1664 " fn tag() -> synta::Tag {{ {}::tag() }}",
1665 base_type
1666 )?;
1667 writeln!(&mut self.output, "}}")?;
1668
1669 self.generate_format_asn1_impl(name, false)?;
1670
1671 Ok(())
1672 }
1673
1674 fn generate_string_validation(
1676 &mut self,
1677 var: &str,
1678 base_type: &str,
1679 constraint: &SubtypeConstraint,
1680 ) -> String {
1681 match constraint {
1682 SubtypeConstraint::SizeConstraint(inner) => {
1683 self.generate_size_validation(var, base_type, inner)
1685 }
1686 SubtypeConstraint::PermittedAlphabet(ranges) => {
1687 self.generate_alphabet_validation(var, ranges)
1689 }
1690 SubtypeConstraint::Pattern(pattern) => {
1691 self.generate_pattern_validation(var, pattern)
1693 }
1694 SubtypeConstraint::ContainedSubtype(ty) => {
1695 self.generate_containing_validation(var, ty)
1697 }
1698 SubtypeConstraint::Intersection(constraints) => {
1699 self.generate_intersection_string_validation(var, base_type, constraints)
1701 }
1702 _ => {
1703 format!(
1705 " Ok({}({}))",
1706 self.get_struct_name_from_var(var),
1707 var
1708 )
1709 }
1710 }
1711 }
1712
1713 fn generate_intersection_string_validation(
1716 &self,
1717 var: &str,
1718 base_type: &str,
1719 constraints: &[SubtypeConstraint],
1720 ) -> String {
1721 let struct_name = self.get_struct_name_from_var(var);
1722
1723 let size_constraint = constraints.iter().find_map(|c| {
1725 if let SubtypeConstraint::SizeConstraint(inner) = c {
1726 Some(inner.as_ref())
1727 } else {
1728 None
1729 }
1730 });
1731
1732 let alphabet_constraint = constraints.iter().find_map(|c| {
1733 if let SubtypeConstraint::PermittedAlphabet(ranges) = c {
1734 Some(ranges)
1735 } else {
1736 None
1737 }
1738 });
1739
1740 match (size_constraint, alphabet_constraint) {
1742 (Some(size), Some(alphabet)) => {
1743 let length_expr = if base_type == "BitString" {
1745 format!("{}.bit_len()", var)
1746 } else if base_type == "OctetString" {
1747 format!("{}.as_bytes().len()", var)
1748 } else {
1749 format!("{}.as_str().len()", var)
1750 };
1751
1752 let size_check: Option<String> = match size {
1754 SubtypeConstraint::SingleValue(ConstraintValue::Integer(n)) => {
1755 Some(format!("{} == {}", length_expr, n))
1756 }
1757 SubtypeConstraint::ValueRange { min, max } => {
1758 let mut parts: Vec<String> = Vec::new();
1759 if let ConstraintValue::Integer(n) = min {
1760 if *n == 1 && base_type != "BitString" {
1761 let obj = length_expr.trim_end_matches(".len()");
1762 parts.push(format!("!{}.is_empty()", obj));
1763 } else {
1764 parts.push(format!("{} >= {}", length_expr, n));
1765 }
1766 }
1767 if let ConstraintValue::Integer(n) = max {
1768 parts.push(format!("{} <= {}", length_expr, n));
1769 }
1770 if parts.is_empty() {
1771 None
1772 } else {
1773 Some(parts.join(" && "))
1774 }
1775 }
1776 _ => None,
1777 };
1778
1779 let range_checks: Vec<String> = alphabet
1781 .iter()
1782 .map(|r| {
1783 if r.min == r.max {
1784 format!("ch == '{}'", r.min)
1785 } else {
1786 format!("(ch >= '{}' && ch <= '{}')", r.min, r.max)
1787 }
1788 })
1789 .collect();
1790 let alphabet_check = range_checks.join(" || ");
1791
1792 let size_error = match size {
1794 SubtypeConstraint::SingleValue(ConstraintValue::Integer(n)) => {
1795 format!("length must equal {}", n)
1796 }
1797 SubtypeConstraint::ValueRange { min, max } => {
1798 let min_str = match min {
1799 ConstraintValue::Integer(n) => n.to_string(),
1800 _ => "MIN".to_string(),
1801 };
1802 let max_str = match max {
1803 ConstraintValue::Integer(n) => n.to_string(),
1804 _ => "MAX".to_string(),
1805 };
1806 format!("length must be in range {}..{}", min_str, max_str)
1807 }
1808 _ => "invalid length".to_string(),
1809 };
1810
1811 let ranges_display: Vec<String> = alphabet
1812 .iter()
1813 .map(|r| {
1814 if r.min == r.max {
1815 format!("'{}'", r.min)
1816 } else {
1817 format!("'{}'..'{}'", r.min, r.max)
1818 }
1819 })
1820 .collect();
1821 let alphabet_error =
1822 format!("characters must be from: {}", ranges_display.join(", "));
1823
1824 let size_check_block = if let Some(cond) = size_check {
1826 format!(
1827 " // Check SIZE constraint\n if !({}) {{\n return Err(\"{}\");\n }}\n",
1828 cond, size_error
1829 )
1830 } else {
1831 String::new()
1832 };
1833 format!(
1834 "{} // Check FROM constraint\n for ch in {}.as_str().chars() {{\n if !({}) {{\n return Err(\"{}\");\n }}\n }}\n Ok({}({}))",
1835 size_check_block, var, alphabet_check, alphabet_error, struct_name, var
1836 )
1837 }
1838 (Some(size), None) => {
1839 self.generate_size_validation(var, base_type, size)
1841 }
1842 (None, Some(alphabet)) => {
1843 self.generate_alphabet_validation(var, alphabet)
1845 }
1846 (None, None) => {
1847 format!(" Ok({}({}))", struct_name, var)
1849 }
1850 }
1851 }
1852
1853 fn generate_size_validation(
1855 &self,
1856 var: &str,
1857 base_type: &str,
1858 size_constraint: &SubtypeConstraint,
1859 ) -> String {
1860 let length_expr = if base_type == "BitString" {
1861 format!("{}.bit_len()", var)
1863 } else if base_type == "OctetString" {
1864 format!("{}.as_bytes().len()", var)
1865 } else {
1866 format!("{}.as_str().len()", var)
1867 };
1868
1869 let struct_name = self.get_struct_name_from_var(var);
1870
1871 match size_constraint {
1872 SubtypeConstraint::SingleValue(ConstraintValue::Integer(n)) => {
1873 format!(
1874 " if {} == {} {{\n Ok({}({}))\n }} else {{\n Err(\"length must equal {}\")\n }}",
1875 length_expr, n, struct_name, var, n
1876 )
1877 }
1878 SubtypeConstraint::ValueRange { min, max } => {
1879 let mut checks: Vec<String> = Vec::new();
1880 if let ConstraintValue::Integer(n) = min {
1881 if *n == 1 && base_type != "BitString" {
1882 let obj = length_expr.trim_end_matches(".len()");
1883 checks.push(format!("!{}.is_empty()", obj));
1884 } else {
1885 checks.push(format!("{} >= {}", length_expr, n));
1886 }
1887 }
1888 if let ConstraintValue::Integer(n) = max {
1889 checks.push(format!("{} <= {}", length_expr, n));
1890 }
1891
1892 let min_str = match min {
1893 ConstraintValue::Integer(n) => n.to_string(),
1894 _ => "0".to_string(),
1895 };
1896 let max_str = match max {
1897 ConstraintValue::Integer(n) => n.to_string(),
1898 _ => "MAX".to_string(),
1899 };
1900
1901 if checks.is_empty() {
1902 format!(" Ok({}({}))", struct_name, var)
1904 } else {
1905 format!(
1906 " if {} {{\n Ok({}({}))\n }} else {{\n Err(\"length must be in range {}..{}\")\n }}",
1907 checks.join(" && "), struct_name, var, min_str, max_str
1908 )
1909 }
1910 }
1911 _ => format!(" Ok({}({}))", struct_name, var),
1912 }
1913 }
1914
1915 fn generate_alphabet_validation(&self, var: &str, ranges: &[CharRange]) -> String {
1917 let struct_name = self.get_struct_name_from_var(var);
1918
1919 let range_checks: Vec<String> = ranges
1921 .iter()
1922 .map(|r| {
1923 if r.min == r.max {
1924 format!("ch == '{}'", r.min)
1925 } else {
1926 format!("(ch >= '{}' && ch <= '{}')", r.min, r.max)
1927 }
1928 })
1929 .collect();
1930
1931 let check_expr = range_checks.join(" || ");
1932
1933 let ranges_display: Vec<String> = ranges
1934 .iter()
1935 .map(|r| {
1936 if r.min == r.max {
1937 format!("'{}'", r.min)
1938 } else {
1939 format!("'{}'..'{}'", r.min, r.max)
1940 }
1941 })
1942 .collect();
1943
1944 format!(
1945 " for ch in {}.as_str().chars() {{\n if !({}) {{\n return Err(\"characters must be from: {}\");\n }}\n }}\n Ok({}({}))",
1946 var, check_expr, ranges_display.join(", "), struct_name, var
1947 )
1948 }
1949
1950 fn generate_pattern_validation(&mut self, var: &str, pattern: &str) -> String {
1952 let struct_name = self.get_struct_name_from_var(var);
1953
1954 let pattern_name = format!("PATTERN_{}", self.pattern_counter);
1956 self.pattern_counter += 1;
1957
1958 let mut result = String::new();
1960
1961 result.push_str(&format!(
1963 " #[cfg(feature = \"regex\")]\n {{\n static {}: Lazy<Regex> = Lazy::new(|| Regex::new(r\"{}\").unwrap());\n",
1964 pattern_name, pattern.replace("\"", "\\\"")
1965 ));
1966
1967 result.push_str(&format!(
1969 " if !{}.is_match({}.as_ref()) {{\n",
1970 pattern_name, var
1971 ));
1972 result.push_str(&format!(
1973 " return Err(format!(\"value does not match pattern: {}\"));\n",
1974 pattern.replace("\"", "\\\"")
1975 ));
1976 result.push_str(" }\n }\n");
1977
1978 result.push_str(" #[cfg(not(feature = \"regex\"))]\n");
1980 result.push_str(&format!(
1981 " // Pattern validation disabled (requires 'regex' feature): {}\n",
1982 pattern
1983 ));
1984
1985 result.push_str(&format!(" Ok({}({}))", struct_name, var));
1986
1987 result
1988 }
1989
1990 fn generate_containing_validation(&self, var: &str, contained_type: &Type) -> String {
1991 let struct_name = self.get_struct_name_from_var(var);
1992 let type_name = self.rust_type(contained_type);
1993
1994 let mut result = String::new();
1995
1996 result.push_str(" #[cfg(feature = \"validate_containing\")]\n");
1998 result.push_str(" {\n");
1999 result.push_str(" use synta::der::Decoder;\n");
2000 result.push_str(&format!(
2001 " // Validate that {} contains a valid DER-encoded {}\n",
2002 var, type_name
2003 ));
2004 result.push_str(&format!(" let bytes = {}.as_ref();\n", var));
2005 result.push_str(
2006 " let mut decoder = Decoder::new(bytes, synta::Encoding::Der)?;\n",
2007 );
2008 result.push_str(&format!(
2009 " let _decoded: {} = decoder.decode().map_err(|e| {{\n",
2010 type_name
2011 ));
2012 result.push_str(&format!(
2013 " format!(\"invalid {} in CONTAINING constraint: {{}}\", e)\n",
2014 type_name
2015 ));
2016 result.push_str(" })?;\n");
2017 result.push_str(" // Optionally verify complete consumption\n");
2018 result.push_str(" if !decoder.is_empty() {\n");
2019 result.push_str(&format!(" return Err(\"trailing bytes after {} in CONTAINING constraint\".into());\n", type_name));
2020 result.push_str(" }\n");
2021 result.push_str(" }\n");
2022
2023 result.push_str(" #[cfg(not(feature = \"validate_containing\"))]\n");
2025 result.push_str(&format!(
2026 " // CONTAINING validation disabled (requires 'validate_containing' feature): {}\n",
2027 type_name
2028 ));
2029
2030 result.push_str(&format!(" Ok({}({}))", struct_name, var));
2031
2032 result
2033 }
2034
2035 fn get_struct_name_from_var(&self, _var: &str) -> String {
2037 "Self".to_string()
2040 }
2041
2042 fn format_constraint_display(&self, constraint: &SubtypeConstraint) -> String {
2044 match constraint {
2045 SubtypeConstraint::SingleValue(val) => match val {
2046 ConstraintValue::Integer(n) => n.to_string(),
2047 ConstraintValue::NamedValue(name) => name.clone(),
2048 ConstraintValue::Min => "MIN".to_string(),
2049 ConstraintValue::Max => "MAX".to_string(),
2050 },
2051 SubtypeConstraint::ValueRange { min, max } => {
2052 let min_str = match min {
2053 ConstraintValue::Integer(n) => n.to_string(),
2054 ConstraintValue::Min => "MIN".to_string(),
2055 ConstraintValue::Max => "MAX".to_string(),
2056 ConstraintValue::NamedValue(n) => n.clone(),
2057 };
2058 let max_str = match max {
2059 ConstraintValue::Integer(n) => n.to_string(),
2060 ConstraintValue::Max => "MAX".to_string(),
2061 ConstraintValue::Min => "MIN".to_string(),
2062 ConstraintValue::NamedValue(n) => n.clone(),
2063 };
2064 format!("{}..{}", min_str, max_str)
2065 }
2066 SubtypeConstraint::Union(elements) => {
2067 let parts: Vec<String> = elements
2068 .iter()
2069 .map(|e| self.format_constraint_display(e))
2070 .collect();
2071 parts.join(" | ")
2072 }
2073 SubtypeConstraint::Intersection(elements) => {
2074 let parts: Vec<String> = elements
2075 .iter()
2076 .map(|e| format!("({})", self.format_constraint_display(e)))
2077 .collect();
2078 parts.join(" ^ ")
2079 }
2080 SubtypeConstraint::Complement(inner) => {
2081 format!("ALL EXCEPT {}", self.format_constraint_display(inner))
2082 }
2083 SubtypeConstraint::SizeConstraint(inner) => {
2084 format!("SIZE ({})", self.format_constraint_display(inner))
2085 }
2086 SubtypeConstraint::PermittedAlphabet(ranges) => {
2087 let range_strs: Vec<String> = ranges
2088 .iter()
2089 .map(|r| {
2090 if r.min == r.max {
2091 format!("\"{}\"", r.min)
2092 } else {
2093 format!("\"{}\"..\"{}\"", r.min, r.max)
2094 }
2095 })
2096 .collect();
2097 format!("FROM ({})", range_strs.join(" | "))
2098 }
2099 SubtypeConstraint::Pattern(pattern) => {
2100 format!("PATTERN \"{}\"", pattern)
2101 }
2102 SubtypeConstraint::ContainedSubtype(ty) => {
2103 format!("CONTAINING {}", self.rust_type(ty))
2104 }
2105 SubtypeConstraint::InnerType(inner) => {
2106 format!("inner type: {}", self.format_constraint_display(inner))
2107 }
2108 SubtypeConstraint::NamedBitList(bits) => {
2109 let names: Vec<String> = bits
2110 .iter()
2111 .map(|b| format!("{}({})", b.name, b.value))
2112 .collect();
2113 format!("{{ {} }}", names.join(", "))
2114 }
2115 }
2116 }
2117
2118 fn generate_sequence_type(
2119 &mut self,
2120 name: &str,
2121 fields: &[SequenceField],
2122 ) -> Result<(), std::fmt::Error> {
2123 let mut effective_fields: Vec<SequenceField> = Vec::with_capacity(fields.len());
2128 for field in fields {
2129 if let Some(anon) = anonymous_inner_type(&field.ty) {
2130 let anon_name = format!("{}{}", name, to_pascal_case(&field.name));
2131 self.generate_definition(&Definition {
2132 name: anon_name.clone(),
2133 ty: anon.clone(),
2134 })?;
2135 writeln!(&mut self.output)?;
2136 let new_ty = match &field.ty {
2137 Type::Tagged { tag, .. } => Type::Tagged {
2138 tag: tag.clone(),
2139 inner: Box::new(Type::TypeRef(anon_name)),
2140 },
2141 _ => Type::TypeRef(anon_name),
2142 };
2143 effective_fields.push(SequenceField {
2144 name: field.name.clone(),
2145 ty: new_ty,
2146 optional: field.optional,
2147 default: field.default.clone(),
2148 });
2149 } else {
2150 effective_fields.push(field.clone());
2151 }
2152 }
2153 let fields: &[SequenceField] = &effective_fields;
2154
2155 let all_optional = fields.iter().all(|f| f.optional && f.default.is_none());
2158 if all_optional {
2159 writeln!(
2160 &mut self.output,
2161 "#[derive(Debug, Clone, PartialEq, Default)]"
2162 )?;
2163 } else {
2164 writeln!(&mut self.output, "#[derive(Debug, Clone, PartialEq)]")?;
2165 }
2166 let attr = self.derive_cfg_attr("derive(Asn1Sequence)");
2167 writeln!(&mut self.output, "{}", attr)?;
2168
2169 let needs_lifetime = self.sequence_needs_lifetime(fields);
2171 if needs_lifetime {
2172 writeln!(&mut self.output, "pub struct {}<'a> {{", name)?;
2173 self.types_with_lifetimes.insert(name.to_string());
2175 } else {
2176 writeln!(&mut self.output, "pub struct {} {{", name)?;
2177 }
2178
2179 for field in fields {
2180 self.generate_field(field)?;
2181 }
2182
2183 writeln!(&mut self.output, "}}")?;
2184
2185 self.generate_format_asn1_impl(name, needs_lifetime)?;
2186
2187 Ok(())
2188 }
2189
2190 fn generate_set_type(
2191 &mut self,
2192 name: &str,
2193 fields: &[SequenceField],
2194 ) -> Result<(), std::fmt::Error> {
2195 let mut effective_fields: Vec<SequenceField> = Vec::with_capacity(fields.len());
2197 for field in fields {
2198 if let Some(anon) = anonymous_inner_type(&field.ty) {
2199 let anon_name = format!("{}{}", name, to_pascal_case(&field.name));
2200 self.generate_definition(&Definition {
2201 name: anon_name.clone(),
2202 ty: anon.clone(),
2203 })?;
2204 writeln!(&mut self.output)?;
2205 let new_ty = match &field.ty {
2206 Type::Tagged { tag, .. } => Type::Tagged {
2207 tag: tag.clone(),
2208 inner: Box::new(Type::TypeRef(anon_name)),
2209 },
2210 _ => Type::TypeRef(anon_name),
2211 };
2212 effective_fields.push(SequenceField {
2213 name: field.name.clone(),
2214 ty: new_ty,
2215 optional: field.optional,
2216 default: field.default.clone(),
2217 });
2218 } else {
2219 effective_fields.push(field.clone());
2220 }
2221 }
2222 let fields: &[SequenceField] = &effective_fields;
2223
2224 writeln!(&mut self.output, "#[derive(Debug, Clone, PartialEq)]")?;
2225 let attr = self.derive_cfg_attr("derive(Asn1Set)");
2226 writeln!(&mut self.output, "{}", attr)?;
2227
2228 let needs_lifetime = self.sequence_needs_lifetime(fields);
2230 if needs_lifetime {
2231 writeln!(&mut self.output, "pub struct {}<'a> {{", name)?;
2232 self.types_with_lifetimes.insert(name.to_string());
2234 } else {
2235 writeln!(&mut self.output, "pub struct {} {{", name)?;
2236 }
2237
2238 for field in fields {
2239 self.generate_field(field)?;
2240 }
2241
2242 writeln!(&mut self.output, "}}")?;
2243
2244 self.generate_format_asn1_impl(name, needs_lifetime)?;
2245
2246 Ok(())
2247 }
2248
2249 fn generate_choice_type(
2250 &mut self,
2251 name: &str,
2252 variants: &[ChoiceVariant],
2253 ) -> Result<(), std::fmt::Error> {
2254 let mut effective_variants: Vec<ChoiceVariant> = Vec::with_capacity(variants.len());
2259 for variant in variants {
2260 if let Some(anon) = anonymous_inner_type(&variant.ty) {
2261 let anon_name = format!("{}{}", name, to_pascal_case(&variant.name));
2262 self.generate_definition(&Definition {
2263 name: anon_name.clone(),
2264 ty: anon.clone(),
2265 })?;
2266 writeln!(&mut self.output)?;
2267 let new_ty = match &variant.ty {
2268 Type::Tagged { tag, .. } => Type::Tagged {
2269 tag: tag.clone(),
2270 inner: Box::new(Type::TypeRef(anon_name)),
2271 },
2272 _ => Type::TypeRef(anon_name),
2273 };
2274 effective_variants.push(ChoiceVariant {
2275 name: variant.name.clone(),
2276 ty: new_ty,
2277 });
2278 } else {
2279 effective_variants.push(variant.clone());
2280 }
2281 }
2282 let variants: &[ChoiceVariant] = &effective_variants;
2283
2284 writeln!(&mut self.output, "#[derive(Debug, Clone, PartialEq)]")?;
2285 let attr = self.derive_cfg_attr("derive(Asn1Choice)");
2286 writeln!(&mut self.output, "{}", attr)?;
2287
2288 let needs_lifetime = self.choice_needs_lifetime(variants);
2290 if needs_lifetime {
2291 writeln!(&mut self.output, "pub enum {}<'a> {{", name)?;
2292 self.types_with_lifetimes.insert(name.to_string());
2294 } else {
2295 writeln!(&mut self.output, "pub enum {} {{", name)?;
2296 }
2297
2298 for variant in variants {
2299 let variant_name = to_pascal_case(&variant.name);
2300
2301 let rust_type = if let Type::Tagged { tag, .. } = &variant.ty {
2306 if tag.class == TagClass::ContextSpecific && tag.tagging == Tagging::Implicit {
2307 let saved = self.config.string_type_mode.clone();
2308 self.config.string_type_mode = StringTypeMode::Owned;
2309 let ty = self.inline_sequence_of_types(&variant.ty);
2310 self.config.string_type_mode = saved;
2311 ty
2312 } else {
2313 self.inline_sequence_of_types(&variant.ty)
2314 }
2315 } else {
2316 self.inline_sequence_of_types(&variant.ty)
2317 };
2318
2319 if let Type::Tagged { tag, .. } = &variant.ty {
2321 match tag.class {
2322 TagClass::ContextSpecific => {
2323 let tagging_str = match tag.tagging {
2324 Tagging::Explicit => "explicit",
2325 Tagging::Implicit => "implicit",
2326 };
2327 let attr = self.field_derive_cfg_attr(&format!(
2328 "asn1(tag({}, {}))",
2329 tag.number, tagging_str
2330 ));
2331 writeln!(&mut self.output, "{}", attr)?;
2332 }
2333 TagClass::Application => {
2334 writeln!(
2335 &mut self.output,
2336 " // APPLICATION [{}] -- use asn1(application_tag) when supported",
2337 tag.number
2338 )?;
2339 let attr = self
2340 .field_derive_cfg_attr(&format!("asn1(tag({}, explicit))", tag.number));
2341 writeln!(&mut self.output, "{}", attr)?;
2342 }
2343 TagClass::Universal => {
2344 writeln!(&mut self.output, " // UNIVERSAL [{}]", tag.number)?;
2345 }
2346 TagClass::Private => {
2347 writeln!(&mut self.output, " // PRIVATE [{}]", tag.number)?;
2348 }
2349 }
2350 }
2351
2352 writeln!(&mut self.output, " {}({}),", variant_name, rust_type)?;
2353 }
2354
2355 writeln!(&mut self.output, "}}")?;
2356
2357 self.generate_format_asn1_impl(name, needs_lifetime)?;
2358
2359 Ok(())
2360 }
2361
2362 fn generate_sequence_of_type(
2363 &mut self,
2364 name: &str,
2365 inner: &Type,
2366 size_constraint: Option<&SizeConstraint>,
2367 ) -> Result<(), std::fmt::Error> {
2368 if matches!(inner, Type::Sequence(_) | Type::Set(_) | Type::Choice(_)) {
2371 let element_name = format!("{}Element", name);
2372 let element_def = Definition {
2373 name: element_name.clone(),
2374 ty: inner.clone(),
2375 };
2376 self.generate_definition(&element_def)?;
2377 writeln!(&mut self.output)?;
2378 if let Some(constraint) = size_constraint {
2379 let constraint_str = self.format_size_constraint(constraint);
2380 writeln!(&mut self.output, "// Constraint: {}", constraint_str)?;
2381 }
2382 let rust_type = format!("Vec<{}>", element_name);
2383 let seq_of_type = Type::SequenceOf(Box::new(inner.clone()), size_constraint.cloned());
2385 self.generate_type_alias(name, &rust_type, &seq_of_type)?;
2386 return Ok(());
2387 }
2388
2389 if let Type::Constrained {
2391 base_type,
2392 constraint,
2393 } = inner
2394 {
2395 let element_name = format!("{}Element", name);
2397
2398 match base_type.as_ref() {
2400 Type::Integer(_, _) => {
2401 if let ConstraintSpec::Subtype(ref subtype) = constraint.spec {
2402 self.generate_constrained_integer(&element_name, subtype)?;
2403 }
2404 }
2405 Type::IA5String(_)
2406 | Type::Utf8String(_)
2407 | Type::PrintableString(_)
2408 | Type::TeletexString(_)
2409 | Type::UniversalString(_)
2410 | Type::BmpString(_)
2411 | Type::GeneralString(_)
2412 | Type::NumericString(_)
2413 | Type::VisibleString(_) => {
2414 let base_type_str = self.rust_type(base_type);
2415 if let ConstraintSpec::Subtype(ref subtype) = constraint.spec {
2416 self.generate_constrained_string(&element_name, &base_type_str, subtype)?;
2417 }
2418 }
2419 _ => {
2420 let inner_type = self.rust_type(inner);
2422 writeln!(
2423 &mut self.output,
2424 "pub type {} = {};",
2425 element_name, inner_type
2426 )?;
2427 }
2428 }
2429
2430 writeln!(&mut self.output)?;
2431
2432 if let Some(constraint) = size_constraint {
2434 let constraint_str = self.format_size_constraint(constraint);
2435 writeln!(&mut self.output, "// Constraint: {}", constraint_str)?;
2436 }
2437 writeln!(
2438 &mut self.output,
2439 "pub type {} = Vec<{}>;",
2440 name, element_name
2441 )?;
2442 } else {
2443 if let Some(constraint) = size_constraint {
2445 let constraint_str = self.format_size_constraint(constraint);
2446 writeln!(&mut self.output, "// Constraint: {}", constraint_str)?;
2447 }
2448 let inner_type = self.rust_type(inner);
2449 let rust_type = format!("Vec<{}>", inner_type);
2450 let seq_of_type = Type::SequenceOf(Box::new(inner.clone()), size_constraint.cloned());
2452 self.generate_type_alias(name, &rust_type, &seq_of_type)?;
2453 }
2454 Ok(())
2455 }
2456
2457 fn generate_set_of_type(
2458 &mut self,
2459 name: &str,
2460 inner: &Type,
2461 size_constraint: Option<&SizeConstraint>,
2462 ) -> Result<(), std::fmt::Error> {
2463 if matches!(inner, Type::Sequence(_) | Type::Set(_) | Type::Choice(_)) {
2465 let element_name = format!("{}Element", name);
2466 let element_def = Definition {
2467 name: element_name.clone(),
2468 ty: inner.clone(),
2469 };
2470 self.generate_definition(&element_def)?;
2471 writeln!(&mut self.output)?;
2472 if let Some(constraint) = size_constraint {
2473 let constraint_str = self.format_size_constraint(constraint);
2474 writeln!(&mut self.output, "// Constraint: {}", constraint_str)?;
2475 }
2476 let rust_type = format!("SetOf<{}>", element_name);
2477 let seq_of_type = Type::SetOf(Box::new(inner.clone()), size_constraint.cloned());
2479 self.generate_type_alias(name, &rust_type, &seq_of_type)?;
2480 return Ok(());
2481 }
2482
2483 if let Type::Constrained {
2485 base_type,
2486 constraint,
2487 } = inner
2488 {
2489 let element_name = format!("{}Element", name);
2491
2492 match base_type.as_ref() {
2494 Type::Integer(_, _) => {
2495 if let ConstraintSpec::Subtype(ref subtype) = constraint.spec {
2496 self.generate_constrained_integer(&element_name, subtype)?;
2497 }
2498 }
2499 Type::IA5String(_)
2500 | Type::Utf8String(_)
2501 | Type::PrintableString(_)
2502 | Type::TeletexString(_)
2503 | Type::UniversalString(_)
2504 | Type::BmpString(_)
2505 | Type::GeneralString(_)
2506 | Type::NumericString(_)
2507 | Type::VisibleString(_) => {
2508 let base_type_str = self.rust_type(base_type);
2509 if let ConstraintSpec::Subtype(ref subtype) = constraint.spec {
2510 self.generate_constrained_string(&element_name, &base_type_str, subtype)?;
2511 }
2512 }
2513 _ => {
2514 let inner_type = self.rust_type(inner);
2516 writeln!(
2517 &mut self.output,
2518 "pub type {} = {};",
2519 element_name, inner_type
2520 )?;
2521 }
2522 }
2523
2524 writeln!(&mut self.output)?;
2525
2526 if let Some(constraint) = size_constraint {
2528 let constraint_str = self.format_size_constraint(constraint);
2529 writeln!(&mut self.output, "// Constraint: {}", constraint_str)?;
2530 }
2531 writeln!(
2532 &mut self.output,
2533 "pub type {} = SetOf<{}>;",
2534 name, element_name
2535 )?;
2536 } else {
2537 if let Some(constraint) = size_constraint {
2539 let constraint_str = self.format_size_constraint(constraint);
2540 writeln!(&mut self.output, "// Constraint: {}", constraint_str)?;
2541 }
2542 let inner_type = self.rust_type(inner);
2543 let rust_type = format!("SetOf<{}>", inner_type);
2544 let seq_of_type = Type::SetOf(Box::new(inner.clone()), size_constraint.cloned());
2546 self.generate_type_alias(name, &rust_type, &seq_of_type)?;
2547 }
2548 Ok(())
2549 }
2550
2551 fn resolves_to_any(&self, ty: &Type) -> bool {
2554 match ty {
2555 Type::Any | Type::AnyDefinedBy(_) => true,
2556 Type::TypeRef(name) => {
2557 let clean = name.trim_end_matches("{}");
2558 matches!(
2559 self.type_definitions.get(clean),
2560 Some(Type::Any) | Some(Type::AnyDefinedBy(_))
2561 )
2562 }
2563 _ => false,
2564 }
2565 }
2566
2567 fn resolves_to_choice(&self, ty: &Type) -> bool {
2574 match ty {
2575 Type::Choice(_) => true,
2576 Type::TypeRef(name) => {
2577 let clean = name.trim_end_matches("{}");
2578 self.config.known_choice_types.contains(clean)
2579 || matches!(self.type_definitions.get(clean), Some(Type::Choice(_)))
2580 }
2581 _ => false,
2582 }
2583 }
2584
2585 fn generate_field(&mut self, field: &SequenceField) -> Result<(), std::fmt::Error> {
2586 let field_name = to_snake_case(&field.name);
2587 let rust_type = self.inline_sequence_of_types(&field.ty);
2589
2590 if let Type::Tagged { tag, inner } = &field.ty {
2592 let tagging = match tag.tagging {
2593 Tagging::Explicit => "explicit",
2594 Tagging::Implicit if self.resolves_to_choice(inner) => "explicit",
2599 Tagging::Implicit => "implicit",
2600 };
2601 match tag.class {
2602 TagClass::ContextSpecific => {
2603 let attr = self
2604 .field_derive_cfg_attr(&format!("asn1(tag({}, {}))", tag.number, tagging));
2605 writeln!(&mut self.output, "{}", attr)?;
2606 if self.config.any_as_raw_der
2613 && tag.tagging == Tagging::Implicit
2614 && self.resolves_to_any(inner)
2615 {
2616 let rawder_attr = self.field_derive_cfg_attr("asn1(rawder)");
2617 writeln!(&mut self.output, "{}", rawder_attr)?;
2618 }
2619 }
2620 TagClass::Application => {
2621 writeln!(
2622 &mut self.output,
2623 " // APPLICATION [{} {}] -- use asn1(application_tag) when supported",
2624 tag.number, tagging
2625 )?;
2626 let attr = self
2627 .field_derive_cfg_attr(&format!("asn1(tag({}, {}))", tag.number, tagging));
2628 writeln!(&mut self.output, "{}", attr)?;
2629 }
2630 TagClass::Universal => {
2631 writeln!(
2632 &mut self.output,
2633 " // UNIVERSAL [{}] {}",
2634 tag.number, tagging
2635 )?;
2636 }
2637 TagClass::Private => {
2638 writeln!(
2639 &mut self.output,
2640 " // PRIVATE [{}] {}",
2641 tag.number, tagging
2642 )?;
2643 }
2644 }
2645 }
2646
2647 if field.optional || field.default.is_some() {
2650 let attr = self.field_derive_cfg_attr("asn1(optional)");
2651 writeln!(&mut self.output, "{}", attr)?;
2652 }
2653
2654 let rust_type = if self.config.raw_der_fields.contains(&field_name) {
2656 "RawDer<'a>".to_string()
2657 } else {
2658 rust_type
2659 };
2660
2661 let final_type = if field.optional || field.default.is_some() {
2663 format!("Option<{}>", rust_type)
2664 } else {
2665 rust_type
2666 };
2667
2668 writeln!(&mut self.output, " pub {}: {},", field_name, final_type)?;
2669
2670 Ok(())
2671 }
2672
2673 fn generate_subtype(
2675 &mut self,
2676 type_name: &str,
2677 base_type: &Type,
2678 constraint: &SubtypeConstraint,
2679 ) -> Result<(), std::fmt::Error> {
2680 let base_type_name = self.rust_type(base_type);
2681 let constraint_display = self.format_constraint_display(constraint);
2682
2683 writeln!(
2685 &mut self.output,
2686 "/// {} ({})",
2687 base_type_name, constraint_display
2688 )?;
2689
2690 writeln!(
2692 &mut self.output,
2693 "#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]"
2694 )?;
2695 writeln!(
2696 &mut self.output,
2697 "pub struct {}({});",
2698 type_name, base_type_name
2699 )?;
2700 writeln!(&mut self.output)?;
2701
2702 writeln!(&mut self.output, "impl {} {{", type_name)?;
2703
2704 let validation_code = self.generate_subtype_validation("val", constraint)?;
2707
2708 writeln!(
2709 &mut self.output,
2710 " /// Create a new {} with validation",
2711 type_name
2712 )?;
2713 writeln!(
2714 &mut self.output,
2715 " pub fn new(value: {}) -> Result<Self, &'static str> {{",
2716 base_type_name
2717 )?;
2718
2719 let is_integer_constraint = matches!(
2721 constraint,
2722 SubtypeConstraint::SingleValue(_)
2723 | SubtypeConstraint::ValueRange { .. }
2724 | SubtypeConstraint::Union(_)
2725 | SubtypeConstraint::Intersection(_)
2726 | SubtypeConstraint::Complement(_)
2727 );
2728
2729 let description = self.generate_constraint_description(constraint);
2730
2731 if is_integer_constraint {
2732 writeln!(&mut self.output, " let val = value.into_inner();")?;
2733 writeln!(&mut self.output, " if {} {{", validation_code)?;
2734 writeln!(&mut self.output, " Ok({}(value))", type_name)?;
2735 writeln!(&mut self.output, " }} else {{")?;
2736 writeln!(&mut self.output, " Err(\"{}\")", description)?;
2737 writeln!(&mut self.output, " }}")?;
2738 } else {
2739 let validation_code =
2741 self.generate_string_validation("value", &base_type_name, constraint);
2742 write!(&mut self.output, "{}", validation_code)?;
2743 }
2744
2745 writeln!(&mut self.output, " }}")?;
2746 writeln!(&mut self.output)?;
2747
2748 writeln!(
2750 &mut self.output,
2751 " /// Create without validation (use with caution)"
2752 )?;
2753 writeln!(
2754 &mut self.output,
2755 " pub const fn new_unchecked(value: {}) -> Self {{",
2756 base_type_name
2757 )?;
2758 writeln!(&mut self.output, " {}(value)", type_name)?;
2759 writeln!(&mut self.output, " }}")?;
2760 writeln!(&mut self.output)?;
2761
2762 writeln!(&mut self.output, " /// Get the inner value")?;
2764 writeln!(
2765 &mut self.output,
2766 " pub const fn get(&self) -> &{} {{",
2767 base_type_name
2768 )?;
2769 writeln!(&mut self.output, " &self.0")?;
2770 writeln!(&mut self.output, " }}")?;
2771 writeln!(&mut self.output)?;
2772
2773 writeln!(
2775 &mut self.output,
2776 " /// Consume and return the inner value"
2777 )?;
2778 writeln!(
2779 &mut self.output,
2780 " pub fn into_inner(self) -> {} {{",
2781 base_type_name
2782 )?;
2783 writeln!(&mut self.output, " self.0")?;
2784 writeln!(&mut self.output, " }}")?;
2785
2786 writeln!(&mut self.output, "}}")?;
2787 writeln!(&mut self.output)?;
2788
2789 let try_from_path = self.try_from_path();
2791 writeln!(
2792 &mut self.output,
2793 "impl {}::convert::TryFrom<{}> for {} {{",
2794 try_from_path, base_type_name, type_name
2795 )?;
2796 writeln!(&mut self.output, " type Error = &'static str;")?;
2797 writeln!(&mut self.output)?;
2798 writeln!(
2799 &mut self.output,
2800 " fn try_from(value: {}) -> Result<Self, Self::Error> {{",
2801 base_type_name
2802 )?;
2803 writeln!(&mut self.output, " Self::new(value)")?;
2804 writeln!(&mut self.output, " }}")?;
2805 writeln!(&mut self.output, "}}")?;
2806
2807 Ok(())
2808 }
2809
2810 fn generate_subtype_validation(
2812 &mut self,
2813 var: &str,
2814 constraint: &SubtypeConstraint,
2815 ) -> Result<String, std::fmt::Error> {
2816 Ok(self.generate_constraint_validation(var, constraint))
2819 }
2820
2821 fn generate_format_asn1_impl(
2829 &mut self,
2830 name: &str,
2831 has_lifetime: bool,
2832 ) -> Result<(), std::fmt::Error> {
2833 writeln!(&mut self.output)?;
2834 if has_lifetime {
2835 writeln!(&mut self.output, "impl<'a> {}<'a> {{", name)?;
2836 } else {
2837 writeln!(&mut self.output, "impl {} {{", name)?;
2838 }
2839 if has_lifetime {
2841 writeln!(
2842 &mut self.output,
2843 " /// Parse a DER-encoded `{}` from borrowed bytes.",
2844 name
2845 )?;
2846 writeln!(&mut self.output, " ///")?;
2847 writeln!(
2848 &mut self.output,
2849 " /// The returned value borrows from `data` for zero-copy fields."
2850 )?;
2851 writeln!(
2852 &mut self.output,
2853 " pub fn from_der(data: &'a [u8]) -> synta::Result<Self> {{"
2854 )?;
2855 } else {
2856 writeln!(
2857 &mut self.output,
2858 " /// Parse a DER-encoded `{}` from bytes.",
2859 name
2860 )?;
2861 writeln!(
2862 &mut self.output,
2863 " pub fn from_der(data: &[u8]) -> synta::Result<Self> {{"
2864 )?;
2865 }
2866 writeln!(
2867 &mut self.output,
2868 " synta::Decoder::new(data, synta::Encoding::Der).decode::<Self>()"
2869 )?;
2870 writeln!(&mut self.output, " }}")?;
2871 writeln!(&mut self.output)?;
2872 writeln!(&mut self.output, " /// Encode this value to DER bytes.")?;
2874 writeln!(&mut self.output, " ///")?;
2875 writeln!(
2876 &mut self.output,
2877 " /// Returns a [`synta::Result`] wrapping the DER-encoded bytes,"
2878 )?;
2879 writeln!(&mut self.output, " /// or an error if encoding fails.")?;
2880 writeln!(
2881 &mut self.output,
2882 " pub fn to_der(&self) -> synta::Result<Vec<u8>> {{"
2883 )?;
2884 writeln!(&mut self.output, " use synta::Encode;")?;
2885 writeln!(
2886 &mut self.output,
2887 " let mut encoder = synta::Encoder::new(synta::Encoding::Der);"
2888 )?;
2889 writeln!(&mut self.output, " self.encode(&mut encoder)?;")?;
2890 writeln!(&mut self.output, " encoder.finish()")?;
2891 writeln!(&mut self.output, " }}")?;
2892 writeln!(&mut self.output)?;
2894 writeln!(
2895 &mut self.output,
2896 " /// Format the encoded DER bytes of this value."
2897 )?;
2898 writeln!(&mut self.output, " ///")?;
2899 writeln!(
2900 &mut self.output,
2901 " /// `mode` controls the output style:"
2902 )?;
2903 writeln!(
2904 &mut self.output,
2905 " /// - [`synta::Asn1FormatMode::Hex`] — space-separated uppercase hex bytes"
2906 )?;
2907 writeln!(
2908 &mut self.output,
2909 " /// - [`synta::Asn1FormatMode::Text`] — indented human-readable ASN.1 dump"
2910 )?;
2911 writeln!(
2912 &mut self.output,
2913 " pub fn format_asn1(&self, mode: synta::Asn1FormatMode) -> String {{"
2914 )?;
2915 writeln!(&mut self.output, " use synta::Encode;")?;
2916 writeln!(
2917 &mut self.output,
2918 " let mut encoder = synta::Encoder::new(synta::Encoding::Der);"
2919 )?;
2920 writeln!(
2921 &mut self.output,
2922 " if self.encode(&mut encoder).is_err() {{"
2923 )?;
2924 writeln!(
2925 &mut self.output,
2926 " return String::from(\"<encode error>\");"
2927 )?;
2928 writeln!(&mut self.output, " }}")?;
2929 writeln!(&mut self.output, " match encoder.finish() {{")?;
2930 writeln!(
2931 &mut self.output,
2932 " Ok(bytes) => synta::format_asn1_bytes(&bytes, mode),"
2933 )?;
2934 writeln!(
2935 &mut self.output,
2936 " Err(_) => String::from(\"<encode error>\"),"
2937 )?;
2938 writeln!(&mut self.output, " }}")?;
2939 writeln!(&mut self.output, " }}")?;
2940 writeln!(&mut self.output, "}}")?;
2941 Ok(())
2942 }
2943
2944 #[inline]
2952 fn string_rust_type(&self, owned: &str, borrowed: &str) -> String {
2953 match self.config.string_type_mode {
2954 StringTypeMode::Owned => owned.to_string(),
2955 StringTypeMode::Borrowed => format!("{}<'a>", borrowed),
2956 }
2957 }
2958
2959 fn rust_type(&self, ty: &Type) -> String {
2960 match ty {
2961 Type::Integer(_, _) => "Integer".to_string(),
2962 Type::Enumerated(_) => "Enumerated".to_string(),
2963 Type::Real => "f64".to_string(),
2964 Type::Boolean => "Boolean".to_string(),
2965 Type::OctetString(_) => self.string_rust_type("OctetString", "OctetStringRef"),
2967 Type::BitString(_) => self.string_rust_type("BitString", "BitStringRef"),
2968 Type::Utf8String(_) => self.string_rust_type("Utf8String", "Utf8StringRef"),
2969 Type::PrintableString(_) => {
2970 self.string_rust_type("PrintableString", "PrintableStringRef")
2971 }
2972 Type::IA5String(_) => self.string_rust_type("IA5String", "IA5StringRef"),
2973 Type::ObjectIdentifier => "ObjectIdentifier".to_string(),
2974 Type::Null => "Null".to_string(),
2975 Type::TeletexString(_) => "TeletexString".to_string(),
2977 Type::UniversalString(_) => "UniversalString".to_string(),
2978 Type::BmpString(_) => "BmpString".to_string(),
2979 Type::GeneralString(_) => "GeneralString".to_string(),
2980 Type::NumericString(_) => "NumericString".to_string(),
2981 Type::VisibleString(_) => "VisibleString".to_string(),
2982 Type::UtcTime => "UtcTime".to_string(),
2983 Type::GeneralizedTime => "GeneralizedTime".to_string(),
2984 Type::TypeRef(name) => {
2985 let type_name = to_pascal_case(name);
2986
2987 if let Some(lifetime) = self.config.imported_type_lifetimes.get(name) {
2993 return format!("{}<{}>", type_name, lifetime);
2994 }
2995
2996 if self.types_with_lifetimes.contains(&type_name) {
2998 return format!("{}<'a>", type_name);
2999 }
3000
3001 type_name
3002 }
3003 Type::Class(_) => "/* class */".to_string(),
3004 Type::Sequence(_) => "/* nested sequence */".to_string(),
3005 Type::Set(_) => "/* nested set */".to_string(),
3006 Type::Choice(_) => "/* nested choice */".to_string(),
3007 Type::SequenceOf(inner, _) => format!("Vec<{}>", self.rust_type(inner)),
3008 Type::SetOf(inner, _) => format!("SetOf<{}>", self.rust_type(inner)),
3009 Type::Tagged { inner, .. } => self.rust_type(inner),
3010 Type::Constrained { base_type, .. } => self.rust_type(base_type),
3011 Type::Any => {
3012 if self.config.any_as_raw_der {
3013 "RawDer<'a>".to_string()
3014 } else {
3015 "Element<'a>".to_string()
3016 }
3017 }
3018 Type::AnyDefinedBy(_) => {
3019 if self.config.any_as_raw_der {
3020 "RawDer<'a>".to_string()
3021 } else {
3022 "Element<'a>".to_string()
3023 }
3024 }
3025 }
3026 }
3027
3028 fn type_needs_lifetime(&self, ty: &Type) -> bool {
3041 match ty {
3042 Type::OctetString(_)
3044 | Type::BitString(_)
3045 | Type::Utf8String(_)
3046 | Type::PrintableString(_)
3047 | Type::IA5String(_) => self.config.string_type_mode == StringTypeMode::Borrowed,
3048 Type::Any => true, Type::AnyDefinedBy(_) => true, Type::TypeRef(name) => {
3052 let type_name = to_pascal_case(name);
3053
3054 if self.config.imported_type_lifetimes.contains_key(name) {
3057 return true;
3058 }
3059
3060 if self.types_with_lifetimes.contains(&type_name) {
3062 return true;
3063 }
3064
3065 false
3066 }
3067 Type::SequenceOf(inner, _) | Type::SetOf(inner, _) => self.type_needs_lifetime(inner),
3068 Type::Tagged { inner, .. }
3069 | Type::Constrained {
3070 base_type: inner, ..
3071 } => self.type_needs_lifetime(inner),
3072 Type::Sequence(fields) => fields.iter().any(|f| self.type_needs_lifetime(&f.ty)),
3073 Type::Set(fields) => fields.iter().any(|f| self.type_needs_lifetime(&f.ty)),
3074 Type::Choice(variants) => variants.iter().any(|v| self.type_needs_lifetime(&v.ty)),
3075 _ => false,
3076 }
3077 }
3078
3079 fn sequence_needs_lifetime(&self, fields: &[SequenceField]) -> bool {
3081 fields.iter().any(|field| {
3082 let field_name = to_snake_case(&field.name);
3083 self.config.raw_der_fields.contains(&field_name) || self.type_needs_lifetime(&field.ty)
3084 })
3085 }
3086
3087 fn choice_needs_lifetime(&self, variants: &[ChoiceVariant]) -> bool {
3089 variants
3095 .iter()
3096 .any(|variant| self.type_needs_lifetime(&variant.ty))
3097 }
3098
3099 fn generate_type_alias(
3101 &mut self,
3102 type_name: &str,
3103 rust_type: &str,
3104 asn1_type: &Type,
3105 ) -> Result<(), std::fmt::Error> {
3106 let needs_lifetime = self.type_needs_lifetime(asn1_type);
3110
3111 if needs_lifetime {
3112 writeln!(
3113 &mut self.output,
3114 "pub type {}<'a> = {};",
3115 type_name, rust_type
3116 )?;
3117 self.types_with_lifetimes.insert(type_name.to_string());
3120 } else {
3121 writeln!(&mut self.output, "pub type {} = {};", type_name, rust_type)?;
3122 }
3123 Ok(())
3124 }
3125
3126 fn build_oid_registry(
3128 &self,
3129 values: &[crate::ast::ValueAssignment],
3130 ) -> std::collections::HashMap<String, Vec<u32>> {
3131 use std::collections::HashMap;
3132 let mut registry: HashMap<String, Vec<u32>> = HashMap::new();
3133
3134 let mut changed = true;
3136 while changed {
3137 changed = false;
3138 for value_assignment in values {
3139 if registry.contains_key(&value_assignment.name) {
3140 continue;
3141 }
3142
3143 if let crate::ast::Value::ObjectIdentifier(components) = &value_assignment.value {
3144 let mut resolved = Vec::new();
3145 let mut can_resolve = true;
3146
3147 for component in components {
3148 match component {
3149 crate::ast::OidComponent::Number(n) => {
3150 resolved.push(*n);
3151 }
3152 crate::ast::OidComponent::NamedRef(name) => {
3153 if let Some(base_oid) = registry.get(name) {
3154 resolved.extend_from_slice(base_oid);
3155 } else {
3156 can_resolve = false;
3157 break;
3158 }
3159 }
3160 }
3161 }
3162
3163 if can_resolve {
3164 registry.insert(value_assignment.name.clone(), resolved);
3165 changed = true;
3166 }
3167 }
3168 }
3169 }
3170
3171 registry
3172 }
3173
3174 fn generate_value_assignment(
3176 &mut self,
3177 value_assignment: &crate::ast::ValueAssignment,
3178 oid_registry: &std::collections::HashMap<String, Vec<u32>>,
3179 ) -> Result<(), std::fmt::Error> {
3180 let const_name = to_screaming_snake_case(&value_assignment.name);
3181
3182 match &value_assignment.value {
3183 crate::ast::Value::ObjectIdentifier(_components) => {
3184 if let Some(oid_values) = oid_registry.get(&value_assignment.name) {
3186 write!(&mut self.output, "pub const {}: &[u32] = &[", const_name)?;
3188 for (i, value) in oid_values.iter().enumerate() {
3189 if i > 0 {
3190 write!(&mut self.output, ", ")?;
3191 }
3192 write!(&mut self.output, "{}", value)?;
3193 }
3194 writeln!(&mut self.output, "];")?;
3195 } else {
3196 writeln!(
3198 &mut self.output,
3199 "// Note: Could not resolve OID for {}",
3200 value_assignment.name
3201 )?;
3202 }
3203 }
3204 crate::ast::Value::Integer(n) => {
3205 writeln!(&mut self.output, "pub const {}: i64 = {};", const_name, n)?;
3206 }
3207 crate::ast::Value::Boolean(b) => {
3208 writeln!(&mut self.output, "pub const {}: bool = {};", const_name, b)?;
3209 }
3210 crate::ast::Value::String(s) => {
3211 writeln!(
3212 &mut self.output,
3213 "pub const {}: &str = \"{}\";",
3214 const_name, s
3215 )?;
3216 }
3217 }
3218
3219 Ok(())
3220 }
3221
3222 fn prescan_types_for_lifetimes(&mut self, definitions: &[Definition]) {
3225 let mut changed = true;
3227 while changed {
3228 changed = false;
3229
3230 for def in definitions {
3231 let type_name = to_pascal_case(&def.name);
3233 if self.types_with_lifetimes.contains(&type_name) {
3234 continue;
3235 }
3236 if self.config.skip_imported_types.contains(&def.name) {
3237 continue;
3238 }
3239
3240 let needs_lifetime = match &def.ty {
3242 Type::Sequence(fields) => self.sequence_needs_lifetime(fields),
3243 Type::Set(fields) => self.sequence_needs_lifetime(fields),
3244 Type::Choice(variants) => self.choice_needs_lifetime(variants),
3245 Type::Constrained {
3247 base_type: _,
3248 constraint,
3249 } => match constraint.spec {
3250 ConstraintSpec::Subtype(SubtypeConstraint::NamedBitList(_)) => false,
3251 ConstraintSpec::Subtype(SubtypeConstraint::Intersection(
3252 ref constraints,
3253 )) if constraints
3254 .iter()
3255 .any(|c| matches!(c, SubtypeConstraint::NamedBitList(_))) =>
3256 {
3257 false
3258 }
3259 _ => self.type_needs_lifetime(&def.ty),
3260 },
3261 other => self.type_needs_lifetime(other),
3263 };
3264
3265 if needs_lifetime {
3266 self.types_with_lifetimes.insert(type_name);
3267 changed = true;
3268 }
3269 }
3270 }
3271 }
3272
3273 fn inline_sequence_of_types(&self, ty: &Type) -> String {
3276 match ty {
3277 Type::TypeRef(type_ref_name) => {
3278 let type_name = to_pascal_case(type_ref_name);
3279 if let Some(def_type) = self.type_definitions.get(&type_name) {
3280 match def_type {
3281 Type::SequenceOf(inner, _) => {
3282 let inner_rust_type = self.inline_sequence_of_types(inner);
3284 format!("Vec<{}>", inner_rust_type)
3285 }
3286 Type::SetOf(inner, _) => {
3287 let inner_rust_type = self.inline_sequence_of_types(inner);
3289 format!("SetOf<{}>", inner_rust_type)
3290 }
3291 _ => self.rust_type(ty),
3292 }
3293 } else {
3294 self.rust_type(ty)
3295 }
3296 }
3297 Type::Tagged { inner, .. } => self.inline_sequence_of_types(inner),
3299 Type::Constrained { base_type, .. } => self.inline_sequence_of_types(base_type),
3301 _ => self.rust_type(ty),
3302 }
3303 }
3304}
3305
3306impl Default for CodeGenerator {
3307 fn default() -> Self {
3308 Self::new()
3309 }
3310}
3311
3312fn anonymous_inner_type(ty: &Type) -> Option<&Type> {
3319 let candidate = match ty {
3320 Type::Tagged { inner, .. } => inner.as_ref(),
3321 Type::Constrained { base_type, .. } => base_type.as_ref(),
3322 other => other,
3323 };
3324 matches!(
3325 candidate,
3326 Type::Sequence(_) | Type::Set(_) | Type::Choice(_)
3327 )
3328 .then_some(candidate)
3329}
3330
3331pub fn generate(module: &Module) -> Result<String, std::fmt::Error> {
3338 let mut gen = CodeGenerator::new();
3339 gen.generate_module(module)
3340}
3341
3342pub fn generate_with_config(
3358 module: &Module,
3359 config: CodeGenConfig,
3360) -> Result<String, std::fmt::Error> {
3361 let mut gen = CodeGenerator::with_config(config);
3362 gen.generate_module(module)
3363}