1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum FieldName {
9 Id,
11 Type,
12 Name,
13
14 Description,
16
17 Refines,
19 DerivesFrom,
20 Satisfies,
21
22 IsRefinedBy,
24 Derives,
25 IsSatisfiedBy,
26
27 DependsOn,
29 IsRequiredBy,
30
31 Specification,
33 Platform,
34 JustifiedBy,
35}
36
37impl FieldName {
38 pub const fn all() -> &'static [FieldName] {
40 &[
41 Self::Id,
42 Self::Type,
43 Self::Name,
44 Self::Description,
45 Self::Refines,
46 Self::DerivesFrom,
47 Self::Satisfies,
48 Self::IsRefinedBy,
49 Self::Derives,
50 Self::IsSatisfiedBy,
51 Self::DependsOn,
52 Self::IsRequiredBy,
53 Self::Specification,
54 Self::Platform,
55 Self::JustifiedBy,
56 ]
57 }
58
59 pub const fn as_str(&self) -> &'static str {
63 match self {
64 Self::Id => "id",
65 Self::Type => "type",
66 Self::Name => "name",
67 Self::Description => "description",
68 Self::Refines => "refines",
69 Self::DerivesFrom => "derives_from",
70 Self::Satisfies => "satisfies",
71 Self::IsRefinedBy => "is_refined_by",
72 Self::Derives => "derives",
73 Self::IsSatisfiedBy => "is_satisfied_by",
74 Self::DependsOn => "depends_on",
75 Self::IsRequiredBy => "is_required_by",
76 Self::Specification => "specification",
77 Self::Platform => "platform",
78 Self::JustifiedBy => "justified_by",
79 }
80 }
81
82 pub const fn display_name(&self) -> &'static str {
86 match self {
87 Self::Id => "ID",
88 Self::Type => "Type",
89 Self::Name => "Name",
90 Self::Description => "Description",
91 Self::Refines => "Refines",
92 Self::DerivesFrom => "Derives from",
93 Self::Satisfies => "Satisfies",
94 Self::IsRefinedBy => "Is refined by",
95 Self::Derives => "Derives",
96 Self::IsSatisfiedBy => "Is satisfied by",
97 Self::DependsOn => "Depends on",
98 Self::IsRequiredBy => "Is required by",
99 Self::Specification => "Specification",
100 Self::Platform => "Platform",
101 Self::JustifiedBy => "Justified by",
102 }
103 }
104
105 pub const fn is_upstream(&self) -> bool {
107 matches!(self, Self::Refines | Self::DerivesFrom | Self::Satisfies)
108 }
109
110 pub const fn is_downstream(&self) -> bool {
112 matches!(
113 self,
114 Self::IsRefinedBy | Self::Derives | Self::IsSatisfiedBy
115 )
116 }
117
118 pub const fn is_peer(&self) -> bool {
120 matches!(self, Self::DependsOn | Self::IsRequiredBy)
121 }
122
123 pub const fn is_traceability(&self) -> bool {
125 self.is_upstream() || self.is_downstream() || self.is_peer()
126 }
127}
128
129impl std::fmt::Display for FieldName {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 write!(f, "{}", self.as_str())
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn test_field_name_as_str() {
141 assert_eq!(FieldName::Id.as_str(), "id");
142 assert_eq!(FieldName::DerivesFrom.as_str(), "derives_from");
143 assert_eq!(FieldName::Specification.as_str(), "specification");
144 }
145
146 #[test]
147 fn test_field_name_is_upstream() {
148 assert!(FieldName::Refines.is_upstream());
149 assert!(FieldName::DerivesFrom.is_upstream());
150 assert!(FieldName::Satisfies.is_upstream());
151 assert!(!FieldName::IsRefinedBy.is_upstream());
152 assert!(!FieldName::Specification.is_upstream());
153 }
154
155 #[test]
156 fn test_field_name_is_downstream() {
157 assert!(FieldName::IsRefinedBy.is_downstream());
158 assert!(FieldName::Derives.is_downstream());
159 assert!(FieldName::IsSatisfiedBy.is_downstream());
160 assert!(!FieldName::Refines.is_downstream());
161 }
162
163 #[test]
164 fn test_field_name_all() {
165 let all = FieldName::all();
166 assert!(all.contains(&FieldName::Id));
167 assert!(all.contains(&FieldName::Refines));
168 assert!(all.contains(&FieldName::Specification));
169 assert_eq!(all.len(), 15);
170 }
171
172 #[test]
173 fn test_field_name_display() {
174 assert_eq!(format!("{}", FieldName::DerivesFrom), "derives_from");
175 }
176}