flagsmith_flag_engine/types/
mod.rs1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2
3use serde::de;
4use std::fmt;
5
6#[derive(Clone, Debug, PartialEq)]
7pub enum FlagsmithValueType {
8 String,
9 Bool,
10 Integer,
11 Float,
12 None,
13}
14
15#[derive(Clone, Debug, PartialEq)]
16pub struct FlagsmithValue {
17 pub value_type: FlagsmithValueType,
18 pub value: String,
19}
20
21impl Default for FlagsmithValue {
22 fn default() -> Self {
23 FlagsmithValue {
24 value_type: FlagsmithValueType::None,
25 value: "".to_string(),
26 }
27 }
28}
29
30impl Serialize for FlagsmithValue {
31 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32 where
33 S: Serializer,
34 {
35 match self.value_type {
36 FlagsmithValueType::Bool => serializer.serialize_bool(self.value.parse().unwrap()),
37 FlagsmithValueType::Integer => serializer.serialize_i64(self.value.parse().unwrap()),
38 FlagsmithValueType::String => serializer.serialize_str(self.value.as_str()),
39 FlagsmithValueType::None => serializer.serialize_none(),
40 FlagsmithValueType::Float => serializer.serialize_f64(self.value.parse().unwrap()),
41 }
42 }
43}
44
45struct FlagsmithValueVisitor;
46impl<'de> de::Visitor<'de> for FlagsmithValueVisitor {
47 type Value = FlagsmithValue;
48
49 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50 formatter.write_str("an integer, a string, a float, a None or boolean")
51 }
52
53 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
54 where
55 E: de::Error,
56 {
57 Ok(FlagsmithValue {
58 value: v.to_string(),
59 value_type: FlagsmithValueType::Integer,
60 })
61 }
62 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
63 where
64 E: de::Error,
65 {
66 Ok(FlagsmithValue {
67 value: v.to_string(),
68 value_type: FlagsmithValueType::Float,
69 })
70 }
71
72 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
73 where
74 E: de::Error,
75 {
76 Ok(FlagsmithValue {
77 value: v.to_string(),
78 value_type: FlagsmithValueType::Integer,
79 })
80 }
81 fn visit_unit<E>(self) -> Result<Self::Value, E>
82 where
83 E: de::Error,
84 {
85 Ok(FlagsmithValue {
86 value: "".to_string(),
87 value_type: FlagsmithValueType::None,
88 })
89 }
90 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
91 where
92 E: de::Error,
93 {
94 Ok(FlagsmithValue {
95 value: v.to_string(),
96 value_type: FlagsmithValueType::String,
97 })
98 }
99 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
100 where
101 E: de::Error,
102 {
103 Ok(FlagsmithValue {
104 value: v.to_string(),
105 value_type: FlagsmithValueType::Bool,
106 })
107 }
108}
109impl<'de> Deserialize<'de> for FlagsmithValue {
110 fn deserialize<D>(deserializer: D) -> Result<FlagsmithValue, D::Error>
111 where
112 D: Deserializer<'de>,
113 {
114 deserializer.deserialize_any(FlagsmithValueVisitor)
115 }
116}
117#[cfg(test)]
118mod tests {
119
120 use super::*;
121 use rstest::*;
122
123 #[rstest]
124 #[case(serde_json::json!(10), FlagsmithValueType::Integer)]
125 #[case(serde_json::json!(-10), FlagsmithValueType::Integer)]
126 #[case(serde_json::json!(10.1), FlagsmithValueType::Float)]
127 #[case(serde_json::json!(-10.1), FlagsmithValueType::Float)]
128 #[case(serde_json::json!(true), FlagsmithValueType::Bool)]
129 #[case(serde_json::json!(false), FlagsmithValueType::Bool)]
130 #[case(serde_json::json!(null), FlagsmithValueType::None)]
131 #[case(serde_json::json!("string"), FlagsmithValueType::String)]
132 #[case(serde_json::json!("10"), FlagsmithValueType::String)]
133 #[case(serde_json::json!("true"), FlagsmithValueType::String)]
134 #[case(serde_json::json!("10.1"), FlagsmithValueType::String)]
135 fn serialize_deserialize_flagsmith_value(
136 #[case] value_as_json: serde_json::Value,
137 #[case] expected_value_type: FlagsmithValueType,
138 ) {
139 let flagsmith_value: FlagsmithValue =
141 serde_json::from_value(value_as_json.clone()).unwrap();
142 assert_eq!(flagsmith_value.value_type, expected_value_type);
143
144 let serialized_value = serde_json::to_value(flagsmith_value).unwrap();
146 assert_eq!(serialized_value, value_as_json);
147 }
148}