Skip to main content

net_mel/
ip.rs

1use melodium_core::{executive::*, *};
2use melodium_macro::{check, mel_data, mel_function, mel_treatment};
3use std::str::FromStr;
4use std::sync::Arc;
5
6/// IP data.
7///
8/// `Ip` data type contains a valid IP v4 or v6.
9///
10/// ℹ️ _Valid IP_ means the data contained makes sense as IP, not that it is reacheable.
11#[mel_data(traits(ToString TryToString Display))]
12#[derive(Debug, Clone, Serialize)]
13pub struct Ip(pub std::net::IpAddr);
14
15impl ToString for Ip {
16    fn to_string(&self) -> string {
17        self.0.to_string()
18    }
19}
20
21impl TryToString for Ip {
22    fn try_to_string(&self) -> Option<string> {
23        Some(self.0.to_string())
24    }
25}
26
27impl Display for Ip {
28    fn display(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
29        write!(f, "{}", &self.0)
30    }
31}
32
33/// IPv4 data.
34///
35/// `Ipv4` data type contains a valid IP v4.
36///
37/// ℹ️ _Valid IP v4_ means the data contained makes sense as IP, not that it is reacheable.
38#[mel_data(traits(ToString TryToString Display))]
39#[derive(Debug, Clone, Serialize)]
40pub struct Ipv4(pub std::net::Ipv4Addr);
41
42impl ToString for Ipv4 {
43    fn to_string(&self) -> string {
44        self.0.to_string()
45    }
46}
47
48impl TryToString for Ipv4 {
49    fn try_to_string(&self) -> Option<string> {
50        Some(self.0.to_string())
51    }
52}
53
54impl Display for Ipv4 {
55    fn display(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
56        write!(f, "{}", &self.0)
57    }
58}
59
60/// Makes IPv4 generic.
61#[mel_function]
62pub fn from_ipv4(ipv4: Ipv4) -> Ip {
63    Ip(std::net::IpAddr::V4(ipv4.0))
64}
65
66/// Makes IPv6 generic.
67#[mel_function]
68pub fn from_ipv6(ipv6: Ipv6) -> Ip {
69    Ip(std::net::IpAddr::V6(ipv6.0))
70}
71
72/// Turn stream of IPv4 into generic IP
73#[mel_treatment(
74    input ipv4 Stream<Ipv4>
75    output ip Stream<Ip>
76)]
77pub async fn from_ipv4() {
78    while let Ok(ips) = ipv4
79        .recv_many()
80        .await
81        .map(|values| Into::<VecDeque<Value>>::into(values))
82    {
83        check!(
84            ip.send_many(TransmissionValue::Other(
85                ips.into_iter()
86                    .map(|ip| Value::Data(Arc::new(Ip(std::net::IpAddr::V4(
87                        GetData::<Arc<dyn Data>>::try_data(ip)
88                            .unwrap()
89                            .downcast_arc::<Ipv4>()
90                            .unwrap()
91                            .0
92                    )))))
93                    .collect()
94            ))
95            .await
96        )
97    }
98}
99
100/// Turn stream of IPv6 into generic IP
101#[mel_treatment(
102    input ipv6 Stream<Ipv6>
103    output ip Stream<Ip>
104)]
105pub async fn from_ipv6() {
106    while let Ok(ips) = ipv6
107        .recv_many()
108        .await
109        .map(|values| Into::<VecDeque<Value>>::into(values))
110    {
111        check!(
112            ip.send_many(TransmissionValue::Other(
113                ips.into_iter()
114                    .map(|ip| Value::Data(Arc::new(Ip(std::net::IpAddr::V6(
115                        GetData::<Arc<dyn Data>>::try_data(ip)
116                            .unwrap()
117                            .downcast_arc::<Ipv6>()
118                            .unwrap()
119                            .0
120                    )))))
121                    .collect()
122            ))
123            .await
124        )
125    }
126}
127
128/// Get the IPv4 of generic IP.
129#[mel_function]
130pub fn as_ipv4(ip: Ip) -> Option<Ipv4> {
131    if let std::net::IpAddr::V4(ip) = ip.0 {
132        Some(Ipv4(ip))
133    } else {
134        None
135    }
136}
137
138/// Get the IPv6 of generic IP.
139#[mel_function]
140pub fn as_ipv6(ip: Ip) -> Option<Ipv6> {
141    if let std::net::IpAddr::V6(ip) = ip.0 {
142        Some(Ipv6(ip))
143    } else {
144        None
145    }
146}
147
148/// Get the IPv4 from generic IP stream
149#[mel_treatment(
150    input ip Stream<Ip>
151    output ipv4 Stream<Option<Ipv4>>
152)]
153pub async fn as_ipv4() {
154    while let Ok(ips) = ip
155        .recv_many()
156        .await
157        .map(|values| Into::<VecDeque<Value>>::into(values))
158    {
159        check!(
160            ipv4.send_many(TransmissionValue::Other(
161                ips.into_iter()
162                    .map(|ip| Value::Option(
163                        match GetData::<Arc<dyn Data>>::try_data(ip)
164                            .unwrap()
165                            .downcast_arc::<Ip>()
166                            .unwrap()
167                            .0
168                        {
169                            std::net::IpAddr::V4(ip) =>
170                                Some(Box::new(Value::Data(Arc::new(Ipv4(ip))))),
171                            std::net::IpAddr::V6(_) => None,
172                        }
173                    ))
174                    .collect()
175            ))
176            .await
177        )
178    }
179}
180
181/// Get the IPv6 from generic IP stream
182#[mel_treatment(
183    input ip Stream<Ip>
184    output ipv6 Stream<Option<Ipv6>>
185)]
186pub async fn as_ipv6() {
187    while let Ok(ips) = ip
188        .recv_many()
189        .await
190        .map(|values| Into::<VecDeque<Value>>::into(values))
191    {
192        check!(
193            ipv6.send_many(TransmissionValue::Other(
194                ips.into_iter()
195                    .map(|ip| Value::Option(
196                        match GetData::<Arc<dyn Data>>::try_data(ip)
197                            .unwrap()
198                            .downcast_arc::<Ip>()
199                            .unwrap()
200                            .0
201                        {
202                            std::net::IpAddr::V4(_) => None,
203                            std::net::IpAddr::V6(ip) =>
204                                Some(Box::new(Value::Data(Arc::new(Ipv6(ip))))),
205                        }
206                    ))
207                    .collect()
208            ))
209            .await
210        )
211    }
212}
213
214/// Tells if generic IP is IPv4.
215#[mel_function]
216pub fn is_ipv4(ip: Ip) -> bool {
217    ip.0.is_ipv4()
218}
219
220/// Tells if generic IP is IPv6.
221#[mel_function]
222pub fn is_ipv6(ip: Ip) -> bool {
223    ip.0.is_ipv6()
224}
225
226/// Tells for IP in stream if they are v4
227#[mel_treatment(
228    input ip Stream<Ip>
229    output ipv4 Stream<bool>
230)]
231pub async fn is_ipv4() {
232    while let Ok(ips) = ip
233        .recv_many()
234        .await
235        .map(|values| Into::<VecDeque<Value>>::into(values))
236    {
237        check!(
238            ipv4.send_many(TransmissionValue::Bool(
239                ips.into_iter()
240                    .map(|ip| GetData::<Arc<dyn Data>>::try_data(ip)
241                        .unwrap()
242                        .downcast_arc::<Ip>()
243                        .unwrap()
244                        .0
245                        .is_ipv4())
246                    .collect()
247            ))
248            .await
249        )
250    }
251}
252
253/// Tells for IP in stream if they are v6
254#[mel_treatment(
255    input ip Stream<Ip>
256    output ipv6 Stream<bool>
257)]
258pub async fn is_ipv6() {
259    while let Ok(ips) = ip
260        .recv_many()
261        .await
262        .map(|values| Into::<VecDeque<Value>>::into(values))
263    {
264        check!(
265            ipv6.send_many(TransmissionValue::Bool(
266                ips.into_iter()
267                    .map(|ip| GetData::<Arc<dyn Data>>::try_data(ip)
268                        .unwrap()
269                        .downcast_arc::<Ip>()
270                        .unwrap()
271                        .0
272                        .is_ipv6())
273                    .collect()
274            ))
275            .await
276        )
277    }
278}
279
280/// Creates new IPv4.
281#[mel_function]
282pub fn ipv4(a: u8, b: u8, c: u8, d: u8) -> Ipv4 {
283    Ipv4(std::net::Ipv4Addr::new(a, b, c, d))
284}
285
286/// Parse string into IPv4.
287#[mel_function]
288pub fn to_ipv4(text: string) -> Option<Ipv4> {
289    std::net::Ipv4Addr::from_str(&text).ok().map(|ip| Ipv4(ip))
290}
291
292/// Parse string into IPv4.
293///
294/// `ipv4` contains some `Ipv4` if input `text` contains valid ip, else none.
295#[mel_treatment(
296    input text Stream<string>
297    output ipv4 Stream<Option<Ipv4>>
298)]
299pub async fn to_ipv4() {
300    while let Ok(text) = text
301        .recv_many()
302        .await
303        .map(|values| TryInto::<Vec<string>>::try_into(values).unwrap())
304    {
305        check!(
306            ipv4.send_many(TransmissionValue::Other(
307                text.iter()
308                    .map(|t| Value::Option(
309                        std::net::Ipv4Addr::from_str(t)
310                            .ok()
311                            .map(|ip| Box::new(Value::Data(Arc::new(Ipv4(ip)))))
312                    ))
313                    .collect()
314            ))
315            .await
316        )
317    }
318}
319
320/// Return IPv4 localhost.
321#[mel_function]
322pub fn localhost_ipv4() -> Ipv4 {
323    Ipv4(std::net::Ipv4Addr::LOCALHOST)
324}
325
326/// Return IPv4 unspecified.
327#[mel_function]
328pub fn unspecified_ipv4() -> Ipv4 {
329    Ipv4(std::net::Ipv4Addr::UNSPECIFIED)
330}
331
332/// IPv6 data.
333///
334/// `Ipv6` data type contains a valid IP v6.
335///
336/// ℹ️ _Valid IP v6_ means the data contained makes sense as IP, not that it is reacheable.
337#[mel_data(traits(ToString TryToString Display))]
338#[derive(Debug, Clone, Serialize)]
339pub struct Ipv6(pub std::net::Ipv6Addr);
340
341impl ToString for Ipv6 {
342    fn to_string(&self) -> string {
343        self.0.to_string()
344    }
345}
346
347impl TryToString for Ipv6 {
348    fn try_to_string(&self) -> Option<string> {
349        Some(self.0.to_string())
350    }
351}
352
353impl Display for Ipv6 {
354    fn display(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
355        write!(f, "{}", &self.0)
356    }
357}
358
359/// Creates new IPv6.
360#[mel_function]
361pub fn ipv6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6 {
362    Ipv6(std::net::Ipv6Addr::new(a, b, c, d, e, f, g, h))
363}
364
365/// Parse string into IPv6.
366#[mel_function]
367pub fn to_ipv6(text: string) -> Option<Ipv6> {
368    std::net::Ipv6Addr::from_str(&text).ok().map(|ip| Ipv6(ip))
369}
370
371/// Parse string into IPv6.
372///
373/// `ipv6` contains some `Ipv6` if input `text` contains valid ip, else none.
374#[mel_treatment(
375    input text Stream<string>
376    output ipv6 Stream<Option<Ipv6>>
377)]
378pub async fn to_ipv6() {
379    while let Ok(text) = text
380        .recv_many()
381        .await
382        .map(|values| TryInto::<Vec<string>>::try_into(values).unwrap())
383    {
384        check!(
385            ipv6.send_many(TransmissionValue::Other(
386                text.iter()
387                    .map(|t| Value::Option(
388                        std::net::Ipv6Addr::from_str(t)
389                            .ok()
390                            .map(|ip| Box::new(Value::Data(Arc::new(Ipv6(ip)))))
391                    ))
392                    .collect()
393            ))
394            .await
395        )
396    }
397}
398
399/// Return IPv6 localhost.
400#[mel_function]
401pub fn localhost_ipv6() -> Ipv6 {
402    Ipv6(std::net::Ipv6Addr::LOCALHOST)
403}
404
405/// Return IPv6 unspecified.
406#[mel_function]
407pub fn unspecified_ipv6() -> Ipv6 {
408    Ipv6(std::net::Ipv6Addr::UNSPECIFIED)
409}