1use serde::{Deserialize, Serialize};
19use std::fmt;
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
23pub struct ProjectionKey(pub(crate) String);
24
25impl ProjectionKey {
26 pub fn new(s: impl Into<String>) -> Self {
34 Self(s.into())
35 }
36
37 pub fn as_str(&self) -> &str {
39 &self.0
40 }
41}
42
43impl fmt::Display for ProjectionKey {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.write_str(&self.0)
46 }
47}
48
49impl From<String> for ProjectionKey {
50 fn from(s: String) -> Self {
51 Self(s)
52 }
53}
54
55impl From<&str> for ProjectionKey {
56 fn from(s: &str) -> Self {
57 Self(s.to_string())
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn new_and_as_str_round_trip() {
67 let k = ProjectionKey::new("warehouse-a");
68 assert_eq!(k.as_str(), "warehouse-a");
69
70 let k2: ProjectionKey = "warehouse-b".into();
71 assert_eq!(k2.as_str(), "warehouse-b");
72
73 let k3 = ProjectionKey::from(String::from("warehouse-c"));
74 assert_eq!(k3.as_str(), "warehouse-c");
75 }
76
77 #[test]
78 fn display_renders_inner_string() {
79 let k = ProjectionKey::new("warehouse-a");
80 assert_eq!(format!("{k}"), "warehouse-a");
81 }
82
83 #[test]
84 fn serde_round_trip_via_json() {
85 let k = ProjectionKey::new("warehouse-a");
86 let s = serde_json::to_string(&k).expect("serialize");
87 assert_eq!(s, "\"warehouse-a\"");
88 let parsed: ProjectionKey = serde_json::from_str(&s).expect("deserialize");
89 assert_eq!(parsed, k);
90 }
91}