use bollard::models::{PortBinding, PortMap};
use std::collections::HashMap;
use std::net;
fn parse_port(port: &str) -> u16 {
port.parse()
.unwrap_or_else(|e| panic!("Failed to parse {} as u16 because {}", port, e))
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Ports {
ipv4_mapping: HashMap<u16, u16>,
ipv6_mapping: HashMap<u16, u16>,
}
impl Ports {
pub fn mapped_port_ipv4(&self, internal_port: u16) -> Option<u16> {
self.ipv4_mapping.get(&internal_port).cloned()
}
pub fn mapped_port_ipv6(&self, internal_port: u16) -> Option<u16> {
self.ipv6_mapping.get(&internal_port).cloned()
}
}
impl From<PortMap> for Ports {
fn from(ports: PortMap) -> Self {
dbg!(&ports);
let mut ipv4_mapping = HashMap::new();
let mut ipv6_mapping = HashMap::new();
for (internal, external) in ports {
let internal_port = if let Some(internal) = internal.split('/').next() {
parse_port(internal)
} else {
continue;
};
for binding in external.into_iter().flatten() {
if let Some(external_port) = binding.host_port.as_ref() {
let external_port = parse_port(external_port);
let mapping = match binding.host_ip.map(|ip| ip.parse()) {
Some(Ok(net::IpAddr::V4(_))) => {
&mut ipv4_mapping
}
Some(Ok(net::IpAddr::V6(_))) => {
&mut ipv6_mapping
}
Some(Err(_)) | None => continue,
};
mapping.insert(internal_port, external_port);
} else {
continue;
}
}
}
Self {
ipv4_mapping,
ipv6_mapping,
}
}
}