elastic_types/ip/
impls.rs1use std::borrow::Borrow;
2use std::marker::PhantomData;
3use std::net::Ipv4Addr;
4use std::str::FromStr;
5use std::error::Error as StdError;
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7use serde::de::{Error, Visitor};
8use super::mapping::{DefaultIpMapping, IpFieldType, IpMapping};
9
10impl IpFieldType<DefaultIpMapping> for Ipv4Addr {}
11
12#[derive(Debug, Clone, PartialEq)]
30pub struct Ip<TMapping>
31where
32 TMapping: IpMapping,
33{
34 value: Ipv4Addr,
35 _m: PhantomData<TMapping>,
36}
37
38impl<TMapping> Ip<TMapping>
39where
40 TMapping: IpMapping,
41{
42 pub fn new<I>(ip: I) -> Ip<TMapping>
58 where
59 I: Into<Ipv4Addr>,
60 {
61 Ip {
62 value: ip.into(),
63 _m: PhantomData,
64 }
65 }
66
67 pub fn remap<TNewMapping>(ip: Ip<TMapping>) -> Ip<TNewMapping>
91 where
92 TNewMapping: IpMapping,
93 {
94 Ip::new(ip.value)
95 }
96}
97
98impl<TMapping> IpFieldType<TMapping> for Ip<TMapping>
99where
100 TMapping: IpMapping,
101{
102}
103
104impl_mapping_type!(Ipv4Addr, Ip, IpMapping);
105
106impl<TMapping> Serialize for Ip<TMapping>
108where
109 TMapping: IpMapping,
110{
111 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 where
113 S: Serializer,
114 {
115 serializer.serialize_str(&self.value.to_string())
116 }
117}
118
119impl<'de, TMapping> Deserialize<'de> for Ip<TMapping>
121where
122 TMapping: IpMapping,
123{
124 fn deserialize<D>(deserializer: D) -> Result<Ip<TMapping>, D::Error>
125 where
126 D: Deserializer<'de>,
127 {
128 #[derive(Default)]
129 struct IpVisitor<TMapping> {
130 _m: PhantomData<TMapping>,
131 }
132
133 impl<'de, TMapping> Visitor<'de> for IpVisitor<TMapping>
134 where
135 TMapping: IpMapping,
136 {
137 type Value = Ip<TMapping>;
138
139 fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
140 write!(formatter, "a json string containing an IpV4 address")
141 }
142
143 fn visit_string<E>(self, v: String) -> Result<Ip<TMapping>, E>
144 where
145 E: Error,
146 {
147 let de = try!(Ipv4Addr::from_str(&v).map_err(|e| E::custom(e.description().to_string())));
148
149 Ok(Ip::new(de))
150 }
151
152 fn visit_str<E>(self, v: &str) -> Result<Ip<TMapping>, E>
153 where
154 E: Error,
155 {
156 let de = try!(Ipv4Addr::from_str(v).map_err(|e| E::custom(e.description().to_string())));
157
158 Ok(Ip::new(de))
159 }
160 }
161
162 deserializer.deserialize_any(IpVisitor::<TMapping>::default())
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use serde_json;
169 use std::net::Ipv4Addr;
170
171 use prelude::*;
172
173 #[derive(Default)]
174 struct MyIpMapping;
175 impl IpMapping for MyIpMapping {}
176
177 #[test]
178 fn can_change_ip_mapping() {
179 fn takes_custom_mapping(_: Ip<MyIpMapping>) -> bool {
180 true
181 }
182
183 let ip: Ip<DefaultIpMapping> = Ip::new(Ipv4Addr::new(127, 0, 0, 1));
184
185 assert!(takes_custom_mapping(Ip::remap(ip)));
186 }
187
188 #[test]
189 fn serialise_elastic_ip() {
190 let ip: Ip<DefaultIpMapping> = Ip::new(Ipv4Addr::new(127, 0, 0, 1));
191
192 let ser = serde_json::to_string(&ip).unwrap();
193
194 assert_eq!(r#""127.0.0.1""#, ser);
195 }
196
197 #[test]
198 fn deserialise_elastic_ip() {
199 let ip: Ip<DefaultIpMapping> = serde_json::from_str(r#""127.0.0.1""#).unwrap();
200
201 assert_eq!(Ipv4Addr::new(127, 0, 0, 1), ip);
202 }
203
204}