1use core::fmt;
4
5use alloc::vec::Vec;
6
7use super::{EnumVariant, List};
8
9#[derive(Debug, Clone, Eq)]
11pub struct CustomEnum<'a> {
12 name: &'a str,
14 variants: List<'a, EnumVariant<'a>>,
16 comments: List<'a, super::Comment<'a>>,
18}
19
20impl<'a> CustomEnum<'a> {
21 pub const fn new(
23 name: &'a str,
24 variants: &'a [&'a EnumVariant<'a>],
25 comments: &'a [&'a super::Comment<'a>],
26 ) -> Self {
27 Self {
28 name,
29 variants: List::Borrowed(variants),
30 comments: List::Borrowed(comments),
31 }
32 }
33
34 pub fn new_owned(
36 name: &'a str,
37 variants: Vec<EnumVariant<'a>>,
38 comments: Vec<super::Comment<'a>>,
39 ) -> Self {
40 Self {
41 name,
42 variants: List::from(variants),
43 comments: List::from(comments),
44 }
45 }
46
47 pub fn name(&self) -> &'a str {
49 self.name
50 }
51
52 pub fn variants(&self) -> impl Iterator<Item = &EnumVariant<'a>> {
54 self.variants.iter()
55 }
56
57 pub fn comments(&self) -> impl Iterator<Item = &super::Comment<'a>> {
59 self.comments.iter()
60 }
61}
62
63impl<'a> fmt::Display for CustomEnum<'a> {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 for comment in self.comments.iter() {
67 writeln!(f, "{comment}")?;
68 }
69
70 let has_variant_comments = self.variants.iter().any(|v| v.has_comments());
72
73 if has_variant_comments {
74 writeln!(f, "type {} (", self.name)?;
76 let last = self.variants.len().saturating_sub(1);
77 for (i, variant) in self.variants.iter().enumerate() {
78 for comment in variant.comments() {
80 writeln!(f, "\t{}", comment)?;
81 }
82 if i == last {
84 writeln!(f, "\t{}", variant.name())?;
85 } else {
86 writeln!(f, "\t{},", variant.name())?;
87 }
88 }
89 write!(f, ")")
90 } else {
91 write!(f, "type {} (", self.name)?;
93 let mut first = true;
94 for variant in self.variants.iter() {
95 if !first {
96 write!(f, ", ")?;
97 }
98 first = false;
99 write!(f, "{}", variant)?;
100 }
101 write!(f, ")")
102 }
103 }
104}
105
106impl<'a> PartialEq for CustomEnum<'a> {
107 fn eq(&self, other: &Self) -> bool {
108 self.name == other.name && self.variants == other.variants
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use alloc::vec;
115
116 use super::*;
117 use crate::idl::{Comment, EnumVariant};
118 use core::fmt::Write;
119
120 #[test]
121 fn display_with_comments() {
122 let comment1 = Comment::new("Status enumeration");
123 let comment2 = Comment::new("Represents current state");
124 let comments = [&comment1, &comment2];
125
126 let var1 = EnumVariant::new("active", &[]);
127 let var2 = EnumVariant::new("inactive", &[]);
128 let var3 = EnumVariant::new("pending", &[]);
129 let variants = [&var1, &var2, &var3];
130
131 let custom_enum = CustomEnum::new("Status", &variants, &comments);
132 let mut displayed = String::new();
133 write!(&mut displayed, "{}", custom_enum).unwrap();
134 assert_eq!(
135 displayed,
136 "# Status enumeration\n# Represents current state\ntype Status (active, inactive, pending)"
137 );
138 }
139
140 #[test]
141 fn display_with_variant_comments() {
142 let var_comment = Comment::new("The active state");
143 let var1 = EnumVariant::new_owned("active", vec![var_comment]);
144 let var2 = EnumVariant::new_owned("inactive", vec![]);
145 let custom_enum = CustomEnum::new_owned("Status", vec![var1, var2], vec![]);
146
147 let mut displayed = String::new();
148 write!(&mut displayed, "{}", custom_enum).unwrap();
149 assert_eq!(
150 displayed,
151 "type Status (\n\t# The active state\n\tactive,\n\tinactive\n)"
152 );
153 }
154
155 #[test_log::test]
156 fn comprehensive_enum_with_per_variant_comments() {
157 let enum_comment = Comment::new("Status enumeration with detailed docs");
159
160 let active_comment = Comment::new("System is operational");
161 let inactive_comment = Comment::new("System is stopped");
162 let pending_comment = Comment::new("System is starting up");
163
164 let var1 = EnumVariant::new_owned("active", vec![active_comment]);
165 let var2 = EnumVariant::new_owned("inactive", vec![inactive_comment]);
166 let var3 = EnumVariant::new_owned("pending", vec![pending_comment]);
167
168 let custom_enum =
169 CustomEnum::new_owned("SystemStatus", vec![var1, var2, var3], vec![enum_comment]);
170
171 assert_eq!(custom_enum.name(), "SystemStatus");
173 assert_eq!(custom_enum.variants().count(), 3);
174 assert_eq!(custom_enum.comments().count(), 1);
175
176 let mut displayed = String::new();
178 write!(&mut displayed, "{}", custom_enum).unwrap();
179
180 assert!(displayed.contains("Status enumeration with detailed docs"));
182 assert!(displayed.contains("# System is operational\n\tactive"));
184 assert!(displayed.contains("# System is stopped\n\tinactive"));
185 assert!(displayed.contains("# System is starting up\n\tpending"));
186
187 debug!("✓ Comprehensive enum display: {}", displayed);
188 }
189
190 #[test]
191 fn formatting_with_and_without_comments() {
192 let var1 = EnumVariant::new("red", &[]);
194 let var2 = EnumVariant::new("green", &[]);
195 let var3 = EnumVariant::new("blue", &[]);
196 let variants_no_comments = [&var1, &var2, &var3];
197
198 let enum_no_comments = CustomEnum::new("Color", &variants_no_comments, &[]);
199 let mut displayed = String::new();
200 write!(&mut displayed, "{}", enum_no_comments).unwrap();
201 assert_eq!(displayed, "type Color (red, green, blue)");
202
203 let comment = Comment::new("Primary color");
205 let comment_refs = [&comment];
206 let var_with_comment = EnumVariant::new("red", &comment_refs);
207 let var_without_comment1 = EnumVariant::new("green", &[]);
208 let var_without_comment2 = EnumVariant::new("blue", &[]);
209 let variants_with_comments = [
210 &var_with_comment,
211 &var_without_comment1,
212 &var_without_comment2,
213 ];
214
215 let enum_with_comments = CustomEnum::new("Color", &variants_with_comments, &[]);
216 let mut displayed = String::new();
217 write!(&mut displayed, "{}", enum_with_comments).unwrap();
218 assert_eq!(
219 displayed,
220 "type Color (\n\t# Primary color\n\tred,\n\tgreen,\n\tblue\n)"
221 );
222 }
223}