use crate::IpPrefix;
use std::fmt;
use std::net::IpAddr;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct StaticRoute {
destination: IpPrefix,
next_hop: IpAddr,
}
impl StaticRoute {
pub fn new(destination: IpPrefix, next_hop: IpAddr) -> Result<Self, StaticRouteError> {
if destination.address().is_ipv4() != next_hop.is_ipv4() {
return Err(StaticRouteError::AddressFamilyMismatch);
}
Ok(Self {
destination,
next_hop,
})
}
pub const fn destination(self) -> IpPrefix {
self.destination
}
pub const fn next_hop(self) -> IpAddr {
self.next_hop
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum StaticRouteError {
AddressFamilyMismatch,
}
impl fmt::Display for StaticRouteError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.write_str("static-route destination and next hop must use the same address family")
}
}
impl std::error::Error for StaticRouteError {}
#[cfg(test)]
mod tests {
use super::*;
use std::net::{Ipv4Addr, Ipv6Addr};
#[test]
fn route_rejects_a_next_hop_from_another_address_family() {
let destination = "192.0.2.0/24".parse::<IpPrefix>().unwrap();
assert_eq!(
StaticRoute::new(destination, IpAddr::V6(Ipv6Addr::LOCALHOST)),
Err(StaticRouteError::AddressFamilyMismatch)
);
assert!(StaticRoute::new(destination, IpAddr::V4(Ipv4Addr::LOCALHOST)).is_ok());
}
}