dia_ip_range/ip_v4_range.rs
1/*
2==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
3
4Dia-IP-Range
5
6Copyright (C) 2021-2024 Anonymous
7
8There are several releases over multiple years,
9they are listed as ranges, such as: "2021-2024".
10
11This program is free software: you can redistribute it and/or modify
12it under the terms of the GNU Lesser General Public License as published by
13the Free Software Foundation, either version 3 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU Lesser General Public License for more details.
20
21You should have received a copy of the GNU Lesser General Public License
22along with this program. If not, see <https://www.gnu.org/licenses/>.
23
24::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
25*/
26
27//! # IPv4 range
28
29use {
30 core::str::FromStr,
31 crate::{Error, IPv4ComponentRange},
32};
33
34#[cfg(feature="iter")]
35#[doc(cfg(feature="iter"))]
36mod ip_v4_range_iter;
37
38#[cfg(feature="iter")]
39#[doc(cfg(feature="iter"))]
40pub use self::ip_v4_range_iter::*;
41
42/// # IPv4 range
43///
44/// A range can be respresented in string, following these rules:
45///
46/// - Start and end are placed inside one of `[]`, `[)`..., separated by a comma.
47/// - `[` and `]` are inclusive.
48/// - `(` and `)` are exclusive.
49/// - White spaces can be included. They will be ignored by parser.
50/// - Length of the string must be equal to or smaller than 64 bytes. It's for protection against flood attack.
51///
52/// Currently this struct is itself useless. You need to enable feature `iter`, in order to use [`IPv4RangeIter`][struct::IPv4RangeIter].
53///
54/// ## Examples
55///
56/// ```
57/// use {
58/// core::str::FromStr,
59/// dia_ip_range::IPv4Range,
60/// };
61///
62/// assert_eq!(
63/// IPv4Range::from_str("10.0.0.[2,100)")?,
64/// IPv4Range::from((10, 0, 0..=0, 2..100)),
65/// );
66///
67/// # Ok::<_, dia_ip_range::Error>(())
68/// ```
69///
70/// [struct::IPv4RangeIter]: struct.IPv4RangeIter.html
71#[derive(Debug, Eq, PartialEq, Hash, Clone)]
72pub struct IPv4Range {
73 a: IPv4ComponentRange,
74 b: IPv4ComponentRange,
75 c: IPv4ComponentRange,
76 d: IPv4ComponentRange,
77}
78
79impl FromStr for IPv4Range {
80
81 type Err = Error;
82
83 fn from_str(s: &str) -> Result<Self, Self::Err> {
84 const MAX_LEN: usize = 64;
85
86 if s.len() > MAX_LEN {
87 return Err(err!("String is too long, max length supported: {} bytes", MAX_LEN));
88 }
89
90 let mut parts = s.trim().split('.');
91 match (parts.next(), parts.next(), parts.next(), parts.next(), parts.next()) {
92 (Some(a), Some(b), Some(c), Some(d), None) => Ok(Self {
93 a: IPv4ComponentRange::from_str(a)?,
94 b: IPv4ComponentRange::from_str(b)?,
95 c: IPv4ComponentRange::from_str(c)?,
96 d: IPv4ComponentRange::from_str(d)?,
97 }),
98 _ => Err(err!("Invalid IPv4 range: {:?}", s)),
99 }
100 }
101
102}
103
104impl<A, B, C, D> From<(A, B, C, D)> for IPv4Range
105where A: Into<IPv4ComponentRange>, B: Into<IPv4ComponentRange>, C: Into<IPv4ComponentRange>, D: Into<IPv4ComponentRange> {
106
107 fn from((a, b, c, d): (A, B, C, D)) -> Self {
108 Self {
109 a: a.into(),
110 b: b.into(),
111 c: c.into(),
112 d: d.into(),
113 }
114 }
115
116}
117
118#[test]
119fn tests() -> crate::Result<()> {
120 for s in &["0.0.0.0", "[255,255].[255,255].[255,255].[255,255]", "192.168.[0,9].[9,10)", "192.168.[ 0 ,9].[9 , 10)"] {
121 IPv4Range::from_str(s)?;
122 }
123 for s in &["0.0.0", "192.168.[09].[9-10)", "192.168.[ 0 ,9.9 , 10)"] {
124 IPv4Range::from_str(s).unwrap_err();
125 }
126
127 Ok(())
128}