rust_eureka/response/
datacenterinfo.rs1use super::AmazonMetaData;
2use super::DcName;
3use serde::de::{Deserialize, Deserializer, Error as DeError, MapAccess, Visitor};
4use serde::ser::{Serialize, SerializeStruct, Serializer};
5use std::fmt;
6
7const NAME: &str = "name";
9const METADATA: &str = "metadata";
10const CLASS: &str = "@class";
12const CLASS_VALUE: &str = "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo";
13const DATA_CENTER_INFO: &str = "DataCenterInfo";
14const FIELDS: &[&str] = &[CLASS, NAME, METADATA];
15
16#[derive(Debug, PartialEq)]
17pub struct DataCenterInfo {
18 pub name: DcName,
19 pub metadata: Option<AmazonMetaData>,
20}
21
22impl Serialize for DataCenterInfo {
23 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
24 where
25 S: Serializer,
26 {
27 let mut s = serializer.serialize_struct(DATA_CENTER_INFO, 2)?;
28 s.serialize_field(CLASS, CLASS_VALUE)?;
30 s.serialize_field(NAME, &self.name)?;
31 s.serialize_field(METADATA, &self.metadata)?;
32 s.end()
33 }
34}
35
36impl<'de> Deserialize<'de> for DataCenterInfo {
37 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
38 where
39 D: Deserializer<'de>,
40 {
41 enum Field {
42 Name,
43 Metadata,
44 Class,
45 }
46
47 impl<'de> Deserialize<'de> for Field {
48 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
49 where
50 D: Deserializer<'de>,
51 {
52 struct FieldVisitor;
53
54 impl<'de> Visitor<'de> for FieldVisitor {
55 type Value = Field;
56
57 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
58 formatter.write_str("Expecting `name` or `metadata` ")
59 }
60
61 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
62 where
63 E: DeError,
64 {
65 match v {
66 NAME => Ok(Field::Name),
67 METADATA => Ok(Field::Metadata),
68 CLASS => Ok(Field::Class),
69 _ => Err(DeError::unknown_field(v, FIELDS)),
70 }
71 }
72 }
73 deserializer.deserialize_identifier(FieldVisitor)
74 }
75 }
76
77 struct DataCenterInfoVisitor;
78
79 impl<'de> Visitor<'de> for DataCenterInfoVisitor {
80 type Value = DataCenterInfo;
81
82 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
83 formatter.write_str("struct DataCenterInfo")
84 }
85 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
86 where
87 A: MapAccess<'de>,
88 {
89 let mut maybe_name = None;
90 let mut maybe_metadata = None;
91 let mut maybe_class: Option<&str> = None;
92
93 while let Some(key) = map.next_key()? {
94 match key {
95 Field::Name => {
96 if maybe_name.is_some() {
97 return Err(DeError::duplicate_field(NAME));
98 }
99 maybe_name = Some(map.next_value()?);
100 }
101 Field::Metadata => {
102 if maybe_metadata.is_some() {
103 return Err(DeError::duplicate_field(METADATA));
104 }
105 maybe_metadata = Some(map.next_value()?);
106 }
107 Field::Class => {
108 maybe_class = Some(map.next_value()?);
109 }
110 }
111 }
112 let name = maybe_name.ok_or_else(|| DeError::missing_field(NAME));
113 debug!("Found ignored field @class {:?} ?", maybe_class);
114 Ok(DataCenterInfo {
115 name: name?,
116 metadata: maybe_metadata,
117 })
118 }
119 }
120 deserializer.deserialize_struct(DATA_CENTER_INFO, FIELDS, DataCenterInfoVisitor)
121 }
122}
123
124#[cfg(test)]
125pub mod test {
126 use super::super::amazonmetadata::tests::sample_meta_data;
127 use super::*;
128 use serde_json;
129
130 #[test]
131 fn test_serialize_data_center_info() {
132 let dci = DataCenterInfo {
133 name: DcName::Amazon,
134 metadata: Some(AmazonMetaData {
135 ami_launch_index: "001a".to_string(),
136 local_hostname: "localhost0".to_string(),
137 availability_zone: "US_East1a".to_string(),
138 instance_id: "instance1a".to_string(),
139 public_ipv4: "32.23.21.212".to_string(),
140 public_hostname: "foo.coma".to_string(),
141 ami_manifest_path: "/dev/nulla".to_string(),
142 local_ipv4: "127.0.0.12".to_string(),
143 hostname: "privatefoo.coma".to_string(),
144 ami_id: "ami0023".to_string(),
145 instance_type: "c4xlarged".to_string(),
146 }),
147 };
148 let json = sample_data_center();
149 let result = serde_json::to_string(&dci).unwrap();
150 assert_eq!(json, result);
151 }
152
153 #[test]
154 fn test_deserialize_data_center_info() {
155 let dci = DataCenterInfo {
156 name: DcName::Amazon,
157 metadata: Some(AmazonMetaData {
158 ami_launch_index: "001a".to_string(),
159 local_hostname: "localhost0".to_string(),
160 availability_zone: "US_East1a".to_string(),
161 instance_id: "instance1a".to_string(),
162 public_ipv4: "32.23.21.212".to_string(),
163 public_hostname: "foo.coma".to_string(),
164 ami_manifest_path: "/dev/nulla".to_string(),
165 local_ipv4: "127.0.0.12".to_string(),
166 hostname: "privatefoo.coma".to_string(),
167 ami_id: "ami0023".to_string(),
168 instance_type: "c4xlarged".to_string(),
169 }),
170 };
171 let json = sample_data_center();
172 println!("json {}", json);
173 let result = serde_json::from_str(&json).unwrap();
174 assert_eq!(dci, result);
175 }
176
177 fn sample_data_center() -> String {
178 format!("{{\"@class\":\"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo\",\"name\":\"Amazon\",\"metadata\":{}}}", sample_meta_data())
179 }
180}