Parse a `[bind_address:]port` string. Examples: - `"8080"` → `ForwardSpec { bind_addr: "127.0.0.1", port: 8080 }` - `"0.0.0.0:8080"` → `ForwardSpec { bind_addr: "0.0.0.0", port: 8080 }` - `"::1:8080"` → `ForwardSpec { bind_addr: "::1", port: 8080 }`
(s: &str)
| 553 | /// - `"0.0.0.0:8080"` → `ForwardSpec { bind_addr: "0.0.0.0", port: 8080 }` |
| 554 | /// - `"::1:8080"` → `ForwardSpec { bind_addr: "::1", port: 8080 }` |
| 555 | pub fn parse(s: &str) -> Result<Self> { |
| 556 | // Split on the last ':' to handle IPv6 addresses like "::1:8080". |
| 557 | if let Some(pos) = s.rfind(':') { |
| 558 | let addr = &s[..pos]; |
| 559 | let port_str = &s[pos + 1..]; |
| 560 | if let Ok(port) = port_str.parse::<u16>() { |
| 561 | if port == 0 { |
| 562 | return Err(miette::miette!("port must be between 1 and 65535")); |
| 563 | } |
| 564 | return Ok(Self { |
| 565 | bind_addr: addr.to_string(), |
| 566 | port, |
| 567 | }); |
| 568 | } |
| 569 | } |
| 570 | |
| 571 | // No colon or the part after the last colon isn't a valid port — |
| 572 | // treat the entire string as a port number. |
| 573 | let port: u16 = s.parse().map_err(|_| { |
| 574 | miette::miette!("invalid forward spec '{s}': expected [bind_address:]port") |
| 575 | })?; |
| 576 | if port == 0 { |
| 577 | return Err(miette::miette!("port must be between 1 and 65535")); |
| 578 | } |
| 579 | Ok(Self::new(port)) |
| 580 | } |
| 581 | |
| 582 | /// The SSH `-L` local-forward argument: `bind_addr:port:127.0.0.1:port`. |
| 583 | pub fn ssh_forward_arg(&self) -> String { |
no outgoing calls