1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#![cfg_attr(feature = "nightly", deny(missing_docs))]
#![cfg_attr(feature = "nightly", feature(external_doc))]
#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
#![cfg_attr(test, deny(warnings))]
#[macro_use]
extern crate structopt;
use std::io;
use std::net::TcpListener;
use std::os::raw::c_int;
use std::os::unix::io::FromRawFd;
#[derive(StructOpt, Debug)]
pub struct Port {
#[structopt(short = "a", long = "address", default_value = "127.0.0.1")]
address: String,
#[structopt(short = "p", long = "port", env = "PORT", group = "bind")]
port: Option<u16>,
#[structopt(long = "listen-fd", env = "LISTEN_FD", group = "bind")]
fd: Option<c_int>,
}
impl Port {
pub fn bind(&self) -> std::io::Result<TcpListener> {
match self {
Self { fd: Some(fd), .. } => unsafe { Ok(TcpListener::from_raw_fd(*fd)) },
Self {
port: Some(port), ..
} => TcpListener::bind((self.address.as_str(), *port)),
_ => Err(io::Error::new(io::ErrorKind::Other, "No port supplied.")),
}
}
pub fn bind_or(&self, port: u16) -> std::io::Result<TcpListener> {
self
.bind()
.or_else(|_| TcpListener::bind((self.address.as_str(), port)))
}
}