Skip to main content

zlink_core/idl/
enum_variant.rs

1//! Enum variant definition for Varlink IDL.
2
3use core::fmt;
4
5use super::{Comment, List};
6
7/// A single variant in an enum type definition.
8#[derive(Debug, Clone, Eq)]
9pub struct EnumVariant<'a> {
10    /// The name of the variant.
11    name: &'a str,
12    /// The comments associated with this variant.
13    comments: List<'a, Comment<'a>>,
14}
15
16impl<'a> EnumVariant<'a> {
17    /// Creates a new enum variant with the given name and borrowed comments.
18    pub const fn new(name: &'a str, comments: &'a [&'a Comment<'a>]) -> Self {
19        Self {
20            name,
21            comments: List::Borrowed(comments),
22        }
23    }
24
25    /// Creates a new enum variant with the given name and owned comments.
26    pub fn new_owned(name: &'a str, comments: alloc::vec::Vec<Comment<'a>>) -> Self {
27        Self {
28            name,
29            comments: List::from(comments),
30        }
31    }
32
33    /// Returns the name of the variant.
34    pub fn name(&self) -> &'a str {
35        self.name
36    }
37
38    /// Returns an iterator over the comments associated with this variant.
39    pub fn comments(&self) -> impl Iterator<Item = &Comment<'a>> {
40        self.comments.iter()
41    }
42
43    /// Returns true if this variant has any comments.
44    pub fn has_comments(&self) -> bool {
45        !self.comments.is_empty()
46    }
47}
48
49impl<'a> fmt::Display for EnumVariant<'a> {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        // Comments first, each on its own line
52        for comment in self.comments.iter() {
53            writeln!(f, "{comment}")?;
54        }
55        // Then the variant name
56        write!(f, "{}", self.name)
57    }
58}
59
60impl<'a> PartialEq for EnumVariant<'a> {
61    fn eq(&self, other: &Self) -> bool {
62        self.name == other.name && self.comments == other.comments
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use core::fmt::Write;
70
71    #[test]
72    fn simple_variant() {
73        let variant = EnumVariant::new("active", &[]);
74        assert_eq!(variant.name(), "active");
75        assert!(!variant.has_comments());
76
77        let mut displayed = String::new();
78        write!(&mut displayed, "{}", variant).unwrap();
79        assert_eq!(displayed, "active");
80    }
81
82    #[test]
83    fn variant_with_comments() {
84        let comment = Comment::new("The active state");
85        let comments = [&comment];
86        let variant = EnumVariant::new("active", &comments);
87
88        assert_eq!(variant.name(), "active");
89        assert!(variant.has_comments());
90
91        let mut displayed = String::new();
92        write!(&mut displayed, "{}", variant).unwrap();
93        assert_eq!(displayed, "# The active state\nactive");
94    }
95
96    #[test]
97    fn variant_with_multiple_comments() {
98        let comment1 = Comment::new("First comment");
99        let comment2 = Comment::new("Second comment");
100        let comments = [&comment1, &comment2];
101        let variant = EnumVariant::new("complex", &comments);
102
103        assert_eq!(variant.name(), "complex");
104        assert!(variant.has_comments());
105        assert_eq!(variant.comments().count(), 2);
106
107        let mut displayed = String::new();
108        write!(&mut displayed, "{}", variant).unwrap();
109        assert_eq!(displayed, "# First comment\n# Second comment\ncomplex");
110    }
111
112    #[test]
113    fn owned_variant_with_comments() {
114        let comments = alloc::vec![
115            Comment::new("Owned comment 1"),
116            Comment::new("Owned comment 2"),
117        ];
118        let variant = EnumVariant::new_owned("owned", comments);
119
120        assert_eq!(variant.name(), "owned");
121        assert!(variant.has_comments());
122
123        let mut displayed = String::new();
124        write!(&mut displayed, "{}", variant).unwrap();
125        assert_eq!(displayed, "# Owned comment 1\n# Owned comment 2\nowned");
126    }
127}