Перечисление IpAddr

#![allow(unused)]
fn main() {
pub enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}
}

IP-адрес, версия 4 или версия 6.

Этот enum может содержать либо адрес IPv4, либо адрес IPv6, с их соответствующими типами. Для представления любого IP-адреса, который может быть либо IPv4, либо IPv6, следует использовать этот тип.

Варианты

V4

#![allow(unused)]
fn main() {
V4(Ipv4Addr)
}

Адрес IPv4.

V6

#![allow(unused)]
fn main() {
V6(Ipv6Addr)
}

Адрес IPv6.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));

assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
assert_eq!("::1".parse(), Ok(localhost_v6));

assert_eq!(localhost_v4.is_ipv4(), true);
assert_eq!(localhost_v6.is_ipv6(), true);
}

Методы

is_unspecified

#![allow(unused)]
fn main() {
pub const fn is_unspecified(&self) -> bool
}

Возвращает true, если это неспецифицированный адрес.

Для IPv4 это 0.0.0.0. Для IPv6 это ::.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
}

is_loopback

#![allow(unused)]
fn main() {
pub const fn is_loopback(&self) -> bool
}

Возвращает true, если это адрес обратной петли.

Для IPv4 это 127.0.0.0/8. Для IPv6 это ::1.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)).is_loopback(), true);
}

is_global

#![allow(unused)]
fn main() {
pub fn is_global(&self) -> bool
}

Возвращает true, если это глобальный адрес.

Глобальные адреса - это все адреса, которые не зарезервированы для специальных целей. Это включает в себя адреса из глобального пула unicast, а также другие адреса, которые могут быть маршрутизированы глобально.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

// Частные адреса не являются глобальными
assert_eq!(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)).is_global(), false);
assert_eq!(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)).is_global(), false);

// Некоторые публичные адреса являются глобальными
assert_eq!(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)).is_global(), true);
}

is_multicast

#![allow(unused)]
fn main() {
pub const fn is_multicast(&self) -> bool
}

Возвращает true, если это многоадресный адрес.

Для IPv4 это 224.0.0.0/4. Для IPv6 это ff00::/8.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 0, 0, 1)).is_multicast(), true);
assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 1)).is_multicast(), true);
}

is_ipv4

#![allow(unused)]
fn main() {
pub const fn is_ipv4(&self) -> bool
}

Возвращает true, если это адрес IPv4.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_ipv4(), true);
assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)).is_ipv4(), false);
}

is_ipv6

#![allow(unused)]
fn main() {
pub const fn is_ipv6(&self) -> bool
}

Возвращает true, если это адрес IPv6.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_ipv6(), false);
assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)).is_ipv6(), true);
}

is_documentation

#![allow(unused)]
fn main() {
pub fn is_documentation(&self) -> bool
}

Возвращает true, если это адрес, зарезервированный для документации.

Для IPv4 это 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24. Для IPv6 это 2001:db8::/32.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

assert_eq!(IpAddr::V4(Ipv4Addr::new(192, 0, 2, 1)).is_documentation(), true);
assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)).is_documentation(), true);
}

to_ipv6_mapped

#![allow(unused)]
fn main() {
pub fn to_ipv6_mapped(&self) -> IpAddr
}

Преобразует адрес IPv4 в IPv4-отображенный адрес IPv6.

Возвращает адрес IPv6, соответствующий адресу IPv4, используя механизм IPv4-отображения IPv6, определенный в IETF RFC 4291 Section 2.5.5.2.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

let ipv4 = IpAddr::V4(Ipv4Addr::new(192, 0, 2, 255));
let ipv6_mapped = ipv4.to_ipv6_mapped();

assert_eq!(
    ipv6_mapped,
    IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff))
);
}

Трайт-реализации

From<Ipv4Addr>

#![allow(unused)]
fn main() {
impl From<Ipv4Addr> for IpAddr
}

Преобразует Ipv4Addr в IpAddr.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr};

let addr = Ipv4Addr::new(127, 0, 0, 1);
let ip_addr = IpAddr::from(addr);

assert_eq!(ip_addr, IpAddr::V4(addr));
}

From<Ipv6Addr>

#![allow(unused)]
fn main() {
impl From<Ipv6Addr> for IpAddr
}

Преобразует Ipv6Addr в IpAddr.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv6Addr};

let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
let ip_addr = IpAddr::from(addr);

assert_eq!(ip_addr, IpAddr::V6(addr));
}

Display, Debug

#![allow(unused)]
fn main() {
impl Display for IpAddr
impl Debug for IpAddr
}

Реализует отображение и отладочное отображение для IpAddr.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr};

let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
println!("IP адрес: {}", ip); // "127.0.0.1"
println!("Отладочная информация: {:?}", ip); // "V4(127.0.0.1)"
}

PartialEq, Eq, PartialOrd, Ord, Hash

#![allow(unused)]
fn main() {
impl PartialEq for IpAddr
impl Eq for IpAddr
impl PartialOrd for IpAddr
impl Ord for IpAddr
impl Hash for IpAddr
}

Реализует сравнение и хеширование для IpAddr.

Примеры

#![allow(unused)]
fn main() {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::collections::HashMap;

let ip1 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let ip2 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let ip3 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));

assert_eq!(ip1, ip2);
assert_ne!(ip1, ip3);

let mut map = HashMap::new();
map.insert(ip1, "localhost");
}

FromStr

#![allow(unused)]
fn main() {
impl FromStr for IpAddr
}

Реализует парсинг из строки для IpAddr.

Примеры

#![allow(unused)]
fn main() {
use std::net::IpAddr;
use std::str::FromStr;

let ipv4 = IpAddr::from_str("192.168.1.1").unwrap();
assert!(ipv4.is_ipv4());

let ipv6 = IpAddr::from_str("::1").unwrap();
assert!(ipv6.is_ipv6());
}

Примеры использования

Проверка типов адресов

use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

fn analyze_ip(ip: IpAddr) {
    println!("Анализ IP адреса: {}", ip);
    
    if ip.is_unspecified() {
        println!("  Это неспецифицированный адрес");
    }
    if ip.is_loopback() {
        println!("  Это адрес обратной петли");
    }
    if ip.is_global() {
        println!("  Это глобальный адрес");
    }
    if ip.is_multicast() {
        println!("  Это многоадресный адрес");
    }
    if ip.is_documentation() {
        println!("  Это адрес для документации");
    }
    if ip.is_ipv4() {
        println!("  Это IPv4 адрес");
    }
    if ip.is_ipv6() {
        println!("  Это IPv6 адрес");
    }
}

fn main() {
    let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
    let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
    let multicast_v4 = IpAddr::V4(Ipv4Addr::new(224, 0, 0, 1));
    let documentation_v4 = IpAddr::V4(Ipv4Addr::new(192, 0, 2, 1));
    
    analyze_ip(localhost_v4);
    analyze_ip(localhost_v6);
    analyze_ip(multicast_v4);
    analyze_ip(documentation_v4);
}

Использование в сетевых операциях

use std::net::{TcpListener, TcpStream, IpAddr};
use std::io;

fn create_server(ip: IpAddr, port: u16) -> io::Result<TcpListener> {
    let addr = (ip, port);
    TcpListener::bind(addr)
}

fn connect_to_server(ip: IpAddr, port: u16) -> io::Result<TcpStream> {
    let addr = (ip, port);
    TcpStream::connect(addr)
}

fn main() -> io::Result<()> {
    // Использование IPv4
    let ipv4 = "127.0.0.1".parse::<IpAddr>().unwrap();
    let _server_v4 = create_server(ipv4, 8080)?;
    
    // Использование IPv6
    let ipv6 = "::1".parse::<IpAddr>().unwrap();
    let _client_v6 = connect_to_server(ipv6, 8080)?;
    
    Ok(())
}

Фильтрация IP-адресов

use std::net::{IpAddr, Ipv4Addr};

fn filter_private_ips(ips: Vec<IpAddr>) -> Vec<IpAddr> {
    ips.into_iter()
        .filter(|ip| {
            if let IpAddr::V4(ipv4) = ip {
                // Фильтруем частные адреса IPv4
                !(ipv4.octets()[0] == 10 || // 10.0.0.0/8
                  (ipv4.octets()[0] == 172 && ipv4.octets()[1] >= 16 && ipv4.octets()[1] <= 31) || // 172.16.0.0/12
                  (ipv4.octets()[0] == 192 && ipv4.octets()[1] == 168)) // 192.168.0.0/16
            } else {
                true // Пропускаем все IPv6 адреса
            }
        })
        .collect()
}

fn main() {
    let ips = vec![
        "10.0.0.1".parse().unwrap(),
        "192.168.1.1".parse().unwrap(),
        "8.8.8.8".parse().unwrap(),
        "::1".parse().unwrap(),
    ];
    
    let public_ips = filter_private_ips(ips);
    println!("Публичные IP адреса:");
    for ip in public_ips {
        println!("  {}", ip);
    }
}

Преобразование между IPv4 и IPv6

use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

fn demonstrate_mapping() {
    let ipv4 = Ipv4Addr::new(192, 168, 1, 1);
    let ip_addr_v4 = IpAddr::V4(ipv4);
    
    // Преобразование в IPv4-отображенный IPv6
    let ipv6_mapped = ip_addr_v4.to_ipv6_mapped();
    
    println!("Оригинальный IPv4: {}", ipv4);
    println!("IPv4-отображенный IPv6: {}", ipv6_mapped);
    
    if let IpAddr::V6(ipv6) = ipv6_mapped {
        // Проверяем, что это действительно IPv4-отображенный адрес
        if ipv6.to_ipv4_mapped().is_some() {
            println!("Это IPv4-отображенный адрес IPv6");
        }
    }
}

fn main() {
    demonstrate_mapping();
}