diff options
| author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 | 
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 | 
| commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
| tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/rustix/src/maybe_polyfill/no_std | |
| parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
| download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip  | |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/rustix/src/maybe_polyfill/no_std')
13 files changed, 3619 insertions, 0 deletions
diff --git a/vendor/rustix/src/maybe_polyfill/no_std/io/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/io/mod.rs new file mode 100644 index 0000000..f0ad750 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/io/mod.rs @@ -0,0 +1,107 @@ +//! The following is derived from Rust's +//! library/std/src/sys/unix/io.rs +//! dca3f1b786efd27be3b325ed1e01e247aa589c3b. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. + +#![allow(unsafe_code)] +use crate::backend::c; +#[cfg(not(linux_raw))] +use c::size_t as __kernel_size_t; +use core::marker::PhantomData; +use core::slice; +#[cfg(linux_raw)] +use linux_raw_sys::general::__kernel_size_t; + +/// <https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html> +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct IoSlice<'a> { +    vec: c::iovec, +    _p: PhantomData<&'a [u8]>, +} + +impl<'a> IoSlice<'a> { +    /// <https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.new> +    #[inline] +    pub fn new(buf: &'a [u8]) -> IoSlice<'a> { +        IoSlice { +            vec: c::iovec { +                iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void, +                iov_len: buf.len() as _, +            }, +            _p: PhantomData, +        } +    } + +    /// <https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance> +    #[inline] +    pub fn advance(&mut self, n: usize) { +        if self.vec.iov_len < n as _ { +            panic!("advancing IoSlice beyond its length"); +        } + +        unsafe { +            // `__kernel_size_t` will always have the same size as `usize`, but it is a `u32` on +            // 32-bit platforms and `u64` on 64-bit platforms when using `linux_raw` backend +            self.vec.iov_len -= n as __kernel_size_t; +            self.vec.iov_base = self.vec.iov_base.add(n); +        } +    } + +    /// <https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.as_slice> +    #[inline] +    pub fn as_slice(&self) -> &[u8] { +        unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) } +    } +} + +/// <https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html> +#[repr(transparent)] +pub struct IoSliceMut<'a> { +    vec: c::iovec, +    _p: PhantomData<&'a mut [u8]>, +} + +impl<'a> IoSliceMut<'a> { +    /// <https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.new> +    #[inline] +    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { +        IoSliceMut { +            vec: c::iovec { +                iov_base: buf.as_mut_ptr() as *mut c::c_void, +                iov_len: buf.len() as _, +            }, +            _p: PhantomData, +        } +    } + +    /// <https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance> +    #[inline] +    pub fn advance(&mut self, n: usize) { +        if self.vec.iov_len < n as _ { +            panic!("advancing IoSliceMut beyond its length"); +        } + +        unsafe { +            // `__kernel_size_t` will always have the same size as `usize`, but it is a `u32` on +            // 32-bit platforms and `u64` on 64-bit platforms when using `linux_raw` backend +            self.vec.iov_len -= n as __kernel_size_t; +            self.vec.iov_base = self.vec.iov_base.add(n); +        } +    } + +    /// <https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.as_slice> +    #[inline] +    pub fn as_slice(&self) -> &[u8] { +        unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) } +    } + +    /// <https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.as_slice_mut> +    #[inline] +    pub fn as_mut_slice(&mut self) -> &mut [u8] { +        unsafe { +            slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) +        } +    } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/mod.rs new file mode 100644 index 0000000..84bf5b7 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/mod.rs @@ -0,0 +1,16 @@ +//! Polyfill of parts of the standard library for `no_std` builds. +//! +//! All code in this subtree is derived from the standard library and licensed +//! MIT or Apache 2.0 at your option. +//! +//! This implementation is used when `std` is not available and polyfills the +//! necessary items from `std`. When the `std` feature is specified (so the +//! standard library is available), the file `src/polyfill/std` is used +//! instead, which just imports the respective items from `std`. + +#[cfg(not(windows))] +pub mod io; +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] +#[cfg(feature = "net")] +pub mod net; +pub mod os; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/net/ip_addr.rs b/vendor/rustix/src/maybe_polyfill/no_std/net/ip_addr.rs new file mode 100644 index 0000000..81415e9 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/net/ip_addr.rs @@ -0,0 +1,2068 @@ +//! The following is derived from Rust's +//! library/std/src/net/ip_addr.rs at revision +//! bd20fc1fd657b32f7aa1d70d8723f04c87f21606. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! This defines `IpAddr`, `Ipv4Addr`, and `Ipv6Addr`. Ideally, these should be +//! defined in `core`. See [RFC 2832]. +//! +//! [RFC 2832]: https://github.com/rust-lang/rfcs/pull/2832 + +#![allow(unsafe_code)] + +use core::cmp::Ordering; +use core::mem::transmute; + +/// An IP address, either IPv4 or IPv6. +/// +/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their +/// respective documentation for more details. +/// +/// # Examples +/// +/// ``` +/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +/// +/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); +/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); +/// +/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4)); +/// assert_eq!("::1".parse(), Ok(localhost_v6)); +/// +/// assert_eq!(localhost_v4.is_ipv6(), false); +/// assert_eq!(localhost_v4.is_ipv4(), true); +/// ``` +#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] +#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] +pub enum IpAddr { +    /// An IPv4 address. +    #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] +    V4(#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] Ipv4Addr), +    /// An IPv6 address. +    #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] +    V6(#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] Ipv6Addr), +} + +/// An IPv4 address. +/// +/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791]. +/// They are usually represented as four octets. +/// +/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. +/// +/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791 +/// +/// # Textual representation +/// +/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal +/// notation, divided by `.` (this is called "dot-decimal notation"). +/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which +/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943]. +/// +/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1 +/// [`FromStr`]: core::str::FromStr +/// +/// # Examples +/// +/// ``` +/// use std::net::Ipv4Addr; +/// +/// let localhost = Ipv4Addr::new(127, 0, 0, 1); +/// assert_eq!("127.0.0.1".parse(), Ok(localhost)); +/// assert_eq!(localhost.is_loopback(), true); +/// assert!("012.004.002.000".parse::<Ipv4Addr>().is_err()); // all octets are in octal +/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal +/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub struct Ipv4Addr { +    octets: [u8; 4], +} + +/// An IPv6 address. +/// +/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291]. +/// They are usually represented as eight 16-bit segments. +/// +/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 +/// +/// # Embedding IPv4 Addresses +/// +/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. +/// +/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined: +/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated. +/// +/// Both types of addresses are not assigned any special meaning by this implementation, +/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`, +/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is. +/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address. +/// +/// ### IPv4-Compatible IPv6 Addresses +/// +/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated. +/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows: +/// +/// ```text +/// |                80 bits               | 16 |      32 bits        | +/// +--------------------------------------+--------------------------+ +/// |0000..............................0000|0000|    IPv4 address     | +/// +--------------------------------------+----+---------------------+ +/// ``` +/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`. +/// +/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`]. +/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address. +/// +/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1 +/// +/// ### IPv4-Mapped IPv6 Addresses +/// +/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2]. +/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows: +/// +/// ```text +/// |                80 bits               | 16 |      32 bits        | +/// +--------------------------------------+--------------------------+ +/// |0000..............................0000|FFFF|    IPv4 address     | +/// +--------------------------------------+----+---------------------+ +/// ``` +/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`. +/// +/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`]. +/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address. +/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use +/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this. +/// +/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2 +/// +/// # Textual representation +/// +/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent +/// an IPv6 address in text, but in general, each segments is written in hexadecimal +/// notation, and segments are separated by `:`. For more information, see +/// [IETF RFC 5952]. +/// +/// [`FromStr`]: core::str::FromStr +/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952 +/// +/// # Examples +/// +/// ``` +/// use std::net::Ipv6Addr; +/// +/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); +/// assert_eq!("::1".parse(), Ok(localhost)); +/// assert_eq!(localhost.is_loopback(), true); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub struct Ipv6Addr { +    octets: [u8; 16], +} + +/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2]. +/// +/// # Stability Guarantees +/// +/// Not all possible values for a multicast scope have been assigned. +/// Future RFCs may introduce new scopes, which will be added as variants to this enum; +/// because of this the enum is marked as `#[non_exhaustive]`. +/// +/// # Examples +/// ``` +/// #![feature(ip)] +/// +/// use std::net::Ipv6Addr; +/// use std::net::Ipv6MulticastScope::*; +/// +/// // An IPv6 multicast address with global scope (`ff0e::`). +/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0); +/// +/// // Will print "Global scope". +/// match address.multicast_scope() { +///     Some(InterfaceLocal) => println!("Interface-Local scope"), +///     Some(LinkLocal) => println!("Link-Local scope"), +///     Some(RealmLocal) => println!("Realm-Local scope"), +///     Some(AdminLocal) => println!("Admin-Local scope"), +///     Some(SiteLocal) => println!("Site-Local scope"), +///     Some(OrganizationLocal) => println!("Organization-Local scope"), +///     Some(Global) => println!("Global scope"), +///     Some(_) => println!("Unknown scope"), +///     None => println!("Not a multicast address!") +/// } +/// +/// ``` +/// +/// [IPv6 multicast address]: Ipv6Addr +/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2 +#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] +#[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +#[non_exhaustive] +pub enum Ipv6MulticastScope { +    /// Interface-Local scope. +    InterfaceLocal, +    /// Link-Local scope. +    LinkLocal, +    /// Realm-Local scope. +    RealmLocal, +    /// Admin-Local scope. +    AdminLocal, +    /// Site-Local scope. +    SiteLocal, +    /// Organization-Local scope. +    OrganizationLocal, +    /// Global scope. +    Global, +} + +impl IpAddr { +    /// Returns [`true`] for the special 'unspecified' address. +    /// +    /// See the documentation for [`Ipv4Addr::is_unspecified()`] and +    /// [`Ipv6Addr::is_unspecified()`] for more details. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] +    #[must_use] +    #[inline] +    pub const fn is_unspecified(&self) -> bool { +        match self { +            IpAddr::V4(ip) => ip.is_unspecified(), +            IpAddr::V6(ip) => ip.is_unspecified(), +        } +    } + +    /// Returns [`true`] if this is a loopback address. +    /// +    /// See the documentation for [`Ipv4Addr::is_loopback()`] and +    /// [`Ipv6Addr::is_loopback()`] for more details. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] +    #[must_use] +    #[inline] +    pub const fn is_loopback(&self) -> bool { +        match self { +            IpAddr::V4(ip) => ip.is_loopback(), +            IpAddr::V6(ip) => ip.is_loopback(), +        } +    } + +    /// Returns [`true`] if the address appears to be globally routable. +    /// +    /// See the documentation for [`Ipv4Addr::is_global()`] and +    /// [`Ipv6Addr::is_global()`] for more details. +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ip", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_global(&self) -> bool { +        match self { +            IpAddr::V4(ip) => ip.is_global(), +            IpAddr::V6(ip) => ip.is_global(), +        } +    } + +    /// Returns [`true`] if this is a multicast address. +    /// +    /// See the documentation for [`Ipv4Addr::is_multicast()`] and +    /// [`Ipv6Addr::is_multicast()`] for more details. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] +    #[must_use] +    #[inline] +    pub const fn is_multicast(&self) -> bool { +        match self { +            IpAddr::V4(ip) => ip.is_multicast(), +            IpAddr::V6(ip) => ip.is_multicast(), +        } +    } + +    /// Returns [`true`] if this address is in a range designated for documentation. +    /// +    /// See the documentation for [`Ipv4Addr::is_documentation()`] and +    /// [`Ipv6Addr::is_documentation()`] for more details. +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); +    /// assert_eq!( +    ///     IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(), +    ///     true +    /// ); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ip", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_documentation(&self) -> bool { +        match self { +            IpAddr::V4(ip) => ip.is_documentation(), +            IpAddr::V6(ip) => ip.is_documentation(), +        } +    } + +    /// Returns [`true`] if this address is in a range designated for benchmarking. +    /// +    /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and +    /// [`Ipv6Addr::is_benchmarking()`] for more details. +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true); +    /// ``` +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_benchmarking(&self) -> bool { +        match self { +            IpAddr::V4(ip) => ip.is_benchmarking(), +            IpAddr::V6(ip) => ip.is_benchmarking(), +        } +    } + +    /// Returns [`true`] if this address is an [`IPv4` address], and [`false`] +    /// otherwise. +    /// +    /// [`IPv4` address]: IpAddr::V4 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "ipaddr_checker", since = "1.16.0"))] +    #[must_use] +    #[inline] +    pub const fn is_ipv4(&self) -> bool { +        matches!(self, IpAddr::V4(_)) +    } + +    /// Returns [`true`] if this address is an [`IPv6` address], and [`false`] +    /// otherwise. +    /// +    /// [`IPv6` address]: IpAddr::V6 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "ipaddr_checker", since = "1.16.0"))] +    #[must_use] +    #[inline] +    pub const fn is_ipv6(&self) -> bool { +        matches!(self, IpAddr::V6(_)) +    } + +    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it +    /// return `self` as-is. +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false); +    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true); +    /// ``` +    #[inline] +    #[must_use = "this returns the result of the operation, \ +                  without modifying the original"] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ip", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    pub const fn to_canonical(&self) -> IpAddr { +        match self { +            &v4 @ IpAddr::V4(_) => v4, +            IpAddr::V6(v6) => v6.to_canonical(), +        } +    } +} + +impl Ipv4Addr { +    /// Creates a new IPv4 address from four eight-bit octets. +    /// +    /// The result will represent the IP address `a`.`b`.`c`.`d`. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// let addr = Ipv4Addr::new(127, 0, 0, 1); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_32", since = "1.32.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[must_use] +    #[inline] +    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { +        Ipv4Addr { +            octets: [a, b, c, d], +        } +    } + +    /// An IPv4 address with the address pointing to localhost: `127.0.0.1` +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// let addr = Ipv4Addr::LOCALHOST; +    /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] +    pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1); + +    /// An IPv4 address representing an unspecified address: `0.0.0.0` +    /// +    /// This corresponds to the constant `INADDR_ANY` in other languages. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// let addr = Ipv4Addr::UNSPECIFIED; +    /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); +    /// ``` +    #[doc(alias = "INADDR_ANY")] +    #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] +    pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); + +    /// An IPv4 address representing the broadcast address: `255.255.255.255` +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// let addr = Ipv4Addr::BROADCAST; +    /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255)); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] +    pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255); + +    /// Returns the four eight-bit integers that make up this address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// let addr = Ipv4Addr::new(127, 0, 0, 1); +    /// assert_eq!(addr.octets(), [127, 0, 0, 1]); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[must_use] +    #[inline] +    pub const fn octets(&self) -> [u8; 4] { +        self.octets +    } + +    /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`). +    /// +    /// This property is defined in _UNIX Network Programming, Second Edition_, +    /// W. Richard Stevens, p. 891; see also [ip7]. +    /// +    /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true); +    /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_32", since = "1.32.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] +    #[must_use] +    #[inline] +    pub const fn is_unspecified(&self) -> bool { +        u32::from_be_bytes(self.octets) == 0 +    } + +    /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`). +    /// +    /// This property is defined by [IETF RFC 1122]. +    /// +    /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true); +    /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_loopback(&self) -> bool { +        self.octets()[0] == 127 +    } + +    /// Returns [`true`] if this is a private address. +    /// +    /// The private address ranges are defined in [IETF RFC 1918] and include: +    /// +    ///  - `10.0.0.0/8` +    ///  - `172.16.0.0/12` +    ///  - `192.168.0.0/16` +    /// +    /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true); +    /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true); +    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true); +    /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true); +    /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false); +    /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true); +    /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_private(&self) -> bool { +        match self.octets() { +            [10, ..] => true, +            [172, b, ..] if b >= 16 && b <= 31 => true, +            [192, 168, ..] => true, +            _ => false, +        } +    } + +    /// Returns [`true`] if the address is link-local (`169.254.0.0/16`). +    /// +    /// This property is defined by [IETF RFC 3927]. +    /// +    /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true); +    /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true); +    /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_link_local(&self) -> bool { +        matches!(self.octets(), [169, 254, ..]) +    } + +    /// Returns [`true`] if the address appears to be globally reachable +    /// as specified by the [IANA IPv4 Special-Purpose Address Registry]. +    /// Whether or not an address is practically reachable will depend on your network configuration. +    /// +    /// Most IPv4 addresses are globally reachable; +    /// unless they are specifically defined as *not* globally reachable. +    /// +    /// Non-exhaustive list of notable addresses that are not globally reachable: +    /// +    /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified)) +    /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private)) +    /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared)) +    /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback)) +    /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local)) +    /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation)) +    /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking)) +    /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved)) +    /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast)) +    /// +    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry]. +    /// +    /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml +    /// [unspecified address]: Ipv4Addr::UNSPECIFIED +    /// [broadcast address]: Ipv4Addr::BROADCAST + +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::Ipv4Addr; +    /// +    /// // Most IPv4 addresses are globally reachable: +    /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); +    /// +    /// // However some addresses have been assigned a special meaning +    /// // that makes them not globally reachable. Some examples are: +    /// +    /// // The unspecified address (`0.0.0.0`) +    /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false); +    /// +    /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16) +    /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); +    /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); +    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); +    /// +    /// // Addresses in the shared address space (`100.64.0.0/10`) +    /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); +    /// +    /// // The loopback addresses (`127.0.0.0/8`) +    /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false); +    /// +    /// // Link-local addresses (`169.254.0.0/16`) +    /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); +    /// +    /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`) +    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); +    /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); +    /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); +    /// +    /// // Addresses reserved for benchmarking (`198.18.0.0/15`) +    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); +    /// +    /// // Reserved addresses (`240.0.0.0/4`) +    /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); +    /// +    /// // The broadcast address (`255.255.255.255`) +    /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false); +    /// +    /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry. +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv4", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_global(&self) -> bool { +        !(self.octets()[0] == 0 // "This network" +            || self.is_private() +            || self.is_shared() +            || self.is_loopback() +            || self.is_link_local() +            // addresses reserved for future protocols (`192.0.0.0/24`) +            ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0) +            || self.is_documentation() +            || self.is_benchmarking() +            || self.is_reserved() +            || self.is_broadcast()) +    } + +    /// Returns [`true`] if this address is part of the Shared Address Space defined in +    /// [IETF RFC 6598] (`100.64.0.0/10`). +    /// +    /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598 +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); +    /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); +    /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv4", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_shared(&self) -> bool { +        self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) +    } + +    /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for +    /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0` +    /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. +    /// +    /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544 +    /// [errata 423]: https://www.rfc-editor.org/errata/eid423 +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); +    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); +    /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); +    /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv4", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_benchmarking(&self) -> bool { +        self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 +    } + +    /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112] +    /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the +    /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since +    /// it is obviously not reserved for future use. +    /// +    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 +    /// +    /// # Warning +    /// +    /// As IANA assigns new addresses, this method will be +    /// updated. This may result in non-reserved addresses being +    /// treated as reserved in code that relies on an outdated version +    /// of this method. +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); +    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); +    /// +    /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); +    /// // The broadcast address is not considered as reserved for future use by this implementation +    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv4", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_reserved(&self) -> bool { +        self.octets()[0] & 240 == 240 && !self.is_broadcast() +    } + +    /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`). +    /// +    /// Multicast addresses have a most significant octet between `224` and `239`, +    /// and is defined by [IETF RFC 5771]. +    /// +    /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true); +    /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true); +    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_multicast(&self) -> bool { +        self.octets()[0] >= 224 && self.octets()[0] <= 239 +    } + +    /// Returns [`true`] if this is a broadcast address (`255.255.255.255`). +    /// +    /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919]. +    /// +    /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true); +    /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_broadcast(&self) -> bool { +        u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets()) +    } + +    /// Returns [`true`] if this address is in a range designated for documentation. +    /// +    /// This is defined in [IETF RFC 5737]: +    /// +    /// - `192.0.2.0/24` (TEST-NET-1) +    /// - `198.51.100.0/24` (TEST-NET-2) +    /// - `203.0.113.0/24` (TEST-NET-3) +    /// +    /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true); +    /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true); +    /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true); +    /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_documentation(&self) -> bool { +        matches!( +            self.octets(), +            [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _] +        ) +    } + +    /// Converts this address to an [IPv4-compatible] [`IPv6` address]. +    /// +    /// `a.b.c.d` becomes `::a.b.c.d` +    /// +    /// Note that IPv4-compatible addresses have been officially deprecated. +    /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead. +    /// +    /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses +    /// [`IPv6` address]: Ipv6Addr +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!( +    ///     Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), +    ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff) +    /// ); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[must_use = "this returns the result of the operation, \ +                  without modifying the original"] +    #[inline] +    pub const fn to_ipv6_compatible(&self) -> Ipv6Addr { +        let [a, b, c, d] = self.octets(); +        Ipv6Addr { +            octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d], +        } +    } + +    /// Converts this address to an [IPv4-mapped] [`IPv6` address]. +    /// +    /// `a.b.c.d` becomes `::ffff:a.b.c.d` +    /// +    /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses +    /// [`IPv6` address]: Ipv6Addr +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(), +    ///            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff)); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[must_use = "this returns the result of the operation, \ +                  without modifying the original"] +    #[inline] +    pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { +        let [a, b, c, d] = self.octets(); +        Ipv6Addr { +            octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d], +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] +impl From<Ipv4Addr> for IpAddr { +    /// Copies this address to a new `IpAddr::V4`. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr}; +    /// +    /// let addr = Ipv4Addr::new(127, 0, 0, 1); +    /// +    /// assert_eq!( +    ///     IpAddr::V4(addr), +    ///     IpAddr::from(addr) +    /// ) +    /// ``` +    #[inline] +    fn from(ipv4: Ipv4Addr) -> IpAddr { +        IpAddr::V4(ipv4) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] +impl From<Ipv6Addr> for IpAddr { +    /// Copies this address to a new `IpAddr::V6`. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv6Addr}; +    /// +    /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); +    /// +    /// assert_eq!( +    ///     IpAddr::V6(addr), +    ///     IpAddr::from(addr) +    /// ); +    /// ``` +    #[inline] +    fn from(ipv6: Ipv6Addr) -> IpAddr { +        IpAddr::V6(ipv6) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialEq<Ipv4Addr> for IpAddr { +    #[inline] +    fn eq(&self, other: &Ipv4Addr) -> bool { +        match self { +            IpAddr::V4(v4) => v4 == other, +            IpAddr::V6(_) => false, +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialEq<IpAddr> for Ipv4Addr { +    #[inline] +    fn eq(&self, other: &IpAddr) -> bool { +        match other { +            IpAddr::V4(v4) => self == v4, +            IpAddr::V6(_) => false, +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl PartialOrd for Ipv4Addr { +    #[inline] +    fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { +        Some(self.cmp(other)) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialOrd<Ipv4Addr> for IpAddr { +    #[inline] +    fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { +        match self { +            IpAddr::V4(v4) => v4.partial_cmp(other), +            IpAddr::V6(_) => Some(Ordering::Greater), +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialOrd<IpAddr> for Ipv4Addr { +    #[inline] +    fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> { +        match other { +            IpAddr::V4(v4) => self.partial_cmp(v4), +            IpAddr::V6(_) => Some(Ordering::Less), +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl Ord for Ipv4Addr { +    #[inline] +    fn cmp(&self, other: &Ipv4Addr) -> Ordering { +        self.octets.cmp(&other.octets) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_u32", since = "1.1.0"))] +impl From<Ipv4Addr> for u32 { +    /// Converts an `Ipv4Addr` into a host byte order `u32`. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); +    /// assert_eq!(0x12345678, u32::from(addr)); +    /// ``` +    #[inline] +    fn from(ip: Ipv4Addr) -> u32 { +        u32::from_be_bytes(ip.octets) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_u32", since = "1.1.0"))] +impl From<u32> for Ipv4Addr { +    /// Converts a host byte order `u32` into an `Ipv4Addr`. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// let addr = Ipv4Addr::from(0x12345678); +    /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr); +    /// ``` +    #[inline] +    fn from(ip: u32) -> Ipv4Addr { +        Ipv4Addr { +            octets: ip.to_be_bytes(), +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "from_slice_v4", since = "1.9.0"))] +impl From<[u8; 4]> for Ipv4Addr { +    /// Creates an `Ipv4Addr` from a four element byte array. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv4Addr; +    /// +    /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]); +    /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); +    /// ``` +    #[inline] +    fn from(octets: [u8; 4]) -> Ipv4Addr { +        Ipv4Addr { octets } +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] +impl From<[u8; 4]> for IpAddr { +    /// Creates an `IpAddr::V4` from a four element byte array. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr}; +    /// +    /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]); +    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr); +    /// ``` +    #[inline] +    fn from(octets: [u8; 4]) -> IpAddr { +        IpAddr::V4(Ipv4Addr::from(octets)) +    } +} + +impl Ipv6Addr { +    /// Creates a new IPv6 address from eight 16-bit segments. +    /// +    /// The result will represent the IP address `a:b:c:d:e:f:g:h`. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_32", since = "1.32.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[allow(clippy::too_many_arguments)] +    #[must_use] +    #[inline] +    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { +        let addr16 = [ +            a.to_be(), +            b.to_be(), +            c.to_be(), +            d.to_be(), +            e.to_be(), +            f.to_be(), +            g.to_be(), +            h.to_be(), +        ]; +        Ipv6Addr { +            // All elements in `addr16` are big endian. +            // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`. +            octets: unsafe { transmute::<_, [u8; 16]>(addr16) }, +        } +    } + +    /// An IPv6 address representing localhost: `::1`. +    /// +    /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other +    /// languages. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// let addr = Ipv6Addr::LOCALHOST; +    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); +    /// ``` +    #[doc(alias = "IN6ADDR_LOOPBACK_INIT")] +    #[doc(alias = "in6addr_loopback")] +    #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] +    pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); + +    /// An IPv6 address representing the unspecified address: `::` +    /// +    /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// let addr = Ipv6Addr::UNSPECIFIED; +    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); +    /// ``` +    #[doc(alias = "IN6ADDR_ANY_INIT")] +    #[doc(alias = "in6addr_any")] +    #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] +    pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); + +    /// Returns the eight 16-bit segments that make up this address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), +    ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[must_use] +    #[inline] +    pub const fn segments(&self) -> [u16; 8] { +        // All elements in `self.octets` must be big endian. +        // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`. +        let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) }; +        // We want native endian u16 +        [ +            u16::from_be(a), +            u16::from_be(b), +            u16::from_be(c), +            u16::from_be(d), +            u16::from_be(e), +            u16::from_be(f), +            u16::from_be(g), +            u16::from_be(h), +        ] +    } + +    /// Returns [`true`] for the special 'unspecified' address (`::`). +    /// +    /// This property is defined in [IETF RFC 4291]. +    /// +    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_unspecified(&self) -> bool { +        u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets()) +    } + +    /// Returns [`true`] if this is the [loopback address] (`::1`), +    /// as defined in [IETF RFC 4291 section 2.5.3]. +    /// +    /// Contrary to IPv4, in IPv6 there is only one loopback address. +    /// +    /// [loopback address]: Ipv6Addr::LOCALHOST +    /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_loopback(&self) -> bool { +        u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) +    } + +    /// Returns [`true`] if the address appears to be globally reachable +    /// as specified by the [IANA IPv6 Special-Purpose Address Registry]. +    /// Whether or not an address is practically reachable will depend on your network configuration. +    /// +    /// Most IPv6 addresses are globally reachable; +    /// unless they are specifically defined as *not* globally reachable. +    /// +    /// Non-exhaustive list of notable addresses that are not globally reachable: +    /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified)) +    /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback)) +    /// - IPv4-mapped addresses +    /// - Addresses reserved for benchmarking +    /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation)) +    /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local)) +    /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local)) +    /// +    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry]. +    /// +    /// Note that an address having global scope is not the same as being globally reachable, +    /// and there is no direct relation between the two concepts: There exist addresses with global scope +    /// that are not globally reachable (for example unique local addresses), +    /// and addresses that are globally reachable without having global scope +    /// (multicast addresses with non-global scope). +    /// +    /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml +    /// [unspecified address]: Ipv6Addr::UNSPECIFIED +    /// [loopback address]: Ipv6Addr::LOCALHOST +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::Ipv6Addr; +    /// +    /// // Most IPv6 addresses are globally reachable: +    /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true); +    /// +    /// // However some addresses have been assigned a special meaning +    /// // that makes them not globally reachable. Some examples are: +    /// +    /// // The unspecified address (`::`) +    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false); +    /// +    /// // The loopback address (`::1`) +    /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false); +    /// +    /// // IPv4-mapped addresses (`::ffff:0:0/96`) +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false); +    /// +    /// // Addresses reserved for benchmarking (`2001:2::/48`) +    /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false); +    /// +    /// // Addresses reserved for documentation (`2001:db8::/32`) +    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false); +    /// +    /// // Unique local addresses (`fc00::/7`) +    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false); +    /// +    /// // Unicast addresses with link-local scope (`fe80::/10`) +    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false); +    /// +    /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry. +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_global(&self) -> bool { +        !(self.is_unspecified() +            || self.is_loopback() +            // IPv4-mapped Address (`::ffff:0:0/96`) +            || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) +            // IPv4-IPv6 Translat. (`64:ff9b:1::/48`) +            || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _]) +            // Discard-Only Address Block (`100::/64`) +            || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _]) +            // IETF Protocol Assignments (`2001::/23`) +            || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200) +                && !( +                    // Port Control Protocol Anycast (`2001:1::1`) +                    u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001 +                    // Traversal Using Relays around NAT Anycast (`2001:1::2`) +                    || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002 +                    // AMT (`2001:3::/32`) +                    || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _]) +                    // AS112-v6 (`2001:4:112::/48`) +                    || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _]) +                    // ORCHIDv2 (`2001:20::/28`) +                    || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F) +                )) +            || self.is_documentation() +            || self.is_unique_local() +            || self.is_unicast_link_local()) +    } + +    /// Returns [`true`] if this is a unique local address (`fc00::/7`). +    /// +    /// This property is defined in [IETF RFC 4193]. +    /// +    /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193 +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); +    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_unique_local(&self) -> bool { +        (self.segments()[0] & 0xfe00) == 0xfc00 +    } + +    /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291]. +    /// Any address that is not a [multicast address] (`ff00::/8`) is unicast. +    /// +    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 +    /// [multicast address]: Ipv6Addr::is_multicast +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::Ipv6Addr; +    /// +    /// // The unspecified and loopback addresses are unicast. +    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true); +    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true); +    /// +    /// // Any address that is not a multicast address (`ff00::/8`) is unicast. +    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true); +    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_unicast(&self) -> bool { +        !self.is_multicast() +    } + +    /// Returns `true` if the address is a unicast address with link-local scope, +    /// as defined in [RFC 4291]. +    /// +    /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4]. +    /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6], +    /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format: +    /// +    /// ```text +    /// | 10 bits  |         54 bits         |          64 bits           | +    /// +----------+-------------------------+----------------------------+ +    /// |1111111010|           0             |       interface ID         | +    /// +----------+-------------------------+----------------------------+ +    /// ``` +    /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`, +    /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated, +    /// and those addresses will have link-local scope. +    /// +    /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope", +    /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it. +    /// +    /// [RFC 4291]: https://tools.ietf.org/html/rfc4291 +    /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 +    /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3 +    /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 +    /// [loopback address]: Ipv6Addr::LOCALHOST +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::Ipv6Addr; +    /// +    /// // The loopback address (`::1`) does not actually have link-local scope. +    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false); +    /// +    /// // Only addresses in `fe80::/10` have link-local scope. +    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false); +    /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); +    /// +    /// // Addresses outside the stricter `fe80::/64` also have link-local scope. +    /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true); +    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_unicast_link_local(&self) -> bool { +        (self.segments()[0] & 0xffc0) == 0xfe80 +    } + +    /// Returns [`true`] if this is an address reserved for documentation +    /// (`2001:db8::/32`). +    /// +    /// This property is defined in [IETF RFC 3849]. +    /// +    /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849 +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); +    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_documentation(&self) -> bool { +        (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) +    } + +    /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`). +    /// +    /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`. +    /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`. +    /// +    /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180 +    /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752 +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false); +    /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true); +    /// ``` +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_benchmarking(&self) -> bool { +        (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0) +    } + +    /// Returns [`true`] if the address is a globally routable unicast address. +    /// +    /// The following return false: +    /// +    /// - the loopback address +    /// - the link-local addresses +    /// - unique local addresses +    /// - the unspecified address +    /// - the address range reserved for documentation +    /// +    /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7] +    /// +    /// ```no_rust +    /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer +    /// be supported in new implementations (i.e., new implementations must treat this prefix as +    /// Global Unicast). +    /// ``` +    /// +    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn is_unicast_global(&self) -> bool { +        self.is_unicast() +            && !self.is_loopback() +            && !self.is_unicast_link_local() +            && !self.is_unique_local() +            && !self.is_unspecified() +            && !self.is_documentation() +            && !self.is_benchmarking() +    } + +    /// Returns the address' multicast scope if the address is multicast. +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// +    /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; +    /// +    /// assert_eq!( +    ///     Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), +    ///     Some(Ipv6MulticastScope::Global) +    /// ); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use] +    #[inline] +    pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> { +        if self.is_multicast() { +            match self.segments()[0] & 0x000f { +                1 => Some(Ipv6MulticastScope::InterfaceLocal), +                2 => Some(Ipv6MulticastScope::LinkLocal), +                3 => Some(Ipv6MulticastScope::RealmLocal), +                4 => Some(Ipv6MulticastScope::AdminLocal), +                5 => Some(Ipv6MulticastScope::SiteLocal), +                8 => Some(Ipv6MulticastScope::OrganizationLocal), +                14 => Some(Ipv6MulticastScope::Global), +                _ => None, +            } +        } else { +            None +        } +    } + +    /// Returns [`true`] if this is a multicast address (`ff00::/8`). +    /// +    /// This property is defined by [IETF RFC 4291]. +    /// +    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] +    #[must_use] +    #[inline] +    pub const fn is_multicast(&self) -> bool { +        (self.segments()[0] & 0xff00) == 0xff00 +    } + +    /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address, +    /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`]. +    /// +    /// `::ffff:a.b.c.d` becomes `a.b.c.d`. +    /// All addresses *not* starting with `::ffff` will return `None`. +    /// +    /// [`IPv4` address]: Ipv4Addr +    /// [IPv4-mapped]: Ipv6Addr +    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(), +    ///            Some(Ipv4Addr::new(192, 10, 2, 255))); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0"))] +    #[must_use = "this returns the result of the operation, \ +                  without modifying the original"] +    #[inline] +    pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> { +        match self.octets() { +            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => { +                Some(Ipv4Addr::new(a, b, c, d)) +            } +            _ => None, +        } +    } + +    /// Converts this address to an [`IPv4` address] if it is either +    /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1], +    /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2], +    /// otherwise returns [`None`]. +    /// +    /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use +    /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this. +    /// +    /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`. +    /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`. +    /// +    /// [`IPv4` address]: Ipv4Addr +    /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses +    /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses +    /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1 +    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{Ipv4Addr, Ipv6Addr}; +    /// +    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(), +    ///            Some(Ipv4Addr::new(192, 10, 2, 255))); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), +    ///            Some(Ipv4Addr::new(0, 0, 0, 1))); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_50", since = "1.50.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[must_use = "this returns the result of the operation, \ +                  without modifying the original"] +    #[inline] +    pub const fn to_ipv4(&self) -> Option<Ipv4Addr> { +        if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() { +            let [a, b] = ab.to_be_bytes(); +            let [c, d] = cd.to_be_bytes(); +            Some(Ipv4Addr::new(a, b, c, d)) +        } else { +            None +        } +    } + +    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it +    /// returns self wrapped in an `IpAddr::V6`. +    /// +    /// # Examples +    /// +    /// ``` +    /// #![feature(ip)] +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false); +    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_ipv6", issue = "76205") +    )] +    #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +    #[must_use = "this returns the result of the operation, \ +                  without modifying the original"] +    #[inline] +    pub const fn to_canonical(&self) -> IpAddr { +        if let Some(mapped) = self.to_ipv4_mapped() { +            return IpAddr::V4(mapped); +        } +        IpAddr::V6(*self) +    } + +    /// Returns the sixteen eight-bit integers the IPv6 address consists of. +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(), +    ///            [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +    /// ``` +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "const_ip_32", since = "1.32.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "ipv6_to_octets", since = "1.12.0"))] +    #[must_use] +    #[inline] +    pub const fn octets(&self) -> [u8; 16] { +        self.octets +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialEq<IpAddr> for Ipv6Addr { +    #[inline] +    fn eq(&self, other: &IpAddr) -> bool { +        match other { +            IpAddr::V4(_) => false, +            IpAddr::V6(v6) => self == v6, +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialEq<Ipv6Addr> for IpAddr { +    #[inline] +    fn eq(&self, other: &Ipv6Addr) -> bool { +        match self { +            IpAddr::V4(_) => false, +            IpAddr::V6(v6) => v6 == other, +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl PartialOrd for Ipv6Addr { +    #[inline] +    fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { +        Some(self.cmp(other)) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialOrd<Ipv6Addr> for IpAddr { +    #[inline] +    fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { +        match self { +            IpAddr::V4(_) => Some(Ordering::Less), +            IpAddr::V6(v6) => v6.partial_cmp(other), +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialOrd<IpAddr> for Ipv6Addr { +    #[inline] +    fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> { +        match other { +            IpAddr::V4(_) => Some(Ordering::Greater), +            IpAddr::V6(v6) => self.partial_cmp(v6), +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl Ord for Ipv6Addr { +    #[inline] +    fn cmp(&self, other: &Ipv6Addr) -> Ordering { +        self.segments().cmp(&other.segments()) +    } +} + +#[cfg_attr(staged_api, stable(feature = "i128", since = "1.26.0"))] +impl From<Ipv6Addr> for u128 { +    /// Convert an `Ipv6Addr` into a host byte order `u128`. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// let addr = Ipv6Addr::new( +    ///     0x1020, 0x3040, 0x5060, 0x7080, +    ///     0x90A0, 0xB0C0, 0xD0E0, 0xF00D, +    /// ); +    /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr)); +    /// ``` +    #[inline] +    fn from(ip: Ipv6Addr) -> u128 { +        u128::from_be_bytes(ip.octets) +    } +} +#[cfg_attr(staged_api, stable(feature = "i128", since = "1.26.0"))] +impl From<u128> for Ipv6Addr { +    /// Convert a host byte order `u128` into an `Ipv6Addr`. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128); +    /// assert_eq!( +    ///     Ipv6Addr::new( +    ///         0x1020, 0x3040, 0x5060, 0x7080, +    ///         0x90A0, 0xB0C0, 0xD0E0, 0xF00D, +    ///     ), +    ///     addr); +    /// ``` +    #[inline] +    fn from(ip: u128) -> Ipv6Addr { +        Ipv6Addr::from(ip.to_be_bytes()) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ipv6_from_octets", since = "1.9.0"))] +impl From<[u8; 16]> for Ipv6Addr { +    /// Creates an `Ipv6Addr` from a sixteen element byte array. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// let addr = Ipv6Addr::from([ +    ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, +    ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, +    /// ]); +    /// assert_eq!( +    ///     Ipv6Addr::new( +    ///         0x1918, 0x1716, +    ///         0x1514, 0x1312, +    ///         0x1110, 0x0f0e, +    ///         0x0d0c, 0x0b0a +    ///     ), +    ///     addr +    /// ); +    /// ``` +    #[inline] +    fn from(octets: [u8; 16]) -> Ipv6Addr { +        Ipv6Addr { octets } +    } +} + +#[cfg_attr(staged_api, stable(feature = "ipv6_from_segments", since = "1.16.0"))] +impl From<[u16; 8]> for Ipv6Addr { +    /// Creates an `Ipv6Addr` from an eight element 16-bit array. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::Ipv6Addr; +    /// +    /// let addr = Ipv6Addr::from([ +    ///     525u16, 524u16, 523u16, 522u16, +    ///     521u16, 520u16, 519u16, 518u16, +    /// ]); +    /// assert_eq!( +    ///     Ipv6Addr::new( +    ///         0x20d, 0x20c, +    ///         0x20b, 0x20a, +    ///         0x209, 0x208, +    ///         0x207, 0x206 +    ///     ), +    ///     addr +    /// ); +    /// ``` +    #[inline] +    fn from(segments: [u16; 8]) -> Ipv6Addr { +        let [a, b, c, d, e, f, g, h] = segments; +        Ipv6Addr::new(a, b, c, d, e, f, g, h) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] +impl From<[u8; 16]> for IpAddr { +    /// Creates an `IpAddr::V6` from a sixteen element byte array. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv6Addr}; +    /// +    /// let addr = IpAddr::from([ +    ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, +    ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, +    /// ]); +    /// assert_eq!( +    ///     IpAddr::V6(Ipv6Addr::new( +    ///         0x1918, 0x1716, +    ///         0x1514, 0x1312, +    ///         0x1110, 0x0f0e, +    ///         0x0d0c, 0x0b0a +    ///     )), +    ///     addr +    /// ); +    /// ``` +    #[inline] +    fn from(octets: [u8; 16]) -> IpAddr { +        IpAddr::V6(Ipv6Addr::from(octets)) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] +impl From<[u16; 8]> for IpAddr { +    /// Creates an `IpAddr::V6` from an eight element 16-bit array. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv6Addr}; +    /// +    /// let addr = IpAddr::from([ +    ///     525u16, 524u16, 523u16, 522u16, +    ///     521u16, 520u16, 519u16, 518u16, +    /// ]); +    /// assert_eq!( +    ///     IpAddr::V6(Ipv6Addr::new( +    ///         0x20d, 0x20c, +    ///         0x20b, 0x20a, +    ///         0x209, 0x208, +    ///         0x207, 0x206 +    ///     )), +    ///     addr +    /// ); +    /// ``` +    #[inline] +    fn from(segments: [u16; 8]) -> IpAddr { +        IpAddr::V6(Ipv6Addr::from(segments)) +    } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/net/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/net/mod.rs new file mode 100644 index 0000000..06e8f94 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/net/mod.rs @@ -0,0 +1,6 @@ +mod ip_addr; +mod socket_addr; + +#[allow(unused_imports)] +pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; +pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6}; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/net/socket_addr.rs b/vendor/rustix/src/maybe_polyfill/no_std/net/socket_addr.rs new file mode 100644 index 0000000..053d8f6 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/net/socket_addr.rs @@ -0,0 +1,641 @@ +//! The following is derived from Rust's +//! library/std/src/net/socket_addr.rs at revision +//! bd20fc1fd657b32f7aa1d70d8723f04c87f21606. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! This defines `SocketAddr`, `SocketAddrV4`, and `SocketAddrV6` in a +//! platform-independent way. It is not the native representation. + +use super::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr}; +use core::cmp::Ordering; +use core::hash; + +/// An internet socket address, either IPv4 or IPv6. +/// +/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well +/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and +/// [`SocketAddrV6`]'s respective documentation for more details. +/// +/// The size of a `SocketAddr` instance may vary depending on the target operating +/// system. +/// +/// [IP address]: IpAddr +/// +/// # Examples +/// +/// ``` +/// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +/// +/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +/// +/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); +/// assert_eq!(socket.port(), 8080); +/// assert_eq!(socket.is_ipv4(), true); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub enum SocketAddr { +    /// An IPv4 socket address. +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    V4(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] SocketAddrV4), +    /// An IPv6 socket address. +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    V6(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] SocketAddrV6), +} + +/// An IPv4 socket address. +/// +/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as +/// stated in [IETF RFC 793]. +/// +/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. +/// +/// The size of a `SocketAddrV4` struct may vary depending on the target operating +/// system. Do not assume that this type has the same memory layout as the underlying +/// system representation. +/// +/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 +/// [`IPv4` address]: Ipv4Addr +/// +/// # Examples +/// +/// ``` +/// use std::net::{Ipv4Addr, SocketAddrV4}; +/// +/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); +/// +/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); +/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); +/// assert_eq!(socket.port(), 8080); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub struct SocketAddrV4 { +    ip: Ipv4Addr, +    port: u16, +} + +/// An IPv6 socket address. +/// +/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well +/// as fields containing the traffic class, the flow label, and a scope identifier +/// (see [IETF RFC 2553, Section 3.3] for more details). +/// +/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. +/// +/// The size of a `SocketAddrV6` struct may vary depending on the target operating +/// system. Do not assume that this type has the same memory layout as the underlying +/// system representation. +/// +/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 +/// [`IPv6` address]: Ipv6Addr +/// +/// # Examples +/// +/// ``` +/// use std::net::{Ipv6Addr, SocketAddrV6}; +/// +/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); +/// +/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket)); +/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); +/// assert_eq!(socket.port(), 8080); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub struct SocketAddrV6 { +    ip: Ipv6Addr, +    port: u16, +    flowinfo: u32, +    scope_id: u32, +} + +impl SocketAddr { +    /// Creates a new socket address from an [IP address] and a port number. +    /// +    /// [IP address]: IpAddr +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +    /// +    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); +    /// assert_eq!(socket.port(), 8080); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] +    #[must_use] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn new(ip: IpAddr, port: u16) -> SocketAddr { +        match ip { +            IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), +            IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)), +        } +    } + +    /// Returns the IP address associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +    /// +    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn ip(&self) -> IpAddr { +        match *self { +            SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), +            SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), +        } +    } + +    /// Changes the IP address associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +    /// +    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +    /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); +    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] +    pub fn set_ip(&mut self, new_ip: IpAddr) { +        // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. +        match (self, new_ip) { +            (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip), +            (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip), +            (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()), +        } +    } + +    /// Returns the port number associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +    /// +    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +    /// assert_eq!(socket.port(), 8080); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn port(&self) -> u16 { +        match *self { +            SocketAddr::V4(ref a) => a.port(), +            SocketAddr::V6(ref a) => a.port(), +        } +    } + +    /// Changes the port number associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +    /// +    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +    /// socket.set_port(1025); +    /// assert_eq!(socket.port(), 1025); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] +    pub fn set_port(&mut self, new_port: u16) { +        match *self { +            SocketAddr::V4(ref mut a) => a.set_port(new_port), +            SocketAddr::V6(ref mut a) => a.set_port(new_port), +        } +    } + +    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an +    /// [`IPv4` address], and [`false`] otherwise. +    /// +    /// [IP address]: IpAddr +    /// [`IPv4` address]: IpAddr::V4 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +    /// +    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +    /// assert_eq!(socket.is_ipv4(), true); +    /// assert_eq!(socket.is_ipv6(), false); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "sockaddr_checker", since = "1.16.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn is_ipv4(&self) -> bool { +        matches!(*self, SocketAddr::V4(_)) +    } + +    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an +    /// [`IPv6` address], and [`false`] otherwise. +    /// +    /// [IP address]: IpAddr +    /// [`IPv6` address]: IpAddr::V6 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; +    /// +    /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); +    /// assert_eq!(socket.is_ipv4(), false); +    /// assert_eq!(socket.is_ipv6(), true); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "sockaddr_checker", since = "1.16.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn is_ipv6(&self) -> bool { +        matches!(*self, SocketAddr::V6(_)) +    } +} + +impl SocketAddrV4 { +    /// Creates a new socket address from an [`IPv4` address] and a port number. +    /// +    /// [`IPv4` address]: Ipv4Addr +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV4, Ipv4Addr}; +    /// +    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[must_use] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { +        SocketAddrV4 { ip, port } +    } + +    /// Returns the IP address associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV4, Ipv4Addr}; +    /// +    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); +    /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn ip(&self) -> &Ipv4Addr { +        &self.ip +    } + +    /// Changes the IP address associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV4, Ipv4Addr}; +    /// +    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); +    /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1)); +    /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1)); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] +    pub fn set_ip(&mut self, new_ip: Ipv4Addr) { +        self.ip = new_ip; +    } + +    /// Returns the port number associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV4, Ipv4Addr}; +    /// +    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); +    /// assert_eq!(socket.port(), 8080); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn port(&self) -> u16 { +        self.port +    } + +    /// Changes the port number associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV4, Ipv4Addr}; +    /// +    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); +    /// socket.set_port(4242); +    /// assert_eq!(socket.port(), 4242); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] +    pub fn set_port(&mut self, new_port: u16) { +        self.port = new_port; +    } +} + +impl SocketAddrV6 { +    /// Creates a new socket address from an [`IPv6` address], a 16-bit port number, +    /// and the `flowinfo` and `scope_id` fields. +    /// +    /// For more information on the meaning and layout of the `flowinfo` and `scope_id` +    /// parameters, see [IETF RFC 2553, Section 3.3]. +    /// +    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 +    /// [`IPv6` address]: Ipv6Addr +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[must_use] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { +        SocketAddrV6 { +            ip, +            port, +            flowinfo, +            scope_id, +        } +    } + +    /// Returns the IP address associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); +    /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn ip(&self) -> &Ipv6Addr { +        &self.ip +    } + +    /// Changes the IP address associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); +    /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); +    /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] +    pub fn set_ip(&mut self, new_ip: Ipv6Addr) { +        self.ip = new_ip; +    } + +    /// Returns the port number associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); +    /// assert_eq!(socket.port(), 8080); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn port(&self) -> u16 { +        self.port +    } + +    /// Changes the port number associated with this socket address. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); +    /// socket.set_port(4242); +    /// assert_eq!(socket.port(), 4242); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] +    pub fn set_port(&mut self, new_port: u16) { +        self.port = new_port; +    } + +    /// Returns the flow information associated with this address. +    /// +    /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`, +    /// as specified in [IETF RFC 2553, Section 3.3]. +    /// It combines information about the flow label and the traffic class as specified +    /// in [IETF RFC 2460], respectively [Section 6] and [Section 7]. +    /// +    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 +    /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460 +    /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6 +    /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); +    /// assert_eq!(socket.flowinfo(), 10); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn flowinfo(&self) -> u32 { +        self.flowinfo +    } + +    /// Changes the flow information associated with this socket address. +    /// +    /// See [`SocketAddrV6::flowinfo`]'s documentation for more details. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); +    /// socket.set_flowinfo(56); +    /// assert_eq!(socket.flowinfo(), 56); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] +    pub fn set_flowinfo(&mut self, new_flowinfo: u32) { +        self.flowinfo = new_flowinfo; +    } + +    /// Returns the scope ID associated with this address. +    /// +    /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`, +    /// as specified in [IETF RFC 2553, Section 3.3]. +    /// +    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); +    /// assert_eq!(socket.scope_id(), 78); +    /// ``` +    #[must_use] +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    #[cfg_attr( +        staged_api, +        rustc_const_unstable(feature = "const_socketaddr", issue = "82485") +    )] +    pub const fn scope_id(&self) -> u32 { +        self.scope_id +    } + +    /// Changes the scope ID associated with this socket address. +    /// +    /// See [`SocketAddrV6::scope_id`]'s documentation for more details. +    /// +    /// # Examples +    /// +    /// ``` +    /// use std::net::{SocketAddrV6, Ipv6Addr}; +    /// +    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); +    /// socket.set_scope_id(42); +    /// assert_eq!(socket.scope_id(), 42); +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] +    pub fn set_scope_id(&mut self, new_scope_id: u32) { +        self.scope_id = new_scope_id; +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] +impl From<SocketAddrV4> for SocketAddr { +    /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`]. +    fn from(sock4: SocketAddrV4) -> SocketAddr { +        SocketAddr::V4(sock4) +    } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] +impl From<SocketAddrV6> for SocketAddr { +    /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`]. +    fn from(sock6: SocketAddrV6) -> SocketAddr { +        SocketAddr::V6(sock6) +    } +} + +#[cfg_attr(staged_api, stable(feature = "addr_from_into_ip", since = "1.17.0"))] +impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr { +    /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`]. +    /// +    /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`] +    /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`]. +    /// +    /// `u16` is treated as port of the newly created [`SocketAddr`]. +    fn from(pieces: (I, u16)) -> SocketAddr { +        SocketAddr::new(pieces.0.into(), pieces.1) +    } +} + +#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] +impl PartialOrd for SocketAddrV4 { +    fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> { +        Some(self.cmp(other)) +    } +} + +#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] +impl PartialOrd for SocketAddrV6 { +    fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> { +        Some(self.cmp(other)) +    } +} + +#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] +impl Ord for SocketAddrV4 { +    fn cmp(&self, other: &SocketAddrV4) -> Ordering { +        self.ip() +            .cmp(other.ip()) +            .then(self.port().cmp(&other.port())) +    } +} + +#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] +impl Ord for SocketAddrV6 { +    fn cmp(&self, other: &SocketAddrV6) -> Ordering { +        self.ip() +            .cmp(other.ip()) +            .then(self.port().cmp(&other.port())) +    } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl hash::Hash for SocketAddrV4 { +    fn hash<H: hash::Hasher>(&self, s: &mut H) { +        (self.port, self.ip).hash(s) +    } +} +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl hash::Hash for SocketAddrV6 { +    fn hash<H: hash::Hasher>(&self, s: &mut H) { +        (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s) +    } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/fd/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/mod.rs new file mode 100644 index 0000000..ea55953 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/mod.rs @@ -0,0 +1,25 @@ +//! The following is derived from Rust's +//! library/std/src/os/fd/mod.rs at revision +//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! Owned and borrowed Unix-like file descriptors. +//! +//! This module is supported on Unix platforms and WASI, which both use a +//! similar file descriptor system for referencing OS resources. + +#![cfg_attr(staged_api, stable(feature = "os_fd", since = "1.66.0"))] +#![deny(unsafe_op_in_unsafe_fn)] + +// `RawFd`, `AsRawFd`, etc. +mod raw; + +// `OwnedFd`, `AsFd`, etc. +mod owned; + +// Export the types and traits for the public API. +#[cfg_attr(staged_api, stable(feature = "os_fd", since = "1.66.0"))] +pub use owned::*; +#[cfg_attr(staged_api, stable(feature = "os_fd", since = "1.66.0"))] +pub use raw::*; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/fd/owned.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/owned.rs new file mode 100644 index 0000000..d765c1d --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/owned.rs @@ -0,0 +1,294 @@ +//! The following is derived from Rust's +//! library/std/src/os/fd/owned.rs at revision +//! 334a54cd83191f38ad8046ed94c45de735c86c65. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! Owned and borrowed Unix-like file descriptors. + +#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +#![deny(unsafe_op_in_unsafe_fn)] +#![allow(unsafe_code)] + +use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use crate::io::close; +use core::fmt; +use core::marker::PhantomData; +use core::mem::forget; + +/// A borrowed file descriptor. +/// +/// This has a lifetime parameter to tie it to the lifetime of something that owns the file +/// descriptor. For the duration of that lifetime, it is guaranteed that nobody will close the file +/// descriptor. +/// +/// This uses `repr(transparent)` and has the representation of a host file +/// descriptor, so it can be used in FFI in places where a file descriptor is +/// passed as an argument, it is not captured or consumed, and it never has the +/// value `-1`. +/// +/// This type's `.to_owned()` implementation returns another `BorrowedFd` +/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file +/// descriptor, which is then borrowed under the same lifetime. +#[derive(Copy, Clone)] +#[repr(transparent)] +#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))] +// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a +// 32-bit c_int. Below is -2, in two's complement, but that only works out +// because c_int is 32 bits. +#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))] +#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)] +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +pub struct BorrowedFd<'fd> { +    fd: RawFd, +    _phantom: PhantomData<&'fd OwnedFd>, +} + +/// An owned file descriptor. +/// +/// This closes the file descriptor on drop. It is guaranteed that nobody else will close the file +/// descriptor. +/// +/// This uses `repr(transparent)` and has the representation of a host file +/// descriptor, so it can be used in FFI in places where a file descriptor is +/// passed as a consumed argument or returned as an owned value, and it never +/// has the value `-1`. +#[repr(transparent)] +#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))] +// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a +// 32-bit c_int. Below is -2, in two's complement, but that only works out +// because c_int is 32 bits. +#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))] +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)] +pub struct OwnedFd { +    fd: RawFd, +} + +impl BorrowedFd<'_> { +    /// Return a `BorrowedFd` holding the given raw file descriptor. +    /// +    /// # Safety +    /// +    /// The resource pointed to by `fd` must remain open for the duration of +    /// the returned `BorrowedFd`, and it must not have the value `-1`. +    #[inline] +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "io_safety", since = "1.63.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +    pub const unsafe fn borrow_raw(fd: RawFd) -> Self { +        assert!(fd != u32::MAX as RawFd); +        // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) +        #[allow(unused_unsafe)] +        unsafe { +            Self { +                fd, +                _phantom: PhantomData, +            } +        } +    } +} + +impl OwnedFd { +    /// Creates a new `OwnedFd` instance that shares the same underlying file handle +    /// as the existing `OwnedFd` instance. +    #[cfg(not(target_arch = "wasm32"))] +    pub fn try_clone(&self) -> crate::io::Result<Self> { +        // We want to atomically duplicate this file descriptor and set the +        // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This +        // is a POSIX flag that was added to Linux in 2.6.24. +        #[cfg(not(target_os = "espidf"))] +        let fd = crate::io::fcntl_dupfd_cloexec(self, 0)?; + +        // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics +        // will never be supported, as this is a bare metal framework with +        // no capabilities for multi-process execution. While F_DUPFD is also +        // not supported yet, it might be (currently it returns ENOSYS). +        #[cfg(target_os = "espidf")] +        let fd = crate::io::fcntl_dupfd(self)?; + +        Ok(fd.into()) +    } + +    /// Creates a new `OwnedFd` instance that shares the same underlying file handle +    /// as the existing `OwnedFd` instance. +    #[cfg(target_arch = "wasm32")] +    pub fn try_clone(&self) -> crate::io::Result<Self> { +        Err(crate::io::Errno::NOSYS) +    } +} + +impl BorrowedFd<'_> { +    /// Creates a new `OwnedFd` instance that shares the same underlying file +    /// description as the existing `BorrowedFd` instance. +    #[cfg(not(any(target_arch = "wasm32", target_os = "hermit")))] +    #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +    pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> { +        // Avoid using file descriptors below 3 as they are used for stdio + +        // We want to atomically duplicate this file descriptor and set the +        // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This +        // is a POSIX flag that was added to Linux in 2.6.24. +        #[cfg(not(target_os = "espidf"))] +        let fd = crate::io::fcntl_dupfd_cloexec(self, 3)?; + +        // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics +        // will never be supported, as this is a bare metal framework with +        // no capabilities for multi-process execution. While F_DUPFD is also +        // not supported yet, it might be (currently it returns ENOSYS). +        #[cfg(target_os = "espidf")] +        let fd = crate::io::fcntl_dupfd(self, 3)?; + +        Ok(fd) +    } + +    /// Creates a new `OwnedFd` instance that shares the same underlying file +    /// description as the existing `BorrowedFd` instance. +    #[cfg(any(target_arch = "wasm32", target_os = "hermit"))] +    #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +    pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> { +        Err(crate::io::Errno::NOSYS) +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsRawFd for BorrowedFd<'_> { +    #[inline] +    fn as_raw_fd(&self) -> RawFd { +        self.fd +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsRawFd for OwnedFd { +    #[inline] +    fn as_raw_fd(&self) -> RawFd { +        self.fd +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl IntoRawFd for OwnedFd { +    #[inline] +    fn into_raw_fd(self) -> RawFd { +        let fd = self.fd; +        forget(self); +        fd +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl FromRawFd for OwnedFd { +    /// Constructs a new instance of `Self` from the given raw file descriptor. +    /// +    /// # Safety +    /// +    /// The resource pointed to by `fd` must be open and suitable for assuming +    /// [ownership][io-safety]. The resource must not require any cleanup other than `close`. +    /// +    /// [io-safety]: io#io-safety +    #[inline] +    unsafe fn from_raw_fd(fd: RawFd) -> Self { +        assert_ne!(fd, u32::MAX as RawFd); +        // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) +        #[allow(unused_unsafe)] +        unsafe { +            Self { fd } +        } +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl Drop for OwnedFd { +    #[inline] +    fn drop(&mut self) { +        unsafe { +            // Errors are ignored when closing a file descriptor. The reason +            // for this is that if an error occurs we don't actually know if +            // the file descriptor was closed or not, and if we retried (for +            // something like EINTR), we might close another valid file +            // descriptor opened after we closed ours. +            close(self.fd as _); +        } +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl fmt::Debug for BorrowedFd<'_> { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        f.debug_struct("BorrowedFd").field("fd", &self.fd).finish() +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl fmt::Debug for OwnedFd { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        f.debug_struct("OwnedFd").field("fd", &self.fd).finish() +    } +} + +/// A trait to borrow the file descriptor from an underlying object. +/// +/// This is only available on unix platforms and must be imported in order to +/// call the method. Windows platforms have a corresponding `AsHandle` and +/// `AsSocket` set of traits. +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +pub trait AsFd { +    /// Borrows the file descriptor. +    /// +    /// # Example +    /// +    /// ```no_run +    /// # #![feature(io_safety)] +    /// use std::fs::File; +    /// # use std::io; +    /// # #[cfg(target_os = "wasi")] +    /// # use std::os::wasi::io::{AsFd, BorrowedFd}; +    /// # #[cfg(unix)] +    /// # use std::os::unix::io::{AsFd, BorrowedFd}; +    /// +    /// let mut f = File::open("foo.txt")?; +    /// # #[cfg(any(unix, target_os = "wasi"))] +    /// let borrowed_fd: BorrowedFd<'_> = f.as_fd(); +    /// # Ok::<(), io::Error>(()) +    /// ``` +    #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +    fn as_fd(&self) -> BorrowedFd<'_>; +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl<T: AsFd> AsFd for &T { +    #[inline] +    fn as_fd(&self) -> BorrowedFd<'_> { +        T::as_fd(self) +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl<T: AsFd> AsFd for &mut T { +    #[inline] +    fn as_fd(&self) -> BorrowedFd<'_> { +        T::as_fd(self) +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsFd for BorrowedFd<'_> { +    #[inline] +    fn as_fd(&self) -> BorrowedFd<'_> { +        *self +    } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsFd for OwnedFd { +    #[inline] +    fn as_fd(&self) -> BorrowedFd<'_> { +        // SAFETY: `OwnedFd` and `BorrowedFd` have the same validity +        // invariants, and the `BorrowedFd` is bounded by the lifetime +        // of `&self`. +        unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } +    } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/fd/raw.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/raw.rs new file mode 100644 index 0000000..8f6b75a --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/raw.rs @@ -0,0 +1,164 @@ +//! The following is derived from Rust's +//! library/std/src/os/fd/raw.rs at revision +//! 334a54cd83191f38ad8046ed94c45de735c86c65. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! Raw Unix-like file descriptors. + +#![cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +#![allow(unsafe_code)] + +use crate::backend::c; + +/// Raw file descriptors. +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub type RawFd = c::c_int; + +/// A trait to extract the raw file descriptor from an underlying object. +/// +/// This is only available on unix and WASI platforms and must be imported in +/// order to call the method. Windows platforms have a corresponding +/// `AsRawHandle` and `AsRawSocket` set of traits. +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub trait AsRawFd { +    /// Extracts the raw file descriptor. +    /// +    /// This function is typically used to **borrow** an owned file descriptor. +    /// When used in this way, this method does **not** pass ownership of the +    /// raw file descriptor to the caller, and the file descriptor is only +    /// guaranteed to be valid while the original object has not yet been +    /// destroyed. +    /// +    /// However, borrowing is not strictly required. See [`AsFd::as_fd`] +    /// for an API which strictly borrows a file descriptor. +    /// +    /// # Example +    /// +    /// ```no_run +    /// use std::fs::File; +    /// # use std::io; +    /// #[cfg(unix)] +    /// use std::os::unix::io::{AsRawFd, RawFd}; +    /// #[cfg(target_os = "wasi")] +    /// use std::os::wasi::io::{AsRawFd, RawFd}; +    /// +    /// let mut f = File::open("foo.txt")?; +    /// // `raw_fd` is only valid as long as `f` exists. +    /// #[cfg(any(unix, target_os = "wasi"))] +    /// let raw_fd: RawFd = f.as_raw_fd(); +    /// # Ok::<(), io::Error>(()) +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    fn as_raw_fd(&self) -> RawFd; +} + +/// A trait to express the ability to construct an object from a raw file +/// descriptor. +#[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] +pub trait FromRawFd { +    /// Constructs a new instance of `Self` from the given raw file +    /// descriptor. +    /// +    /// This function is typically used to **consume ownership** of the +    /// specified file descriptor. When used in this way, the returned object +    /// will take responsibility for closing it when the object goes out of +    /// scope. +    /// +    /// However, consuming ownership is not strictly required. Use a +    /// [`From<OwnedFd>::from`] implementation for an API which strictly +    /// consumes ownership. +    /// +    /// # Safety +    /// +    /// The `fd` passed in must be an [owned file descriptor][io-safety]; +    /// in particular, it must be open. +    /// +    /// [io-safety]: io#io-safety +    /// +    /// # Example +    /// +    /// ```no_run +    /// use std::fs::File; +    /// # use std::io; +    /// #[cfg(unix)] +    /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; +    /// #[cfg(target_os = "wasi")] +    /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd}; +    /// +    /// let f = File::open("foo.txt")?; +    /// # #[cfg(any(unix, target_os = "wasi"))] +    /// let raw_fd: RawFd = f.into_raw_fd(); +    /// // SAFETY: no other functions should call `from_raw_fd`, so there +    /// // is only one owner for the file descriptor. +    /// # #[cfg(any(unix, target_os = "wasi"))] +    /// let f = unsafe { File::from_raw_fd(raw_fd) }; +    /// # Ok::<(), io::Error>(()) +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] +    unsafe fn from_raw_fd(fd: RawFd) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw file descriptor. +#[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] +pub trait IntoRawFd { +    /// Consumes this object, returning the raw underlying file descriptor. +    /// +    /// This function is typically used to **transfer ownership** of the underlying +    /// file descriptor to the caller. When used in this way, callers are then the unique +    /// owners of the file descriptor and must close it once it's no longer needed. +    /// +    /// However, transferring ownership is not strictly required. Use a +    /// [`Into<OwnedFd>::into`] implementation for an API which strictly +    /// transfers ownership. +    /// +    /// # Example +    /// +    /// ```no_run +    /// use std::fs::File; +    /// # use std::io; +    /// #[cfg(unix)] +    /// use std::os::unix::io::{IntoRawFd, RawFd}; +    /// #[cfg(target_os = "wasi")] +    /// use std::os::wasi::io::{IntoRawFd, RawFd}; +    /// +    /// let f = File::open("foo.txt")?; +    /// #[cfg(any(unix, target_os = "wasi"))] +    /// let raw_fd: RawFd = f.into_raw_fd(); +    /// # Ok::<(), io::Error>(()) +    /// ``` +    #[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] +    fn into_raw_fd(self) -> RawFd; +} + +#[cfg_attr( +    staged_api, +    stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") +)] +impl AsRawFd for RawFd { +    #[inline] +    fn as_raw_fd(&self) -> RawFd { +        *self +    } +} +#[cfg_attr( +    staged_api, +    stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") +)] +impl IntoRawFd for RawFd { +    #[inline] +    fn into_raw_fd(self) -> RawFd { +        self +    } +} +#[cfg_attr( +    staged_api, +    stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") +)] +impl FromRawFd for RawFd { +    #[inline] +    unsafe fn from_raw_fd(fd: RawFd) -> RawFd { +        fd +    } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/mod.rs new file mode 100644 index 0000000..67f41f5 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/mod.rs @@ -0,0 +1,4 @@ +#[cfg(any(unix, target_os = "wasi"))] +pub mod fd; +#[cfg(windows)] +pub mod windows; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/mod.rs new file mode 100644 index 0000000..77abd03 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/mod.rs @@ -0,0 +1,5 @@ +mod raw; +mod socket; + +pub use raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; +pub use socket::{AsSocket, BorrowedSocket, OwnedSocket}; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/raw.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/raw.rs new file mode 100644 index 0000000..1e73e00 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/raw.rs @@ -0,0 +1,71 @@ +//! The following is derived from Rust's +//! library/std/src/os/windows/io/raw.rs +//! at revision +//! 4f9b394c8a24803e57ba892fa00e539742ebafc0. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. + +use super::super::raw; + +/// Raw SOCKETs. +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub type RawSocket = raw::SOCKET; + +/// Extracts raw sockets. +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub trait AsRawSocket { +    /// Extracts the raw socket. +    /// +    /// This function is typically used to **borrow** an owned socket. +    /// When used in this way, this method does **not** pass ownership of the +    /// raw socket to the caller, and the socket is only guaranteed +    /// to be valid while the original object has not yet been destroyed. +    /// +    /// However, borrowing is not strictly required. See [`AsSocket::as_socket`] +    /// for an API which strictly borrows a socket. +    #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +    fn as_raw_socket(&self) -> RawSocket; +} + +/// Creates I/O objects from raw sockets. +#[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] +pub trait FromRawSocket { +    /// Constructs a new I/O object from the specified raw socket. +    /// +    /// This function is typically used to **consume ownership** of the socket +    /// given, passing responsibility for closing the socket to the returned +    /// object. When used in this way, the returned object +    /// will take responsibility for closing it when the object goes out of +    /// scope. +    /// +    /// However, consuming ownership is not strictly required. Use a +    /// `From<OwnedSocket>::from` implementation for an API which strictly +    /// consumes ownership. +    /// +    /// # Safety +    /// +    /// The `socket` passed in must: +    ///   - be a valid an open socket, +    ///   - be a socket that may be freed via [`closesocket`]. +    /// +    /// [`closesocket`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket +    #[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] +    unsafe fn from_raw_socket(sock: RawSocket) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw `SOCKET`. +#[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] +pub trait IntoRawSocket { +    /// Consumes this object, returning the raw underlying socket. +    /// +    /// This function is typically used to **transfer ownership** of the underlying +    /// socket to the caller. When used in this way, callers are then the unique +    /// owners of the socket and must close it once it's no longer needed. +    /// +    /// However, transferring ownership is not strictly required. Use a +    /// `Into<OwnedSocket>::into` implementation for an API which strictly +    /// transfers ownership. +    #[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] +    fn into_raw_socket(self) -> RawSocket; +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/socket.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/socket.rs new file mode 100644 index 0000000..bc637aa --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/socket.rs @@ -0,0 +1,199 @@ +//! The following is derived from Rust's +//! library/std/src/os/windows/io/socket.rs +//! at revision +//! 4f9b394c8a24803e57ba892fa00e539742ebafc0. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. + +use super::raw::*; +use crate::backend::c; +use crate::backend::fd::LibcFd as LibcSocket; +use core::fmt; +use core::marker::PhantomData; +use core::mem::forget; + +/// A borrowed socket. +/// +/// This has a lifetime parameter to tie it to the lifetime of something that +/// owns the socket. +/// +/// This uses `repr(transparent)` and has the representation of a host socket, +/// so it can be used in FFI in places where a socket is passed as an argument, +/// it is not captured or consumed, and it never has the value +/// `INVALID_SOCKET`. +/// +/// This type's `.to_owned()` implementation returns another `BorrowedSocket` +/// rather than an `OwnedSocket`. It just makes a trivial copy of the raw +/// socket, which is then borrowed under the same lifetime. +#[derive(Copy, Clone)] +#[repr(transparent)] +#[cfg_attr(staged_api, rustc_layout_scalar_valid_range_start(0))] +// This is -2, in two's complement. -1 is `INVALID_SOCKET`. +#[cfg_attr( +    all(staged_api, target_pointer_width = "32"), +    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE) +)] +#[cfg_attr( +    all(staged_api, target_pointer_width = "64"), +    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE) +)] +#[cfg_attr(staged_api, rustc_nonnull_optimization_guaranteed)] +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +pub struct BorrowedSocket<'socket> { +    socket: RawSocket, +    _phantom: PhantomData<&'socket OwnedSocket>, +} + +/// An owned socket. +/// +/// This closes the socket on drop. +/// +/// This uses `repr(transparent)` and has the representation of a host socket, +/// so it can be used in FFI in places where a socket is passed as a consumed +/// argument or returned as an owned value, and it never has the value +/// `INVALID_SOCKET`. +#[repr(transparent)] +#[cfg_attr(staged_api, rustc_layout_scalar_valid_range_start(0))] +// This is -2, in two's complement. -1 is `INVALID_SOCKET`. +#[cfg_attr( +    all(staged_api, target_pointer_width = "32"), +    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE) +)] +#[cfg_attr( +    all(staged_api, target_pointer_width = "64"), +    rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE) +)] +#[cfg_attr(staged_api, rustc_nonnull_optimization_guaranteed)] +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +pub struct OwnedSocket { +    socket: RawSocket, +} + +impl BorrowedSocket<'_> { +    /// Return a `BorrowedSocket` holding the given raw socket. +    /// +    /// # Safety +    /// +    /// The resource pointed to by `raw` must remain open for the duration of +    /// the returned `BorrowedSocket`, and it must not have the value +    /// `INVALID_SOCKET`. +    #[inline] +    #[cfg_attr( +        staged_api, +        rustc_const_stable(feature = "io_safety", since = "1.63.0") +    )] +    #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +    pub const unsafe fn borrow_raw(socket: RawSocket) -> Self { +        assert!(socket != c::INVALID_SOCKET as RawSocket); +        Self { +            socket, +            _phantom: PhantomData, +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsRawSocket for BorrowedSocket<'_> { +    #[inline] +    fn as_raw_socket(&self) -> RawSocket { +        self.socket +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsRawSocket for OwnedSocket { +    #[inline] +    fn as_raw_socket(&self) -> RawSocket { +        self.socket +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl IntoRawSocket for OwnedSocket { +    #[inline] +    fn into_raw_socket(self) -> RawSocket { +        let socket = self.socket; +        forget(self); +        socket +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl FromRawSocket for OwnedSocket { +    #[inline] +    unsafe fn from_raw_socket(socket: RawSocket) -> Self { +        debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket); +        Self { socket } +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl Drop for OwnedSocket { +    #[inline] +    fn drop(&mut self) { +        unsafe { +            let _ = c::closesocket(self.socket as LibcSocket); +        } +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl fmt::Debug for BorrowedSocket<'_> { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        f.debug_struct("BorrowedSocket") +            .field("socket", &self.socket) +            .finish() +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl fmt::Debug for OwnedSocket { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        f.debug_struct("OwnedSocket") +            .field("socket", &self.socket) +            .finish() +    } +} + +/// A trait to borrow the socket from an underlying object. +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +pub trait AsSocket { +    /// Borrows the socket. +    #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +    fn as_socket(&self) -> BorrowedSocket<'_>; +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl<T: AsSocket> AsSocket for &T { +    #[inline] +    fn as_socket(&self) -> BorrowedSocket<'_> { +        T::as_socket(self) +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl<T: AsSocket> AsSocket for &mut T { +    #[inline] +    fn as_socket(&self) -> BorrowedSocket<'_> { +        T::as_socket(self) +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsSocket for BorrowedSocket<'_> { +    #[inline] +    fn as_socket(&self) -> BorrowedSocket<'_> { +        *self +    } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsSocket for OwnedSocket { +    #[inline] +    fn as_socket(&self) -> BorrowedSocket<'_> { +        // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity +        // invariants, and the `BorrowdSocket` is bounded by the lifetime +        // of `&self`. +        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } +    } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/windows/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/mod.rs new file mode 100644 index 0000000..02f3894 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/mod.rs @@ -0,0 +1,19 @@ +//! The following is derived from Rust's +//! library/std/src/os/windows/raw.rs, +//! library/std/src/os/windows/io/raw.rs and +//! library/std/src/os/windows/io/socket.rs +//! at revision +//! 4f9b394c8a24803e57ba892fa00e539742ebafc0. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. + +mod raw { +    #[cfg(target_pointer_width = "32")] +    #[cfg_attr(staged_api, stable(feature = "raw_ext", since = "1.1.0"))] +    pub type SOCKET = u32; +    #[cfg(target_pointer_width = "64")] +    #[cfg_attr(staged_api, stable(feature = "raw_ext", since = "1.1.0"))] +    pub type SOCKET = u64; +} + +pub mod io;  | 
