Skip to content

Commit

Permalink
Add SocketAddress Abstraction for IP Address and Port Handling (#359)
Browse files Browse the repository at this point in the history
* add SocketAddress
* extract common methods into parse_utils.rs
  • Loading branch information
hafihaf123 authored Dec 10, 2024
1 parent 846a978 commit 2417ddc
Show file tree
Hide file tree
Showing 5 changed files with 339 additions and 32 deletions.
23 changes: 6 additions & 17 deletions rama-net/src/address/authority.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{Domain, Host};
use rama_core::error::{ErrorContext, ErrorExt, OpaqueError};
use super::{parse_utils, Domain, Host};
use rama_core::error::{ErrorContext, OpaqueError};
use std::net::{Ipv4Addr, Ipv6Addr};
use std::{
fmt,
Expand Down Expand Up @@ -116,12 +116,12 @@ impl From<&SocketAddr> for Authority {
}

impl fmt::Display for Authority {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.host {
Host::Name(domain) => write!(f, "{}:{}", domain, self.port),
Host::Address(ip) => match ip {
std::net::IpAddr::V4(ip) => write!(f, "{}:{}", ip, self.port),
std::net::IpAddr::V6(ip) => write!(f, "[{}]:{}", ip, self.port),
IpAddr::V4(ip) => write!(f, "{}:{}", ip, self.port),
IpAddr::V6(ip) => write!(f, "[{}]:{}", ip, self.port),
},
}
}
Expand All @@ -147,7 +147,7 @@ impl TryFrom<&str> for Authority {
type Error = OpaqueError;

fn try_from(s: &str) -> Result<Self, Self::Error> {
let (host, port) = split_port_from_str(s)?;
let (host, port) = parse_utils::split_port_from_str(s)?;
let host = Host::try_from(host).context("parse host from authority")?;
match host {
Host::Address(IpAddr::V6(_)) if !s.starts_with('[') => Err(OpaqueError::from_display(
Expand Down Expand Up @@ -194,17 +194,6 @@ impl TryFrom<&[u8]> for Authority {
}
}

fn split_port_from_str(s: &str) -> Result<(&str, u16), OpaqueError> {
if let Some(colon) = s.as_bytes().iter().rposition(|c| *c == b':') {
match s[colon + 1..].parse() {
Ok(port) => Ok((&s[..colon], port)),
Err(err) => Err(err.context("parse port as u16")),
}
} else {
Err(OpaqueError::from_display("missing port"))
}
}

impl serde::Serialize for Authority {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down
19 changes: 4 additions & 15 deletions rama-net/src/address/host.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::Domain;
use super::{parse_utils, Domain};
use rama_core::error::{ErrorContext, OpaqueError};
use std::{
fmt,
Expand Down Expand Up @@ -153,7 +153,7 @@ impl TryFrom<String> for Host {
type Error = OpaqueError;

fn try_from(name: String) -> Result<Self, Self::Error> {
try_to_parse_str_to_ip(name.as_str())
parse_utils::try_to_parse_str_to_ip(name.as_str())
.map(Host::Address)
.or_else(|| Domain::try_from(name).ok().map(Host::Name))
.context("parse host from string")
Expand All @@ -164,7 +164,7 @@ impl TryFrom<&str> for Host {
type Error = OpaqueError;

fn try_from(name: &str) -> Result<Self, Self::Error> {
try_to_parse_str_to_ip(name)
parse_utils::try_to_parse_str_to_ip(name)
.map(Host::Address)
.or_else(|| Domain::try_from(name.to_owned()).ok().map(Host::Name))
.context("parse host from string")
Expand Down Expand Up @@ -295,21 +295,10 @@ impl<'de> serde::Deserialize<'de> for Host {
}
}

fn try_to_parse_str_to_ip(value: &str) -> Option<IpAddr> {
if value.starts_with('[') || value.ends_with(']') {
let value = value
.strip_prefix('[')
.and_then(|value| value.strip_suffix(']'))?;
Some(IpAddr::V6(value.parse::<Ipv6Addr>().ok()?))
} else {
value.parse::<IpAddr>().ok()
}
}

fn try_to_parse_bytes_to_ip(value: &[u8]) -> Option<IpAddr> {
if let Some(ip) = std::str::from_utf8(value)
.ok()
.and_then(try_to_parse_str_to_ip)
.and_then(parse_utils::try_to_parse_str_to_ip)
{
return Some(ip);
}
Expand Down
7 changes: 7 additions & 0 deletions rama-net/src/address/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ mod authority;
#[doc(inline)]
pub use authority::Authority;

mod socket_address;
#[doc(inline)]
pub use socket_address::SocketAddress;

mod proxy;

mod parse_utils;

#[doc(inline)]
pub use proxy::ProxyAddress;
24 changes: 24 additions & 0 deletions rama-net/src/address/parse_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use rama_core::error::{ErrorExt, OpaqueError};
use std::net::{IpAddr, Ipv6Addr};

pub(super) fn split_port_from_str(s: &str) -> Result<(&str, u16), OpaqueError> {
if let Some(colon) = s.as_bytes().iter().rposition(|c| *c == b':') {
match s[colon + 1..].parse() {
Ok(port) => Ok((&s[..colon], port)),
Err(err) => Err(err.context("parse port as u16")),
}
} else {
Err(OpaqueError::from_display("missing port"))
}
}

pub(super) fn try_to_parse_str_to_ip(value: &str) -> Option<IpAddr> {
if value.starts_with('[') || value.ends_with(']') {
let value = value
.strip_prefix('[')
.and_then(|value| value.strip_suffix(']'))?;
Some(IpAddr::V6(value.parse::<Ipv6Addr>().ok()?))
} else {
value.parse::<IpAddr>().ok()
}
}
Loading

0 comments on commit 2417ddc

Please sign in to comment.