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