http_acl/
utils.rs

1//! Utility functions for the http-acl crate.
2
3use std::collections::HashSet;
4use std::hash::Hash;
5use std::net::IpAddr;
6use std::ops::RangeInclusive;
7
8use ipnet::IpNet;
9
10pub mod authority;
11pub(crate) mod ip;
12pub mod url;
13
14// Taken from https://stackoverflow.com/a/46767732
15pub(crate) fn has_unique_elements<T>(iter: T) -> bool
16where
17    T: IntoIterator,
18    T::Item: Eq + Hash,
19{
20    let mut uniq = HashSet::new();
21    iter.into_iter().all(move |x| uniq.insert(x))
22}
23
24/// Converts a type into an IP range.
25pub trait IntoIpRange {
26    /// Converts the type into an IP range.
27    fn into_range(self) -> Option<RangeInclusive<IpAddr>>;
28
29    /// Validates the IP range.
30    fn validate(ip_range: RangeInclusive<IpAddr>) -> Option<RangeInclusive<IpAddr>> {
31        if ip_range.start() <= ip_range.end() {
32            Some(ip_range)
33        } else {
34            None
35        }
36    }
37}
38
39impl IntoIpRange for IpNet {
40    fn into_range(self) -> Option<RangeInclusive<IpAddr>> {
41        let start = self.network();
42        let end = self.broadcast();
43        Some(start..=end)
44    }
45}
46
47impl IntoIpRange for RangeInclusive<IpAddr> {
48    fn into_range(self) -> Option<RangeInclusive<IpAddr>> {
49        Self::validate(self)
50    }
51}
52
53impl IntoIpRange for (IpAddr, IpAddr) {
54    fn into_range(self) -> Option<RangeInclusive<IpAddr>> {
55        Self::validate(self.0..=self.1)
56    }
57}