1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct KeyValue {
10 key: String,
12 value: String,
14}
15
16impl KeyValue {
17 #[inline]
19 pub fn new<K, V>(key: K, value: V) -> Self
20 where
21 K: Into<String>,
22 V: Into<String>,
23 {
24 Self {
25 key: key.into(),
26 value: value.into(),
27 }
28 }
29
30 #[inline]
32 pub fn key(&self) -> &str {
33 &self.key
34 }
35
36 #[inline]
38 pub fn value(&self) -> &str {
39 &self.value
40 }
41}
42
43impl From<(String, String)> for KeyValue {
44 #[inline]
45 fn from((key, value): (String, String)) -> Self {
46 Self { key, value }
47 }
48}
49
50impl From<(&str, &str)> for KeyValue {
51 #[inline]
52 fn from((key, value): (&str, &str)) -> Self {
53 Self {
54 key: key.to_string(),
55 value: value.to_string(),
56 }
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::KeyValue;
63
64 #[test]
65 fn new_sets_key_and_value() {
66 let kv = KeyValue::new("FOO", "bar");
67 assert_eq!(kv.key(), "FOO");
68 assert_eq!(kv.value(), "bar");
69 }
70
71 #[test]
72 fn from_str_tuple_creates_keyvalue() {
73 let kv: KeyValue = ("FOO", "bar").into();
74 assert_eq!(kv.key(), "FOO");
75 assert_eq!(kv.value(), "bar");
76 }
77
78 #[test]
79 fn from_string_tuple_creates_keyvalue() {
80 let kv: KeyValue = (String::from("FOO"), String::from("bar")).into();
81 assert_eq!(kv.key(), "FOO");
82 assert_eq!(kv.value(), "bar");
83 }
84
85 #[test]
86 fn equality_works_for_same_key_and_value() {
87 let a = KeyValue::new("FOO", "bar");
88 let b = KeyValue::new("FOO", "bar");
89 let c = KeyValue::new("FOO", "baz");
90
91 assert_eq!(a, b);
92 assert_ne!(a, c);
93 }
94
95 #[test]
96 fn serde_roundtrip_json() {
97 let kv = KeyValue::new("FOO", "bar");
98 let json = serde_json::to_string(&kv).unwrap();
99
100 assert!(json.contains("\"key\":\"FOO\""));
101 assert!(json.contains("\"value\":\"bar\""));
102
103 let back: KeyValue = serde_json::from_str(&json).unwrap();
104 assert_eq!(back.key(), "FOO");
105 assert_eq!(back.value(), "bar");
106 }
107}