1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! IP Prefixes types and utilities
//!

mod slot;
mod ipv6trunc;
mod ipstd;
mod cover;

#[cfg(test)] mod tests;

use std::error::Error;
pub use slot::*;
pub use ipv6trunc::*;
pub use ipstd::*;
pub use cover::*;

use std::fmt;
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ipnet::{Ipv4Net, Ipv6Net};

/// Bit prefix
#[allow(clippy::len_without_is_empty)]
pub trait IpPrefix: Debug+Clone+Copy
{
    /// The slot manipulated inside this prefix
    type Slot: BitSlot;

    /// Root prefix has a length of 0
    fn root() -> Self; // root prefix, of len =0

    /// The inner slot _as is_
    ///
    /// Depending of the implementation, there is no warranty that
    /// the masked bits (i.e. with position greater than the length)
    /// are set to 0.
    ///
    /// For a version of a slot with masked bits set to 0,
    /// see [`Self::bitslot_trunc`].
    fn bitslot(&self) -> Self::Slot;

    /// The inner slot with all the masked bits set to 0.
    ///
    /// The result always equals `self.bitslot() & self.bitmask()`
    /// but it is usually faster to compute (depending on the prefix structure)
    fn bitslot_trunc(&self) -> Self::Slot;

    /// Length of the prefix.
    ///
    /// This is the number of significant first bits.
    /// Others should be considered as 0 (event if not)
    fn len(&self) -> u8;

    /// Mask of the prefix.
    ///
    /// The n (prefix length) first bits are set to 1 and the last ones are set to 0.
    #[inline]
    fn bitmask(&self) -> Self::Slot { <Self::Slot as BitSlot>::bitmask(self.len()) }

    /// The maximum allowed length for this prefix
    const MAX_LEN: u8;

    /// The underlying ip address (usually Ipv4Addr or Ipv6Addr)
    type Addr: Display+Clone+Copy+Eq+Hash;

    /// The address of the network defined by the prefixv
    ///
    /// All the bits greater than the prefix length are set to `0`
    fn network(&self) -> Self::Addr;
}



/// Error generated when building an Ip prefix
#[derive(Debug,PartialEq,Eq,Copy, Clone)]
pub enum IpPrefixError {
    /// The specified length of the prefix is not valid.
    ///
    /// For Ipv4, this error is generated if the specified length
    /// is greater than 32 for an  [`Ipv4Prefix`] or [`Ipv4Net`].
    ///
    /// For Ipv6, this error is generated if the specified length
    /// is greater than 128 for an  [`Ipv6Prefix`] or [`Ipv6Net`]
    /// or greater than 120 for an [`Ipv6Prefix120`]
    /// or greater than 56 for an [`Ipv6Prefix56`].
    PrefixLenError,

    /// The parsed string does not contains a valid Ip address.
    ///
    /// It occurs also if when parsing an Ipv4 (resp. Ipv6) address on a string
    /// which contains an Ipv6 (resp. Ipv4) syntax.
    AddrParseError,
}

impl Display for IpPrefixError
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            IpPrefixError::PrefixLenError => {
                fmt.write_str("invalid IP prefix length")
            }
            IpPrefixError::AddrParseError => {
                fmt.write_str("invalid IP address syntax")
            }
        }
    }
}

impl Error for IpPrefixError {}

impl From<ipnet::AddrParseError> for IpPrefixError {
    fn from(_: ipnet::AddrParseError) -> Self {
        IpPrefixError::AddrParseError
    }
}

impl From<std::net::AddrParseError> for IpPrefixError {
    fn from(_: std::net::AddrParseError) -> Self {
        IpPrefixError::AddrParseError
    }
}

impl From<ipnet::PrefixLenError> for IpPrefixError {
    fn from(_: ipnet::PrefixLenError) -> Self {
        IpPrefixError::PrefixLenError
    }
}