diff --git a/Makefile b/Makefile index e92a0cab..65eb005f 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,9 @@ $(TARGETS): install_targets: rustup target add $(TARGETS) +doc: + RUSTDOCFLAGS="--cfg docsrs" rustup run nightly cargo doc --all-features + # NOTE: when using this command you might want to change the `test` target to # only run a subset of the tests you're actively working on. dev: @@ -27,4 +30,4 @@ dev: clean: cargo clean -.PHONY: test test_all check_all_targets $(TARGETS) install_targets dev clean +.PHONY: test test_all check_all_targets $(TARGETS) install_targets doc dev clean diff --git a/src/lib.rs b/src/lib.rs index 8ff72d4a..75144c07 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -115,6 +115,60 @@ macro_rules! from { }; } +/// Link to online documentation for (almost) all supported OSs. +// NOTE: this macro requires the `extended_key_value_attributes` feature, which +// was stabilised in Rust 1.54, but at the time of writing we support 1.46 as +// MSRV. +#[cfg(docsrs)] +#[rustfmt::skip] +macro_rules! man_links { + // Links to all OSs. + ($syscall: tt ( $section: tt ) ) => { + concat!( + man_links!(__ intro), + man_links!(__ unix $syscall($section)), + man_links!(__ windows $syscall($section)), + ); + }; + // Links to Unix-like OSs. + (unix: $syscall: tt ( $section: tt ) ) => { + concat!( + man_links!(__ intro), + man_links!(__ unix $syscall($section)), + ); + }; + // Links to Windows only. + (windows: $syscall: tt ( $section: tt ) ) => { + concat!( + man_links!(__ intro), + man_links!(__ windows $syscall($section)), + ); + }; + // Internals. + (__ intro) => { + "Additional documentation can be found in documentation of the OS:\n\n" + }; + // List for Unix-like OSs. + (__ unix $syscall: tt ( $section: tt ) ) => { + concat!( + " * DragonFly BSD: \n", + " * FreeBSD: \n", + " * Linux: \n", + " * macOS: (archived, actually for iOS)\n", + " * NetBSD: \n", + " * OpenBSD: \n", + " * iOS: (archived)\n", + " * illumos: \n", + ); + }; + // List for Window (so just Windows). + (__ windows $syscall: tt ( $section: tt ) ) => { + concat!( + " * Windows: \n", + ); + }; +} + mod sockaddr; mod socket; mod sockref; diff --git a/src/socket.rs b/src/socket.rs index de14d632..b59e1306 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -116,12 +116,12 @@ impl Socket { /// /// This function corresponds to `socket(2)` on Unix and `WSASocketW` on /// Windows. + #[cfg_attr(docsrs, doc = man_links!(socket(2)))] /// /// On Unix-like systems, the close-on-exec flag is set on the new socket. /// Additionally, on Apple platforms `SOCK_NOSIGPIPE` is set. On Windows, - /// the socket is made non-inheritable. - /// - /// [`Socket::new_raw`] can be used if you don't want these flags to be set. + /// the socket is made non-inheritable. [`Socket::new_raw`] can be used if + /// you don't want these flags to be set. pub fn new(domain: Domain, ty: Type, protocol: Option) -> io::Result { let ty = set_common_type(ty); Socket::new_raw(domain, ty, protocol).and_then(set_common_flags) @@ -139,8 +139,9 @@ impl Socket { /// Creates a pair of sockets which are connected to each other. /// /// This function corresponds to `socketpair(2)`. + #[cfg_attr(docsrs, doc = man_links!(unix: socketpair(2)))] /// - /// This function sets the same flags as in done for [`Socket::new`], + /// This function sets the same flags as in done for [`Socket::new`]. /// [`Socket::pair_raw`] can be used if you don't want to set those flags. #[cfg(any(doc, all(feature = "all", unix)))] #[cfg_attr(docsrs, doc(cfg(all(feature = "all", unix))))] @@ -175,6 +176,7 @@ impl Socket { /// /// This function directly corresponds to the `bind(2)` function on Windows /// and Unix. + #[cfg_attr(docsrs, doc = man_links!(bind(2)))] pub fn bind(&self, address: &SockAddr) -> io::Result<()> { sys::bind(self.as_raw(), address) } @@ -183,6 +185,7 @@ impl Socket { /// /// This function directly corresponds to the `connect(2)` function on /// Windows and Unix. + #[cfg_attr(docsrs, doc = man_links!(connect(2)))] /// /// An error will be returned if `listen` or `connect` has already been /// called on this builder. @@ -237,6 +240,7 @@ impl Socket { /// /// This function directly corresponds to the `listen(2)` function on /// Windows and Unix. + #[cfg_attr(docsrs, doc = man_links!(listen(2)))] /// /// An error will be returned if `listen` or `connect` has already been /// called on this builder. @@ -248,6 +252,7 @@ impl Socket { /// /// This function uses `accept4(2)` on platforms that support it and /// `accept(2)` platforms that do not. + #[cfg_attr(docsrs, doc = man_links!(accept(2)))] /// /// This function sets the same flags as in done for [`Socket::new`], /// [`Socket::accept_raw`] can be used if you don't want to set those flags. @@ -297,6 +302,10 @@ impl Socket { /// Returns the socket address of the local half of this socket. /// + /// This function directly corresponds to the `getsockname(2)` function on + /// Windows and Unix. + #[cfg_attr(docsrs, doc = man_links!(getsockname(2)))] + /// /// # Notes /// /// Depending on the OS this may return an error if the socket is not @@ -309,6 +318,10 @@ impl Socket { /// Returns the socket address of the remote peer of this socket. /// + /// This function directly corresponds to the `getpeername(2)` function on + /// Windows and Unix. + #[cfg_attr(docsrs, doc = man_links!(getpeername(2)))] + /// /// # Notes /// /// This returns an error if the socket is not [`connect`ed]. @@ -334,8 +347,7 @@ impl Socket { /// On Windows this uses `WSA_FLAG_NO_HANDLE_INHERIT` setting inheriting to /// false. /// - /// On Windows this can **not** be used function cannot be used on a - /// QOS-enabled socket, see + /// On Windows this function cannot be used on a QOS-enabled socket, see /// . pub fn try_clone(&self) -> io::Result { sys::try_clone(self.as_raw()).map(Socket::from_raw) @@ -357,6 +369,8 @@ impl Socket { /// /// This function will cause all pending and future I/O on the specified /// portions to return immediately with an appropriate value. + /// + #[cfg_attr(docsrs, doc = man_links!(shutdown(2)))] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { sys::shutdown(self.as_raw(), how) } diff --git a/src/sys/unix.rs b/src/sys/unix.rs index d1c1af22..8aa95d09 100644 --- a/src/sys/unix.rs +++ b/src/sys/unix.rs @@ -372,11 +372,13 @@ impl_debug!( impl RecvFlags { /// Check if the message terminates a record. /// - /// Not all socket types support the notion of records. - /// For socket types that do support it (such as [`SEQPACKET`][Type::SEQPACKET]), - /// a record is terminated by sending a message with the end-of-record flag set. + /// Not all socket types support the notion of records. For socket types + /// that do support it (such as [`SEQPACKET`]), a record is terminated by + /// sending a message with the end-of-record flag set. /// /// On Unix this corresponds to the MSG_EOR flag. + /// + /// [`SEQPACKET`]: Type::SEQPACKET pub const fn is_end_of_record(self) -> bool { self.0 & libc::MSG_EOR != 0 } @@ -990,6 +992,7 @@ impl crate::Socket { /// Accept a new incoming connection from this listener. /// /// This function directly corresponds to the `accept4(2)` function. + #[cfg_attr(docsrs, doc = man_links!(accept4(2)))] /// /// This function will block the calling thread until a new connection is /// established. When established, the corresponding `Socket` and the remote @@ -1512,6 +1515,7 @@ impl crate::Socket { /// Different OSs support different kinds of `file`s, see the OS /// documentation for what kind of files are supported. Generally *regular* /// files are supported by all OSs. + #[cfg_attr(docsrs, doc = man_links!(sendfile(2)))] /// /// The `offset` is the absolute offset into the `file` to use as starting /// point. diff --git a/tests/socket.rs b/tests/socket.rs index d51a1310..c2e0bae7 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1147,10 +1147,10 @@ test!(IPv4 ttl, set_ttl(40)); test!(IPv4 broadcast, set_broadcast(true)); test!(IPv6 unicast_hops_v6, set_unicast_hops_v6(20)); -#[cfg(not(any(windows, any(target_os = "dragonfly", target_os = "freebsd"))))] +#[cfg(not(any(windows, target_os = "dragonfly", target_os = "freebsd")))] test!(IPv6 only_v6, set_only_v6(true)); // IPv6 socket are already IPv6 only on FreeBSD and Windows. -#[cfg(any(windows, any(target_os = "freebsd")))] +#[cfg(any(windows, target_os = "freebsd"))] test!(IPv6 only_v6, set_only_v6(false)); #[cfg(all(