mirror of
https://github.com/jht5945/rust_util.git
synced 2026-01-12 23:30:05 +08:00
Compare commits
3 Commits
c5749c8137
...
79e2618e98
| Author | SHA1 | Date | |
|---|---|---|---|
| 79e2618e98 | |||
| 90fc790b64 | |||
| bd8152f59b |
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rust_util"
|
name = "rust_util"
|
||||||
version = "0.6.5"
|
version = "0.6.7"
|
||||||
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Hatter's Rust Util"
|
description = "Hatter's Rust Util"
|
||||||
|
|||||||
153
src/util_net.rs
153
src/util_net.rs
@@ -1,6 +1,39 @@
|
|||||||
|
use std::fmt::{ Display, Formatter };
|
||||||
|
use std::result::Result;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use crate::XResult;
|
use crate::XResult;
|
||||||
|
|
||||||
|
const DEFAULT_LISTEN_ADDR: [u8; 4] = [127, 0, 0, 1];
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum IpAddress {
|
||||||
|
Ipv4([u8; 4]),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IpAddress {
|
||||||
|
pub fn parse_ipv4(addr: &str) -> Option<Self> {
|
||||||
|
parse_ipv4_addr(addr).map(|parts| IpAddress::Ipv4(parts))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_address(&self) -> String {
|
||||||
|
match self {
|
||||||
|
IpAddress::Ipv4(ipv4) => ipv4.iter().map(|p| p.to_string()).collect::<Vec<_>>().join("."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_matches(&self, socket_addr: &SocketAddr) -> bool {
|
||||||
|
match self {
|
||||||
|
IpAddress::Ipv4(self_ipv4_octets) => IpAddressMask::Ipv4(self_ipv4_octets.clone(), 32).is_matches(socket_addr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for IpAddress {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
|
write!(f, "{}", self.to_address())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum IpAddressMask {
|
pub enum IpAddressMask {
|
||||||
Ipv4([u8; 4], u8),
|
Ipv4([u8; 4], u8),
|
||||||
@@ -20,21 +53,7 @@ impl IpAddressMask {
|
|||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let addr_parts = addr_ip.split('.').collect::<Vec<_>>();
|
parse_ipv4_addr(addr_ip).map(|parts| IpAddressMask::Ipv4(parts, mask))
|
||||||
if addr_parts.len() != 4 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let parsed_addr = || -> XResult<[u8; 4]> {
|
|
||||||
Ok([addr_parts[0].parse::<u8>()?,
|
|
||||||
addr_parts[1].parse::<u8>()?,
|
|
||||||
addr_parts[2].parse::<u8>()?,
|
|
||||||
addr_parts[3].parse::<u8>()?
|
|
||||||
])
|
|
||||||
};
|
|
||||||
match parsed_addr() {
|
|
||||||
Ok(parts) => Some(IpAddressMask::Ipv4(parts, mask)),
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_address(&self) -> String {
|
pub fn to_address(&self) -> String {
|
||||||
@@ -63,6 +82,66 @@ impl IpAddressMask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for IpAddressMask {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
|
write!(f, "{}", self.to_address())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct IpAddressAndPort {
|
||||||
|
pub ip: IpAddress,
|
||||||
|
pub port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IpAddressAndPort {
|
||||||
|
pub fn parse(ip_address_and_port: &str) -> Option<Self> {
|
||||||
|
if let Some((ipv4, port)) = parse_ip_and_port(ip_address_and_port) {
|
||||||
|
return Some(IpAddressAndPort {
|
||||||
|
ip: IpAddress::Ipv4(ipv4),
|
||||||
|
port,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_address(&self) -> String {
|
||||||
|
format!("{}:{}", self.ip, self.port)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_ipv4_and_port(&self) -> ([u8; 4], u16) {
|
||||||
|
match self.ip {
|
||||||
|
IpAddress::Ipv4(ipv4) => (ipv4, self.port),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for IpAddressAndPort {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
|
write!(f, "{}:{}", self.ip, self.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// :8080 -> 127.0.0.1:8080
|
||||||
|
fn parse_ip_and_port(listen: &str) -> Option<([u8; 4], u16)> {
|
||||||
|
let listen_addr = match listen.split(':').next() {
|
||||||
|
None => DEFAULT_LISTEN_ADDR,
|
||||||
|
Some(addr) if addr.is_empty() => DEFAULT_LISTEN_ADDR,
|
||||||
|
Some(addr) => match parse_ipv4_addr(addr) {
|
||||||
|
Some(parsed_ip_address) => parsed_ip_address, None => return None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let listen_port = match listen.split(':').nth(1) {
|
||||||
|
None => return None,
|
||||||
|
Some(port) => match port.parse::<u16>() {
|
||||||
|
Ok(port) => port, Err(_) => return None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Some((listen_addr, listen_port))
|
||||||
|
}
|
||||||
|
|
||||||
fn ipv4_mask(mask: u8) -> u32 {
|
fn ipv4_mask(mask: u8) -> u32 {
|
||||||
let mut r = 0_u32;
|
let mut r = 0_u32;
|
||||||
for _ in 0..mask {
|
for _ in 0..mask {
|
||||||
@@ -79,17 +158,41 @@ fn ipv4_to_u32(ipv4: &[u8; 4]) -> u32 {
|
|||||||
((ipv4[0] as u32) << (8 * 3)) + ((ipv4[1] as u32) << (8 * 2)) + ((ipv4[2] as u32) << 8) + (ipv4[3] as u32)
|
((ipv4[0] as u32) << (8 * 3)) + ((ipv4[1] as u32) << (8 * 2)) + ((ipv4[2] as u32) << 8) + (ipv4[3] as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_ipv4_addr(addr: &str) -> Option<[u8; 4]> {
|
||||||
|
let addr_parts = addr.split('.').collect::<Vec<_>>();
|
||||||
|
if addr_parts.len() != 4 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let parsed_addr = || -> XResult<[u8; 4]> {
|
||||||
|
Ok([addr_parts[0].parse::<u8>()?,
|
||||||
|
addr_parts[1].parse::<u8>()?,
|
||||||
|
addr_parts[2].parse::<u8>()?,
|
||||||
|
addr_parts[3].parse::<u8>()?
|
||||||
|
])
|
||||||
|
};
|
||||||
|
parsed_addr().ok()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_matches() {
|
fn test_ip_address_is_matches() {
|
||||||
let addr = SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)), 123);
|
let addr = SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)), 123);
|
||||||
let addr2 = SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 2)), 123);
|
let addr2 = SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 2)), 123);
|
||||||
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1").unwrap().is_matches(&addr));
|
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1").unwrap().is_matches(&addr));
|
||||||
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1/32").unwrap().is_matches(&addr));
|
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1/32").unwrap().is_matches(&addr));
|
||||||
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1/31").unwrap().is_matches(&addr));
|
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1/31").unwrap().is_matches(&addr));
|
||||||
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1/30").unwrap().is_matches(&addr));
|
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1/30").unwrap().is_matches(&addr));
|
||||||
assert_eq!(false, IpAddressMask::parse_ipv4("127.0.0.1").unwrap().is_matches(&addr2));
|
assert_eq!(false, IpAddressMask::parse_ipv4("127.0.0.1").unwrap().is_matches(&addr2));
|
||||||
assert_eq!(false, IpAddressMask::parse_ipv4("127.0.0.1/32").unwrap().is_matches(&addr2));
|
assert_eq!(false, IpAddressMask::parse_ipv4("127.0.0.1/32").unwrap().is_matches(&addr2));
|
||||||
assert_eq!(false, IpAddressMask::parse_ipv4("127.0.0.1/31").unwrap().is_matches(&addr2));
|
assert_eq!(false, IpAddressMask::parse_ipv4("127.0.0.1/31").unwrap().is_matches(&addr2));
|
||||||
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1/30").unwrap().is_matches(&addr2));
|
assert_eq!(true, IpAddressMask::parse_ipv4("127.0.0.1/30").unwrap().is_matches(&addr2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ip_address_port() {
|
||||||
|
let ip_address_and_port = IpAddressAndPort::parse(":80");
|
||||||
|
assert_eq!("127.0.0.1:80", format!("{}", ip_address_and_port.unwrap()));
|
||||||
|
let ip_address_and_port = IpAddressAndPort::parse("0.0.0.0:80");
|
||||||
|
assert_eq!("0.0.0.0:80", format!("{}", ip_address_and_port.unwrap()));
|
||||||
|
let ip_address_and_port = IpAddressAndPort::parse("1.1.1.1:80");
|
||||||
|
assert_eq!("1.1.1.1:80", format!("{}", ip_address_and_port.unwrap()));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user