1use serde::de::{self, MapAccess, Visitor};
4use serde::{Deserialize, Deserializer, Serialize};
5
6use crate::connector::Connector;
7use crate::tier::Tier;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case")]
12pub struct FlowLabels {
13 items: Vec<String>,
14}
15
16impl FlowLabels {
17 pub fn new(items: Vec<String>) -> Self {
19 Self { items }
20 }
21
22 pub fn items(&self) -> &[String] {
24 &self.items
25 }
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize)]
45#[serde(rename_all = "snake_case")]
46#[non_exhaustive]
47pub enum Layer {
48 Tier(Tier),
50 Connector(Connector),
52 FlowLabels(FlowLabels),
54}
55
56impl<'de> Deserialize<'de> for Layer {
57 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58 where
59 D: Deserializer<'de>,
60 {
61 deserializer.deserialize_map(LayerVisitor)
62 }
63}
64
65struct LayerVisitor;
66
67impl<'de> Visitor<'de> for LayerVisitor {
68 type Value = Layer;
69
70 fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 f.write_str("a map with a single key: \"tier\", \"connector\", or \"flow_labels\"")
72 }
73
74 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
75 where
76 A: MapAccess<'de>,
77 {
78 let key: String = map
79 .next_key()?
80 .ok_or_else(|| de::Error::custom("expected a layer variant key"))?;
81
82 let layer = match key.as_str() {
83 "tier" => Layer::Tier(map.next_value()?),
84 "connector" => Layer::Connector(map.next_value()?),
85 "flow_labels" => Layer::FlowLabels(map.next_value()?),
86 other => {
87 return Err(de::Error::unknown_variant(
88 other,
89 &["tier", "connector", "flow_labels"],
90 ));
91 }
92 };
93
94 Ok(layer)
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use crate::connector::ConnectorStyle;
102 use crate::id::NodeId;
103
104 #[test]
105 fn test_flow_labels() {
106 let labels = FlowLabels::new(vec!["SQL queries".to_owned(), "cache reads".to_owned()]);
107 assert_eq!(labels.items().len(), 2);
108 }
109
110 #[test]
111 fn test_layer_variants() {
112 let tier = Tier::new(NodeId::new("test").unwrap(), vec![]);
113 let layer = Layer::Tier(tier);
114 assert!(matches!(layer, Layer::Tier(_)));
115
116 let conn = Connector::new(ConnectorStyle::Dots);
117 let layer = Layer::Connector(conn);
118 assert!(matches!(layer, Layer::Connector(_)));
119
120 let labels = FlowLabels::new(vec!["test".to_owned()]);
121 let layer = Layer::FlowLabels(labels);
122 assert!(matches!(layer, Layer::FlowLabels(_)));
123 }
124
125 #[test]
126 fn test_yaml_round_trip_tier() {
127 let tier = Tier::new(NodeId::new("test").unwrap(), vec![]);
128 let layer = Layer::Tier(tier);
129 let json = serde_json::to_string(&layer).unwrap();
130 let deserialized: Layer = serde_json::from_str(&json).unwrap();
131 assert_eq!(layer, deserialized);
132 }
133
134 #[test]
135 fn test_yaml_round_trip_connector() {
136 let conn = Connector::new(ConnectorStyle::Dots);
137 let layer = Layer::Connector(conn);
138 let json = serde_json::to_string(&layer).unwrap();
139 let deserialized: Layer = serde_json::from_str(&json).unwrap();
140 assert_eq!(layer, deserialized);
141 }
142
143 #[test]
144 fn test_yaml_round_trip_flow_labels() {
145 let labels = FlowLabels::new(vec!["test".to_owned()]);
146 let layer = Layer::FlowLabels(labels);
147 let json = serde_json::to_string(&layer).unwrap();
148 let deserialized: Layer = serde_json::from_str(&json).unwrap();
149 assert_eq!(layer, deserialized);
150 }
151
152 #[test]
153 fn test_deserialize_unknown_variant() {
154 let json = r#"{"unknown": {}}"#;
155 let err = serde_json::from_str::<Layer>(json).unwrap_err();
156 let msg = format!("{err}");
157 assert!(msg.contains("unknown"));
158 }
159
160 #[test]
161 fn test_deserialize_empty_map_rejected() {
162 let json = "{}";
163 let err = serde_json::from_str::<Layer>(json).unwrap_err();
164 let msg = format!("{err}");
165 assert!(msg.contains("expected a layer variant key"));
166 }
167
168 #[test]
169 fn test_flow_labels_items_accessor() {
170 let labels = FlowLabels::new(vec!["a".to_owned(), "b".to_owned(), "c".to_owned()]);
171 assert_eq!(labels.items().len(), 3);
172 assert_eq!(labels.items()[0], "a");
173 assert_eq!(labels.items()[2], "c");
174 }
175
176 #[test]
177 fn test_flow_labels_serde_round_trip() {
178 let labels = FlowLabels::new(vec!["SQL queries".to_owned()]);
179 let json = serde_json::to_string(&labels).unwrap();
180 let deserialized: FlowLabels = serde_json::from_str(&json).unwrap();
181 assert_eq!(labels, deserialized);
182 }
183
184 #[test]
185 fn test_layer_debug() {
186 let labels = FlowLabels::new(vec!["test".to_owned()]);
187 let layer = Layer::FlowLabels(labels);
188 let debug = format!("{layer:?}");
189 assert!(debug.contains("FlowLabels"));
190 }
191
192 #[test]
193 fn test_layer_clone_eq() {
194 let conn = Connector::new(ConnectorStyle::Line);
195 let layer = Layer::Connector(conn);
196 let cloned = layer.clone();
197 assert_eq!(layer, cloned);
198 }
199
200 #[test]
201 fn test_deserialize_from_non_map_type_rejected() {
202 let json = r#"["tier", {}]"#;
204 let err = serde_json::from_str::<Layer>(json).unwrap_err();
205 let msg = format!("{err}");
206 assert!(
208 msg.contains("tier")
209 || msg.contains("connector")
210 || msg.contains("flow_labels")
211 || msg.contains("map")
212 || msg.contains("invalid type")
213 );
214 }
215
216 #[test]
217 fn test_deserialize_from_string_rejected() {
218 let json = r#""tier""#;
219 let err = serde_json::from_str::<Layer>(json).unwrap_err();
220 let msg = format!("{err}");
221 assert!(msg.contains("invalid type") || msg.contains("map"));
222 }
223
224 #[test]
225 fn test_flow_labels_empty() {
226 let labels = FlowLabels::new(vec![]);
227 assert!(labels.items().is_empty());
228 }
229}