apolloconfig/objects/
configurations.rs1use core::fmt;
2
3use serde::{ser, Serialize};
4use serde_json::{Map, Value};
5
6use crate::types::NamespaceFormat;
7
8pub const KEY_CONTENT: &str = "content";
10
11#[derive(Debug, Clone)]
13pub enum Configurations {
14 Properties(Map<String, Value>),
15 Json(Value),
16 Txt(Box<str>),
17 Other(Box<str>),
18}
19
20impl Configurations {
21 pub fn from_map(
22 map: &Map<String, Value>,
23 namespace_format: NamespaceFormat,
24 ) -> Result<Self, ConfigurationsFromMapError> {
25 match namespace_format {
26 NamespaceFormat::Properties => Ok(Self::Properties(map.to_owned())),
27 NamespaceFormat::Xml
28 | NamespaceFormat::Json
29 | NamespaceFormat::Yml
30 | NamespaceFormat::Yaml
31 | NamespaceFormat::Txt => {
32 let content = map
33 .get(KEY_CONTENT)
34 .ok_or(ConfigurationsFromMapError::ContentMissing)?;
35
36 match namespace_format {
37 NamespaceFormat::Properties => unreachable!(),
38 NamespaceFormat::Xml => {
39 let content = content
40 .as_str()
41 .ok_or(ConfigurationsFromMapError::ContentTypeMismatch("String"))?;
42 Ok(Self::Other(content.into()))
43 }
44 NamespaceFormat::Json => {
45 let content = content
46 .as_str()
47 .ok_or(ConfigurationsFromMapError::ContentTypeMismatch("String"))?;
48 let value = serde_json::from_str(content)
49 .map_err(ConfigurationsFromMapError::JsonError)?;
50 Ok(Self::Json(value))
51 }
52 NamespaceFormat::Yml => {
53 let content = content
54 .as_str()
55 .ok_or(ConfigurationsFromMapError::ContentTypeMismatch("String"))?;
56 Ok(Self::Other(content.into()))
57 }
58 NamespaceFormat::Yaml => {
59 let content = content
60 .as_str()
61 .ok_or(ConfigurationsFromMapError::ContentTypeMismatch("String"))?;
62 Ok(Self::Other(content.into()))
63 }
64 NamespaceFormat::Txt => {
65 let content = content
66 .as_str()
67 .ok_or(ConfigurationsFromMapError::ContentTypeMismatch("String"))?;
68 Ok(Self::Txt(content.into()))
69 }
70 }
71 }
72 }
73 }
74
75 pub fn to_map(&self) -> Result<Map<String, Value>, ConfigurationsToMapError> {
76 match self {
77 Configurations::Properties(map) => Ok(map.to_owned()),
78 Configurations::Json(value) => {
79 let s = serde_json::to_string(value)
80 .map_err(ser::Error::custom)
81 .map_err(ConfigurationsToMapError::JsonError)?;
82 let mut map = Map::new();
83 map.insert(KEY_CONTENT.to_string(), Value::String(s));
84 Ok(map.to_owned())
85 }
86 Configurations::Txt(s) | Configurations::Other(s) => {
87 let mut map = Map::new();
88 map.insert(KEY_CONTENT.to_string(), Value::String(s.to_string()));
89 Ok(map.to_owned())
90 }
91 }
92 }
93}
94
95#[derive(Debug)]
97pub enum ConfigurationsFromMapError {
98 ContentMissing,
99 ContentTypeMismatch(&'static str),
100 JsonError(serde_json::Error),
101}
102
103impl fmt::Display for ConfigurationsFromMapError {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 write!(f, "{:?}", self)
106 }
107}
108
109impl std::error::Error for ConfigurationsFromMapError {}
110
111#[derive(Debug)]
113pub enum ConfigurationsToMapError {
114 JsonError(serde_json::Error),
115}
116
117impl fmt::Display for ConfigurationsToMapError {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 write!(f, "{:?}", self)
120 }
121}
122
123impl std::error::Error for ConfigurationsToMapError {}
124
125impl Serialize for Configurations {
127 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
128 where
129 S: ser::Serializer,
130 {
131 let map = self.to_map().map_err(ser::Error::custom)?;
132 map.serialize(serializer)
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[derive(Serialize)]
141 struct Foo {
142 configurations: Configurations,
143 }
144
145 #[test]
146 fn test_ser() {
147 let mut map = Map::new();
149 map.insert("content".to_string(), Value::String("content".into()));
150 assert_eq!(
151 serde_json::to_string(&Foo {
152 configurations: Configurations::Properties(map)
153 })
154 .unwrap(),
155 r#"{"configurations":{"content":"content"}}"#
156 );
157
158 let mut map = Map::new();
160 map.insert("k".to_string(), Value::String("v".into()));
161 assert_eq!(
162 serde_json::to_string(&Foo {
163 configurations: Configurations::Json(Value::Object(map))
164 })
165 .unwrap(),
166 r#"{"configurations":{"content":"{\"k\":\"v\"}"}}"#
167 );
168
169 assert_eq!(
171 serde_json::to_string(&Foo {
172 configurations: Configurations::Txt("test".into())
173 })
174 .unwrap(),
175 r#"{"configurations":{"content":"test"}}"#
176 );
177
178 assert_eq!(
180 serde_json::to_string(&Foo {
181 configurations: Configurations::Other("xxx".into())
182 })
183 .unwrap(),
184 r#"{"configurations":{"content":"xxx"}}"#
185 );
186 }
187}