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 for variant in self.variants.iter() {
77 for comment in variant.comments() {
79 writeln!(f, "\t{}", comment)?;
80 }
81 writeln!(f, "\t{}", variant.name())?;
83 }
84 write!(f, ")")
85 } else {
86 write!(f, "type {} (", self.name)?;
88 let mut first = true;
89 for variant in self.variants.iter() {
90 if !first {
91 write!(f, ", ")?;
92 }
93 first = false;
94 write!(f, "{}", variant)?;
95 }
96 write!(f, ")")
97 }
98 }
99}
100
101impl<'a> PartialEq for CustomEnum<'a> {
102 fn eq(&self, other: &Self) -> bool {
103 self.name == other.name && self.variants == other.variants
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use alloc::vec;
110
111 use super::*;
112 use crate::idl::{Comment, EnumVariant};
113 use core::fmt::Write;
114
115 #[test]
116 fn display_with_comments() {
117 let comment1 = Comment::new("Status enumeration");
118 let comment2 = Comment::new("Represents current state");
119 let comments = [&comment1, &comment2];
120
121 let var1 = EnumVariant::new("active", &[]);
122 let var2 = EnumVariant::new("inactive", &[]);
123 let var3 = EnumVariant::new("pending", &[]);
124 let variants = [&var1, &var2, &var3];
125
126 let custom_enum = CustomEnum::new("Status", &variants, &comments);
127 let mut displayed = String::new();
128 write!(&mut displayed, "{}", custom_enum).unwrap();
129 assert_eq!(
130 displayed,
131 "# Status enumeration\n# Represents current state\ntype Status (active, inactive, pending)"
132 );
133 }
134
135 #[test]
136 fn display_with_variant_comments() {
137 let var_comment = Comment::new("The active state");
138 let var1 = EnumVariant::new_owned("active", vec![var_comment]);
139 let var2 = EnumVariant::new_owned("inactive", vec![]);
140 let custom_enum = CustomEnum::new_owned("Status", vec![var1, var2], vec![]);
141
142 let mut displayed = String::new();
143 write!(&mut displayed, "{}", custom_enum).unwrap();
144 assert_eq!(
145 displayed,
146 "type Status (\n\t# The active state\n\tactive\n\tinactive\n)"
147 );
148 }
149
150 #[test_log::test]
151 fn comprehensive_enum_with_per_variant_comments() {
152 let enum_comment = Comment::new("Status enumeration with detailed docs");
154
155 let active_comment = Comment::new("System is operational");
156 let inactive_comment = Comment::new("System is stopped");
157 let pending_comment = Comment::new("System is starting up");
158
159 let var1 = EnumVariant::new_owned("active", vec![active_comment]);
160 let var2 = EnumVariant::new_owned("inactive", vec![inactive_comment]);
161 let var3 = EnumVariant::new_owned("pending", vec![pending_comment]);
162
163 let custom_enum =
164 CustomEnum::new_owned("SystemStatus", vec![var1, var2, var3], vec![enum_comment]);
165
166 assert_eq!(custom_enum.name(), "SystemStatus");
168 assert_eq!(custom_enum.variants().count(), 3);
169 assert_eq!(custom_enum.comments().count(), 1);
170
171 let mut displayed = String::new();
173 write!(&mut displayed, "{}", custom_enum).unwrap();
174
175 assert!(displayed.contains("Status enumeration with detailed docs"));
177 assert!(displayed.contains("# System is operational\n\tactive"));
179 assert!(displayed.contains("# System is stopped\n\tinactive"));
180 assert!(displayed.contains("# System is starting up\n\tpending"));
181
182 debug!("✓ Comprehensive enum display: {}", displayed);
183 }
184
185 #[test]
186 fn formatting_with_and_without_comments() {
187 let var1 = EnumVariant::new("red", &[]);
189 let var2 = EnumVariant::new("green", &[]);
190 let var3 = EnumVariant::new("blue", &[]);
191 let variants_no_comments = [&var1, &var2, &var3];
192
193 let enum_no_comments = CustomEnum::new("Color", &variants_no_comments, &[]);
194 let mut displayed = String::new();
195 write!(&mut displayed, "{}", enum_no_comments).unwrap();
196 assert_eq!(displayed, "type Color (red, green, blue)");
197
198 let comment = Comment::new("Primary color");
200 let comment_refs = [&comment];
201 let var_with_comment = EnumVariant::new("red", &comment_refs);
202 let var_without_comment1 = EnumVariant::new("green", &[]);
203 let var_without_comment2 = EnumVariant::new("blue", &[]);
204 let variants_with_comments = [
205 &var_with_comment,
206 &var_without_comment1,
207 &var_without_comment2,
208 ];
209
210 let enum_with_comments = CustomEnum::new("Color", &variants_with_comments, &[]);
211 let mut displayed = String::new();
212 write!(&mut displayed, "{}", enum_with_comments).unwrap();
213 assert_eq!(
214 displayed,
215 "type Color (\n\t# Primary color\n\tred\n\tgreen\n\tblue\n)"
216 );
217 }
218}