diff options
Diffstat (limited to 'library')
471 files changed, 25761 insertions, 15684 deletions
diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs index 1f6b87fb0e4..ec1b0a8eba0 100644 --- a/library/alloc/benches/btree/map.rs +++ b/library/alloc/benches/btree/map.rs @@ -1,5 +1,4 @@ use std::collections::BTreeMap; -use std::iter::Iterator; use std::ops::RangeBounds; use std::vec::Vec; diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index 663f6b9dd1c..c1d3e1bdfe7 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -1,5 +1,5 @@ use rand::RngCore; -use std::iter::{repeat, FromIterator}; +use std::iter::repeat; use test::{black_box, Bencher}; #[bench] diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 3a797bd5eca..6f2ba957bcd 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -14,8 +14,6 @@ use core::ptr::{self, NonNull}; #[doc(inline)] pub use core::alloc::*; -use core::marker::Destruct; - #[cfg(test)] mod tests; @@ -331,16 +329,12 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { #[cfg_attr(not(test), lang = "box_free")] #[inline] -#[rustc_const_unstable(feature = "const_box", issue = "92521")] // This signature has to be the same as `Box`, otherwise an ICE will happen. // When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as // well. // For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`, // this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well. -pub(crate) const unsafe fn box_free<T: ?Sized, A: ~const Allocator + ~const Destruct>( - ptr: Unique<T>, - alloc: A, -) { +pub(crate) unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A) { unsafe { let size = size_of_val(ptr.as_ref()); let align = min_align_of_val(ptr.as_ref()); diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 83a1385599b..84331eba2d4 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -115,7 +115,7 @@ where /// ``` /// use std::borrow::Cow; /// -/// fn abs_all(input: &mut Cow<[i32]>) { +/// fn abs_all(input: &mut Cow<'_, [i32]>) { /// for i in 0..input.len() { /// let v = input[i]; /// if v < 0 { @@ -145,7 +145,7 @@ where /// ``` /// use std::borrow::Cow; /// -/// struct Items<'a, X: 'a> where [X]: ToOwned<Owned = Vec<X>> { +/// struct Items<'a, X> where [X]: ToOwned<Owned = Vec<X>> { /// values: Cow<'a, [X]>, /// } /// @@ -267,7 +267,7 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> { /// /// assert_eq!( /// cow, - /// Cow::Owned(String::from("FOO")) as Cow<str> + /// Cow::Owned(String::from("FOO")) as Cow<'_, str> /// ); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -311,7 +311,7 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> { /// use std::borrow::Cow; /// /// let s = "Hello world!"; - /// let cow: Cow<str> = Cow::Owned(String::from(s)); + /// let cow: Cow<'_, str> = Cow::Owned(String::from(s)); /// /// assert_eq!( /// cow.into_owned(), @@ -328,10 +328,9 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_deref", issue = "88955")] -impl<B: ?Sized + ToOwned> const Deref for Cow<'_, B> +impl<B: ?Sized + ToOwned> Deref for Cow<'_, B> where - B::Owned: ~const Borrow<B>, + B::Owned: Borrow<B>, { type Target = B; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index a563b258723..1768687e8cd 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -150,16 +150,13 @@ use core::any::Any; use core::async_iter::AsyncIterator; use core::borrow; use core::cmp::Ordering; -use core::convert::{From, TryFrom}; use core::error::Error; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; -#[cfg(not(no_global_oom_handling))] -use core::iter::FromIterator; -use core::iter::{FusedIterator, Iterator}; +use core::iter::FusedIterator; use core::marker::Tuple; -use core::marker::{Destruct, Unpin, Unsize}; +use core::marker::Unsize; use core::mem; use core::ops::{ CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, @@ -214,6 +211,7 @@ impl<T> Box<T> { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] + #[rustc_diagnostic_item = "box_new"] pub fn new(x: T) -> Self { #[rustc_box] Box::new(x) @@ -283,9 +281,7 @@ impl<T> Box<T> { #[must_use] #[inline(always)] pub fn pin(x: T) -> Pin<Box<T>> { - (#[rustc_box] - Box::new(x)) - .into() + Box::new(x).into() } /// Allocates memory on the heap then places `x` into it, @@ -377,12 +373,11 @@ impl<T, A: Allocator> Box<T, A> { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline] - pub const fn new_in(x: T, alloc: A) -> Self + pub fn new_in(x: T, alloc: A) -> Self where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let mut boxed = Self::new_uninit_in(alloc); unsafe { @@ -407,12 +402,10 @@ impl<T, A: Allocator> Box<T, A> { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> + pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> where - T: ~const Destruct, - A: ~const Allocator + ~const Destruct, + A: Allocator, { let mut boxed = Self::try_new_uninit_in(alloc)?; unsafe { @@ -442,13 +435,12 @@ impl<T, A: Allocator> Box<T, A> { /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[cfg(not(no_global_oom_handling))] #[must_use] // #[unstable(feature = "new_uninit", issue = "63291")] - pub const fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> + pub fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let layout = Layout::new::<mem::MaybeUninit<T>>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -483,10 +475,9 @@ impl<T, A: Allocator> Box<T, A> { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] - pub const fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> + pub fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let layout = Layout::new::<mem::MaybeUninit<T>>(); let ptr = alloc.allocate(layout)?.cast(); @@ -514,13 +505,12 @@ impl<T, A: Allocator> Box<T, A> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] #[must_use] - pub const fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> + pub fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let layout = Layout::new::<mem::MaybeUninit<T>>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -555,10 +545,9 @@ impl<T, A: Allocator> Box<T, A> { /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] - pub const fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> + pub fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let layout = Layout::new::<mem::MaybeUninit<T>>(); let ptr = alloc.allocate_zeroed(layout)?.cast(); @@ -574,12 +563,11 @@ impl<T, A: Allocator> Box<T, A> { /// construct a (pinned) `Box` in a different way than with [`Box::new_in`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline(always)] - pub const fn pin_in(x: T, alloc: A) -> Pin<Self> + pub fn pin_in(x: T, alloc: A) -> Pin<Self> where - A: 'static + ~const Allocator + ~const Destruct, + A: 'static + Allocator, { Self::into_pin(Self::new_in(x, alloc)) } @@ -588,8 +576,7 @@ impl<T, A: Allocator> Box<T, A> { /// /// This conversion does not allocate on the heap and happens in place. #[unstable(feature = "box_into_boxed_slice", issue = "71582")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] - pub const fn into_boxed_slice(boxed: Self) -> Box<[T], A> { + pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(boxed); unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) } } @@ -606,12 +593,8 @@ impl<T, A: Allocator> Box<T, A> { /// assert_eq!(Box::into_inner(c), 5); /// ``` #[unstable(feature = "box_into_inner", issue = "80437")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const fn into_inner(boxed: Self) -> T - where - Self: ~const Destruct, - { + pub fn into_inner(boxed: Self) -> T { *boxed } } @@ -825,9 +808,8 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> { /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "63291")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const unsafe fn assume_init(self) -> Box<T, A> { + pub unsafe fn assume_init(self) -> Box<T, A> { let (raw, alloc) = Box::into_raw_with_allocator(self); unsafe { Box::from_raw_in(raw as *mut T, alloc) } } @@ -860,9 +842,8 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> { /// } /// ``` #[unstable(feature = "new_uninit", issue = "63291")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const fn write(mut boxed: Self, value: T) -> Box<T, A> { + pub fn write(mut boxed: Self, value: T) -> Box<T, A> { unsafe { (*boxed).write(value); boxed.assume_init() @@ -1106,9 +1087,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { /// /// [memory layout]: self#memory-layout #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const fn into_raw_with_allocator(b: Self) -> (*mut T, A) { + pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { let (leaked, alloc) = Box::into_unique(b); (leaked.as_ptr(), alloc) } @@ -1118,10 +1098,9 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { issue = "none", reason = "use `Box::leak(b).into()` or `Unique::from(Box::leak(b))` instead" )] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] #[doc(hidden)] - pub const fn into_unique(b: Self) -> (Unique<T>, A) { + pub fn into_unique(b: Self) -> (Unique<T>, A) { // Box is recognized as a "unique pointer" by Stacked Borrows, but internally it is a // raw pointer for the type system. Turning it directly into a raw pointer would not be // recognized as "releasing" the unique pointer to permit aliased raw accesses, @@ -1179,9 +1158,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { /// assert_eq!(*static_ref, [4, 2, 3]); /// ``` #[stable(feature = "box_leak", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const fn leak<'a>(b: Self) -> &'a mut T + pub fn leak<'a>(b: Self) -> &'a mut T where A: 'a, { @@ -1242,16 +1220,16 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<T: Default> Default for Box<T> { /// Creates a `Box<T>`, with the `Default` value for T. + #[inline] fn default() -> Self { - #[rustc_box] Box::new(T::default()) } } #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T> const Default for Box<[T]> { +impl<T> Default for Box<[T]> { + #[inline] fn default() -> Self { let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling(); Box(ptr, Global) @@ -1260,8 +1238,8 @@ impl<T> const Default for Box<[T]> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "default_box_extra", since = "1.17.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl const Default for Box<str> { +impl Default for Box<str> { + #[inline] fn default() -> Self { // SAFETY: This is the same as `Unique::cast<U>` but with an unsized `U = str`. let ptr: Unique<str> = unsafe { @@ -1457,8 +1435,7 @@ impl<T> From<T> for Box<T> { } #[stable(feature = "pin", since = "1.33.0")] -#[rustc_const_unstable(feature = "const_box", issue = "92521")] -impl<T: ?Sized, A: Allocator> const From<Box<T, A>> for Pin<Box<T, A>> +impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Pin<Box<T, A>> where A: 'static, { @@ -1478,9 +1455,36 @@ where } } +/// Specialization trait used for `From<&[T]>`. +#[cfg(not(no_global_oom_handling))] +trait BoxFromSlice<T> { + fn from_slice(slice: &[T]) -> Self; +} + +#[cfg(not(no_global_oom_handling))] +impl<T: Clone> BoxFromSlice<T> for Box<[T]> { + #[inline] + default fn from_slice(slice: &[T]) -> Self { + slice.to_vec().into_boxed_slice() + } +} + +#[cfg(not(no_global_oom_handling))] +impl<T: Copy> BoxFromSlice<T> for Box<[T]> { + #[inline] + fn from_slice(slice: &[T]) -> Self { + let len = slice.len(); + let buf = RawVec::with_capacity(len); + unsafe { + ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); + buf.into_box(slice.len()).assume_init() + } + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_slice", since = "1.17.0")] -impl<T: Copy> From<&[T]> for Box<[T]> { +impl<T: Clone> From<&[T]> for Box<[T]> { /// Converts a `&[T]` into a `Box<[T]>` /// /// This conversion allocates on the heap @@ -1494,19 +1498,15 @@ impl<T: Copy> From<&[T]> for Box<[T]> { /// /// println!("{boxed_slice:?}"); /// ``` + #[inline] fn from(slice: &[T]) -> Box<[T]> { - let len = slice.len(); - let buf = RawVec::with_capacity(len); - unsafe { - ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); - buf.into_box(slice.len()).assume_init() - } + <Self as BoxFromSlice<T>>::from_slice(slice) } } #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_cow", since = "1.45.0")] -impl<T: Copy> From<Cow<'_, [T]>> for Box<[T]> { +impl<T: Clone> From<Cow<'_, [T]>> for Box<[T]> { /// Converts a `Cow<'_, [T]>` into a `Box<[T]>` /// /// When `cow` is the `Cow::Borrowed` variant, this @@ -1616,7 +1616,6 @@ impl<T, const N: usize> From<[T; N]> for Box<[T]> { /// println!("{boxed:?}"); /// ``` fn from(array: [T; N]) -> Box<[T]> { - #[rustc_box] Box::new(array) } } @@ -1895,8 +1894,7 @@ impl<T: ?Sized, A: Allocator> fmt::Pointer for Box<T, A> { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_box", issue = "92521")] -impl<T: ?Sized, A: Allocator> const Deref for Box<T, A> { +impl<T: ?Sized, A: Allocator> Deref for Box<T, A> { type Target = T; fn deref(&self) -> &T { @@ -1905,8 +1903,7 @@ impl<T: ?Sized, A: Allocator> const Deref for Box<T, A> { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_box", issue = "92521")] -impl<T: ?Sized, A: Allocator> const DerefMut for Box<T, A> { +impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> { fn deref_mut(&mut self) -> &mut T { &mut **self } diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index ad48315fd70..f83c8f83cc9 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -7,7 +7,7 @@ use core::fmt::{self, Debug, Display, Formatter}; use core::marker::PhantomData; #[cfg(not(no_global_oom_handling))] use core::marker::Unsize; -use core::mem; +use core::mem::{self, SizedTypeProperties}; use core::ops::{Deref, DerefMut}; use core::ptr::Pointee; use core::ptr::{self, NonNull}; @@ -202,9 +202,7 @@ impl<H> WithHeader<H> { let ptr = if layout.size() == 0 { // Some paranoia checking, mostly so that the ThinBox tests are // more able to catch issues. - debug_assert!( - value_offset == 0 && mem::size_of::<T>() == 0 && mem::size_of::<H>() == 0 - ); + debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST); layout.dangling() } else { let ptr = alloc::alloc(layout); @@ -249,9 +247,7 @@ impl<H> WithHeader<H> { alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout); } else { debug_assert!( - value_offset == 0 - && mem::size_of::<H>() == 0 - && self.value_layout.size() == 0 + value_offset == 0 && H::IS_ZST && self.value_layout.size() == 0 ); } } diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 0b73b1af4eb..2c089bb3149 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -144,7 +144,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use core::fmt; -use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen}; +use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen}; use core::mem::{self, swap, ManuallyDrop}; use core::num::NonZeroUsize; use core::ops::{Deref, DerefMut}; @@ -154,8 +154,6 @@ use crate::collections::TryReserveError; use crate::slice; use crate::vec::{self, AsVecIntoIter, Vec}; -use super::SpecExtend; - #[cfg(test)] mod tests; @@ -265,7 +263,6 @@ mod tests; /// more detailed analysis. /// /// [`core::cmp::Reverse`]: core::cmp::Reverse -/// [`Ord`]: core::cmp::Ord /// [`Cell`]: core::cell::Cell /// [`RefCell`]: core::cell::RefCell /// [push]: BinaryHeap::push @@ -400,6 +397,17 @@ impl<T: fmt::Debug> fmt::Debug for BinaryHeap<T> { } } +struct RebuildOnDrop<'a, T: Ord> { + heap: &'a mut BinaryHeap<T>, + rebuild_from: usize, +} + +impl<'a, T: Ord> Drop for RebuildOnDrop<'a, T> { + fn drop(&mut self) { + self.heap.rebuild_tail(self.rebuild_from); + } +} + impl<T: Ord> BinaryHeap<T> { /// Creates an empty `BinaryHeap` as a max-heap. /// @@ -837,7 +845,6 @@ impl<T: Ord> BinaryHeap<T> { /// Basic usage: /// /// ``` - /// #![feature(binary_heap_retain)] /// use std::collections::BinaryHeap; /// /// let mut heap = BinaryHeap::from([-10, -5, 1, 2, 4, 13]); @@ -846,23 +853,24 @@ impl<T: Ord> BinaryHeap<T> { /// /// assert_eq!(heap.into_sorted_vec(), [-10, 2, 4]) /// ``` - #[unstable(feature = "binary_heap_retain", issue = "71503")] + #[stable(feature = "binary_heap_retain", since = "1.70.0")] pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool, { - let mut first_removed = self.len(); + // rebuild_start will be updated to the first touched element below, and the rebuild will + // only be done for the tail. + let mut guard = RebuildOnDrop { rebuild_from: self.len(), heap: self }; let mut i = 0; - self.data.retain(|e| { + + guard.heap.data.retain(|e| { let keep = f(e); - if !keep && i < first_removed { - first_removed = i; + if !keep && i < guard.rebuild_from { + guard.rebuild_from = i; } i += 1; keep }); - // data[0..first_removed] is untouched, so we only need to rebuild the tail: - self.rebuild_tail(first_removed); } } @@ -1409,7 +1417,6 @@ impl<T> FusedIterator for Iter<'_, T> {} /// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: BinaryHeap::into_iter -/// [`IntoIterator`]: core::iter::IntoIterator #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct IntoIter<T> { @@ -1456,6 +1463,20 @@ impl<T> ExactSizeIterator for IntoIter<T> { #[stable(feature = "fused", since = "1.26.0")] impl<T> FusedIterator for IntoIter<T> {} +#[stable(feature = "default_iters", since = "1.70.0")] +impl<T> Default for IntoIter<T> { + /// Creates an empty `binary_heap::IntoIter`. + /// + /// ``` + /// # use std::collections::binary_heap; + /// let iter: binary_heap::IntoIter<u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoIter { iter: Default::default() } + } +} + // In addition to the SAFETY invariants of the following three unsafe traits // also refer to the vec::in_place_collect module documentation to get an overview #[unstable(issue = "none", feature = "inplace_iteration")] @@ -1703,7 +1724,8 @@ impl<'a, T> IntoIterator for &'a BinaryHeap<T> { impl<T: Ord> Extend<T> for BinaryHeap<T> { #[inline] fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { - <Self as SpecExtend<I>>::spec_extend(self, iter); + let guard = RebuildOnDrop { rebuild_from: self.len(), heap: self }; + guard.heap.data.extend(iter); } #[inline] @@ -1717,37 +1739,6 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> { } } -impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> { - default fn spec_extend(&mut self, iter: I) { - self.extend_desugared(iter.into_iter()); - } -} - -impl<T: Ord> SpecExtend<Vec<T>> for BinaryHeap<T> { - fn spec_extend(&mut self, ref mut other: Vec<T>) { - let start = self.data.len(); - self.data.append(other); - self.rebuild_tail(start); - } -} - -impl<T: Ord> SpecExtend<BinaryHeap<T>> for BinaryHeap<T> { - fn spec_extend(&mut self, ref mut other: BinaryHeap<T>) { - self.append(other); - } -} - -impl<T: Ord> BinaryHeap<T> { - fn extend_desugared<I: IntoIterator<Item = T>>(&mut self, iter: I) { - let iterator = iter.into_iter(); - let (lower, _) = iterator.size_hint(); - - self.reserve(lower); - - iterator.for_each(move |elem| self.push(elem)); - } -} - #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs index ffbb6c80ac0..500caa35678 100644 --- a/library/alloc/src/collections/binary_heap/tests.rs +++ b/library/alloc/src/collections/binary_heap/tests.rs @@ -474,6 +474,25 @@ fn test_retain() { assert!(a.is_empty()); } +#[test] +fn test_retain_catch_unwind() { + let mut heap = BinaryHeap::from(vec![3, 1, 2]); + + // Removes the 3, then unwinds out of retain. + let _ = catch_unwind(AssertUnwindSafe(|| { + heap.retain(|e| { + if *e == 1 { + panic!(); + } + false + }); + })); + + // Naively this would be [1, 2] (an invalid heap) if BinaryHeap delegates to + // Vec's retain impl and then does not rebuild the heap after that unwinds. + assert_eq!(heap.into_vec(), [2, 1]); +} + // old binaryheap failed this test // // Integrity means that all elements are present after a comparison panics, diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 386cd1a1657..2daef82d6f1 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -3,7 +3,7 @@ use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; -use core::iter::{FromIterator, FusedIterator}; +use core::iter::FusedIterator; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop}; use core::ops::{Bound, Index, RangeBounds}; @@ -362,6 +362,20 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Iter<'_, K, V> { } } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<'a, K: 'a, V: 'a> Default for Iter<'a, K, V> { + /// Creates an empty `btree_map::Iter`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::Iter<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Iter { range: Default::default(), length: 0 } + } +} + /// A mutable iterator over the entries of a `BTreeMap`. /// /// This `struct` is created by the [`iter_mut`] method on [`BTreeMap`]. See its @@ -386,13 +400,26 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> { } } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<'a, K: 'a, V: 'a> Default for IterMut<'a, K, V> { + /// Creates an empty `btree_map::IterMut`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::IterMut<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IterMut { range: Default::default(), length: 0, _marker: PhantomData {} } + } +} + /// An owning iterator over the entries of a `BTreeMap`. /// /// This `struct` is created by the [`into_iter`] method on [`BTreeMap`] /// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: IntoIterator::into_iter -/// [`IntoIterator`]: core::iter::IntoIterator #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] pub struct IntoIter< @@ -421,6 +448,23 @@ impl<K: Debug, V: Debug, A: Allocator + Clone> Debug for IntoIter<K, V, A> { } } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<K, V, A> Default for IntoIter<K, V, A> +where + A: Allocator + Default + Clone, +{ + /// Creates an empty `btree_map::IntoIter`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::IntoIter<u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoIter { range: Default::default(), length: 0, alloc: Default::default() } + } +} + /// An iterator over the keys of a `BTreeMap`. /// /// This `struct` is created by the [`keys`] method on [`BTreeMap`]. See its @@ -605,7 +649,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> { #[stable(feature = "rust1", since = "1.0.0")] pub fn clear(&mut self) { // avoid moving the allocator - mem::drop(BTreeMap { + drop(BTreeMap { root: mem::replace(&mut self.root, None), length: mem::replace(&mut self.length, 0), alloc: self.alloc.clone(), @@ -1499,11 +1543,17 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { self.next_back() } - fn min(mut self) -> Option<(&'a K, &'a V)> { + fn min(mut self) -> Option<(&'a K, &'a V)> + where + (&'a K, &'a V): Ord, + { self.next() } - fn max(mut self) -> Option<(&'a K, &'a V)> { + fn max(mut self) -> Option<(&'a K, &'a V)> + where + (&'a K, &'a V): Ord, + { self.next_back() } } @@ -1568,11 +1618,17 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { self.next_back() } - fn min(mut self) -> Option<(&'a K, &'a mut V)> { + fn min(mut self) -> Option<(&'a K, &'a mut V)> + where + (&'a K, &'a mut V): Ord, + { self.next() } - fn max(mut self) -> Option<(&'a K, &'a mut V)> { + fn max(mut self) -> Option<(&'a K, &'a mut V)> + where + (&'a K, &'a mut V): Ord, + { self.next_back() } } @@ -1735,11 +1791,17 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { self.next_back() } - fn min(mut self) -> Option<&'a K> { + fn min(mut self) -> Option<&'a K> + where + &'a K: Ord, + { self.next() } - fn max(mut self) -> Option<&'a K> { + fn max(mut self) -> Option<&'a K> + where + &'a K: Ord, + { self.next_back() } } @@ -1768,6 +1830,20 @@ impl<K, V> Clone for Keys<'_, K, V> { } } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<K, V> Default for Keys<'_, K, V> { + /// Creates an empty `btree_map::Keys`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::Keys<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Keys { inner: Default::default() } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Values<'a, K, V> { type Item = &'a V; @@ -1809,6 +1885,20 @@ impl<K, V> Clone for Values<'_, K, V> { } } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<K, V> Default for Values<'_, K, V> { + /// Creates an empty `btree_map::Values`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::Values<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Values { inner: Default::default() } + } +} + /// An iterator produced by calling `drain_filter` on BTreeMap. #[unstable(feature = "btree_drain_filter", issue = "70530")] pub struct DrainFilter< @@ -1936,15 +2026,35 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { self.next_back() } - fn min(mut self) -> Option<(&'a K, &'a V)> { + fn min(mut self) -> Option<(&'a K, &'a V)> + where + (&'a K, &'a V): Ord, + { self.next() } - fn max(mut self) -> Option<(&'a K, &'a V)> { + fn max(mut self) -> Option<(&'a K, &'a V)> + where + (&'a K, &'a V): Ord, + { self.next_back() } } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<K, V> Default for Range<'_, K, V> { + /// Creates an empty `btree_map::Range`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::Range<'_, u8, u8> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + Range { inner: Default::default() } + } +} + #[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { type Item = &'a mut V; @@ -1995,11 +2105,17 @@ impl<K, V, A: Allocator + Clone> Iterator for IntoKeys<K, V, A> { self.next_back() } - fn min(mut self) -> Option<K> { + fn min(mut self) -> Option<K> + where + K: Ord, + { self.next() } - fn max(mut self) -> Option<K> { + fn max(mut self) -> Option<K> + where + K: Ord, + { self.next_back() } } @@ -2021,6 +2137,23 @@ impl<K, V, A: Allocator + Clone> ExactSizeIterator for IntoKeys<K, V, A> { #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl<K, V, A: Allocator + Clone> FusedIterator for IntoKeys<K, V, A> {} +#[stable(feature = "default_iters", since = "1.70.0")] +impl<K, V, A> Default for IntoKeys<K, V, A> +where + A: Allocator + Default + Clone, +{ + /// Creates an empty `btree_map::IntoKeys`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::IntoKeys<u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoKeys { inner: Default::default() } + } +} + #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl<K, V, A: Allocator + Clone> Iterator for IntoValues<K, V, A> { type Item = V; @@ -2055,6 +2188,23 @@ impl<K, V, A: Allocator + Clone> ExactSizeIterator for IntoValues<K, V, A> { #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl<K, V, A: Allocator + Clone> FusedIterator for IntoValues<K, V, A> {} +#[stable(feature = "default_iters", since = "1.70.0")] +impl<K, V, A> Default for IntoValues<K, V, A> +where + A: Allocator + Default + Clone, +{ + /// Creates an empty `btree_map::IntoValues`. + /// + /// ``` + /// # use std::collections::btree_map; + /// let iter: btree_map::IntoValues<u8, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoValues { inner: Default::default() } + } +} + #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a V)> { @@ -2084,11 +2234,17 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { self.next_back() } - fn min(mut self) -> Option<(&'a K, &'a mut V)> { + fn min(mut self) -> Option<(&'a K, &'a mut V)> + where + (&'a K, &'a mut V): Ord, + { self.next() } - fn max(mut self) -> Option<(&'a K, &'a mut V)> { + fn max(mut self) -> Option<(&'a K, &'a mut V)> + where + (&'a K, &'a mut V): Ord, + { self.next_back() } } @@ -2923,8 +3079,8 @@ impl<'a, K, V, A> CursorMut<'a, K, V, A> { unsafe { self.root.reborrow() } .as_mut()? .borrow_mut() - .first_leaf_edge() - .next_kv() + .last_leaf_edge() + .next_back_kv() .ok()? .into_kv_valmut() } @@ -3062,7 +3218,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { panic!("key must be ordered above the current element"); } } - if let Some((next, _)) = self.peek_prev() { + if let Some((next, _)) = self.peek_next() { if &key >= next { panic!("key must be ordered below the next element"); } diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 76c2f27b466..7ecffe3eef2 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -8,9 +8,9 @@ use crate::testing::crash_test::{CrashTestDummy, Panic}; use crate::testing::ord_chaos::{Cyclic3, Governed, Governor}; use crate::testing::rng::DeterministicRng; use crate::vec::Vec; +use core::assert_matches::assert_matches; use std::cmp::Ordering; -use std::convert::TryFrom; -use std::iter::{self, FromIterator}; +use std::iter; use std::mem; use std::ops::Bound::{self, Excluded, Included, Unbounded}; use std::ops::RangeBounds; @@ -2385,3 +2385,85 @@ fn test_cursor_mut() { assert_eq!(cur.key(), Some(&4)); assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd')])); } + +#[should_panic(expected = "key must be ordered above the previous element")] +#[test] +fn test_cursor_mut_insert_before_1() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(0, 'd'); +} + +#[should_panic(expected = "key must be ordered above the previous element")] +#[test] +fn test_cursor_mut_insert_before_2() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(1, 'd'); +} + +#[should_panic(expected = "key must be ordered below the current element")] +#[test] +fn test_cursor_mut_insert_before_3() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(2, 'd'); +} + +#[should_panic(expected = "key must be ordered below the current element")] +#[test] +fn test_cursor_mut_insert_before_4() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_before(3, 'd'); +} + +#[should_panic(expected = "key must be ordered above the current element")] +#[test] +fn test_cursor_mut_insert_after_1() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(1, 'd'); +} + +#[should_panic(expected = "key must be ordered above the current element")] +#[test] +fn test_cursor_mut_insert_after_2() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(2, 'd'); +} + +#[should_panic(expected = "key must be ordered below the next element")] +#[test] +fn test_cursor_mut_insert_after_3() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(3, 'd'); +} + +#[should_panic(expected = "key must be ordered below the next element")] +#[test] +fn test_cursor_mut_insert_after_4() { + let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); + let mut cur = map.upper_bound_mut(Bound::Included(&2)); + cur.insert_after(4, 'd'); +} + +#[test] +fn cursor_peek_prev_agrees_with_cursor_mut() { + let mut map = BTreeMap::from([(1, 1), (2, 2), (3, 3)]); + + let cursor = map.lower_bound(Bound::Excluded(&3)); + assert!(cursor.key().is_none()); + + let prev = cursor.peek_prev(); + assert_matches!(prev, Some((&3, _))); + + // Shadow names so the two parts of this test match. + let mut cursor = map.lower_bound_mut(Bound::Excluded(&3)); + assert!(cursor.key().is_none()); + + let prev = cursor.peek_prev(); + assert_matches!(prev, Some((&3, _))); +} diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index 7552f2fc04c..c7d0144de30 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -13,7 +13,6 @@ pub mod set; mod set_val; mod split; -#[doc(hidden)] trait Recover<Q: ?Sized> { type Key; diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index b890717e50b..a85a3162451 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -19,6 +19,12 @@ impl<'a, K: 'a, V: 'a> Clone for LeafRange<marker::Immut<'a>, K, V> { } } +impl<B, K, V> Default for LeafRange<B, K, V> { + fn default() -> Self { + LeafRange { front: None, back: None } + } +} + impl<BorrowType, K, V> LeafRange<BorrowType, K, V> { pub fn none() -> Self { LeafRange { front: None, back: None } @@ -124,6 +130,12 @@ pub struct LazyLeafRange<BorrowType, K, V> { back: Option<LazyLeafHandle<BorrowType, K, V>>, } +impl<B, K, V> Default for LazyLeafRange<B, K, V> { + fn default() -> Self { + LazyLeafRange { front: None, back: None } + } +} + impl<'a, K: 'a, V: 'a> Clone for LazyLeafRange<marker::Immut<'a>, K, V> { fn clone(&self) -> Self { LazyLeafRange { front: self.front.clone(), back: self.back.clone() } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 4ddb2119252..940fa30afb8 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1,13 +1,10 @@ -// This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface -// to TreeMap - use crate::vec::Vec; use core::borrow::Borrow; use core::cmp::Ordering::{self, Equal, Greater, Less}; use core::cmp::{max, min}; use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; -use core::iter::{FromIterator, FusedIterator, Peekable}; +use core::iter::{FusedIterator, Peekable}; use core::mem::ManuallyDrop; use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub}; @@ -18,8 +15,6 @@ use super::Recover; use crate::alloc::{Allocator, Global}; -// FIXME(conventions): implement bounded iterators - /// An ordered set based on a B-Tree. /// /// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance @@ -35,7 +30,6 @@ use crate::alloc::{Allocator, Global}; /// Iterators returned by [`BTreeSet::iter`] produce their items in order, and take worst-case /// logarithmic and amortized constant time per item returned. /// -/// [`Ord`]: core::cmp::Ord /// [`Cell`]: core::cell::Cell /// [`RefCell`]: core::cell::RefCell /// @@ -152,7 +146,6 @@ impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> { /// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: BTreeSet#method.into_iter -/// [`IntoIterator`]: core::iter::IntoIterator #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct IntoIter< @@ -1508,11 +1501,17 @@ impl<'a, T> Iterator for Iter<'a, T> { self.next_back() } - fn min(mut self) -> Option<&'a T> { + fn min(mut self) -> Option<&'a T> + where + &'a T: Ord, + { self.next() } - fn max(mut self) -> Option<&'a T> { + fn max(mut self) -> Option<&'a T> + where + &'a T: Ord, + { self.next_back() } } @@ -1544,6 +1543,21 @@ impl<T, A: Allocator + Clone> Iterator for IntoIter<T, A> { self.iter.size_hint() } } + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<T> Default for Iter<'_, T> { + /// Creates an empty `btree_set::Iter`. + /// + /// ``` + /// # use std::collections::btree_set; + /// let iter: btree_set::Iter<'_, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Iter { iter: Default::default() } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<T, A: Allocator + Clone> DoubleEndedIterator for IntoIter<T, A> { fn next_back(&mut self) -> Option<T> { @@ -1560,6 +1574,23 @@ impl<T, A: Allocator + Clone> ExactSizeIterator for IntoIter<T, A> { #[stable(feature = "fused", since = "1.26.0")] impl<T, A: Allocator + Clone> FusedIterator for IntoIter<T, A> {} +#[stable(feature = "default_iters", since = "1.70.0")] +impl<T, A> Default for IntoIter<T, A> +where + A: Allocator + Default + Clone, +{ + /// Creates an empty `btree_set::IntoIter`. + /// + /// ``` + /// # use std::collections::btree_set; + /// let iter: btree_set::IntoIter<u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + IntoIter { iter: Default::default() } + } +} + #[stable(feature = "btree_range", since = "1.17.0")] impl<T> Clone for Range<'_, T> { fn clone(&self) -> Self { @@ -1579,11 +1610,17 @@ impl<'a, T> Iterator for Range<'a, T> { self.next_back() } - fn min(mut self) -> Option<&'a T> { + fn min(mut self) -> Option<&'a T> + where + &'a T: Ord, + { self.next() } - fn max(mut self) -> Option<&'a T> { + fn max(mut self) -> Option<&'a T> + where + &'a T: Ord, + { self.next_back() } } @@ -1598,6 +1635,20 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> { #[stable(feature = "fused", since = "1.26.0")] impl<T> FusedIterator for Range<'_, T> {} +#[stable(feature = "default_iters", since = "1.70.0")] +impl<T> Default for Range<'_, T> { + /// Creates an empty `btree_set::Range`. + /// + /// ``` + /// # use std::collections::btree_set; + /// let iter: btree_set::Range<'_, u8> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + Range { iter: Default::default() } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<T, A: Allocator + Clone> Clone for Difference<'_, T, A> { fn clone(&self) -> Self { diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 7b8d41a6031..a7c839d77ed 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -4,7 +4,6 @@ use crate::testing::rng::DeterministicRng; use crate::vec::Vec; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; -use std::iter::FromIterator; use std::ops::Bound::{Excluded, Included}; use std::panic::{catch_unwind, AssertUnwindSafe}; diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index f2f5dffc25d..4cd34ac2fa7 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -15,12 +15,13 @@ use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; -use core::iter::{FromIterator, FusedIterator}; +use core::iter::FusedIterator; use core::marker::PhantomData; use core::mem; -use core::ptr::NonNull; +use core::ptr::{NonNull, Unique}; use super::SpecExtend; +use crate::alloc::{Allocator, Global}; use crate::boxed::Box; #[cfg(test)] @@ -47,11 +48,15 @@ mod tests; #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "LinkedList")] #[rustc_insignificant_dtor] -pub struct LinkedList<T> { +pub struct LinkedList< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { head: Option<NonNull<Node<T>>>, tail: Option<NonNull<Node<T>>>, len: usize, - marker: PhantomData<Box<Node<T>>>, + alloc: A, + marker: PhantomData<Box<Node<T>, A>>, } struct Node<T> { @@ -81,6 +86,7 @@ impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> { head: self.head, tail: self.tail, len: self.len, + alloc: Global, marker: PhantomData, })) .field(&self.len) @@ -117,6 +123,7 @@ impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> { head: self.head, tail: self.tail, len: self.len, + alloc: Global, marker: PhantomData, })) .field(&self.len) @@ -130,15 +137,17 @@ impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> { /// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: LinkedList::into_iter -/// [`IntoIterator`]: core::iter::IntoIterator #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter<T> { - list: LinkedList<T>, +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + list: LinkedList<T, A>, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl<T: fmt::Debug> fmt::Debug for IntoIter<T> { +impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.list).finish() } @@ -149,22 +158,25 @@ impl<T> Node<T> { Node { next: None, prev: None, element } } - fn into_element(self: Box<Self>) -> T { + fn into_element<A: Allocator>(self: Box<Self, A>) -> T { self.element } } // private methods -impl<T> LinkedList<T> { +impl<T, A: Allocator> LinkedList<T, A> { /// Adds the given node to the front of the list. + /// + /// # Safety + /// `node` must point to a valid node that was boxed using the list's allocator. #[inline] - fn push_front_node(&mut self, mut node: Box<Node<T>>) { + unsafe fn push_front_node(&mut self, node: Unique<Node<T>>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. unsafe { - node.next = self.head; - node.prev = None; - let node = Some(Box::leak(node).into()); + (*node.as_ptr()).next = self.head; + (*node.as_ptr()).prev = None; + let node = Some(NonNull::from(node)); match self.head { None => self.tail = node, @@ -179,11 +191,11 @@ impl<T> LinkedList<T> { /// Removes and returns the node at the front of the list. #[inline] - fn pop_front_node(&mut self) -> Option<Box<Node<T>>> { + fn pop_front_node(&mut self) -> Option<Box<Node<T>, &A>> { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. self.head.map(|node| unsafe { - let node = Box::from_raw(node.as_ptr()); + let node = Box::from_raw_in(node.as_ptr(), &self.alloc); self.head = node.next; match self.head { @@ -198,14 +210,17 @@ impl<T> LinkedList<T> { } /// Adds the given node to the back of the list. + /// + /// # Safety + /// `node` must point to a valid node that was boxed using the list's allocator. #[inline] - fn push_back_node(&mut self, mut node: Box<Node<T>>) { + unsafe fn push_back_node(&mut self, node: Unique<Node<T>>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. unsafe { - node.next = None; - node.prev = self.tail; - let node = Some(Box::leak(node).into()); + (*node.as_ptr()).next = None; + (*node.as_ptr()).prev = self.tail; + let node = Some(NonNull::from(node)); match self.tail { None => self.head = node, @@ -220,11 +235,11 @@ impl<T> LinkedList<T> { /// Removes and returns the node at the back of the list. #[inline] - fn pop_back_node(&mut self) -> Option<Box<Node<T>>> { + fn pop_back_node(&mut self) -> Option<Box<Node<T>, &A>> { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. self.tail.map(|node| unsafe { - let node = Box::from_raw(node.as_ptr()); + let node = Box::from_raw_in(node.as_ptr(), &self.alloc); self.tail = node.prev; match self.tail { @@ -322,7 +337,10 @@ impl<T> LinkedList<T> { &mut self, split_node: Option<NonNull<Node<T>>>, at: usize, - ) -> Self { + ) -> Self + where + A: Clone, + { // The split node is the new head node of the second part if let Some(mut split_node) = split_node { let first_part_head; @@ -343,6 +361,7 @@ impl<T> LinkedList<T> { head: first_part_head, tail: first_part_tail, len: at, + alloc: self.alloc.clone(), marker: PhantomData, }; @@ -352,7 +371,7 @@ impl<T> LinkedList<T> { first_part } else { - mem::replace(self, LinkedList::new()) + mem::replace(self, LinkedList::new_in(self.alloc.clone())) } } @@ -361,7 +380,10 @@ impl<T> LinkedList<T> { &mut self, split_node: Option<NonNull<Node<T>>>, at: usize, - ) -> Self { + ) -> Self + where + A: Clone, + { // The split node is the new tail node of the first part and owns // the head of the second part. if let Some(mut split_node) = split_node { @@ -383,6 +405,7 @@ impl<T> LinkedList<T> { head: second_part_head, tail: second_part_tail, len: self.len - at, + alloc: self.alloc.clone(), marker: PhantomData, }; @@ -392,7 +415,7 @@ impl<T> LinkedList<T> { second_part } else { - mem::replace(self, LinkedList::new()) + mem::replace(self, LinkedList::new_in(self.alloc.clone())) } } } @@ -421,7 +444,7 @@ impl<T> LinkedList<T> { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { - LinkedList { head: None, tail: None, len: 0, marker: PhantomData } + LinkedList { head: None, tail: None, len: 0, alloc: Global, marker: PhantomData } } /// Moves all elements from `other` to the end of the list. @@ -472,7 +495,26 @@ impl<T> LinkedList<T> { } } } +} +impl<T, A: Allocator> LinkedList<T, A> { + /// Constructs an empty `LinkedList<T, A>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::LinkedList; + /// + /// let list: LinkedList<u32, _> = LinkedList::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + LinkedList { head: None, tail: None, len: 0, alloc, marker: PhantomData } + } /// Provides a forward iterator. /// /// # Examples @@ -533,7 +575,7 @@ impl<T> LinkedList<T> { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_front(&self) -> Cursor<'_, T> { + pub fn cursor_front(&self) -> Cursor<'_, T, A> { Cursor { index: 0, current: self.head, list: self } } @@ -543,7 +585,7 @@ impl<T> LinkedList<T> { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> { + pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T, A> { CursorMut { index: 0, current: self.head, list: self } } @@ -553,7 +595,7 @@ impl<T> LinkedList<T> { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_back(&self) -> Cursor<'_, T> { + pub fn cursor_back(&self) -> Cursor<'_, T, A> { Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } } @@ -563,7 +605,7 @@ impl<T> LinkedList<T> { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> { + pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T, A> { CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } } @@ -639,7 +681,15 @@ impl<T> LinkedList<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn clear(&mut self) { - *self = Self::new(); + // We need to drop the nodes while keeping self.alloc + // We can do this by moving (head, tail, len) into a new list that borrows self.alloc + drop(LinkedList { + head: self.head.take(), + tail: self.tail.take(), + len: mem::take(&mut self.len), + alloc: &self.alloc, + marker: PhantomData, + }); } /// Returns `true` if the `LinkedList` contains an element equal to the @@ -791,7 +841,12 @@ impl<T> LinkedList<T> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_front(&mut self, elt: T) { - self.push_front_node(Box::new(Node::new(elt))); + let node = Box::new_in(Node::new(elt), &self.alloc); + let node_ptr = Unique::from(Box::leak(node)); + // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc + unsafe { + self.push_front_node(node_ptr); + } } /// Removes the first element and returns it, or `None` if the list is @@ -834,7 +889,12 @@ impl<T> LinkedList<T> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_back(&mut self, elt: T) { - self.push_back_node(Box::new(Node::new(elt))); + let node = Box::new_in(Node::new(elt), &self.alloc); + let node_ptr = Unique::from(Box::leak(node)); + // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc + unsafe { + self.push_back_node(node_ptr); + } } /// Removes the last element from a list and returns it, or `None` if @@ -884,13 +944,16 @@ impl<T> LinkedList<T> { /// assert_eq!(split.pop_front(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn split_off(&mut self, at: usize) -> LinkedList<T> { + pub fn split_off(&mut self, at: usize) -> LinkedList<T, A> + where + A: Clone, + { let len = self.len(); assert!(at <= len, "Cannot split off at a nonexistent index"); if at == 0 { - return mem::take(self); + return mem::replace(self, Self::new_in(self.alloc.clone())); } else if at == len { - return Self::new(); + return Self::new_in(self.alloc.clone()); } // Below, we iterate towards the `i-1`th node, either from the start or the end, @@ -988,7 +1051,7 @@ impl<T> LinkedList<T> { /// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 9, 11, 13, 15]); /// ``` #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] - pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F> + pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -1001,11 +1064,11 @@ impl<T> LinkedList<T> { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T> Drop for LinkedList<T> { +unsafe impl<#[may_dangle] T, A: Allocator> Drop for LinkedList<T, A> { fn drop(&mut self) { - struct DropGuard<'a, T>(&'a mut LinkedList<T>); + struct DropGuard<'a, T, A: Allocator>(&'a mut LinkedList<T, A>); - impl<'a, T> Drop for DropGuard<'a, T> { + impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { fn drop(&mut self) { // Continue the same loop we do below. This only runs when a destructor has // panicked. If another one panics this will abort. @@ -1013,11 +1076,10 @@ unsafe impl<#[may_dangle] T> Drop for LinkedList<T> { } } - while let Some(node) = self.pop_front_node() { - let guard = DropGuard(self); - drop(node); - mem::forget(guard); - } + // Wrap self so that if a destructor panics, we can try to keep looping + let guard = DropGuard(self); + while guard.0.pop_front_node().is_some() {} + mem::forget(guard); } } @@ -1075,6 +1137,20 @@ impl<T> ExactSizeIterator for Iter<'_, T> {} #[stable(feature = "fused", since = "1.26.0")] impl<T> FusedIterator for Iter<'_, T> {} +#[stable(feature = "default_iters", since = "1.70.0")] +impl<T> Default for Iter<'_, T> { + /// Creates an empty `linked_list::Iter`. + /// + /// ``` + /// # use std::collections::linked_list; + /// let iter: linked_list::Iter<'_, u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Iter { head: None, tail: None, len: 0, marker: Default::default() } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; @@ -1129,6 +1205,13 @@ impl<T> ExactSizeIterator for IterMut<'_, T> {} #[stable(feature = "fused", since = "1.26.0")] impl<T> FusedIterator for IterMut<'_, T> {} +#[stable(feature = "default_iters", since = "1.70.0")] +impl<T> Default for IterMut<'_, T> { + fn default() -> Self { + IterMut { head: None, tail: None, len: 0, marker: Default::default() } + } +} + /// A cursor over a `LinkedList`. /// /// A `Cursor` is like an iterator, except that it can freely seek back-and-forth. @@ -1139,14 +1222,18 @@ impl<T> FusedIterator for IterMut<'_, T> {} /// /// When created, cursors start at the front of the list, or the "ghost" non-element if the list is empty. #[unstable(feature = "linked_list_cursors", issue = "58533")] -pub struct Cursor<'a, T: 'a> { +pub struct Cursor< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { index: usize, current: Option<NonNull<Node<T>>>, - list: &'a LinkedList<T>, + list: &'a LinkedList<T, A>, } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl<T> Clone for Cursor<'_, T> { +impl<T, A: Allocator> Clone for Cursor<'_, T, A> { fn clone(&self) -> Self { let Cursor { index, current, list } = *self; Cursor { index, current, list } @@ -1154,7 +1241,7 @@ impl<T> Clone for Cursor<'_, T> { } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl<T: fmt::Debug> fmt::Debug for Cursor<'_, T> { +impl<T: fmt::Debug, A: Allocator> fmt::Debug for Cursor<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Cursor").field(&self.list).field(&self.index()).finish() } @@ -1171,20 +1258,24 @@ impl<T: fmt::Debug> fmt::Debug for Cursor<'_, T> { /// To accommodate this, there is a "ghost" non-element that yields `None` between the head and /// tail of the list. #[unstable(feature = "linked_list_cursors", issue = "58533")] -pub struct CursorMut<'a, T: 'a> { +pub struct CursorMut< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { index: usize, current: Option<NonNull<Node<T>>>, - list: &'a mut LinkedList<T>, + list: &'a mut LinkedList<T, A>, } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl<T: fmt::Debug> fmt::Debug for CursorMut<'_, T> { +impl<T: fmt::Debug, A: Allocator> fmt::Debug for CursorMut<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("CursorMut").field(&self.list).field(&self.index()).finish() } } -impl<'a, T> Cursor<'a, T> { +impl<'a, T, A: Allocator> Cursor<'a, T, A> { /// Returns the cursor position index within the `LinkedList`. /// /// This returns `None` if the cursor is currently pointing to the @@ -1301,7 +1392,7 @@ impl<'a, T> Cursor<'a, T> { } } -impl<'a, T> CursorMut<'a, T> { +impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// Returns the cursor position index within the `LinkedList`. /// /// This returns `None` if the cursor is currently pointing to the @@ -1406,7 +1497,7 @@ impl<'a, T> CursorMut<'a, T> { /// `CursorMut` is frozen for the lifetime of the `Cursor`. #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn as_cursor(&self) -> Cursor<'_, T> { + pub fn as_cursor(&self) -> Cursor<'_, T, A> { Cursor { list: self.list, current: self.current, index: self.index } } } @@ -1414,6 +1505,51 @@ impl<'a, T> CursorMut<'a, T> { // Now the list editing operations impl<'a, T> CursorMut<'a, T> { + /// Inserts the elements from the given `LinkedList` after the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new elements are + /// inserted at the start of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn splice_after(&mut self, list: LinkedList<T>) { + unsafe { + let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { + Some(parts) => parts, + _ => return, + }; + let node_next = match self.current { + None => self.list.head, + Some(node) => node.as_ref().next, + }; + self.list.splice_nodes(self.current, node_next, splice_head, splice_tail, splice_len); + if self.current.is_none() { + // The "ghost" non-element's index has changed. + self.index = self.list.len; + } + } + } + + /// Inserts the elements from the given `LinkedList` before the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new elements are + /// inserted at the end of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn splice_before(&mut self, list: LinkedList<T>) { + unsafe { + let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { + Some(parts) => parts, + _ => return, + }; + let node_prev = match self.current { + None => self.list.tail, + Some(node) => node.as_ref().prev, + }; + self.list.splice_nodes(node_prev, self.current, splice_head, splice_tail, splice_len); + self.index += splice_len; + } + } +} + +impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// Inserts a new element into the `LinkedList` after the current one. /// /// If the cursor is pointing at the "ghost" non-element then the new element is @@ -1421,7 +1557,7 @@ impl<'a, T> CursorMut<'a, T> { #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn insert_after(&mut self, item: T) { unsafe { - let spliced_node = Box::leak(Box::new(Node::new(item))).into(); + let spliced_node = Box::leak(Box::new_in(Node::new(item), &self.list.alloc)).into(); let node_next = match self.current { None => self.list.head, Some(node) => node.as_ref().next, @@ -1441,7 +1577,7 @@ impl<'a, T> CursorMut<'a, T> { #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn insert_before(&mut self, item: T) { unsafe { - let spliced_node = Box::leak(Box::new(Node::new(item))).into(); + let spliced_node = Box::leak(Box::new_in(Node::new(item), &self.list.alloc)).into(); let node_prev = match self.current { None => self.list.tail, Some(node) => node.as_ref().prev, @@ -1477,7 +1613,10 @@ impl<'a, T> CursorMut<'a, T> { /// If the cursor is currently pointing to the "ghost" non-element then no element /// is removed and `None` is returned. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn remove_current_as_list(&mut self) -> Option<LinkedList<T>> { + pub fn remove_current_as_list(&mut self) -> Option<LinkedList<T, A>> + where + A: Clone, + { let mut unlinked_node = self.current?; unsafe { self.current = unlinked_node.as_ref().next; @@ -1489,54 +1628,12 @@ impl<'a, T> CursorMut<'a, T> { head: Some(unlinked_node), tail: Some(unlinked_node), len: 1, + alloc: self.list.alloc.clone(), marker: PhantomData, }) } } - /// Inserts the elements from the given `LinkedList` after the current one. - /// - /// If the cursor is pointing at the "ghost" non-element then the new elements are - /// inserted at the start of the `LinkedList`. - #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn splice_after(&mut self, list: LinkedList<T>) { - unsafe { - let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { - Some(parts) => parts, - _ => return, - }; - let node_next = match self.current { - None => self.list.head, - Some(node) => node.as_ref().next, - }; - self.list.splice_nodes(self.current, node_next, splice_head, splice_tail, splice_len); - if self.current.is_none() { - // The "ghost" non-element's index has changed. - self.index = self.list.len; - } - } - } - - /// Inserts the elements from the given `LinkedList` before the current one. - /// - /// If the cursor is pointing at the "ghost" non-element then the new elements are - /// inserted at the end of the `LinkedList`. - #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn splice_before(&mut self, list: LinkedList<T>) { - unsafe { - let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { - Some(parts) => parts, - _ => return, - }; - let node_prev = match self.current { - None => self.list.tail, - Some(node) => node.as_ref().prev, - }; - self.list.splice_nodes(node_prev, self.current, splice_head, splice_tail, splice_len); - self.index += splice_len; - } - } - /// Splits the list into two after the current element. This will return a /// new list consisting of everything after the cursor, with the original /// list retaining everything before. @@ -1544,7 +1641,10 @@ impl<'a, T> CursorMut<'a, T> { /// If the cursor is pointing at the "ghost" non-element then the entire contents /// of the `LinkedList` are moved. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn split_after(&mut self) -> LinkedList<T> { + pub fn split_after(&mut self) -> LinkedList<T, A> + where + A: Clone, + { let split_off_idx = if self.index == self.list.len { 0 } else { self.index + 1 }; if self.index == self.list.len { // The "ghost" non-element's index has changed to 0. @@ -1560,7 +1660,10 @@ impl<'a, T> CursorMut<'a, T> { /// If the cursor is pointing at the "ghost" non-element then the entire contents /// of the `LinkedList` are moved. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn split_before(&mut self) -> LinkedList<T> { + pub fn split_before(&mut self) -> LinkedList<T, A> + where + A: Clone, + { let split_off_idx = self.index; self.index = 0; unsafe { self.list.split_off_before_node(self.current, split_off_idx) } @@ -1702,11 +1805,15 @@ impl<'a, T> CursorMut<'a, T> { /// An iterator produced by calling `drain_filter` on LinkedList. #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -pub struct DrainFilter<'a, T: 'a, F: 'a> -where +pub struct DrainFilter< + 'a, + T: 'a, + F: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where F: FnMut(&mut T) -> bool, { - list: &'a mut LinkedList<T>, + list: &'a mut LinkedList<T, A>, it: Option<NonNull<Node<T>>>, pred: F, idx: usize, @@ -1714,7 +1821,7 @@ where } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl<T, F> Iterator for DrainFilter<'_, T, F> +impl<T, F, A: Allocator> Iterator for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -1743,16 +1850,16 @@ where } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl<T, F> Drop for DrainFilter<'_, T, F> +impl<T, F, A: Allocator> Drop for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { - struct DropGuard<'r, 'a, T, F>(&'r mut DrainFilter<'a, T, F>) + struct DropGuard<'r, 'a, T, F, A: Allocator>(&'r mut DrainFilter<'a, T, F, A>) where F: FnMut(&mut T) -> bool; - impl<'r, 'a, T, F> Drop for DropGuard<'r, 'a, T, F> + impl<'r, 'a, T, F, A: Allocator> Drop for DropGuard<'r, 'a, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -1780,7 +1887,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> Iterator for IntoIter<T> { +impl<T, A: Allocator> Iterator for IntoIter<T, A> { type Item = T; #[inline] @@ -1795,7 +1902,7 @@ impl<T> Iterator for IntoIter<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> DoubleEndedIterator for IntoIter<T> { +impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> { #[inline] fn next_back(&mut self) -> Option<T> { self.list.pop_back() @@ -1803,10 +1910,24 @@ impl<T> DoubleEndedIterator for IntoIter<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> ExactSizeIterator for IntoIter<T> {} +impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {} #[stable(feature = "fused", since = "1.26.0")] -impl<T> FusedIterator for IntoIter<T> {} +impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<T> Default for IntoIter<T> { + /// Creates an empty `linked_list::IntoIter`. + /// + /// ``` + /// # use std::collections::linked_list; + /// let iter: linked_list::IntoIter<u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + LinkedList::new().into_iter() + } +} #[stable(feature = "rust1", since = "1.0.0")] impl<T> FromIterator<T> for LinkedList<T> { @@ -1818,19 +1939,19 @@ impl<T> FromIterator<T> for LinkedList<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> IntoIterator for LinkedList<T> { +impl<T, A: Allocator> IntoIterator for LinkedList<T, A> { type Item = T; - type IntoIter = IntoIter<T>; + type IntoIter = IntoIter<T, A>; /// Consumes the list into an iterator yielding elements by value. #[inline] - fn into_iter(self) -> IntoIter<T> { + fn into_iter(self) -> IntoIter<T, A> { IntoIter { list: self } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a LinkedList<T> { +impl<'a, T, A: Allocator> IntoIterator for &'a LinkedList<T, A> { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1840,7 +1961,7 @@ impl<'a, T> IntoIterator for &'a LinkedList<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a mut LinkedList<T> { +impl<'a, T, A: Allocator> IntoIterator for &'a mut LinkedList<T, A> { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; @@ -1850,7 +1971,7 @@ impl<'a, T> IntoIterator for &'a mut LinkedList<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> Extend<T> for LinkedList<T> { +impl<T, A: Allocator> Extend<T> for LinkedList<T, A> { fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { <Self as SpecExtend<I>>::spec_extend(self, iter); } @@ -1861,7 +1982,7 @@ impl<T> Extend<T> for LinkedList<T> { } } -impl<I: IntoIterator> SpecExtend<I> for LinkedList<I::Item> { +impl<I: IntoIterator, A: Allocator> SpecExtend<I> for LinkedList<I::Item, A> { default fn spec_extend(&mut self, iter: I) { iter.into_iter().for_each(move |elt| self.push_back(elt)); } @@ -1874,7 +1995,7 @@ impl<T> SpecExtend<LinkedList<T>> for LinkedList<T> { } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> { +impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for LinkedList<T, A> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } @@ -1886,7 +2007,7 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: PartialEq> PartialEq for LinkedList<T> { +impl<T: PartialEq, A: Allocator> PartialEq for LinkedList<T, A> { fn eq(&self, other: &Self) -> bool { self.len() == other.len() && self.iter().eq(other) } @@ -1897,17 +2018,17 @@ impl<T: PartialEq> PartialEq for LinkedList<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Eq> Eq for LinkedList<T> {} +impl<T: Eq, A: Allocator> Eq for LinkedList<T, A> {} #[stable(feature = "rust1", since = "1.0.0")] -impl<T: PartialOrd> PartialOrd for LinkedList<T> { +impl<T: PartialOrd, A: Allocator> PartialOrd for LinkedList<T, A> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.iter().partial_cmp(other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Ord> Ord for LinkedList<T> { +impl<T: Ord, A: Allocator> Ord for LinkedList<T, A> { #[inline] fn cmp(&self, other: &Self) -> Ordering { self.iter().cmp(other) @@ -1915,9 +2036,11 @@ impl<T: Ord> Ord for LinkedList<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Clone> Clone for LinkedList<T> { +impl<T: Clone, A: Allocator + Clone> Clone for LinkedList<T, A> { fn clone(&self) -> Self { - self.iter().cloned().collect() + let mut list = Self::new_in(self.alloc.clone()); + list.extend(self.iter().cloned()); + list } fn clone_from(&mut self, other: &Self) { @@ -1935,14 +2058,14 @@ impl<T: Clone> Clone for LinkedList<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: fmt::Debug> fmt::Debug for LinkedList<T> { +impl<T: fmt::Debug, A: Allocator> fmt::Debug for LinkedList<T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self).finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Hash> Hash for LinkedList<T> { +impl<T: Hash, A: Allocator> Hash for LinkedList<T, A> { fn hash<H: Hasher>(&self, state: &mut H) { state.write_length_prefix(self.len()); for elt in self { @@ -1982,10 +2105,10 @@ fn assert_covariance() { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<T: Send> Send for LinkedList<T> {} +unsafe impl<T: Send, A: Allocator + Send> Send for LinkedList<T, A> {} #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<T: Sync> Sync for LinkedList<T> {} +unsafe impl<T: Sync, A: Allocator + Sync> Sync for LinkedList<T, A> {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<T: Sync> Send for Iter<'_, T> {} @@ -2000,13 +2123,13 @@ unsafe impl<T: Send> Send for IterMut<'_, T> {} unsafe impl<T: Sync> Sync for IterMut<'_, T> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl<T: Sync> Send for Cursor<'_, T> {} +unsafe impl<T: Sync, A: Allocator + Sync> Send for Cursor<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl<T: Sync> Sync for Cursor<'_, T> {} +unsafe impl<T: Sync, A: Allocator + Sync> Sync for Cursor<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl<T: Send> Send for CursorMut<'_, T> {} +unsafe impl<T: Send, A: Allocator + Send> Send for CursorMut<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl<T: Sync> Sync for CursorMut<'_, T> {} +unsafe impl<T: Sync, A: Allocator + Sync> Sync for CursorMut<'_, T, A> {} diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 89feb361ddc..0be274a3822 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -52,36 +52,22 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { } } - // Only returns pointers to the slices, as that's - // all we need to drop them. May only be called if `self.remaining != 0`. + // Only returns pointers to the slices, as that's all we need + // to drop them. May only be called if `self.remaining != 0`. unsafe fn as_slices(&self) -> (*mut [T], *mut [T]) { unsafe { let deque = self.deque.as_ref(); - // FIXME: This is doing almost exactly the same thing as the else branch in `VecDeque::slice_ranges`. - // Unfortunately, we can't just call `slice_ranges` here, as the deque's `len` is currently - // just `drain_start`, so the range check would (almost) always panic. Between temporarily - // adjusting the deques `len` to call `slice_ranges`, and just copy pasting the `slice_ranges` - // implementation, this seemed like the less hacky solution, though it might be good to - // find a better one in the future. - - // because `self.remaining != 0`, we know that `self.idx < deque.original_len`, so it's a valid - // logical index. - let wrapped_start = deque.to_physical_idx(self.idx); - - let head_len = deque.capacity() - wrapped_start; - - let (a_range, b_range) = if head_len >= self.remaining { - (wrapped_start..wrapped_start + self.remaining, 0..0) - } else { - let tail_len = self.remaining - head_len; - (wrapped_start..deque.capacity(), 0..tail_len) - }; - - // SAFETY: the range `self.idx..self.idx+self.remaining` lies strictly inside - // the range `0..deque.original_len`. because of this, and because of the fact - // that we acquire `a_range` and `b_range` exactly like `slice_ranges` would, - // it's guaranteed that `a_range` and `b_range` represent valid ranges into - // the deques buffer. + + // We know that `self.idx + self.remaining <= deque.len <= usize::MAX`, so this won't overflow. + let logical_remaining_range = self.idx..self.idx + self.remaining; + + // SAFETY: `logical_remaining_range` represents the + // range into the logical buffer of elements that + // haven't been drained yet, so they're all initialized, + // and `slice::range(start..end, end) == start..end`, + // so the preconditions for `slice_ranges` are met. + let (a_range, b_range) = + deque.slice_ranges(logical_remaining_range.clone(), logical_remaining_range.end); (deque.buffer_range(a_range), deque.buffer_range(b_range)) } } diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index 34bc0ce9177..d9e274df0f5 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -1,4 +1,5 @@ use core::iter::{FusedIterator, TrustedLen}; +use core::num::NonZeroUsize; use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr}; use crate::alloc::{Allocator, Global}; @@ -11,7 +12,6 @@ use super::VecDeque; /// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: VecDeque::into_iter -/// [`IntoIterator`]: core::iter::IntoIterator #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter< @@ -54,15 +54,16 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - if self.inner.len < n { - let len = self.inner.len; + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let len = self.inner.len; + let rem = if len < n { self.inner.clear(); - Err(len) + n - len } else { self.inner.drain(..n); - Ok(()) - } + 0 + }; + NonZeroUsize::new(rem).map_or(Ok(()), Err) } #[inline] @@ -182,15 +183,16 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let len = self.inner.len; - if len >= n { - self.inner.truncate(len - n); - Ok(()) - } else { + let rem = if len < n { self.inner.clear(); - Err(len) - } + n - len + } else { + self.inner.truncate(len - n); + 0 + }; + NonZeroUsize::new(rem).map_or(Ok(()), Err) } fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> R diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index d9f3937144d..646a2a991e7 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -1,4 +1,5 @@ use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use core::num::NonZeroUsize; use core::ops::Try; use core::{fmt, mem, slice}; @@ -55,13 +56,15 @@ impl<'a, T> Iterator for Iter<'a, T> { } } - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let m = match self.i1.advance_by(n) { - Ok(_) => return Ok(()), - Err(m) => m, - }; - mem::swap(&mut self.i1, &mut self.i2); - self.i1.advance_by(n - m).map_err(|o| o + m) + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let remaining = self.i1.advance_by(n); + match remaining { + Ok(()) => return Ok(()), + Err(n) => { + mem::swap(&mut self.i1, &mut self.i2); + self.i1.advance_by(n.get()) + } + } } #[inline] @@ -125,14 +128,14 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { } } - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - let m = match self.i2.advance_back_by(n) { - Ok(_) => return Ok(()), - Err(m) => m, - }; - - mem::swap(&mut self.i1, &mut self.i2); - self.i2.advance_back_by(n - m).map_err(|o| m + o) + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + match self.i2.advance_back_by(n) { + Ok(()) => return Ok(()), + Err(n) => { + mem::swap(&mut self.i1, &mut self.i2); + self.i2.advance_back_by(n.get()) + } + } } fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 2c59d95cd53..7defbb1090f 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -1,4 +1,5 @@ use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use core::num::NonZeroUsize; use core::ops::Try; use core::{fmt, mem, slice}; @@ -47,13 +48,14 @@ impl<'a, T> Iterator for IterMut<'a, T> { } } - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let m = match self.i1.advance_by(n) { - Ok(_) => return Ok(()), - Err(m) => m, - }; - mem::swap(&mut self.i1, &mut self.i2); - self.i1.advance_by(n - m).map_err(|o| o + m) + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + match self.i1.advance_by(n) { + Ok(()) => return Ok(()), + Err(remaining) => { + mem::swap(&mut self.i1, &mut self.i2); + self.i1.advance_by(remaining.get()) + } + } } #[inline] @@ -117,14 +119,14 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { } } - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - let m = match self.i2.advance_back_by(n) { - Ok(_) => return Ok(()), - Err(m) => m, - }; - - mem::swap(&mut self.i1, &mut self.i2); - self.i2.advance_back_by(n - m).map_err(|o| m + o) + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + match self.i2.advance_back_by(n) { + Ok(()) => return Ok(()), + Err(remaining) => { + mem::swap(&mut self.i1, &mut self.i2); + self.i2.advance_back_by(remaining.get()) + } + } } fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 1573b3d77dc..896da37f94c 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -10,7 +10,7 @@ use core::cmp::{self, Ordering}; use core::fmt; use core::hash::{Hash, Hasher}; -use core::iter::{repeat_n, repeat_with, ByRefSized, FromIterator}; +use core::iter::{repeat_n, repeat_with, ByRefSized}; use core::mem::{ManuallyDrop, SizedTypeProperties}; use core::ops::{Index, IndexMut, Range, RangeBounds}; use core::ptr; @@ -944,65 +944,72 @@ impl<T, A: Allocator> VecDeque<T, A> { return; } - if target_cap < self.capacity() { - // There are three cases of interest: - // All elements are out of desired bounds - // Elements are contiguous, and head is out of desired bounds - // Elements are discontiguous, and tail is out of desired bounds + // There are three cases of interest: + // All elements are out of desired bounds + // Elements are contiguous, and tail is out of desired bounds + // Elements are discontiguous + // + // At all other times, element positions are unaffected. + + // `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can + // overflow. + let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len)); + + if self.len == 0 { + self.head = 0; + } else if self.head >= target_cap && tail_outside { + // Head and tail are both out of bounds, so copy all of them to the front. // - // At all other times, element positions are unaffected. + // H := head + // L := last element + // H L + // [. . . . . . . . o o o o o o o . ] + // H L + // [o o o o o o o . ] + unsafe { + // nonoverlapping because `self.head >= target_cap >= self.len`. + self.copy_nonoverlapping(self.head, 0, self.len); + } + self.head = 0; + } else if self.head < target_cap && tail_outside { + // Head is in bounds, tail is out of bounds. + // Copy the overflowing part to the beginning of the + // buffer. This won't overlap because `target_cap >= self.len`. // - // Indicates that elements at the head should be moved. - - let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len)); - // Move elements from out of desired bounds (positions after target_cap) - if self.len == 0 { - self.head = 0; - } else if self.head >= target_cap && tail_outside { - // H := head - // L := last element - // H L - // [. . . . . . . . o o o o o o o . ] - // H L - // [o o o o o o o . ] - unsafe { - // nonoverlapping because self.head >= target_cap >= self.len - self.copy_nonoverlapping(self.head, 0, self.len); - } - self.head = 0; - } else if self.head < target_cap && tail_outside { - // H := head - // L := last element - // H L - // [. . . o o o o o o o . . . . . . ] - // L H - // [o o . o o o o o ] - let len = self.head + self.len - target_cap; - unsafe { - self.copy_nonoverlapping(target_cap, 0, len); - } - } else if self.head >= target_cap { - // H := head - // L := last element - // L H - // [o o o o o . . . . . . . . . o o ] - // L H - // [o o o o o . o o ] - let len = self.capacity() - self.head; - let new_head = target_cap - len; - unsafe { - // can't use copy_nonoverlapping here for the same reason - // as in `handle_capacity_increase()` - self.copy(self.head, new_head, len); - } - self.head = new_head; + // H := head + // L := last element + // H L + // [. . . o o o o o o o . . . . . . ] + // L H + // [o o . o o o o o ] + let len = self.head + self.len - target_cap; + unsafe { + self.copy_nonoverlapping(target_cap, 0, len); } - - self.buf.shrink_to_fit(target_cap); - - debug_assert!(self.head < self.capacity() || self.capacity() == 0); - debug_assert!(self.len <= self.capacity()); + } else if !self.is_contiguous() { + // The head slice is at least partially out of bounds, tail is in bounds. + // Copy the head backwards so it lines up with the target capacity. + // This won't overlap because `target_cap >= self.len`. + // + // H := head + // L := last element + // L H + // [o o o o o . . . . . . . . . o o ] + // L H + // [o o o o o . o o ] + let head_len = self.capacity() - self.head; + let new_head = target_cap - head_len; + unsafe { + // can't use `copy_nonoverlapping()` here because the new and old + // regions for the head might overlap. + self.copy(self.head, new_head, head_len); + } + self.head = new_head; } + self.buf.shrink_to_fit(target_cap); + + debug_assert!(self.head < self.capacity() || self.capacity() == 0); + debug_assert!(self.len <= self.capacity()); } /// Shortens the deque, keeping the first `len` elements and dropping @@ -1149,7 +1156,7 @@ impl<T, A: Allocator> VecDeque<T, A> { #[inline] #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn as_slices(&self) -> (&[T], &[T]) { - let (a_range, b_range) = self.slice_ranges(..); + let (a_range, b_range) = self.slice_ranges(.., self.len); // SAFETY: `slice_ranges` always returns valid ranges into // the physical buffer. unsafe { (&*self.buffer_range(a_range), &*self.buffer_range(b_range)) } @@ -1183,7 +1190,7 @@ impl<T, A: Allocator> VecDeque<T, A> { #[inline] #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { - let (a_range, b_range) = self.slice_ranges(..); + let (a_range, b_range) = self.slice_ranges(.., self.len); // SAFETY: `slice_ranges` always returns valid ranges into // the physical buffer. unsafe { (&mut *self.buffer_range(a_range), &mut *self.buffer_range(b_range)) } @@ -1225,19 +1232,28 @@ impl<T, A: Allocator> VecDeque<T, A> { /// Given a range into the logical buffer of the deque, this function /// return two ranges into the physical buffer that correspond to - /// the given range. - fn slice_ranges<R>(&self, range: R) -> (Range<usize>, Range<usize>) + /// the given range. The `len` parameter should usually just be `self.len`; + /// the reason it's passed explicitly is that if the deque is wrapped in + /// a `Drain`, then `self.len` is not actually the length of the deque. + /// + /// # Safety + /// + /// This function is always safe to call. For the resulting ranges to be valid + /// ranges into the physical buffer, the caller must ensure that the result of + /// calling `slice::range(range, ..len)` represents a valid range into the + /// logical buffer, and that all elements in that range are initialized. + fn slice_ranges<R>(&self, range: R, len: usize) -> (Range<usize>, Range<usize>) where R: RangeBounds<usize>, { - let Range { start, end } = slice::range(range, ..self.len); + let Range { start, end } = slice::range(range, ..len); let len = end - start; if len == 0 { (0..0, 0..0) } else { - // `slice::range` guarantees that `start <= end <= self.len`. - // because `len != 0`, we know that `start < end`, so `start < self.len` + // `slice::range` guarantees that `start <= end <= len`. + // because `len != 0`, we know that `start < end`, so `start < len` // and the indexing is valid. let wrapped_start = self.to_physical_idx(start); @@ -1283,7 +1299,7 @@ impl<T, A: Allocator> VecDeque<T, A> { where R: RangeBounds<usize>, { - let (a_range, b_range) = self.slice_ranges(range); + let (a_range, b_range) = self.slice_ranges(range, self.len); // SAFETY: The ranges returned by `slice_ranges` // are valid ranges into the physical buffer, so // it's ok to pass them to `buffer_range` and @@ -1323,7 +1339,7 @@ impl<T, A: Allocator> VecDeque<T, A> { where R: RangeBounds<usize>, { - let (a_range, b_range) = self.slice_ranges(range); + let (a_range, b_range) = self.slice_ranges(range, self.len); // SAFETY: The ranges returned by `slice_ranges` // are valid ranges into the physical buffer, so // it's ok to pass them to `buffer_range` and @@ -1917,7 +1933,7 @@ impl<T, A: Allocator> VecDeque<T, A> { #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { if T::IS_ZST { - self.len += other.len; + self.len = self.len.checked_add(other.len).expect("capacity overflow"); other.len = 0; other.head = 0; return; @@ -2378,7 +2394,8 @@ impl<T, A: Allocator> VecDeque<T, A> { } /// Binary searches this `VecDeque` for a given element. - /// This behaves similarly to [`contains`] if this `VecDeque` is sorted. + /// If the `VecDeque` is not sorted, the returned result is unspecified and + /// meaningless. /// /// If the value is found then [`Result::Ok`] is returned, containing the /// index of the matching element. If there are multiple matches, then any @@ -2388,7 +2405,6 @@ impl<T, A: Allocator> VecDeque<T, A> { /// /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`]. /// - /// [`contains`]: VecDeque::contains /// [`binary_search_by`]: VecDeque::binary_search_by /// [`binary_search_by_key`]: VecDeque::binary_search_by_key /// [`partition_point`]: VecDeque::partition_point @@ -2434,12 +2450,13 @@ impl<T, A: Allocator> VecDeque<T, A> { } /// Binary searches this `VecDeque` with a comparator function. - /// This behaves similarly to [`contains`] if this `VecDeque` is sorted. /// - /// The comparator function should implement an order consistent - /// with the sort order of the deque, returning an order code that - /// indicates whether its argument is `Less`, `Equal` or `Greater` - /// than the desired target. + /// The comparator function should return an order code that indicates + /// whether its argument is `Less`, `Equal` or `Greater` the desired + /// target. + /// If the `VecDeque` is not sorted or if the comparator function does not + /// implement an order consistent with the sort order of the underlying + /// `VecDeque`, the returned result is unspecified and meaningless. /// /// If the value is found then [`Result::Ok`] is returned, containing the /// index of the matching element. If there are multiple matches, then any @@ -2449,7 +2466,6 @@ impl<T, A: Allocator> VecDeque<T, A> { /// /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`]. /// - /// [`contains`]: VecDeque::contains /// [`binary_search`]: VecDeque::binary_search /// [`binary_search_by_key`]: VecDeque::binary_search_by_key /// [`partition_point`]: VecDeque::partition_point @@ -2489,10 +2505,11 @@ impl<T, A: Allocator> VecDeque<T, A> { } /// Binary searches this `VecDeque` with a key extraction function. - /// This behaves similarly to [`contains`] if this `VecDeque` is sorted. /// /// Assumes that the deque is sorted by the key, for instance with /// [`make_contiguous().sort_by_key()`] using the same key extraction function. + /// If the deque is not sorted by the key, the returned result is + /// unspecified and meaningless. /// /// If the value is found then [`Result::Ok`] is returned, containing the /// index of the matching element. If there are multiple matches, then any @@ -2502,7 +2519,6 @@ impl<T, A: Allocator> VecDeque<T, A> { /// /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`]. /// - /// [`contains`]: VecDeque::contains /// [`make_contiguous().sort_by_key()`]: VecDeque::make_contiguous /// [`binary_search`]: VecDeque::binary_search /// [`binary_search_by`]: VecDeque::binary_search_by @@ -2799,7 +2815,7 @@ impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque<T, A> { } #[inline] - fn extend_one(&mut self, &elem: &T) { + fn extend_one(&mut self, &elem: &'a T) { self.push_back(elem); } diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs index 7650492ebda..2708c7fe102 100644 --- a/library/alloc/src/collections/vec_deque/spec_from_iter.rs +++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs @@ -12,7 +12,7 @@ where default fn spec_from_iter(iterator: I) -> Self { // Since converting is O(1) now, just re-use the `Vec` logic for // anything where we can't do something extra-special for `VecDeque`, - // especially as that could save us some monomorphiziation work + // especially as that could save us some monomorphization work // if one uses the same iterators (like slice ones) with both. crate::vec::Vec::from_iter(iterator).into() } diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index 220ad71beab..205a8ff3c19 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -749,6 +749,48 @@ fn test_drain() { } #[test] +fn issue_108453() { + let mut deque = VecDeque::with_capacity(10); + + deque.push_back(1u8); + deque.push_back(2); + deque.push_back(3); + + deque.push_front(10); + deque.push_front(9); + + deque.shrink_to(9); + + assert_eq!(deque.into_iter().collect::<Vec<_>>(), vec![9, 10, 1, 2, 3]); +} + +#[test] +fn test_shrink_to() { + // test deques with capacity 16 with all possible head positions, lengths and target capacities. + let cap = 16; + + for len in 0..cap { + for head in 0..cap { + let expected = (1..=len).collect::<VecDeque<_>>(); + + for target_cap in len..cap { + let mut deque = VecDeque::with_capacity(cap); + // currently, `with_capacity` always allocates the exact capacity if it's greater than 8. + assert_eq!(deque.capacity(), cap); + + // we can let the head point anywhere in the buffer since the deque is empty. + deque.head = head; + deque.extend(1..=len); + + deque.shrink_to(target_cap); + + assert_eq!(deque, expected); + } + } + } +} + +#[test] fn test_shrink_to_fit() { // This test checks that every single combination of head and tail position, // is tested. Capacity 15 should be large enough to cover every case. diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 1da86e1a46a..fb8d00e8d87 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -363,7 +363,7 @@ //! # use std::fmt; //! # struct Foo; // our custom type //! # impl fmt::Display for Foo { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { //! # write!(f, "testing, testing") //! # } } //! ``` @@ -399,7 +399,7 @@ //! } //! //! impl fmt::Display for Vector2D { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { //! // The `f` value implements the `Write` trait, which is what the //! // write! macro is expecting. Note that this formatting ignores the //! // various flags provided to format strings. @@ -410,7 +410,7 @@ //! // Different traits allow different forms of output of a type. The meaning //! // of this format is to print the magnitude of a vector. //! impl fmt::Binary for Vector2D { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { //! let magnitude = (self.x * self.x + self.y * self.y) as f64; //! let magnitude = magnitude.sqrt(); //! @@ -517,7 +517,7 @@ //! let mut some_writer = io::stdout(); //! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro")); //! -//! fn my_fmt_fn(args: fmt::Arguments) { +//! fn my_fmt_fn(args: fmt::Arguments<'_>) { //! write!(&mut io::stdout(), "{args}"); //! } //! my_fmt_fn(format_args!(", or a {} too", "function")); @@ -551,8 +551,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[unstable(feature = "fmt_internals", issue = "none")] -pub use core::fmt::rt; #[stable(feature = "fmt_flags_align", since = "1.28.0")] pub use core::fmt::Alignment; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index e9cc3875f68..59fa91c1066 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -87,35 +87,37 @@ #![warn(missing_debug_implementations)] #![warn(missing_docs)] #![allow(explicit_outlives_requirements)] -#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))] +#![warn(multiple_supertrait_upcastable)] // // Library features: +// tidy-alphabetical-start +#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] +#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] +#![cfg_attr(test, feature(is_sorted))] +#![cfg_attr(test, feature(new_uninit))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_chunks)] #![feature(array_into_iter_constructors)] #![feature(array_methods)] #![feature(array_windows)] +#![feature(ascii_char)] #![feature(assert_matches)] #![feature(async_iterator)] #![feature(coerce_unsized)] -#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] +#![feature(const_align_of_val)] #![feature(const_box)] -#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] #![feature(const_cow_is_borrowed)] -#![feature(const_convert)] -#![feature(const_size_of_val)] -#![feature(const_align_of_val)] -#![feature(const_ptr_read)] -#![feature(const_maybe_uninit_zeroed)] -#![feature(const_maybe_uninit_write)] +#![feature(const_eval_select)] #![feature(const_maybe_uninit_as_mut_ptr)] +#![feature(const_maybe_uninit_write)] +#![feature(const_maybe_uninit_zeroed)] +#![feature(const_pin)] #![feature(const_refs_to_cell)] +#![feature(const_size_of_val)] +#![feature(const_waker)] #![feature(core_intrinsics)] #![feature(core_panic)] -#![feature(const_eval_select)] -#![feature(const_pin)] -#![feature(const_waker)] #![feature(dispatch_from_dyn)] #![feature(error_generic_member_access)] #![feature(error_in_core)] @@ -126,7 +128,6 @@ #![feature(hasher_prefixfree_extras)] #![feature(inline_const)] #![feature(inplace_iteration)] -#![cfg_attr(test, feature(is_sorted))] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] #![feature(iter_repeat_n)] @@ -134,8 +135,6 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array_transpose)] -#![cfg_attr(test, feature(new_uninit))] -#![feature(nonnull_slice_from_raw_parts)] #![feature(pattern)] #![feature(pointer_byte_offsets)] #![feature(provide_any)] @@ -151,6 +150,7 @@ #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] #![feature(slice_range)] +#![feature(std_internals)] #![feature(str_internals)] #![feature(strict_provenance)] #![feature(trusted_len)] @@ -161,41 +161,42 @@ #![feature(unicode_internals)] #![feature(unsize)] #![feature(utf8_chunks)] -#![feature(std_internals)] +// tidy-alphabetical-end // // Language features: +// tidy-alphabetical-start +#![cfg_attr(not(test), feature(generator_trait))] +#![cfg_attr(test, feature(panic_update_hook))] +#![cfg_attr(test, feature(test))] #![feature(allocator_internals)] #![feature(allow_internal_unstable)] #![feature(associated_type_bounds)] +#![feature(c_unwind)] #![feature(cfg_sanitize)] -#![feature(const_deref)] #![feature(const_mut_refs)] -#![feature(const_ptr_write)] #![feature(const_precise_live_drops)] +#![feature(const_ptr_write)] #![feature(const_trait_impl)] #![feature(const_try)] #![feature(dropck_eyepatch)] #![feature(exclusive_range_pattern)] #![feature(fundamental)] -#![cfg_attr(not(test), feature(generator_trait))] #![feature(hashmap_internals)] #![feature(lang_items)] #![feature(min_specialization)] +#![feature(multiple_supertrait_upcastable)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(pointer_is_aligned)] #![feature(rustc_allow_const_fn_unstable)] #![feature(rustc_attrs)] -#![feature(pointer_is_aligned)] #![feature(slice_internals)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] -#![cfg_attr(test, feature(test))] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] -#![feature(c_unwind)] #![feature(with_negative_coherence)] -#![cfg_attr(test, feature(panic_update_hook))] -#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))] +// tidy-alphabetical-end // // Rustdoc features: #![feature(doc_cfg)] diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 5198bf297d9..4c6ae8f2579 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -48,6 +48,8 @@ macro_rules! vec { ); ($($x:expr),+ $(,)?) => ( $crate::__rust_force_expr!(<[_]>::into_vec( + // This rustc_box is not required, but it produces a dramatic improvement in compile + // time when constructing arrays with many elements. #[rustc_box] $crate::boxed::Box::new([$($x),+]) )) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 3751f2a2454..dfd30d99cf0 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -4,7 +4,6 @@ use core::alloc::LayoutError; use core::cmp; use core::intrinsics; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; -use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index fd1e3e0f75b..38a711ac750 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -15,7 +15,7 @@ //! //! [`Rc`] uses non-atomic reference counting. This means that overhead is very //! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`] -//! does not implement [`Send`][send]. As a result, the Rust compiler +//! does not implement [`Send`]. As a result, the Rust compiler //! will check *at compile time* that you are not sending [`Rc`]s between //! threads. If you need multi-threaded, atomic reference counting, use //! [`sync::Arc`][arc]. @@ -232,7 +232,6 @@ //! [clone]: Clone::clone //! [`Cell`]: core::cell::Cell //! [`RefCell`]: core::cell::RefCell -//! [send]: core::marker::Send //! [arc]: crate::sync::Arc //! [`Deref`]: core::ops::Deref //! [downgrade]: Rc::downgrade @@ -251,13 +250,12 @@ use core::any::Any; use core::borrow; use core::cell::Cell; use core::cmp::Ordering; -use core::convert::{From, TryFrom}; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; #[cfg(not(no_global_oom_handling))] use core::iter; -use core::marker::{self, PhantomData, Unpin, Unsize}; +use core::marker::{PhantomData, Unsize}; #[cfg(not(no_global_oom_handling))] use core::mem::size_of_val; use core::mem::{self, align_of_val_raw, forget}; @@ -321,7 +319,7 @@ pub struct Rc<T: ?Sized> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> !marker::Send for Rc<T> {} +impl<T: ?Sized> !Send for Rc<T> {} // Note that this negative impl isn't strictly necessary for correctness, // as `Rc` transitively contains a `Cell`, which is itself `!Sync`. @@ -329,7 +327,7 @@ impl<T: ?Sized> !marker::Send for Rc<T> {} // having an explicit negative impl is nice for documentation purposes // and results in nicer error messages. #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> !marker::Sync for Rc<T> {} +impl<T: ?Sized> !Sync for Rc<T> {} #[stable(feature = "catch_unwind", since = "1.9.0")] impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Rc<T> {} @@ -681,6 +679,24 @@ impl<T> Rc<T> { Err(this) } } + + /// Returns the inner value, if the `Rc` has exactly one strong reference. + /// + /// Otherwise, [`None`] is returned and the `Rc` is dropped. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// If `Rc::into_inner` is called on every clone of this `Rc`, + /// it is guaranteed that exactly one of the calls returns the inner value. + /// This means in particular that the inner value is not dropped. + /// + /// This is equivalent to `Rc::try_unwrap(this).ok()`. (Note that these are not equivalent for + /// [`Arc`](crate::sync::Arc), due to race conditions that do not apply to `Rc`.) + #[inline] + #[stable(feature = "rc_into_inner", since = "1.70.0")] + pub fn into_inner(this: Self) -> Option<T> { + Rc::try_unwrap(this).ok() + } } impl<T> Rc<[T]> { @@ -1042,7 +1058,7 @@ impl<T: ?Sized> Rc<T> { #[inline] #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] pub unsafe fn decrement_strong_count(ptr: *const T) { - unsafe { mem::drop(Rc::from_raw(ptr)) }; + unsafe { drop(Rc::from_raw(ptr)) }; } /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to @@ -1478,7 +1494,7 @@ impl<T> Rc<[T]> { /// /// Behavior is undefined should the size be wrong. #[cfg(not(no_global_oom_handling))] - unsafe fn from_iter_exact(iter: impl iter::Iterator<Item = T>, len: usize) -> Rc<[T]> { + unsafe fn from_iter_exact(iter: impl Iterator<Item = T>, len: usize) -> Rc<[T]> { // Panic guard while cloning T elements. // In the event of a panic, elements that have been written // into the new RcBox will be dropped, then the memory freed. @@ -1720,11 +1736,11 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> { /// Inequality for two `Rc`s. /// - /// Two `Rc`s are unequal if their inner values are unequal. + /// Two `Rc`s are not equal if their inner values are not equal. /// /// If `T` also implements `Eq` (implying reflexivity of equality), /// two `Rc`s that point to the same allocation are - /// never unequal. + /// always equal. /// /// # Examples /// @@ -2023,7 +2039,7 @@ where /// ```rust /// # use std::rc::Rc; /// # use std::borrow::Cow; - /// let cow: Cow<str> = Cow::Borrowed("eggplant"); + /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); /// let shared: Rc<str> = Rc::from(cow); /// assert_eq!("eggplant", &shared[..]); /// ``` @@ -2070,7 +2086,7 @@ impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_iter", since = "1.37.0")] -impl<T> iter::FromIterator<T> for Rc<[T]> { +impl<T> FromIterator<T> for Rc<[T]> { /// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`. /// /// # Performance characteristics @@ -2109,7 +2125,7 @@ impl<T> iter::FromIterator<T> for Rc<[T]> { /// let evens: Rc<[u8]> = (0..10).collect(); // Just a single allocation happens here. /// # assert_eq!(&*evens, &*(0..10).collect::<Vec<_>>()); /// ``` - fn from_iter<I: iter::IntoIterator<Item = T>>(iter: I) -> Self { + fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { ToRcSlice::to_rc_slice(iter.into_iter()) } } @@ -2145,7 +2161,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I { Rc::from_iter_exact(self, low) } } else { - // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator + // TrustedLen contract guarantees that `upper_bound == None` implies an iterator // length exceeding `usize::MAX`. // The default implementation would collect into a vec which would panic. // Thus we panic here immediately without invoking `Vec` code. @@ -2186,9 +2202,9 @@ pub struct Weak<T: ?Sized> { } #[stable(feature = "rc_weak", since = "1.4.0")] -impl<T: ?Sized> !marker::Send for Weak<T> {} +impl<T: ?Sized> !Send for Weak<T> {} #[stable(feature = "rc_weak", since = "1.4.0")] -impl<T: ?Sized> !marker::Sync for Weak<T> {} +impl<T: ?Sized> !Sync for Weak<T> {} #[unstable(feature = "coerce_unsized", issue = "18598")] impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {} diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 32433cfbdcf..2784108e0e6 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -152,6 +152,21 @@ fn try_unwrap() { } #[test] +fn into_inner() { + let x = Rc::new(3); + assert_eq!(Rc::into_inner(x), Some(3)); + + let x = Rc::new(4); + let y = Rc::clone(&x); + assert_eq!(Rc::into_inner(x), None); + assert_eq!(Rc::into_inner(y), Some(4)); + + let x = Rc::new(5); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::into_inner(x), Some(5)); +} + +#[test] fn into_from_raw() { let x = Rc::new(Box::new("hello")); let y = x.clone(); diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index afbe5cfaf8e..84977409904 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -256,7 +256,7 @@ impl str { /// assert_eq!("than an old", s.replace("is", "an")); /// ``` /// - /// When the pattern doesn't match: + /// When the pattern doesn't match, it returns this string slice as [`String`]: /// /// ``` /// let s = "this is old"; @@ -297,7 +297,7 @@ impl str { /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1)); /// ``` /// - /// When the pattern doesn't match: + /// When the pattern doesn't match, it returns this string slice as [`String`]: /// /// ``` /// let s = "this is old"; @@ -404,12 +404,12 @@ impl str { // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 // for the definition of `Final_Sigma`. debug_assert!('Σ'.len_utf8() == 2); - let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) - && !case_ignoreable_then_cased(from[i + 2..].chars()); + let is_word_final = case_ignorable_then_cased(from[..i].chars().rev()) + && !case_ignorable_then_cased(from[i + 2..].chars()); to.push_str(if is_word_final { "ς" } else { "σ" }); } - fn case_ignoreable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool { + fn case_ignorable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool { use core::unicode::{Case_Ignorable, Cased}; match iter.skip_while(|&c| Case_Ignorable(c)).next() { Some(c) => Cased(c), diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 2b843647dd5..088139a6907 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -45,9 +45,9 @@ use core::error::Error; use core::fmt; use core::hash; -use core::iter::FusedIterator; #[cfg(not(no_global_oom_handling))] -use core::iter::{from_fn, FromIterator}; +use core::iter::from_fn; +use core::iter::FusedIterator; #[cfg(not(no_global_oom_handling))] use core::ops::Add; #[cfg(not(no_global_oom_handling))] @@ -359,7 +359,7 @@ use crate::vec::Vec; /// [Deref]: core::ops::Deref "ops::Deref" /// [`Deref`]: core::ops::Deref "ops::Deref" /// [`as_str()`]: String::as_str -#[derive(PartialOrd, Eq, Ord)] +#[derive(PartialEq, PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), lang = "String")] pub struct String { @@ -2207,18 +2207,6 @@ impl<'a, 'b> Pattern<'a> for &'b String { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for String { - #[inline] - fn eq(&self, other: &String) -> bool { - PartialEq::eq(&self[..], &other[..]) - } - #[inline] - fn ne(&self, other: &String) -> bool { - PartialEq::ne(&self[..], &other[..]) - } -} - macro_rules! impl_eq { ($lhs:ty, $rhs: ty) => { #[stable(feature = "rust1", since = "1.0.0")] @@ -2259,8 +2247,7 @@ impl_eq! { Cow<'a, str>, &'b str } impl_eq! { Cow<'a, str>, String } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl const Default for String { +impl Default for String { /// Creates an empty `String`. #[inline] fn default() -> String { @@ -2540,6 +2527,15 @@ impl<T: fmt::Display + ?Sized> ToString for T { } #[cfg(not(no_global_oom_handling))] +#[unstable(feature = "ascii_char", issue = "110998")] +impl ToString for core::ascii::Char { + #[inline] + fn to_string(&self) -> String { + self.as_str().to_owned() + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "char_to_string_specialization", since = "1.46.0")] impl ToString for char { #[inline] @@ -2745,7 +2741,7 @@ impl<'a> From<Cow<'a, str>> for String { /// ``` /// # use std::borrow::Cow; /// // If the string is not owned... - /// let cow: Cow<str> = Cow::Borrowed("eggplant"); + /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); /// // It will allocate on the heap and copy the string. /// let owned: String = String::from(cow); /// assert_eq!(&owned[..], "eggplant"); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f20486ca9e4..7347980abbc 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -11,14 +11,13 @@ use core::any::Any; use core::borrow; use core::cmp::Ordering; -use core::convert::{From, TryFrom}; use core::fmt; use core::hash::{Hash, Hasher}; use core::hint; use core::intrinsics::abort; #[cfg(not(no_global_oom_handling))] use core::iter; -use core::marker::{PhantomData, Unpin, Unsize}; +use core::marker::{PhantomData, Unsize}; #[cfg(not(no_global_oom_handling))] use core::mem::size_of_val; use core::mem::{self, align_of_val_raw}; @@ -51,8 +50,16 @@ mod tests; /// /// Going above this limit will abort your program (although not /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. +/// Trying to go above it might call a `panic` (if not actually going above it). +/// +/// This is a global invariant, and also applies when using a compare-exchange loop. +/// +/// See comment in `Arc::clone`. const MAX_REFCOUNT: usize = (isize::MAX) as usize; +/// The error in case either counter reaches above `MAX_REFCOUNT`, and we can `panic` safely. +const INTERNAL_OVERFLOW_ERROR: &str = "Arc counter overflow"; + #[cfg(not(sanitize = "thread"))] macro_rules! acquire { ($x:expr) => { @@ -180,8 +187,6 @@ macro_rules! acquire { /// [mutex]: ../../std/sync/struct.Mutex.html /// [rwlock]: ../../std/sync/struct.RwLock.html /// [atomic]: core::sync::atomic -/// [`Send`]: core::marker::Send -/// [`Sync`]: core::marker::Sync /// [deref]: core::ops::Deref /// [downgrade]: Arc::downgrade /// [upgrade]: Weak::upgrade @@ -654,20 +659,17 @@ impl<T> Arc<T> { /// /// This will succeed even if there are outstanding weak references. /// - // FIXME: when `Arc::into_inner` is stabilized, add this paragraph: - /* /// It is strongly recommended to use [`Arc::into_inner`] instead if you don't /// want to keep the `Arc` in the [`Err`] case. /// Immediately dropping the [`Err`] payload, like in the expression /// `Arc::try_unwrap(this).ok()`, can still cause the strong count to /// drop to zero and the inner value of the `Arc` to be dropped: - /// For instance if two threads execute this expression in parallel, then + /// For instance if two threads each execute this expression in parallel, then /// there is a race condition. The threads could first both check whether they /// have the last clone of their `Arc` via `Arc::try_unwrap`, and then /// both drop their `Arc` in the call to [`ok`][`Result::ok`], /// taking the strong count from two down to zero. /// - */ /// # Examples /// /// ``` @@ -711,20 +713,13 @@ impl<T> Arc<T> { /// This means in particular that the inner value is not dropped. /// /// The similar expression `Arc::try_unwrap(this).ok()` does not - /// offer such a guarantee. See the last example below. - // - // FIXME: when `Arc::into_inner` is stabilized, add this to end - // of the previous sentence: - /* + /// offer such a guarantee. See the last example below /// and the documentation of [`Arc::try_unwrap`]. - */ /// /// # Examples /// /// Minimal example demonstrating the guarantee that `Arc::into_inner` gives. /// ``` - /// #![feature(arc_into_inner)] - /// /// use std::sync::Arc; /// /// let x = Arc::new(3); @@ -748,8 +743,6 @@ impl<T> Arc<T> { /// /// A more practical example demonstrating the need for `Arc::into_inner`: /// ``` - /// #![feature(arc_into_inner)] - /// /// use std::sync::Arc; /// /// // Definition of a simple singly linked list using `Arc`: @@ -799,13 +792,8 @@ impl<T> Arc<T> { /// x_thread.join().unwrap(); /// y_thread.join().unwrap(); /// ``` - - // FIXME: when `Arc::into_inner` is stabilized, adjust above documentation - // and the documentation of `Arc::try_unwrap` according to the `FIXME`s. Also - // open an issue on rust-lang/rust-clippy, asking for a lint against - // `Arc::try_unwrap(...).ok()`. #[inline] - #[unstable(feature = "arc_into_inner", issue = "106894")] + #[stable(feature = "arc_into_inner", since = "1.70.0")] pub fn into_inner(this: Self) -> Option<T> { // Make sure that the ordinary `Drop` implementation isn’t called as well let mut this = mem::ManuallyDrop::new(this); @@ -1104,6 +1092,9 @@ impl<T: ?Sized> Arc<T> { continue; } + // We can't allow the refcount to increase much past `MAX_REFCOUNT`. + assert!(cur <= MAX_REFCOUNT, "{}", INTERNAL_OVERFLOW_ERROR); + // NOTE: this code currently ignores the possibility of overflow // into usize::MAX; in general both Rc and Arc need to be adjusted // to deal with overflow. @@ -1247,7 +1238,7 @@ impl<T: ?Sized> Arc<T> { #[inline] #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] pub unsafe fn decrement_strong_count(ptr: *const T) { - unsafe { mem::drop(Arc::from_raw(ptr)) }; + unsafe { drop(Arc::from_raw(ptr)) }; } #[inline] @@ -1410,7 +1401,7 @@ impl<T> Arc<[T]> { /// /// Behavior is undefined should the size be wrong. #[cfg(not(no_global_oom_handling))] - unsafe fn from_iter_exact(iter: impl iter::Iterator<Item = T>, len: usize) -> Arc<[T]> { + unsafe fn from_iter_exact(iter: impl Iterator<Item = T>, len: usize) -> Arc<[T]> { // Panic guard while cloning T elements. // In the event of a panic, elements that have been written // into the new ArcInner will be dropped, then the memory freed. @@ -1519,6 +1510,11 @@ impl<T: ?Sized> Clone for Arc<T> { // the worst already happened and we actually do overflow the `usize` counter. However, that // requires the counter to grow from `isize::MAX` to `usize::MAX` between the increment // above and the `abort` below, which seems exceedingly unlikely. + // + // This is a global invariant, and also applies when using a compare-exchange loop to increment + // counters in other methods. + // Otherwise, the counter could be brought to an almost-overflow using a compare-exchange loop, + // and then overflow using a few `fetch_add`s. if old_size > MAX_REFCOUNT { abort(); } @@ -2180,9 +2176,7 @@ impl<T: ?Sized> Weak<T> { return None; } // See comments in `Arc::clone` for why we do this (for `mem::forget`). - if n > MAX_REFCOUNT { - abort(); - } + assert!(n <= MAX_REFCOUNT, "{}", INTERNAL_OVERFLOW_ERROR); Some(n + 1) }) .ok() @@ -2461,10 +2455,10 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> { /// Inequality for two `Arc`s. /// - /// Two `Arc`s are unequal if their inner values are unequal. + /// Two `Arc`s are not equal if their inner values are not equal. /// /// If `T` also implements `Eq` (implying reflexivity of equality), - /// two `Arc`s that point to the same value are never unequal. + /// two `Arc`s that point to the same value are always equal. /// /// # Examples /// @@ -2774,7 +2768,7 @@ where /// ```rust /// # use std::sync::Arc; /// # use std::borrow::Cow; - /// let cow: Cow<str> = Cow::Borrowed("eggplant"); + /// let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); /// let shared: Arc<str> = Arc::from(cow); /// assert_eq!("eggplant", &shared[..]); /// ``` @@ -2821,7 +2815,7 @@ impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_iter", since = "1.37.0")] -impl<T> iter::FromIterator<T> for Arc<[T]> { +impl<T> FromIterator<T> for Arc<[T]> { /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`. /// /// # Performance characteristics @@ -2860,7 +2854,7 @@ impl<T> iter::FromIterator<T> for Arc<[T]> { /// let evens: Arc<[u8]> = (0..10).collect(); // Just a single allocation happens here. /// # assert_eq!(&*evens, &*(0..10).collect::<Vec<_>>()); /// ``` - fn from_iter<I: iter::IntoIterator<Item = T>>(iter: I) -> Self { + fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { ToArcSlice::to_arc_slice(iter.into_iter()) } } @@ -2895,7 +2889,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToArcSlice<T> for I { Arc::from_iter_exact(self, low) } } else { - // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator + // TrustedLen contract guarantees that `upper_bound == None` implies an iterator // length exceeding `usize::MAX`. // The default implementation would collect into a vec which would panic. // Thus we panic here immediately without invoking `Vec` code. diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 9d8e309a978..5d9772b878b 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -39,6 +39,7 @@ use crate::sync::Arc; /// use std::sync::Arc; /// use std::task::{Context, Poll, Wake}; /// use std::thread::{self, Thread}; +/// use core::pin::pin; /// /// /// A waker that wakes up the current thread when called. /// struct ThreadWaker(Thread); @@ -52,7 +53,7 @@ use crate::sync::Arc; /// /// Run a future to completion on the current thread. /// fn block_on<T>(fut: impl Future<Output = T>) -> T { /// // Pin the future so it can be polled. -/// let mut fut = Box::pin(fut); +/// let mut fut = pin!(fut); /// /// // Create a new context to be passed to the future. /// let t = thread::current(); diff --git a/library/alloc/src/tests.rs b/library/alloc/src/tests.rs index 299ed156a5d..b1d3a9fa8ac 100644 --- a/library/alloc/src/tests.rs +++ b/library/alloc/src/tests.rs @@ -4,7 +4,6 @@ use core::any::Any; use core::clone::Clone; use core::convert::TryInto; use core::ops::Deref; -use core::result::Result::{Err, Ok}; use std::boxed::Box; @@ -15,7 +14,7 @@ fn test_owned_clone() { assert!(a == b); } -#[derive(PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] struct Test; #[test] @@ -23,24 +22,17 @@ fn any_move() { let a = Box::new(8) as Box<dyn Any>; let b = Box::new(Test) as Box<dyn Any>; - match a.downcast::<i32>() { - Ok(a) => { - assert!(a == Box::new(8)); - } - Err(..) => panic!(), - } - match b.downcast::<Test>() { - Ok(a) => { - assert!(a == Box::new(Test)); - } - Err(..) => panic!(), - } + let a: Box<i32> = a.downcast::<i32>().unwrap(); + assert_eq!(*a, 8); + + let b: Box<Test> = b.downcast::<Test>().unwrap(); + assert_eq!(*b, Test); let a = Box::new(8) as Box<dyn Any>; let b = Box::new(Test) as Box<dyn Any>; - assert!(a.downcast::<Box<Test>>().is_err()); - assert!(b.downcast::<Box<i32>>().is_err()); + assert!(a.downcast::<Box<i32>>().is_err()); + assert!(b.downcast::<Box<Test>>().is_err()); } #[test] diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index 64943a273c9..2c799605b7b 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -1,5 +1,4 @@ use crate::borrow::Cow; -use core::iter::FromIterator; use super::Vec; diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index 2b1a787cc54..f0b63759ac7 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -16,7 +16,7 @@ use super::Vec; /// /// ``` /// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::Drain<_> = v.drain(..); +/// let iter: std::vec::Drain<'_, _> = v.drain(..); /// ``` #[stable(feature = "drain", since = "1.6.0")] pub struct Drain< @@ -112,9 +112,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { let unyielded_ptr = this.iter.as_slice().as_ptr(); // ZSTs have no identity, so we don't need to move them around. - let needs_move = mem::size_of::<T>() != 0; - - if needs_move { + if !T::IS_ZST { let start_ptr = source_vec.as_mut_ptr().add(start); // memmove back unyielded elements @@ -197,7 +195,7 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> { } } - let iter = mem::replace(&mut self.iter, (&mut []).iter()); + let iter = mem::take(&mut self.iter); let drop_len = iter.len(); let mut vec = self.vec; diff --git a/library/alloc/src/vec/drain_filter.rs b/library/alloc/src/vec/drain_filter.rs index 8c03f1692d9..21b09023462 100644 --- a/library/alloc/src/vec/drain_filter.rs +++ b/library/alloc/src/vec/drain_filter.rs @@ -1,5 +1,5 @@ use crate::alloc::{Allocator, Global}; -use core::mem::{self, ManuallyDrop}; +use core::mem::{ManuallyDrop, SizedTypeProperties}; use core::ptr; use core::slice; @@ -16,7 +16,7 @@ use super::Vec; /// #![feature(drain_filter)] /// /// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); +/// let iter: std::vec::DrainFilter<'_, _, _> = v.drain_filter(|x| *x % 2 == 0); /// ``` #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[derive(Debug)] @@ -96,9 +96,7 @@ where unsafe { // ZSTs have no identity, so we don't need to move them around. - let needs_move = mem::size_of::<T>() != 0; - - if needs_move && this.idx < this.old_len && this.del > 0 { + if !T::IS_ZST && this.idx < this.old_len && this.del > 0 { let ptr = this.vec.as_mut_ptr(); let src = ptr.add(this.idx); let dst = src.sub(this.del); diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 87d61deb1eb..2f1ee8b0353 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -201,7 +201,7 @@ where // // Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce // contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the - // module documenttation why this is ok anyway. + // module documentation why this is ok anyway. let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap }; src.forget_allocation_drop_remaining(); mem::forget(dst_guard); diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 37966007eb7..b2db2fdfd18 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -11,6 +11,7 @@ use core::iter::{ }; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; +use core::num::NonZeroUsize; #[cfg(not(no_global_oom_handling))] use core::ops::Deref; use core::ptr::{self, NonNull}; @@ -107,7 +108,7 @@ impl<T, A: Allocator> IntoIter<T, A> { /// ``` /// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter(); /// let mut into_iter = std::mem::replace(&mut into_iter, Vec::new().into_iter()); - /// (&mut into_iter).for_each(core::mem::drop); + /// (&mut into_iter).for_each(drop); /// std::mem::forget(into_iter); /// ``` /// @@ -213,7 +214,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let step_size = self.len().min(n); let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size); if T::IS_ZST { @@ -227,10 +228,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> { unsafe { ptr::drop_in_place(to_drop); } - if step_size < n { - return Err(step_size); - } - Ok(()) + NonZeroUsize::new(n - step_size).map_or(Ok(()), Err) } #[inline] @@ -313,7 +311,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let step_size = self.len().min(n); if T::IS_ZST { // SAFETY: same as for advance_by() @@ -327,10 +325,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> { unsafe { ptr::drop_in_place(to_drop); } - if step_size < n { - return Err(step_size); - } - Ok(()) + NonZeroUsize::new(n - step_size).map_or(Ok(()), Err) } } @@ -347,6 +342,24 @@ impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<T, A: Allocator> TrustedLen for IntoIter<T, A> {} +#[stable(feature = "default_iters", since = "1.70.0")] +impl<T, A> Default for IntoIter<T, A> +where + A: Allocator + Default, +{ + /// Creates an empty `vec::IntoIter`. + /// + /// ``` + /// # use std::vec; + /// let iter: vec::IntoIter<u8> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// assert_eq!(iter.as_slice(), &[]); + /// ``` + fn default() -> Self { + super::Vec::new_in(Default::default()).into_iter() + } +} + #[doc(hidden)] #[unstable(issue = "none", feature = "std_internals")] #[rustc_unsafe_specialization_marker] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a07f3da78d3..97da6f06b70 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -56,13 +56,9 @@ #[cfg(not(no_global_oom_handling))] use core::cmp; use core::cmp::Ordering; -use core::convert::TryFrom; use core::fmt; use core::hash::{Hash, Hasher}; -use core::intrinsics::assume; use core::iter; -#[cfg(not(no_global_oom_handling))] -use core::iter::FromIterator; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; @@ -378,8 +374,8 @@ mod spec_extend; /// Currently, `Vec` does not guarantee the order in which elements are dropped. /// The order has changed in the past and may change again. /// -/// [`get`]: ../../std/vec/struct.Vec.html#method.get -/// [`get_mut`]: ../../std/vec/struct.Vec.html#method.get_mut +/// [`get`]: slice::get +/// [`get_mut`]: slice::get_mut /// [`String`]: crate::string::String /// [`&str`]: type@str /// [`shrink_to_fit`]: Vec::shrink_to_fit @@ -1240,11 +1236,7 @@ impl<T, A: Allocator> Vec<T, A> { pub fn as_ptr(&self) -> *const T { // We shadow the slice method of the same name to avoid going through // `deref`, which creates an intermediate reference. - let ptr = self.buf.ptr(); - unsafe { - assume(!ptr.is_null()); - } - ptr + self.buf.ptr() } /// Returns an unsafe mutable pointer to the vector's buffer, or a dangling @@ -1277,11 +1269,7 @@ impl<T, A: Allocator> Vec<T, A> { pub fn as_mut_ptr(&mut self) -> *mut T { // We shadow the slice method of the same name to avoid going through // `deref_mut`, which creates an intermediate reference. - let ptr = self.buf.ptr(); - unsafe { - assume(!ptr.is_null()); - } - ptr + self.buf.ptr() } /// Returns a reference to the underlying allocator. @@ -2999,7 +2987,7 @@ impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec<T, A> { } } -/// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). +/// Implements comparison of vectors, [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] impl<T: PartialOrd, A: Allocator> PartialOrd for Vec<T, A> { #[inline] @@ -3011,7 +2999,7 @@ impl<T: PartialOrd, A: Allocator> PartialOrd for Vec<T, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<T: Eq, A: Allocator> Eq for Vec<T, A> {} -/// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). +/// Implements ordering of vectors, [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] impl<T: Ord, A: Allocator> Ord for Vec<T, A> { #[inline] @@ -3034,8 +3022,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec<T, A> { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T> const Default for Vec<T> { +impl<T> Default for Vec<T> { /// Creates an empty `Vec<T>`. /// /// The vector will not allocate until elements are pushed onto it. @@ -3131,10 +3118,7 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> { /// ``` #[cfg(not(test))] fn from(s: [T; N]) -> Vec<T> { - <[T]>::into_vec( - #[rustc_box] - Box::new(s), - ) + <[T]>::into_vec(Box::new(s)) } #[cfg(test)] @@ -3158,8 +3142,8 @@ where /// /// ``` /// # use std::borrow::Cow; - /// let o: Cow<[i32]> = Cow::Owned(vec![1, 2, 3]); - /// let b: Cow<[i32]> = Cow::Borrowed(&[1, 2, 3]); + /// let o: Cow<'_, [i32]> = Cow::Owned(vec![1, 2, 3]); + /// let b: Cow<'_, [i32]> = Cow::Borrowed(&[1, 2, 3]); /// assert_eq!(Vec::from(o), Vec::from(b)); /// ``` fn from(s: Cow<'a, [T]>) -> Vec<T> { diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index 1861147fe72..852fdcc3f5c 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -14,7 +14,7 @@ use super::{Drain, Vec}; /// ``` /// let mut v = vec![0, 1, 2]; /// let new = [7, 8]; -/// let iter: std::vec::Splice<_> = v.splice(1.., new); +/// let iter: std::vec::Splice<'_, _> = v.splice(1.., new); /// ``` #[derive(Debug)] #[stable(feature = "vec_splice", since = "1.21.0")] diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index af49826ff30..4cacee0414d 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -61,7 +61,7 @@ fn box_deref_lval() { pub struct ConstAllocator; -unsafe impl const Allocator for ConstAllocator { +unsafe impl Allocator for ConstAllocator { fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { match layout.size() { 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), @@ -179,18 +179,3 @@ unsafe impl const Allocator for ConstAllocator { self } } - -#[test] -fn const_box() { - const VALUE: u32 = { - let mut boxed = Box::new_in(1u32, ConstAllocator); - assert!(*boxed == 1); - - *boxed = 42; - assert!(*boxed == 42); - - *Box::leak(boxed) - }; - - assert!(VALUE == 42); -} diff --git a/library/alloc/tests/const_fns.rs b/library/alloc/tests/const_fns.rs index 49b837becbc..4e7d7fc833e 100644 --- a/library/alloc/tests/const_fns.rs +++ b/library/alloc/tests/const_fns.rs @@ -1,13 +1,16 @@ // Test const functions in the library pub const MY_VEC: Vec<usize> = Vec::new(); -pub const MY_VEC2: Vec<usize> = Default::default(); + +// FIXME(#110395) +// pub const MY_VEC2: Vec<usize> = Default::default(); pub const MY_STRING: String = String::new(); -pub const MY_STRING2: String = Default::default(); -pub const MY_BOXED_SLICE: Box<[usize]> = Default::default(); -pub const MY_BOXED_STR: Box<str> = Default::default(); +// pub const MY_STRING2: String = Default::default(); + +// pub const MY_BOXED_SLICE: Box<[usize]> = Default::default(); +// pub const MY_BOXED_STR: Box<str> = Default::default(); use std::collections::{BTreeMap, BTreeSet}; @@ -23,11 +26,11 @@ pub const SET_IS_EMPTY: bool = SET.is_empty(); #[test] fn test_const() { - assert_eq!(MY_VEC, MY_VEC2); - assert_eq!(MY_STRING, MY_STRING2); + assert_eq!(MY_VEC, /* MY_VEC */ vec![]); + assert_eq!(MY_STRING, /* MY_STRING2 */ String::default()); - assert_eq!(MY_VEC, *MY_BOXED_SLICE); - assert_eq!(MY_STRING, *MY_BOXED_STR); + // assert_eq!(MY_VEC, *MY_BOXED_SLICE); + // assert_eq!(MY_STRING, *MY_BOXED_STR); assert_eq!(MAP_LEN, 0); assert_eq!(SET_LEN, 0); diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 2a93a242d51..0eca4c9bb07 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -3,12 +3,10 @@ #![feature(assert_matches)] #![feature(btree_drain_filter)] #![feature(cow_is_borrowed)] -#![feature(const_box)] -#![feature(const_convert)] #![feature(const_cow_is_borrowed)] #![feature(const_heap)] #![feature(const_mut_refs)] -#![feature(const_nonnull_slice_from_raw_parts)] +#![feature(const_slice_from_raw_parts_mut)] #![feature(const_ptr_write)] #![feature(const_try)] #![feature(core_intrinsics)] @@ -25,7 +23,6 @@ #![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_drain_sorted)] #![feature(slice_ptr_get)] -#![feature(binary_heap_retain)] #![feature(binary_heap_as_slice)] #![feature(inplace_iteration)] #![feature(iter_advance_by)] @@ -35,16 +32,13 @@ #![feature(slice_partition_dedup)] #![feature(string_remove_matches)] #![feature(const_btree_len)] -#![feature(const_default_impls)] #![feature(const_trait_impl)] #![feature(const_str_from_utf8)] -#![feature(nonnull_slice_from_raw_parts)] #![feature(panic_update_hook)] #![feature(pointer_is_aligned)] #![feature(slice_flatten)] #![feature(thin_box)] #![feature(strict_provenance)] -#![feature(once_cell)] #![feature(drain_keep_rest)] #![deny(fuzzy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index 0693beb48c4..9aa5575ca93 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -705,7 +705,7 @@ fn test_move_rev_iterator() { } #[test] -fn test_splitator() { +fn test_split_iterator() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1], &[3], &[5]]; @@ -725,7 +725,7 @@ fn test_splitator() { } #[test] -fn test_splitator_inclusive() { +fn test_split_iterator_inclusive() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; @@ -745,7 +745,7 @@ fn test_splitator_inclusive() { } #[test] -fn test_splitator_inclusive_reverse() { +fn test_split_iterator_inclusive_reverse() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; @@ -765,7 +765,7 @@ fn test_splitator_inclusive_reverse() { } #[test] -fn test_splitator_mut_inclusive() { +fn test_split_iterator_mut_inclusive() { let xs = &mut [1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; @@ -785,7 +785,7 @@ fn test_splitator_mut_inclusive() { } #[test] -fn test_splitator_mut_inclusive_reverse() { +fn test_split_iterator_mut_inclusive_reverse() { let xs = &mut [1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; @@ -805,7 +805,7 @@ fn test_splitator_mut_inclusive_reverse() { } #[test] -fn test_splitnator() { +fn test_splitn_iterator() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; @@ -821,7 +821,7 @@ fn test_splitnator() { } #[test] -fn test_splitnator_mut() { +fn test_splitn_iterator_mut() { let xs = &mut [1, 2, 3, 4, 5]; let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]]; @@ -837,7 +837,7 @@ fn test_splitnator_mut() { } #[test] -fn test_rsplitator() { +fn test_rsplit_iterator() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[5], &[3], &[1]]; @@ -855,7 +855,7 @@ fn test_rsplitator() { } #[test] -fn test_rsplitnator() { +fn test_rsplitn_iterator() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; @@ -932,7 +932,7 @@ fn test_split_iterators_size_hint() { } #[test] -fn test_windowsator() { +fn test_windows_iterator() { let v = &[1, 2, 3, 4]; let wins: &[&[_]] = &[&[1, 2], &[2, 3], &[3, 4]]; @@ -948,13 +948,13 @@ fn test_windowsator() { #[test] #[should_panic] -fn test_windowsator_0() { +fn test_windows_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.windows(0); } #[test] -fn test_chunksator() { +fn test_chunks_iterator() { let v = &[1, 2, 3, 4, 5]; assert_eq!(v.chunks(2).len(), 3); @@ -972,13 +972,13 @@ fn test_chunksator() { #[test] #[should_panic] -fn test_chunksator_0() { +fn test_chunks_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.chunks(0); } #[test] -fn test_chunks_exactator() { +fn test_chunks_exact_iterator() { let v = &[1, 2, 3, 4, 5]; assert_eq!(v.chunks_exact(2).len(), 2); @@ -996,13 +996,13 @@ fn test_chunks_exactator() { #[test] #[should_panic] -fn test_chunks_exactator_0() { +fn test_chunks_exact_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.chunks_exact(0); } #[test] -fn test_rchunksator() { +fn test_rchunks_iterator() { let v = &[1, 2, 3, 4, 5]; assert_eq!(v.rchunks(2).len(), 3); @@ -1020,13 +1020,13 @@ fn test_rchunksator() { #[test] #[should_panic] -fn test_rchunksator_0() { +fn test_rchunks_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.rchunks(0); } #[test] -fn test_rchunks_exactator() { +fn test_rchunks_exact_iterator() { let v = &[1, 2, 3, 4, 5]; assert_eq!(v.rchunks_exact(2).len(), 2); @@ -1044,7 +1044,7 @@ fn test_rchunks_exactator() { #[test] #[should_panic] -fn test_rchunks_exactator_0() { +fn test_rchunks_exact_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.rchunks_exact(0); } @@ -1219,7 +1219,7 @@ fn test_ends_with() { } #[test] -fn test_mut_splitator() { +fn test_mut_split_iterator() { let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0]; assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); for slice in xs.split_mut(|x| *x == 0) { @@ -1235,7 +1235,7 @@ fn test_mut_splitator() { } #[test] -fn test_mut_splitator_rev() { +fn test_mut_split_iterator_rev() { let mut xs = [1, 2, 0, 3, 4, 0, 0, 5, 6, 0]; for slice in xs.split_mut(|x| *x == 0).rev().take(4) { slice.reverse(); diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index 4d182be02c9..c1dbbde08b6 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1499,13 +1499,25 @@ fn test_split_whitespace() { #[test] fn test_lines() { - let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n"; - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); - - let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); + fn t(data: &str, expected: &[&str]) { + let lines: Vec<&str> = data.lines().collect(); + assert_eq!(lines, expected); + } + t("", &[]); + t("\n", &[""]); + t("\n2nd", &["", "2nd"]); + t("\r\n", &[""]); + t("bare\r", &["bare\r"]); + t("bare\rcr", &["bare\rcr"]); + t("Text\n\r", &["Text", "\r"]); + t( + "\nMäry häd ä little lämb\n\r\nLittle lämb\n", + &["", "Märy häd ä little lämb", "", "Little lämb"], + ); + t( + "\r\nMäry häd ä little lämb\n\nLittle lämb", + &["", "Märy häd ä little lämb", "", "Little lämb"], + ); } #[test] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 2f07c2911a5..cc4c1f12728 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1,5 +1,7 @@ use core::alloc::{Allocator, Layout}; +use core::assert_eq; use core::iter::IntoIterator; +use core::num::NonZeroUsize; use core::ptr::NonNull; use std::alloc::System; use std::assert_matches::assert_matches; @@ -1062,21 +1064,21 @@ fn test_into_iter_leak() { #[test] fn test_into_iter_advance_by() { - let mut i = [1, 2, 3, 4, 5].into_iter(); - i.advance_by(0).unwrap(); - i.advance_back_by(0).unwrap(); + let mut i = vec![1, 2, 3, 4, 5].into_iter(); + assert_eq!(i.advance_by(0), Ok(())); + assert_eq!(i.advance_back_by(0), Ok(())); assert_eq!(i.as_slice(), [1, 2, 3, 4, 5]); - i.advance_by(1).unwrap(); - i.advance_back_by(1).unwrap(); + assert_eq!(i.advance_by(1), Ok(())); + assert_eq!(i.advance_back_by(1), Ok(())); assert_eq!(i.as_slice(), [2, 3, 4]); - assert_eq!(i.advance_back_by(usize::MAX), Err(3)); + assert_eq!(i.advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 3).unwrap())); - assert_eq!(i.advance_by(usize::MAX), Err(0)); + assert_eq!(i.advance_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX).unwrap())); - i.advance_by(0).unwrap(); - i.advance_back_by(0).unwrap(); + assert_eq!(i.advance_by(0), Ok(())); + assert_eq!(i.advance_back_by(0), Ok(())); assert_eq!(i.len(), 0); } @@ -1124,7 +1126,7 @@ fn test_into_iter_zst() { for _ in vec![C; 5].into_iter().rev() {} let mut it = vec![C, C].into_iter(); - it.advance_by(1).unwrap(); + assert_eq!(it.advance_by(1), Ok(())); drop(it); let mut it = vec![C, C].into_iter(); @@ -2468,7 +2470,7 @@ fn test_vec_dedup_panicking() { // Regression test for issue #82533 #[test] -fn test_extend_from_within_panicing_clone() { +fn test_extend_from_within_panicking_clone() { struct Panic<'dc> { drop_count: &'dc AtomicU32, aaaaa: bool, diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index 0b8f5281b78..ddc27e34ed9 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -1,3 +1,4 @@ +use core::num::NonZeroUsize; use std::assert_matches::assert_matches; use std::collections::TryReserveErrorKind::*; use std::collections::{vec_deque::Drain, VecDeque}; @@ -426,6 +427,28 @@ fn test_into_iter() { assert_eq!(it.next(), Some(7)); assert_eq!(it.size_hint(), (5, Some(5))); } + + // advance_by + { + let mut d = VecDeque::new(); + for i in 0..=4 { + d.push_back(i); + } + for i in 6..=8 { + d.push_front(i); + } + + let mut it = d.into_iter(); + assert_eq!(it.advance_by(1), Ok(())); + assert_eq!(it.next(), Some(7)); + assert_eq!(it.advance_back_by(1), Ok(())); + assert_eq!(it.next_back(), Some(3)); + + let mut it = VecDeque::from(vec![1, 2, 3, 4, 5]).into_iter(); + assert_eq!(it.advance_by(10), Err(NonZeroUsize::new(5).unwrap())); + let mut it = VecDeque::from(vec![1, 2, 3, 4, 5]).into_iter(); + assert_eq!(it.advance_back_by(10), Err(NonZeroUsize::new(5).unwrap())); + } } #[test] @@ -1046,6 +1069,20 @@ fn test_append_double_drop() { } #[test] +#[should_panic] +fn test_append_zst_capacity_overflow() { + let mut v = Vec::with_capacity(usize::MAX); + // note: using resize instead of set_len here would + // be *extremely* slow in unoptimized builds. + // SAFETY: `v` has capacity `usize::MAX`, and no initialization + // is needed for empty tuples. + unsafe { v.set_len(usize::MAX) }; + let mut v = VecDeque::from(v); + let mut w = vec![()].into(); + v.append(&mut w); +} + +#[test] fn test_retain() { let mut buf = VecDeque::new(); buf.extend(1..5); diff --git a/library/backtrace b/library/backtrace -Subproject 07872f28cd8a65c3c7428811548dc85f1f2fb05 +Subproject 4245978ca8169c40c088ff733825e4527f7b914 diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index e4100120d82..74ef0949b8a 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -20,6 +20,7 @@ mod ops; mod pattern; mod slice; mod str; +mod tuple; /// Returns a `rand::Rng` seeded with a consistent seed. /// diff --git a/library/core/benches/num/flt2dec/strategy/grisu.rs b/library/core/benches/num/flt2dec/strategy/grisu.rs index 6bea5e55d37..17d6b474ad2 100644 --- a/library/core/benches/num/flt2dec/strategy/grisu.rs +++ b/library/core/benches/num/flt2dec/strategy/grisu.rs @@ -81,3 +81,30 @@ fn bench_big_exact_inf(b: &mut Bencher) { format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } + +#[bench] +fn bench_one_exact_inf(b: &mut Bencher) { + let decoded = decode_finite(1.0); + let mut buf = [MaybeUninit::new(0); 1024]; + b.iter(|| { + format_exact(black_box(&decoded), &mut buf, i16::MIN); + }); +} + +#[bench] +fn bench_trailing_zero_exact_inf(b: &mut Bencher) { + let decoded = decode_finite(250.000000000000000000000000); + let mut buf = [MaybeUninit::new(0); 1024]; + b.iter(|| { + format_exact(black_box(&decoded), &mut buf, i16::MIN); + }); +} + +#[bench] +fn bench_halfway_point_exact_inf(b: &mut Bencher) { + let decoded = decode_finite(1.00000000000000011102230246251565404236316680908203125); + let mut buf = [MaybeUninit::new(0); 1024]; + b.iter(|| { + format_exact(black_box(&decoded), &mut buf, i16::MIN); + }); +} diff --git a/library/core/benches/tuple.rs b/library/core/benches/tuple.rs new file mode 100644 index 00000000000..d9ff9d0dd93 --- /dev/null +++ b/library/core/benches/tuple.rs @@ -0,0 +1,22 @@ +use rand::prelude::*; +use test::{black_box, Bencher}; + +#[bench] +fn bench_tuple_comparison(b: &mut Bencher) { + let mut rng = black_box(super::bench_rng()); + + let data = black_box([ + ("core::iter::adapters::Chain", 123_usize), + ("core::iter::adapters::Clone", 456_usize), + ("core::iter::adapters::Copie", 789_usize), + ("core::iter::adapters::Cycle", 123_usize), + ("core::iter::adapters::Flatt", 456_usize), + ("core::iter::adapters::TakeN", 789_usize), + ]); + + b.iter(|| { + let x = data.choose(&mut rng).unwrap(); + let y = data.choose(&mut rng).unwrap(); + [x < y, x <= y, x > y, x >= y] + }); +} diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index ac3d84718d5..59730303734 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -231,9 +231,8 @@ impl Layout { /// Returns an error if the combination of `self.size()` and the given /// `align` violates the conditions listed in [`Layout::from_size_align`]. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] - #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub const fn align_to(&self, align: usize) -> Result<Self, LayoutError> { + pub fn align_to(&self, align: usize) -> Result<Self, LayoutError> { Layout::from_size_align(self.size(), cmp::max(self.align(), align)) } @@ -315,9 +314,8 @@ impl Layout { /// /// On arithmetic overflow, returns `LayoutError`. #[unstable(feature = "alloc_layout_extra", issue = "55724")] - #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { + pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { // This cannot overflow. Quoting from the invariant of Layout: // > `size`, when rounded up to the nearest multiple of `align`, // > must not overflow isize (i.e., the rounded value must be @@ -376,9 +374,8 @@ impl Layout { /// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16]))); /// ``` #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] - #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { + pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { let new_align = cmp::max(self.align, next.align); let pad = self.padding_needed_for(next.align()); @@ -403,9 +400,8 @@ impl Layout { /// /// On arithmetic overflow, returns `LayoutError`. #[unstable(feature = "alloc_layout_extra", issue = "55724")] - #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub const fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> { + pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> { let size = self.size().checked_mul(n).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. Layout::from_size_alignment(size, self.align) @@ -418,9 +414,8 @@ impl Layout { /// /// On arithmetic overflow, returns `LayoutError`. #[unstable(feature = "alloc_layout_extra", issue = "55724")] - #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub const fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> { + pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> { let new_size = self.size().checked_add(next.size()).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. Layout::from_size_alignment(new_size, self.align) diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index a6082455fac..d6ae2b8213f 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -95,17 +95,16 @@ impl fmt::Display for AllocError { /// # Safety /// /// * Memory blocks returned from an allocator must point to valid memory and retain their validity -/// until the instance and all of its clones are dropped, +/// until the instance and all of its copies and clones are dropped, /// -/// * cloning or moving the allocator must not invalidate memory blocks returned from this -/// allocator. A cloned allocator must behave like the same allocator, and +/// * copying, cloning, or moving the allocator must not invalidate memory blocks returned from this +/// allocator. A copied or cloned allocator must behave like the same allocator, and /// /// * any pointer to a memory block which is [*currently allocated*] may be passed to any other /// method of the allocator. /// /// [*currently allocated*]: #currently-allocated-memory #[unstable(feature = "allocator_api", issue = "32838")] -#[const_trait] pub unsafe trait Allocator { /// Attempts to allocate a block of memory. /// diff --git a/library/core/src/any.rs b/library/core/src/any.rs index c0fb0d993c3..bb93ea509d8 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -56,7 +56,7 @@ //! let value_any = value as &dyn Any; //! //! // Try to convert our value to a `String`. If successful, we want to -//! // output the String`'s length as well as its value. If not, it's a +//! // output the `String`'s length as well as its value. If not, it's a //! // different type: just print it out unadorned. //! match value_any.downcast_ref::<String>() { //! Some(as_string) => { @@ -662,8 +662,7 @@ impl dyn Any + Send + Sync { /// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth /// noting that the hashes and ordering will vary between Rust releases. Beware /// of relying on them inside of your code! -#[derive(Clone, Copy, Debug, Hash, Eq)] -#[derive_const(PartialEq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct TypeId { t: u64, diff --git a/library/core/src/array/ascii.rs b/library/core/src/array/ascii.rs new file mode 100644 index 00000000000..3fea9a44049 --- /dev/null +++ b/library/core/src/array/ascii.rs @@ -0,0 +1,47 @@ +use crate::ascii; + +#[cfg(not(test))] +impl<const N: usize> [u8; N] { + /// Converts this array of bytes into a array of ASCII characters, + /// or returns `None` if any of the characters is non-ASCII. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char)] + /// #![feature(const_option)] + /// + /// const HEX_DIGITS: [std::ascii::Char; 16] = + /// *b"0123456789abcdef".as_ascii().unwrap(); + /// + /// assert_eq!(HEX_DIGITS[1].as_str(), "1"); + /// assert_eq!(HEX_DIGITS[10].as_str(), "a"); + /// ``` + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const fn as_ascii(&self) -> Option<&[ascii::Char; N]> { + if self.is_ascii() { + // SAFETY: Just checked that it's ASCII + Some(unsafe { self.as_ascii_unchecked() }) + } else { + None + } + } + + /// Converts this array of bytes into a array of ASCII characters, + /// without checking whether they're valid. + /// + /// # Safety + /// + /// Every byte in the array must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char; N] { + let byte_ptr: *const [u8; N] = self; + let ascii_ptr = byte_ptr as *const [ascii::Char; N]; + // SAFETY: The caller promised all the bytes are ASCII + unsafe { &*ascii_ptr } + } +} diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index b2c895f882c..d749865f76f 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -1,6 +1,5 @@ +use crate::cmp::BytewiseEq; use crate::convert::TryInto; -use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; -use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; #[stable(feature = "rust1", since = "1.0.0")] impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N] @@ -144,74 +143,14 @@ impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T { } } -impl<T: IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T { +impl<T: BytewiseEq<U>, U, const N: usize> SpecArrayEq<U, N> for T { fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { - // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`. - unsafe { - let b = &*b.as_ptr().cast::<[T; N]>(); - crate::intrinsics::raw_eq(a, b) - } + // SAFETY: Arrays are compared element-wise, and don't add any padding + // between elements, so when the elements are `BytewiseEq`, we can + // compare the entire array at once. + unsafe { crate::intrinsics::raw_eq(a, crate::mem::transmute(b)) } } fn spec_ne(a: &[T; N], b: &[U; N]) -> bool { !Self::spec_eq(a, b) } } - -/// `U` exists on here mostly because `min_specialization` didn't let me -/// repeat the `T` type parameter in the above specialization, so instead -/// the `T == U` constraint comes from the impls on this. -/// # Safety -/// - Neither `Self` nor `U` has any padding. -/// - `Self` and `U` have the same layout. -/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things) -#[rustc_specialization_trait] -unsafe trait IsRawEqComparable<U>: PartialEq<U> {} - -macro_rules! is_raw_eq_comparable { - ($($t:ty),+ $(,)?) => {$( - unsafe impl IsRawEqComparable<$t> for $t {} - )+}; -} - -// SAFETY: All the ordinary integer types have no padding, and are not pointers. -is_raw_eq_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); - -// SAFETY: bool and char have *niches*, but no *padding* (and these are not pointer types), so this -// is sound -is_raw_eq_comparable!(bool, char); - -// SAFETY: Similarly, the non-zero types have a niche, but no undef and no pointers, -// and they compare like their underlying numeric type. -is_raw_eq_comparable!( - NonZeroU8, - NonZeroU16, - NonZeroU32, - NonZeroU64, - NonZeroU128, - NonZeroUsize, - NonZeroI8, - NonZeroI16, - NonZeroI32, - NonZeroI64, - NonZeroI128, - NonZeroIsize, -); - -// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus -// are also safe to equality-compare bitwise inside an `Option`. -// The way `PartialOrd` is defined for `Option` means that this wouldn't work -// for `<` or `>` on the signed types, but since we only do `==` it's fine. -is_raw_eq_comparable!( - Option<NonZeroU8>, - Option<NonZeroU16>, - Option<NonZeroU32>, - Option<NonZeroU64>, - Option<NonZeroU128>, - Option<NonZeroUsize>, - Option<NonZeroI8>, - Option<NonZeroI16>, - Option<NonZeroI32>, - Option<NonZeroI64>, - Option<NonZeroI128>, - Option<NonZeroIsize>, -); diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 8259c087d22..587877dff55 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -1,9 +1,11 @@ //! Defines the `IntoIter` owned iterator for arrays. +use crate::num::NonZeroUsize; use crate::{ fmt, + intrinsics::transmute_unchecked, iter::{self, ExactSizeIterator, FusedIterator, TrustedLen}, - mem::{self, MaybeUninit}, + mem::MaybeUninit, ops::{IndexRange, Range}, ptr, }; @@ -62,18 +64,11 @@ impl<T, const N: usize> IntoIterator for [T; N] { // an array of `T`. // // With that, this initialization satisfies the invariants. - - // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it - // works with const generics: - // `mem::transmute::<[T; N], [MaybeUninit<T>; N]>(array)` // - // Until then, we can use `mem::transmute_copy` to create a bitwise copy - // as a different type, then forget `array` so that it is not dropped. - unsafe { - let iter = IntoIter { data: mem::transmute_copy(&self), alive: IndexRange::zero_to(N) }; - mem::forget(self); - iter - } + // FIXME: If normal `transmute` ever gets smart enough to allow this + // directly, use it instead of `transmute_unchecked`. + let data: [MaybeUninit<T>; N] = unsafe { transmute_unchecked(self) }; + IntoIter { data, alive: IndexRange::zero_to(N) } } } @@ -284,12 +279,11 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> { self.next_back() } - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let original_len = self.len(); - + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // This also moves the start, which marks them as conceptually "dropped", // so if anything goes bad then our drop impl won't double-free them. let range_to_drop = self.alive.take_prefix(n); + let remaining = n - range_to_drop.len(); // SAFETY: These elements are currently initialized, so it's fine to drop them. unsafe { @@ -297,7 +291,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> { ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); } - if n > original_len { Err(original_len) } else { Ok(()) } + NonZeroUsize::new(remaining).map_or(Ok(()), Err) } } @@ -334,12 +328,11 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> { }) } - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - let original_len = self.len(); - + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // This also moves the end, which marks them as conceptually "dropped", // so if anything goes bad then our drop impl won't double-free them. let range_to_drop = self.alive.take_suffix(n); + let remaining = n - range_to_drop.len(); // SAFETY: These elements are currently initialized, so it's fine to drop them. unsafe { @@ -347,7 +340,7 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> { ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); } - if n > original_len { Err(original_len) } else { Ok(()) } + NonZeroUsize::new(remaining).map_or(Ok(()), Err) } } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 1643842d607..bdb4c975909 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -17,6 +17,7 @@ use crate::ops::{ }; use crate::slice::{Iter, IterMut}; +mod ascii; mod drain; mod equality; mod iter; @@ -148,8 +149,7 @@ impl Error for TryFromSliceError { } #[stable(feature = "try_from_slice_error", since = "1.36.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl const From<Infallible> for TryFromSliceError { +impl From<Infallible> for TryFromSliceError { fn from(x: Infallible) -> TryFromSliceError { match x {} } @@ -172,16 +172,14 @@ impl<T, const N: usize> AsMut<[T]> for [T; N] { } #[stable(feature = "array_borrow", since = "1.4.0")] -#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] -impl<T, const N: usize> const Borrow<[T]> for [T; N] { +impl<T, const N: usize> Borrow<[T]> for [T; N] { fn borrow(&self) -> &[T] { self } } #[stable(feature = "array_borrow", since = "1.4.0")] -#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] -impl<T, const N: usize> const BorrowMut<[T]> for [T; N] { +impl<T, const N: usize> BorrowMut<[T]> for [T; N] { fn borrow_mut(&mut self) -> &mut [T] { self } @@ -251,7 +249,7 @@ where impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { type Error = TryFromSliceError; - fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> { + fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> { if slice.len() == N { let ptr = slice.as_ptr() as *const [T; N]; // SAFETY: ok because we just checked that the length fits @@ -278,7 +276,7 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { type Error = TryFromSliceError; - fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> { + fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> { if slice.len() == N { let ptr = slice.as_mut_ptr() as *mut [T; N]; // SAFETY: ok because we just checked that the length fits @@ -336,10 +334,9 @@ impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] { } #[stable(feature = "index_trait_on_arrays", since = "1.50.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -impl<T, I, const N: usize> const Index<I> for [T; N] +impl<T, I, const N: usize> Index<I> for [T; N] where - [T]: ~const Index<I>, + [T]: Index<I>, { type Output = <[T] as Index<I>>::Output; @@ -350,10 +347,9 @@ where } #[stable(feature = "index_trait_on_arrays", since = "1.50.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -impl<T, I, const N: usize> const IndexMut<I> for [T; N] +impl<T, I, const N: usize> IndexMut<I> for [T; N] where - [T]: ~const IndexMut<I>, + [T]: IndexMut<I>, { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { @@ -435,8 +431,7 @@ impl<T: Copy> SpecArrayClone for T { macro_rules! array_impl_default { {$n:expr, $t:ident $($ts:ident)*} => { #[stable(since = "1.4.0", feature = "array_default")] - #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] - impl<T> const Default for [T; $n] where T: ~const Default { + impl<T> Default for [T; $n] where T: Default { fn default() -> [T; $n] { [$t::default(), $($ts::default()),*] } @@ -445,8 +440,7 @@ macro_rules! array_impl_default { }; {$n:expr,} => { #[stable(since = "1.4.0", feature = "array_default")] - #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] - impl<T> const Default for [T; $n] { + impl<T> Default for [T; $n] { fn default() -> [T; $n] { [] } } }; diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index 8a4cb78cc7f..7fd14a7e1ea 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -9,10 +9,14 @@ #![stable(feature = "core_ascii", since = "1.26.0")] +use crate::escape; use crate::fmt; use crate::iter::FusedIterator; -use crate::ops::Range; -use crate::str::from_utf8_unchecked; +use crate::num::NonZeroUsize; + +mod ascii_char; +#[unstable(feature = "ascii_char", issue = "110998")] +pub use ascii_char::AsciiChar as Char; /// An iterator over the escaped version of a byte. /// @@ -21,10 +25,7 @@ use crate::str::from_utf8_unchecked; #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] -pub struct EscapeDefault { - range: Range<u8>, - data: [u8; 4], -} +pub struct EscapeDefault(escape::EscapeIterInner<4>); /// Returns an iterator that produces an escaped version of a `u8`. /// @@ -90,21 +91,9 @@ pub struct EscapeDefault { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn escape_default(c: u8) -> EscapeDefault { - let (data, len) = match c { - b'\t' => ([b'\\', b't', 0, 0], 2), - b'\r' => ([b'\\', b'r', 0, 0], 2), - b'\n' => ([b'\\', b'n', 0, 0], 2), - b'\\' => ([b'\\', b'\\', 0, 0], 2), - b'\'' => ([b'\\', b'\'', 0, 0], 2), - b'"' => ([b'\\', b'"', 0, 0], 2), - b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1), - _ => { - let hex_digits: &[u8; 16] = b"0123456789abcdef"; - ([b'\\', b'x', hex_digits[(c >> 4) as usize], hex_digits[(c & 0xf) as usize]], 4) - } - }; - - return EscapeDefault { range: 0..len, data }; + let mut data = [0; 4]; + let range = escape::escape_ascii_into(&mut data, c); + EscapeDefault(escape::EscapeIterInner::new(data, range)) } #[stable(feature = "rust1", since = "1.0.0")] @@ -113,33 +102,59 @@ impl Iterator for EscapeDefault { #[inline] fn next(&mut self) -> Option<u8> { - self.range.next().map(|i| self.data[i as usize]) + self.0.next() } + + #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - self.range.size_hint() + let n = self.0.len(); + (n, Some(n)) } + + #[inline] + fn count(self) -> usize { + self.0.len() + } + + #[inline] fn last(mut self) -> Option<u8> { - self.next_back() + self.0.next_back() + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.0.advance_by(n) } } + #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for EscapeDefault { + #[inline] fn next_back(&mut self) -> Option<u8> { - self.range.next_back().map(|i| self.data[i as usize]) + self.0.next_back() + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.0.advance_back_by(n) } } + #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for EscapeDefault {} +impl ExactSizeIterator for EscapeDefault { + #[inline] + fn len(&self) -> usize { + self.0.len() + } +} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDefault {} #[stable(feature = "ascii_escape_display", since = "1.39.0")] impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // SAFETY: ok because `escape_default` created only valid utf-8 data - f.write_str(unsafe { - from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)]) - }) + f.write_str(self.0.as_str()) } } diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs new file mode 100644 index 00000000000..f093a0990d1 --- /dev/null +++ b/library/core/src/ascii/ascii_char.rs @@ -0,0 +1,565 @@ +//! This uses the name `AsciiChar`, even though it's not exposed that way right now, +//! because it avoids a whole bunch of "are you sure you didn't mean `char`?" +//! suggestions from rustc if you get anything slightly wrong in here, and overall +//! helps with clarity as we're also referring to `char` intentionally in here. + +use crate::fmt; +use crate::mem::transmute; + +/// One of the 128 Unicode characters from U+0000 through U+007F, +/// often known as the [ASCII] subset. +/// +/// Officially, this is the first [block] in Unicode, _Basic Latin_. +/// For details, see the [*C0 Controls and Basic Latin*][chart] code chart. +/// +/// This block was based on older 7-bit character code standards such as +/// ANSI X3.4-1977, ISO 646-1973, and [NIST FIPS 1-2]. +/// +/// # When to use this +/// +/// The main advantage of this subset is that it's always valid UTF-8. As such, +/// the `&[ascii::Char]` -> `&str` conversion function (as well as other related +/// ones) are O(1): *no* runtime checks are needed. +/// +/// If you're consuming strings, you should usually handle Unicode and thus +/// accept `str`s, not limit yourself to `ascii::Char`s. +/// +/// However, certain formats are intentionally designed to produce ASCII-only +/// output in order to be 8-bit-clean. In those cases, it can be simpler and +/// faster to generate `ascii::Char`s instead of dealing with the variable width +/// properties of general UTF-8 encoded strings, while still allowing the result +/// to be used freely with other Rust things that deal in general `str`s. +/// +/// For example, a UUID library might offer a way to produce the string +/// representation of a UUID as an `[ascii::Char; 36]` to avoid memory +/// allocation yet still allow it to be used as UTF-8 via `as_str` without +/// paying for validation (or needing `unsafe` code) the way it would if it +/// were provided as a `[u8; 36]`. +/// +/// # Layout +/// +/// This type is guaranteed to have a size and alignment of 1 byte. +/// +/// # Names +/// +/// The variants on this type are [Unicode names][NamesList] of the characters +/// in upper camel case, with a few tweaks: +/// - For `<control>` characters, the primary alias name is used. +/// - `LATIN` is dropped, as this block has no non-latin letters. +/// - `LETTER` is dropped, as `CAPITAL`/`SMALL` suffices in this block. +/// - `DIGIT`s use a single digit rather than writing out `ZERO`, `ONE`, etc. +/// +/// [ASCII]: https://www.unicode.org/glossary/index.html#ASCII +/// [block]: https://www.unicode.org/glossary/index.html#block +/// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf +/// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf +/// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[unstable(feature = "ascii_char", issue = "110998")] +#[repr(u8)] +pub enum AsciiChar { + /// U+0000 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Null = 0, + /// U+0001 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + StartOfHeading = 1, + /// U+0002 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + StartOfText = 2, + /// U+0003 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfText = 3, + /// U+0004 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfTransmission = 4, + /// U+0005 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Enquiry = 5, + /// U+0006 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Acknowledge = 6, + /// U+0007 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Bell = 7, + /// U+0008 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Backspace = 8, + /// U+0009 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CharacterTabulation = 9, + /// U+000A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LineFeed = 10, + /// U+000B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LineTabulation = 11, + /// U+000C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + FormFeed = 12, + /// U+000D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CarriageReturn = 13, + /// U+000E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ShiftOut = 14, + /// U+000F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ShiftIn = 15, + /// U+0010 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DataLinkEscape = 16, + /// U+0011 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlOne = 17, + /// U+0012 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlTwo = 18, + /// U+0013 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlThree = 19, + /// U+0014 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DeviceControlFour = 20, + /// U+0015 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + NegativeAcknowledge = 21, + /// U+0016 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SynchronousIdle = 22, + /// U+0017 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfTransmissionBlock = 23, + /// U+0018 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Cancel = 24, + /// U+0019 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EndOfMedium = 25, + /// U+001A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Substitute = 26, + /// U+001B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Escape = 27, + /// U+001C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorFour = 28, + /// U+001D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorThree = 29, + /// U+001E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorTwo = 30, + /// U+001F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + InformationSeparatorOne = 31, + /// U+0020 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Space = 32, + /// U+0021 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ExclamationMark = 33, + /// U+0022 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + QuotationMark = 34, + /// U+0023 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + NumberSign = 35, + /// U+0024 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + DollarSign = 36, + /// U+0025 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + PercentSign = 37, + /// U+0026 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Ampersand = 38, + /// U+0027 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Apostrophe = 39, + /// U+0028 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftParenthesis = 40, + /// U+0029 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightParenthesis = 41, + /// U+002A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Asterisk = 42, + /// U+002B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + PlusSign = 43, + /// U+002C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Comma = 44, + /// U+002D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + HyphenMinus = 45, + /// U+002E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + FullStop = 46, + /// U+002F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Solidus = 47, + /// U+0030 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit0 = 48, + /// U+0031 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit1 = 49, + /// U+0032 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit2 = 50, + /// U+0033 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit3 = 51, + /// U+0034 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit4 = 52, + /// U+0035 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit5 = 53, + /// U+0036 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit6 = 54, + /// U+0037 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit7 = 55, + /// U+0038 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit8 = 56, + /// U+0039 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Digit9 = 57, + /// U+003A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Colon = 58, + /// U+003B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Semicolon = 59, + /// U+003C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LessThanSign = 60, + /// U+003D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + EqualsSign = 61, + /// U+003E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + GreaterThanSign = 62, + /// U+003F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + QuestionMark = 63, + /// U+0040 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CommercialAt = 64, + /// U+0041 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalA = 65, + /// U+0042 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalB = 66, + /// U+0043 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalC = 67, + /// U+0044 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalD = 68, + /// U+0045 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalE = 69, + /// U+0046 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalF = 70, + /// U+0047 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalG = 71, + /// U+0048 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalH = 72, + /// U+0049 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalI = 73, + /// U+004A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalJ = 74, + /// U+004B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalK = 75, + /// U+004C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalL = 76, + /// U+004D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalM = 77, + /// U+004E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalN = 78, + /// U+004F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalO = 79, + /// U+0050 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalP = 80, + /// U+0051 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalQ = 81, + /// U+0052 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalR = 82, + /// U+0053 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalS = 83, + /// U+0054 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalT = 84, + /// U+0055 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalU = 85, + /// U+0056 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalV = 86, + /// U+0057 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalW = 87, + /// U+0058 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalX = 88, + /// U+0059 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalY = 89, + /// U+005A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CapitalZ = 90, + /// U+005B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftSquareBracket = 91, + /// U+005C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + ReverseSolidus = 92, + /// U+005D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightSquareBracket = 93, + /// U+005E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + CircumflexAccent = 94, + /// U+005F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LowLine = 95, + /// U+0060 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + GraveAccent = 96, + /// U+0061 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallA = 97, + /// U+0062 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallB = 98, + /// U+0063 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallC = 99, + /// U+0064 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallD = 100, + /// U+0065 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallE = 101, + /// U+0066 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallF = 102, + /// U+0067 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallG = 103, + /// U+0068 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallH = 104, + /// U+0069 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallI = 105, + /// U+006A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallJ = 106, + /// U+006B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallK = 107, + /// U+006C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallL = 108, + /// U+006D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallM = 109, + /// U+006E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallN = 110, + /// U+006F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallO = 111, + /// U+0070 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallP = 112, + /// U+0071 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallQ = 113, + /// U+0072 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallR = 114, + /// U+0073 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallS = 115, + /// U+0074 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallT = 116, + /// U+0075 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallU = 117, + /// U+0076 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallV = 118, + /// U+0077 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallW = 119, + /// U+0078 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallX = 120, + /// U+0079 + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallY = 121, + /// U+007A + #[unstable(feature = "ascii_char_variants", issue = "110998")] + SmallZ = 122, + /// U+007B + #[unstable(feature = "ascii_char_variants", issue = "110998")] + LeftCurlyBracket = 123, + /// U+007C + #[unstable(feature = "ascii_char_variants", issue = "110998")] + VerticalLine = 124, + /// U+007D + #[unstable(feature = "ascii_char_variants", issue = "110998")] + RightCurlyBracket = 125, + /// U+007E + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Tilde = 126, + /// U+007F + #[unstable(feature = "ascii_char_variants", issue = "110998")] + Delete = 127, +} + +impl AsciiChar { + /// Creates an ascii character from the byte `b`, + /// or returns `None` if it's too large. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn from_u8(b: u8) -> Option<Self> { + if b <= 127 { + // SAFETY: Just checked that `b` is in-range + Some(unsafe { Self::from_u8_unchecked(b) }) + } else { + None + } + } + + /// Creates an ASCII character from the byte `b`, + /// without checking whether it's valid. + /// + /// # Safety + /// + /// `b` must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const unsafe fn from_u8_unchecked(b: u8) -> Self { + // SAFETY: Our safety precondition is that `b` is in-range. + unsafe { transmute(b) } + } + + /// When passed the *number* `0`, `1`, …, `9`, returns the *character* + /// `'0'`, `'1'`, …, `'9'` respectively. + /// + /// If `d >= 10`, returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn digit(d: u8) -> Option<Self> { + if d < 10 { + // SAFETY: Just checked it's in-range. + Some(unsafe { Self::digit_unchecked(d) }) + } else { + None + } + } + + /// When passed the *number* `0`, `1`, …, `9`, returns the *character* + /// `'0'`, `'1'`, …, `'9'` respectively, without checking that it's in-range. + /// + /// # Safety + /// + /// This is immediate UB if called with `d > 64`. + /// + /// If `d >= 10` and `d <= 64`, this is allowed to return any value or panic. + /// Notably, it should not be expected to return hex digits, or any other + /// reasonable extension of the decimal digits. + /// + /// (This lose safety condition is intended to simplify soundness proofs + /// when writing code using this method, since the implementation doesn't + /// need something really specific, not to make those other arguments do + /// something useful. It might be tightened before stabilization.) + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const unsafe fn digit_unchecked(d: u8) -> Self { + debug_assert!(d < 10); + + // SAFETY: `'0'` through `'9'` are U+00030 through U+0039, + // so because `d` must be 64 or less the addition can return at most + // 112 (0x70), which doesn't overflow and is within the ASCII range. + unsafe { + let byte = b'0'.unchecked_add(d); + Self::from_u8_unchecked(byte) + } + } + + /// Gets this ASCII character as a byte. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_u8(self) -> u8 { + self as u8 + } + + /// Gets this ASCII character as a `char` Unicode Scalar Value. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_char(self) -> char { + self as u8 as char + } + + /// Views this ASCII character as a one-code-unit UTF-8 `str`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_str(&self) -> &str { + crate::slice::from_ref(self).as_str() + } +} + +impl [AsciiChar] { + /// Views this slice of ASCII characters as a UTF-8 `str`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_str(&self) -> &str { + let ascii_ptr: *const Self = self; + let str_ptr = ascii_ptr as *const str; + // SAFETY: Each ASCII codepoint in UTF-8 is encoded as one single-byte + // code unit having the same value as the ASCII byte. + unsafe { &*str_ptr } + } + + /// Views this slice of ASCII characters as a slice of `u8` bytes. + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_bytes(&self) -> &[u8] { + self.as_str().as_bytes() + } +} + +#[unstable(feature = "ascii_char", issue = "110998")] +impl fmt::Display for AsciiChar { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + <str as fmt::Display>::fmt(self.as_str(), f) + } +} diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index db1c505ba38..03cdff9b13b 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -1,7 +1,5 @@ //! impl bool {} -use crate::marker::Destruct; - impl bool { /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), /// or `None` otherwise. @@ -31,12 +29,8 @@ impl bool { /// assert_eq!(a, 2); /// ``` #[stable(feature = "bool_to_option", since = "1.62.0")] - #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] - pub const fn then_some<T>(self, t: T) -> Option<T> - where - T: ~const Destruct, - { + pub fn then_some<T>(self, t: T) -> Option<T> { if self { Some(t) } else { None } } @@ -61,13 +55,8 @@ impl bool { /// assert_eq!(a, 1); /// ``` #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] - #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] - pub const fn then<T, F>(self, f: F) -> Option<T> - where - F: ~const FnOnce() -> T, - F: ~const Destruct, - { + pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> { if self { Some(f()) } else { None } } } diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs index 4a8302ee404..efc9ada3891 100644 --- a/library/core/src/borrow.rs +++ b/library/core/src/borrow.rs @@ -154,7 +154,6 @@ /// [`String`]: ../../std/string/struct.String.html #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Borrow"] -#[const_trait] pub trait Borrow<Borrowed: ?Sized> { /// Immutably borrows from an owned value. /// @@ -185,7 +184,6 @@ pub trait Borrow<Borrowed: ?Sized> { /// an underlying type by providing a mutable reference. See [`Borrow<T>`] /// for more information on borrowing as another type. #[stable(feature = "rust1", since = "1.0.0")] -#[const_trait] pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> { /// Mutably borrows from an owned value. /// @@ -207,8 +205,7 @@ pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] -impl<T: ?Sized> const Borrow<T> for T { +impl<T: ?Sized> Borrow<T> for T { #[rustc_diagnostic_item = "noop_method_borrow"] fn borrow(&self) -> &T { self @@ -216,32 +213,28 @@ impl<T: ?Sized> const Borrow<T> for T { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] -impl<T: ?Sized> const BorrowMut<T> for T { +impl<T: ?Sized> BorrowMut<T> for T { fn borrow_mut(&mut self) -> &mut T { self } } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] -impl<T: ?Sized> const Borrow<T> for &T { +impl<T: ?Sized> Borrow<T> for &T { fn borrow(&self) -> &T { &**self } } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] -impl<T: ?Sized> const Borrow<T> for &mut T { +impl<T: ?Sized> Borrow<T> for &mut T { fn borrow(&self) -> &T { &**self } } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] -impl<T: ?Sized> const BorrowMut<T> for &mut T { +impl<T: ?Sized> BorrowMut<T> for &mut T { fn borrow_mut(&mut self) -> &mut T { &mut **self } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 7f109491350..a96dfafd9c4 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -11,36 +11,77 @@ //! mutate it. //! //! Shareable mutable containers exist to permit mutability in a controlled manner, even in the -//! presence of aliasing. Both [`Cell<T>`] and [`RefCell<T>`] allow doing this in a single-threaded -//! way. However, neither `Cell<T>` nor `RefCell<T>` are thread safe (they do not implement -//! [`Sync`]). If you need to do aliasing and mutation between multiple threads it is possible to -//! use [`Mutex<T>`], [`RwLock<T>`] or [`atomic`] types. +//! presence of aliasing. [`Cell<T>`], [`RefCell<T>`], and [`OnceCell<T>`] allow doing this in +//! a single-threaded way—they do not implement [`Sync`]. (If you need to do aliasing and +//! mutation among multiple threads, [`Mutex<T>`], [`RwLock<T>`], [`OnceLock<T>`] or [`atomic`] +//! types are the correct data structures to do so). //! -//! Values of the `Cell<T>` and `RefCell<T>` types may be mutated through shared references (i.e. -//! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) -//! references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast -//! with typical Rust types that exhibit 'inherited mutability'. +//! Values of the `Cell<T>`, `RefCell<T>`, and `OnceCell<T>` types may be mutated through shared +//! references (i.e. the common `&T` type), whereas most Rust types can only be mutated through +//! unique (`&mut T`) references. We say these cell types provide 'interior mutability' +//! (mutable via `&T`), in contrast with typical Rust types that exhibit 'inherited mutability' +//! (mutable only via `&mut T`). //! -//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` implements interior -//! mutability by moving values in and out of the `Cell<T>`. To use references instead of values, -//! one must use the `RefCell<T>` type, acquiring a write lock before mutating. `Cell<T>` provides -//! methods to retrieve and change the current interior value: +//! Cell types come in three flavors: `Cell<T>`, `RefCell<T>`, and `OnceCell<T>`. Each provides +//! a different way of providing safe interior mutability. +//! +//! ## `Cell<T>` +//! +//! [`Cell<T>`] implements interior mutability by moving values in and out of the cell. That is, an +//! `&mut T` to the inner value can never be obtained, and the value itself cannot be directly +//! obtained without replacing it with something else. Both of these rules ensure that there is +//! never more than one reference pointing to the inner value. This type provides the following +//! methods: //! //! - For types that implement [`Copy`], the [`get`](Cell::get) method retrieves the current -//! interior value. +//! interior value by duplicating it. //! - For types that implement [`Default`], the [`take`](Cell::take) method replaces the current //! interior value with [`Default::default()`] and returns the replaced value. -//! - For all types, the [`replace`](Cell::replace) method replaces the current interior value and -//! returns the replaced value and the [`into_inner`](Cell::into_inner) method consumes the -//! `Cell<T>` and returns the interior value. Additionally, the [`set`](Cell::set) method -//! replaces the interior value, dropping the replaced value. +//! - All types have: +//! - [`replace`](Cell::replace): replaces the current interior value and returns the replaced +//! value. +//! - [`into_inner`](Cell::into_inner): this method consumes the `Cell<T>` and returns the +//! interior value. +//! - [`set`](Cell::set): this method replaces the interior value, dropping the replaced value. +//! +//! `Cell<T>` is typically used for more simple types where copying or moving values isn't too +//! resource intensive (e.g. numbers), and should usually be preferred over other cell types when +//! possible. For larger and non-copy types, `RefCell` provides some advantages. +//! +//! ## `RefCell<T>` //! -//! `RefCell<T>` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can +//! [`RefCell<T>`] uses Rust's lifetimes to implement "dynamic borrowing", a process whereby one can //! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are -//! tracked 'at runtime', unlike Rust's native reference types which are entirely tracked -//! statically, at compile time. Because `RefCell<T>` borrows are dynamic it is possible to attempt -//! to borrow a value that is already mutably borrowed; when this happens it results in thread -//! panic. +//! tracked at _runtime_, unlike Rust's native reference types which are entirely tracked +//! statically, at compile time. +//! +//! An immutable reference to a `RefCell`'s inner value (`&T`) can be obtained with +//! [`borrow`](`RefCell::borrow`), and a mutable borrow (`&mut T`) can be obtained with +//! [`borrow_mut`](`RefCell::borrow_mut`). When these functions are called, they first verify that +//! Rust's borrow rules will be satisfied: any number of immutable borrows are allowed or a +//! single immutable borrow is allowed, but never both. If a borrow is attempted that would violate +//! these rules, the thread will panic. +//! +//! The corresponding [`Sync`] version of `RefCell<T>` is [`RwLock<T>`]. +//! +//! ## `OnceCell<T>` +//! +//! [`OnceCell<T>`] is somewhat of a hybrid of `Cell` and `RefCell` that works for values that +//! typically only need to be set once. This means that a reference `&T` can be obtained without +//! moving or copying the inner value (unlike `Cell`) but also without runtime checks (unlike +//! `RefCell`). However, its value can also not be updated once set unless you have a mutable +//! reference to the `OnceCell`. +//! +//! `OnceCell` provides the following methods: +//! +//! - [`get`](OnceCell::get): obtain a reference to the inner value +//! - [`set`](OnceCell::set): set the inner value if it is unset (returns a `Result`) +//! - [`get_or_init`](OnceCell::get_or_init): return the inner value, initializing it if needed +//! - [`get_mut`](OnceCell::get_mut): provide a mutable reference to the inner value, only available +//! if you have a mutable reference to the cell itself. +//! +//! The corresponding [`Sync`] version of `OnceCell<T>` is [`OnceLock<T>`]. +//! //! //! # When to choose interior mutability //! @@ -74,7 +115,7 @@ //! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new())); //! // Create a new block to limit the scope of the dynamic borrow //! { -//! let mut map: RefMut<_> = shared_map.borrow_mut(); +//! let mut map: RefMut<'_, _> = shared_map.borrow_mut(); //! map.insert("africa", 92388); //! map.insert("kyoto", 11837); //! map.insert("piccadilly", 11826); @@ -188,6 +229,8 @@ //! [`Rc<T>`]: ../../std/rc/struct.Rc.html //! [`RwLock<T>`]: ../../std/sync/struct.RwLock.html //! [`Mutex<T>`]: ../../std/sync/struct.Mutex.html +//! [`OnceLock<T>`]: ../../std/sync/struct.OnceLock.html +//! [`Sync`]: ../../std/marker/trait.Sync.html //! [`atomic`]: crate::sync::atomic #![stable(feature = "rust1", since = "1.0.0")] @@ -202,13 +245,19 @@ use crate::ptr::{self, NonNull}; mod lazy; mod once; -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] pub use lazy::LazyCell; -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] pub use once::OnceCell; /// A mutable memory location. /// +/// # Memory layout +/// +/// `Cell<T>` has the same [memory layout and caveats as +/// `UnsafeCell<T>`](UnsafeCell#memory-layout). In particular, this means that +/// `Cell<T>` has the same in-memory representation as its inner type `T`. +/// /// # Examples /// /// In this example, you can see that `Cell<T>` enables mutation inside an @@ -321,8 +370,7 @@ impl<T: Ord + Copy> Ord for Cell<T> { } #[stable(feature = "cell_from", since = "1.12.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<T> for Cell<T> { +impl<T> From<T> for Cell<T> { /// Creates a new `Cell<T>` containing the given value. fn from(t: T) -> Cell<T> { Cell::new(t) @@ -413,7 +461,7 @@ impl<T> Cell<T> { mem::replace(unsafe { &mut *self.value.get() }, val) } - /// Unwraps the value. + /// Unwraps the value, consuming the cell. /// /// # Examples /// @@ -632,7 +680,7 @@ pub struct RefCell<T: ?Sized> { // Stores the location of the earliest currently active borrow. // This gets updated whenever we go from having zero borrows // to having a single borrow. When a borrow occurs, this gets included - // in the generated `BorrowError/`BorrowMutError` + // in the generated `BorrowError`/`BorrowMutError` #[cfg(feature = "debug_refcell")] borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>, value: UnsafeCell<T>, @@ -1269,8 +1317,7 @@ impl<T: ?Sized + Ord> Ord for RefCell<T> { } #[stable(feature = "cell_from", since = "1.12.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<T> for RefCell<T> { +impl<T> From<T> for RefCell<T> { /// Creates a new `RefCell<T>` containing the given value. fn from(t: T) -> RefCell<T> { RefCell::new(t) @@ -1388,8 +1435,8 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// use std::cell::{RefCell, Ref}; /// /// let c = RefCell::new((5, 'b')); - /// let b1: Ref<(u32, char)> = c.borrow(); - /// let b2: Ref<u32> = Ref::map(b1, |t| &t.0); + /// let b1: Ref<'_, (u32, char)> = c.borrow(); + /// let b2: Ref<'_, u32> = Ref::map(b1, |t| &t.0); /// assert_eq!(*b2, 5) /// ``` #[stable(feature = "cell_map", since = "1.8.0")] @@ -1417,8 +1464,8 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// use std::cell::{RefCell, Ref}; /// /// let c = RefCell::new(vec![1, 2, 3]); - /// let b1: Ref<Vec<u32>> = c.borrow(); - /// let b2: Result<Ref<u32>, _> = Ref::filter_map(b1, |v| v.get(1)); + /// let b1: Ref<'_, Vec<u32>> = c.borrow(); + /// let b2: Result<Ref<'_, u32>, _> = Ref::filter_map(b1, |v| v.get(1)); /// assert_eq!(*b2.unwrap(), 2); /// ``` #[stable(feature = "cell_filter_map", since = "1.63.0")] @@ -1530,8 +1577,8 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// /// let c = RefCell::new((5, 'b')); /// { - /// let b1: RefMut<(u32, char)> = c.borrow_mut(); - /// let mut b2: RefMut<u32> = RefMut::map(b1, |t| &mut t.0); + /// let b1: RefMut<'_, (u32, char)> = c.borrow_mut(); + /// let mut b2: RefMut<'_, u32> = RefMut::map(b1, |t| &mut t.0); /// assert_eq!(*b2, 5); /// *b2 = 42; /// } @@ -1565,8 +1612,8 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// let c = RefCell::new(vec![1, 2, 3]); /// /// { - /// let b1: RefMut<Vec<u32>> = c.borrow_mut(); - /// let mut b2: Result<RefMut<u32>, _> = RefMut::filter_map(b1, |v| v.get_mut(1)); + /// let b1: RefMut<'_, Vec<u32>> = c.borrow_mut(); + /// let mut b2: Result<RefMut<'_, u32>, _> = RefMut::filter_map(b1, |v| v.get_mut(1)); /// /// if let Ok(mut b2) = b2 { /// *b2 += 2; @@ -1767,7 +1814,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> { /// `UnsafeCell<T>` opts-out of the immutability guarantee for `&T`: a shared reference /// `&UnsafeCell<T>` may point to data that is being mutated. This is called "interior mutability". /// -/// All other types that allow internal mutability, such as `Cell<T>` and `RefCell<T>`, internally +/// All other types that allow internal mutability, such as [`Cell<T>`] and [`RefCell<T>`], internally /// use `UnsafeCell` to wrap their data. /// /// Note that only the immutability guarantee for shared references is affected by `UnsafeCell`. The @@ -1963,7 +2010,7 @@ impl<T> UnsafeCell<T> { UnsafeCell { value } } - /// Unwraps the value. + /// Unwraps the value, consuming the cell. /// /// # Examples /// @@ -2077,8 +2124,7 @@ impl<T: Default> Default for UnsafeCell<T> { } #[stable(feature = "cell_from", since = "1.12.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<T> for UnsafeCell<T> { +impl<T> From<T> for UnsafeCell<T> { /// Creates a new `UnsafeCell<T>` containing the given value. fn from(t: T) -> UnsafeCell<T> { UnsafeCell::new(t) @@ -2127,7 +2173,7 @@ impl<T> SyncUnsafeCell<T> { Self { value: UnsafeCell { value } } } - /// Unwraps the value. + /// Unwraps the value, consuming the cell. #[inline] pub const fn into_inner(self) -> T { self.value.into_inner() @@ -2177,8 +2223,7 @@ impl<T: Default> Default for SyncUnsafeCell<T> { } #[unstable(feature = "sync_unsafe_cell", issue = "95439")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<T> for SyncUnsafeCell<T> { +impl<T> From<T> for SyncUnsafeCell<T> { /// Creates a new `SyncUnsafeCell<T>` containing the given value. fn from(t: T) -> SyncUnsafeCell<T> { SyncUnsafeCell::new(t) diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index 65d12c25c51..1b213f6a294 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -1,6 +1,13 @@ -use crate::cell::{Cell, OnceCell}; -use crate::fmt; use crate::ops::Deref; +use crate::{fmt, mem}; + +use super::UnsafeCell; + +enum State<T, F> { + Uninit(F), + Init(T), + Poisoned, +} /// A value which is initialized on the first access. /// @@ -11,7 +18,7 @@ use crate::ops::Deref; /// # Examples /// /// ``` -/// #![feature(once_cell)] +/// #![feature(lazy_cell)] /// /// use std::cell::LazyCell; /// @@ -29,10 +36,9 @@ use crate::ops::Deref; /// // 92 /// // 92 /// ``` -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] pub struct LazyCell<T, F = fn() -> T> { - cell: OnceCell<T>, - init: Cell<Option<F>>, + state: UnsafeCell<State<T, F>>, } impl<T, F: FnOnce() -> T> LazyCell<T, F> { @@ -41,7 +47,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(lazy_cell)] /// /// use std::cell::LazyCell; /// @@ -52,9 +58,37 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// assert_eq!(&*lazy, "HELLO, WORLD!"); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] - pub const fn new(init: F) -> LazyCell<T, F> { - LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) } + #[unstable(feature = "lazy_cell", issue = "109736")] + pub const fn new(f: F) -> LazyCell<T, F> { + LazyCell { state: UnsafeCell::new(State::Uninit(f)) } + } + + /// Consumes this `LazyCell` returning the stored value. + /// + /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(lazy_cell)] + /// #![feature(lazy_cell_consume)] + /// + /// use std::cell::LazyCell; + /// + /// let hello = "Hello, World!".to_string(); + /// + /// let lazy = LazyCell::new(|| hello.to_uppercase()); + /// + /// assert_eq!(&*lazy, "HELLO, WORLD!"); + /// assert_eq!(LazyCell::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string())); + /// ``` + #[unstable(feature = "lazy_cell_consume", issue = "109736")] + pub fn into_inner(this: Self) -> Result<T, F> { + match this.state.into_inner() { + State::Init(data) => Ok(data), + State::Uninit(f) => Err(f), + State::Poisoned => panic!("LazyCell instance has previously been poisoned"), + } } /// Forces the evaluation of this lazy value and returns a reference to @@ -65,7 +99,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(lazy_cell)] /// /// use std::cell::LazyCell; /// @@ -75,16 +109,71 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// assert_eq!(&*lazy, &92); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "lazy_cell", issue = "109736")] pub fn force(this: &LazyCell<T, F>) -> &T { - this.cell.get_or_init(|| match this.init.take() { - Some(f) => f(), - None => panic!("`Lazy` instance has previously been poisoned"), - }) + // SAFETY: + // This invalidates any mutable references to the data. The resulting + // reference lives either until the end of the borrow of `this` (in the + // initialized case) or is invalidated in `really_init` (in the + // uninitialized case; `really_init` will create and return a fresh reference). + let state = unsafe { &*this.state.get() }; + match state { + State::Init(data) => data, + // SAFETY: The state is uninitialized. + State::Uninit(_) => unsafe { LazyCell::really_init(this) }, + State::Poisoned => panic!("LazyCell has previously been poisoned"), + } + } + + /// # Safety + /// May only be called when the state is `Uninit`. + #[cold] + unsafe fn really_init(this: &LazyCell<T, F>) -> &T { + // SAFETY: + // This function is only called when the state is uninitialized, + // so no references to `state` can exist except for the reference + // in `force`, which is invalidated here and not accessed again. + let state = unsafe { &mut *this.state.get() }; + // Temporarily mark the state as poisoned. This prevents reentrant + // accesses and correctly poisons the cell if the closure panicked. + let State::Uninit(f) = mem::replace(state, State::Poisoned) else { unreachable!() }; + + let data = f(); + + // SAFETY: + // If the closure accessed the cell through something like a reentrant + // mutex, but caught the panic resulting from the state being poisoned, + // the mutable borrow for `state` will be invalidated, so we need to + // go through the `UnsafeCell` pointer here. The state can only be + // poisoned at this point, so using `write` to skip the destructor + // of `State` should help the optimizer. + unsafe { this.state.get().write(State::Init(data)) }; + + // SAFETY: + // The previous references were invalidated by the `write` call above, + // so do a new shared borrow of the state instead. + let state = unsafe { &*this.state.get() }; + let State::Init(data) = state else { unreachable!() }; + data + } +} + +impl<T, F> LazyCell<T, F> { + #[inline] + fn get(&self) -> Option<&T> { + // SAFETY: + // This is sound for the same reason as in `force`: once the state is + // initialized, it will not be mutably accessed again, so this reference + // will stay valid for the duration of the borrow to `self`. + let state = unsafe { &*self.state.get() }; + match state { + State::Init(data) => Some(data), + _ => None, + } } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { type Target = T; #[inline] @@ -93,7 +182,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T: Default> Default for LazyCell<T> { /// Creates a new lazy value using `Default` as the initializing function. #[inline] @@ -102,9 +191,14 @@ impl<T: Default> Default for LazyCell<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() + let mut d = f.debug_tuple("LazyCell"); + match self.get() { + Some(data) => d.field(data), + None => d.field(&format_args!("<uninit>")), + }; + d.finish() } } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index f74e563f1b9..5f06a7b0795 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -4,8 +4,10 @@ use crate::mem; /// A cell which can be written to only once. /// -/// Unlike [`RefCell`], a `OnceCell` only provides shared `&T` references to its value. -/// Unlike [`Cell`], a `OnceCell` doesn't require copying or replacing the value to access it. +/// This allows obtaining a shared `&T` reference to its inner value without copying or replacing +/// it (unlike [`Cell`]), and without runtime borrow checks (unlike [`RefCell`]). However, +/// only immutable references can be obtained unless one has a mutable reference to the cell +/// itself. /// /// For a thread-safe version of this struct, see [`std::sync::OnceLock`]. /// @@ -16,8 +18,6 @@ use crate::mem; /// # Examples /// /// ``` -/// #![feature(once_cell)] -/// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); @@ -29,7 +29,7 @@ use crate::mem; /// assert_eq!(value, "Hello, World!"); /// assert!(cell.get().is_some()); /// ``` -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] pub struct OnceCell<T> { // Invariant: written to at most once. inner: UnsafeCell<Option<T>>, @@ -39,7 +39,8 @@ impl<T> OnceCell<T> { /// Creates a new empty cell. #[inline] #[must_use] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_const_stable(feature = "once_cell", since = "1.70.0")] pub const fn new() -> OnceCell<T> { OnceCell { inner: UnsafeCell::new(None) } } @@ -48,7 +49,7 @@ impl<T> OnceCell<T> { /// /// Returns `None` if the cell is empty. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get(&self) -> Option<&T> { // SAFETY: Safe due to `inner`'s invariant unsafe { &*self.inner.get() }.as_ref() @@ -58,7 +59,7 @@ impl<T> OnceCell<T> { /// /// Returns `None` if the cell is empty. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_mut(&mut self) -> Option<&mut T> { self.inner.get_mut().as_mut() } @@ -73,8 +74,6 @@ impl<T> OnceCell<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); @@ -86,7 +85,7 @@ impl<T> OnceCell<T> { /// assert!(cell.get().is_some()); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn set(&self, value: T) -> Result<(), T> { // SAFETY: Safe because we cannot have overlapping mutable borrows let slot = unsafe { &*self.inner.get() }; @@ -117,8 +116,6 @@ impl<T> OnceCell<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); @@ -128,7 +125,7 @@ impl<T> OnceCell<T> { /// assert_eq!(value, &92); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_or_init<F>(&self, f: F) -> &T where F: FnOnce() -> T, @@ -153,7 +150,7 @@ impl<T> OnceCell<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(once_cell_try)] /// /// use std::cell::OnceCell; /// @@ -166,7 +163,7 @@ impl<T> OnceCell<T> { /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "once_cell_try", issue = "109737")] pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result<T, E>, @@ -199,8 +196,6 @@ impl<T> OnceCell<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::cell::OnceCell; /// /// let cell: OnceCell<String> = OnceCell::new(); @@ -211,7 +206,7 @@ impl<T> OnceCell<T> { /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn into_inner(self) -> Option<T> { // Because `into_inner` takes `self` by value, the compiler statically verifies // that it is not currently borrowed. So it is safe to move out `Option<T>`. @@ -227,8 +222,6 @@ impl<T> OnceCell<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::cell::OnceCell; /// /// let mut cell: OnceCell<String> = OnceCell::new(); @@ -240,13 +233,13 @@ impl<T> OnceCell<T> { /// assert_eq!(cell.get(), None); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn take(&mut self) -> Option<T> { mem::take(self).into_inner() } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T> Default for OnceCell<T> { #[inline] fn default() -> Self { @@ -254,7 +247,7 @@ impl<T> Default for OnceCell<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { @@ -264,7 +257,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: Clone> Clone for OnceCell<T> { #[inline] fn clone(&self) -> OnceCell<T> { @@ -279,7 +272,7 @@ impl<T: Clone> Clone for OnceCell<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: PartialEq> PartialEq for OnceCell<T> { #[inline] fn eq(&self, other: &Self) -> bool { @@ -287,11 +280,11 @@ impl<T: PartialEq> PartialEq for OnceCell<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: Eq> Eq for OnceCell<T> {} -#[unstable(feature = "once_cell", issue = "74465")] -impl<T> const From<T> for OnceCell<T> { +#[stable(feature = "once_cell", since = "1.70.0")] +impl<T> From<T> for OnceCell<T> { /// Creates a new `OnceCell<T>` which already contains the given `value`. #[inline] fn from(value: T) -> Self { @@ -300,5 +293,5 @@ impl<T> const From<T> for OnceCell<T> { } // Just like for `Cell<T>` this isn't needed, but results in nicer error messages. -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T> !Sync for OnceCell<T> {} diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 136bbcb8b21..b84e4b35b1c 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -27,8 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char { } #[stable(feature = "char_convert", since = "1.13.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl const From<char> for u32 { +impl From<char> for u32 { /// Converts a [`char`] into a [`u32`]. /// /// # Examples @@ -47,8 +46,7 @@ impl const From<char> for u32 { } #[stable(feature = "more_char_conversions", since = "1.51.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl const From<char> for u64 { +impl From<char> for u64 { /// Converts a [`char`] into a [`u64`]. /// /// # Examples @@ -69,8 +67,7 @@ impl const From<char> for u64 { } #[stable(feature = "more_char_conversions", since = "1.51.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl const From<char> for u128 { +impl From<char> for u128 { /// Converts a [`char`] into a [`u128`]. /// /// # Examples @@ -123,8 +120,7 @@ impl TryFrom<char> for u8 { /// for a superset of Windows-1252 that fills the remaining blanks with corresponding /// C0 and C1 control codes. #[stable(feature = "char_convert", since = "1.13.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl const From<u8> for char { +impl From<u8> for char { /// Converts a [`u8`] into a [`char`]. /// /// # Examples diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 9bc97ea0bff..1dfa9c34db1 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1,5 +1,6 @@ //! impl char {} +use crate::ascii; use crate::slice; use crate::str::from_utf8_unchecked_mut; use crate::unicode::printable::is_printable; @@ -380,20 +381,7 @@ impl char { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn escape_unicode(self) -> EscapeUnicode { - let c = self as u32; - - // or-ing 1 ensures that for c==0 the code computes that one - // digit should be printed and (which is the same) avoids the - // (31 - 32) underflow - let msb = 31 - (c | 1).leading_zeros(); - - // the index of the most significant hex digit - let ms_hex_digit = msb / 4; - EscapeUnicode { - c: self, - state: EscapeUnicodeState::Backslash, - hex_digit_idx: ms_hex_digit as usize, - } + EscapeUnicode::new(self) } /// An extended version of `escape_debug` that optionally permits escaping @@ -403,21 +391,20 @@ impl char { /// characters, and double quotes in strings. #[inline] pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug { - let init_state = match self { - '\0' => EscapeDefaultState::Backslash('0'), - '\t' => EscapeDefaultState::Backslash('t'), - '\r' => EscapeDefaultState::Backslash('r'), - '\n' => EscapeDefaultState::Backslash('n'), - '\\' => EscapeDefaultState::Backslash(self), - '"' if args.escape_double_quote => EscapeDefaultState::Backslash(self), - '\'' if args.escape_single_quote => EscapeDefaultState::Backslash(self), + match self { + '\0' => EscapeDebug::backslash(b'0'), + '\t' => EscapeDebug::backslash(b't'), + '\r' => EscapeDebug::backslash(b'r'), + '\n' => EscapeDebug::backslash(b'n'), + '\\' => EscapeDebug::backslash(b'\\'), + '"' if args.escape_double_quote => EscapeDebug::backslash(b'"'), + '\'' if args.escape_single_quote => EscapeDebug::backslash(b'\''), _ if args.escape_grapheme_extended && self.is_grapheme_extended() => { - EscapeDefaultState::Unicode(self.escape_unicode()) + EscapeDebug::from_unicode(self.escape_unicode()) } - _ if is_printable(self) => EscapeDefaultState::Char(self), - _ => EscapeDefaultState::Unicode(self.escape_unicode()), - }; - EscapeDebug(EscapeDefault { state: init_state }) + _ if is_printable(self) => EscapeDebug::printable(self), + _ => EscapeDebug::from_unicode(self.escape_unicode()), + } } /// Returns an iterator that yields the literal escape code of a character @@ -515,15 +502,14 @@ impl char { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn escape_default(self) -> EscapeDefault { - let init_state = match self { - '\t' => EscapeDefaultState::Backslash('t'), - '\r' => EscapeDefaultState::Backslash('r'), - '\n' => EscapeDefaultState::Backslash('n'), - '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self), - '\x20'..='\x7e' => EscapeDefaultState::Char(self), - _ => EscapeDefaultState::Unicode(self.escape_unicode()), - }; - EscapeDefault { state: init_state } + match self { + '\t' => EscapeDefault::backslash(b't'), + '\r' => EscapeDefault::backslash(b'r'), + '\n' => EscapeDefault::backslash(b'n'), + '\\' | '\'' | '"' => EscapeDefault::backslash(self as u8), + '\x20'..='\x7e' => EscapeDefault::printable(self as u8), + _ => EscapeDefault::from_unicode(self.escape_unicode()), + } } /// Returns the number of bytes this `char` would need if encoded in UTF-8. @@ -1116,6 +1102,24 @@ impl char { *self as u32 <= 0x7F } + /// Returns `Some` if the value is within the ASCII range, + /// or `None` if it's not. + /// + /// This is preferred to [`Self::is_ascii`] when you're passing the value + /// along to something else that can take [`ascii::Char`] rather than + /// needing to check again for itself whether the value is in ASCII. + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_ascii(&self) -> Option<ascii::Char> { + if self.is_ascii() { + // SAFETY: Just checked that this is ASCII. + Some(unsafe { ascii::Char::from_u8_unchecked(*self as u8) }) + } else { + None + } + } + /// Makes a copy of the value in its ASCII upper case equivalent. /// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 8ec78e88733..e186db7052c 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -39,8 +39,10 @@ pub use self::methods::encode_utf16_raw; pub use self::methods::encode_utf8_raw; use crate::error::Error; +use crate::escape; use crate::fmt::{self, Write}; use crate::iter::FusedIterator; +use crate::num::NonZeroUsize; pub(crate) use self::methods::EscapeDebugExtArgs; @@ -146,86 +148,44 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> { /// [`escape_unicode`]: char::escape_unicode #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct EscapeUnicode { - c: char, - state: EscapeUnicodeState, - - // The index of the next hex digit to be printed (0 if none), - // i.e., the number of remaining hex digits to be printed; - // increasing from the least significant digit: 0x543210 - hex_digit_idx: usize, -} +pub struct EscapeUnicode(escape::EscapeIterInner<10>); -// The enum values are ordered so that their representation is the -// same as the remaining length (besides the hexadecimal digits). This -// likely makes `len()` a single load from memory) and inline-worth. -#[derive(Clone, Debug)] -enum EscapeUnicodeState { - Done, - RightBrace, - Value, - LeftBrace, - Type, - Backslash, +impl EscapeUnicode { + fn new(chr: char) -> Self { + let mut data = [0; 10]; + let range = escape::escape_unicode_into(&mut data, chr); + Self(escape::EscapeIterInner::new(data, range)) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for EscapeUnicode { type Item = char; + #[inline] fn next(&mut self) -> Option<char> { - match self.state { - EscapeUnicodeState::Backslash => { - self.state = EscapeUnicodeState::Type; - Some('\\') - } - EscapeUnicodeState::Type => { - self.state = EscapeUnicodeState::LeftBrace; - Some('u') - } - EscapeUnicodeState::LeftBrace => { - self.state = EscapeUnicodeState::Value; - Some('{') - } - EscapeUnicodeState::Value => { - let hex_digit = ((self.c as u32) >> (self.hex_digit_idx * 4)) & 0xf; - let c = char::from_digit(hex_digit, 16).unwrap(); - if self.hex_digit_idx == 0 { - self.state = EscapeUnicodeState::RightBrace; - } else { - self.hex_digit_idx -= 1; - } - Some(c) - } - EscapeUnicodeState::RightBrace => { - self.state = EscapeUnicodeState::Done; - Some('}') - } - EscapeUnicodeState::Done => None, - } + self.0.next().map(char::from) } #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let n = self.len(); + let n = self.0.len(); (n, Some(n)) } #[inline] fn count(self) -> usize { - self.len() + self.0.len() } - fn last(self) -> Option<char> { - match self.state { - EscapeUnicodeState::Done => None, + #[inline] + fn last(mut self) -> Option<char> { + self.0.next_back().map(char::from) + } - EscapeUnicodeState::RightBrace - | EscapeUnicodeState::Value - | EscapeUnicodeState::LeftBrace - | EscapeUnicodeState::Type - | EscapeUnicodeState::Backslash => Some('}'), - } + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.0.advance_by(n) } } @@ -233,16 +193,7 @@ impl Iterator for EscapeUnicode { impl ExactSizeIterator for EscapeUnicode { #[inline] fn len(&self) -> usize { - // The match is a single memory access with no branching - self.hex_digit_idx - + match self.state { - EscapeUnicodeState::Done => 0, - EscapeUnicodeState::RightBrace => 1, - EscapeUnicodeState::Value => 2, - EscapeUnicodeState::LeftBrace => 3, - EscapeUnicodeState::Type => 4, - EscapeUnicodeState::Backslash => 5, - } + self.0.len() } } @@ -252,10 +203,7 @@ impl FusedIterator for EscapeUnicode {} #[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for EscapeUnicode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for c in self.clone() { - f.write_char(c)?; - } - Ok(()) + f.write_str(self.0.as_str()) } } @@ -267,90 +215,60 @@ impl fmt::Display for EscapeUnicode { /// [`escape_default`]: char::escape_default #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct EscapeDefault { - state: EscapeDefaultState, -} +pub struct EscapeDefault(escape::EscapeIterInner<10>); -#[derive(Clone, Debug)] -enum EscapeDefaultState { - Done, - Char(char), - Backslash(char), - Unicode(EscapeUnicode), +impl EscapeDefault { + fn printable(chr: u8) -> Self { + let data = [chr, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + Self(escape::EscapeIterInner::new(data, 0..1)) + } + + fn backslash(chr: u8) -> Self { + let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0]; + Self(escape::EscapeIterInner::new(data, 0..2)) + } + + fn from_unicode(esc: EscapeUnicode) -> Self { + Self(esc.0) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for EscapeDefault { type Item = char; + #[inline] fn next(&mut self) -> Option<char> { - match self.state { - EscapeDefaultState::Backslash(c) => { - self.state = EscapeDefaultState::Char(c); - Some('\\') - } - EscapeDefaultState::Char(c) => { - self.state = EscapeDefaultState::Done; - Some(c) - } - EscapeDefaultState::Done => None, - EscapeDefaultState::Unicode(ref mut iter) => iter.next(), - } + self.0.next().map(char::from) } #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let n = self.len(); + let n = self.0.len(); (n, Some(n)) } #[inline] fn count(self) -> usize { - self.len() + self.0.len() } - fn nth(&mut self, n: usize) -> Option<char> { - match self.state { - EscapeDefaultState::Backslash(c) if n == 0 => { - self.state = EscapeDefaultState::Char(c); - Some('\\') - } - EscapeDefaultState::Backslash(c) if n == 1 => { - self.state = EscapeDefaultState::Done; - Some(c) - } - EscapeDefaultState::Backslash(_) => { - self.state = EscapeDefaultState::Done; - None - } - EscapeDefaultState::Char(c) => { - self.state = EscapeDefaultState::Done; - - if n == 0 { Some(c) } else { None } - } - EscapeDefaultState::Done => None, - EscapeDefaultState::Unicode(ref mut i) => i.nth(n), - } + #[inline] + fn last(mut self) -> Option<char> { + self.0.next_back().map(char::from) } - fn last(self) -> Option<char> { - match self.state { - EscapeDefaultState::Unicode(iter) => iter.last(), - EscapeDefaultState::Done => None, - EscapeDefaultState::Backslash(c) | EscapeDefaultState::Char(c) => Some(c), - } + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.0.advance_by(n) } } #[stable(feature = "exact_size_escape", since = "1.11.0")] impl ExactSizeIterator for EscapeDefault { + #[inline] fn len(&self) -> usize { - match self.state { - EscapeDefaultState::Done => 0, - EscapeDefaultState::Char(_) => 1, - EscapeDefaultState::Backslash(_) => 2, - EscapeDefaultState::Unicode(ref iter) => iter.len(), - } + self.0.len() } } @@ -360,10 +278,7 @@ impl FusedIterator for EscapeDefault {} #[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for c in self.clone() { - f.write_char(c)?; - } - Ok(()) + f.write_str(self.0.as_str()) } } @@ -375,21 +290,74 @@ impl fmt::Display for EscapeDefault { /// [`escape_debug`]: char::escape_debug #[stable(feature = "char_escape_debug", since = "1.20.0")] #[derive(Clone, Debug)] -pub struct EscapeDebug(EscapeDefault); +pub struct EscapeDebug(EscapeDebugInner); + +#[derive(Clone, Debug)] +// Note: It’s possible to manually encode the EscapeDebugInner inside of +// EscapeIterInner (e.g. with alive=254..255 indicating that data[0..4] holds +// a char) which would likely result in a more optimised code. For now we use +// the option easier to implement. +enum EscapeDebugInner { + Bytes(escape::EscapeIterInner<10>), + Char(char), +} + +impl EscapeDebug { + fn printable(chr: char) -> Self { + Self(EscapeDebugInner::Char(chr)) + } + + fn backslash(chr: u8) -> Self { + let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0]; + let iter = escape::EscapeIterInner::new(data, 0..2); + Self(EscapeDebugInner::Bytes(iter)) + } + + fn from_unicode(esc: EscapeUnicode) -> Self { + Self(EscapeDebugInner::Bytes(esc.0)) + } + + fn clear(&mut self) { + let bytes = escape::EscapeIterInner::new([0; 10], 0..0); + self.0 = EscapeDebugInner::Bytes(bytes); + } +} #[stable(feature = "char_escape_debug", since = "1.20.0")] impl Iterator for EscapeDebug { type Item = char; + + #[inline] fn next(&mut self) -> Option<char> { - self.0.next() + match self.0 { + EscapeDebugInner::Bytes(ref mut bytes) => bytes.next().map(char::from), + EscapeDebugInner::Char(chr) => { + self.clear(); + Some(chr) + } + } } + fn size_hint(&self) -> (usize, Option<usize>) { - self.0.size_hint() + let n = self.len(); + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.len() } } #[stable(feature = "char_escape_debug", since = "1.20.0")] -impl ExactSizeIterator for EscapeDebug {} +impl ExactSizeIterator for EscapeDebug { + fn len(&self) -> usize { + match &self.0 { + EscapeDebugInner::Bytes(bytes) => bytes.len(), + EscapeDebugInner::Char(_) => 1, + } + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDebug {} @@ -397,7 +365,10 @@ impl FusedIterator for EscapeDebug {} #[stable(feature = "char_escape_debug", since = "1.20.0")] impl fmt::Display for EscapeDebug { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.0, f) + match &self.0 { + EscapeDebugInner::Bytes(bytes) => f.write_str(bytes.as_str()), + EscapeDebugInner::Char(chr) => f.write_char(*chr), + } } } diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 398437d9a02..a6d6230d3a6 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -36,8 +36,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::marker::Destruct; - /// A common trait for the ability to explicitly duplicate an object. /// /// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while @@ -106,7 +104,6 @@ use crate::marker::Destruct; #[lang = "clone"] #[rustc_diagnostic_item = "Clone"] #[rustc_trivial_field_reads] -#[const_trait] pub trait Clone: Sized { /// Returns a copy of the value. /// @@ -129,10 +126,7 @@ pub trait Clone: Sized { /// allocations. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn clone_from(&mut self, source: &Self) - where - Self: ~const Destruct, - { + fn clone_from(&mut self, source: &Self) { *self = source.clone() } } @@ -182,8 +176,7 @@ mod impls { ($($t:ty)*) => { $( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_clone", issue = "91805")] - impl const Clone for $t { + impl Clone for $t { #[inline(always)] fn clone(&self) -> Self { *self @@ -201,8 +194,7 @@ mod impls { } #[unstable(feature = "never_type", issue = "35121")] - #[rustc_const_unstable(feature = "const_clone", issue = "91805")] - impl const Clone for ! { + impl Clone for ! { #[inline] fn clone(&self) -> Self { *self @@ -210,8 +202,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_clone", issue = "91805")] - impl<T: ?Sized> const Clone for *const T { + impl<T: ?Sized> Clone for *const T { #[inline(always)] fn clone(&self) -> Self { *self @@ -219,8 +210,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_clone", issue = "91805")] - impl<T: ?Sized> const Clone for *mut T { + impl<T: ?Sized> Clone for *mut T { #[inline(always)] fn clone(&self) -> Self { *self @@ -229,8 +219,7 @@ mod impls { /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_clone", issue = "91805")] - impl<T: ?Sized> const Clone for &T { + impl<T: ?Sized> Clone for &T { #[inline(always)] #[rustc_diagnostic_item = "noop_method_clone"] fn clone(&self) -> Self { diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index b4d58376aea..faf48ae570f 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -22,7 +22,8 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::marker::Destruct; +mod bytewise; +pub(crate) use bytewise::BytewiseEq; use self::Ordering::*; @@ -209,7 +210,6 @@ use self::Ordering::*; label = "no implementation for `{Self} == {Rhs}`", append_const_msg )] -#[const_trait] #[rustc_diagnostic_item = "PartialEq"] pub trait PartialEq<Rhs: ?Sized = Self> { /// This method tests for `self` and `other` values to be equal, and is used @@ -228,7 +228,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> { } } -/// Derive macro generating an impl of the trait `PartialEq`. +/// Derive macro generating an impl of the trait [`PartialEq`]. +/// The behavior of this macro is described in detail [here](PartialEq#derivable). #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, structural_match)] @@ -294,7 +295,7 @@ pub trait Eq: PartialEq<Self> { fn assert_receiver_is_total_eq(&self) {} } -/// Derive macro generating an impl of the trait `Eq`. +/// Derive macro generating an impl of the trait [`Eq`]. #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_eq, structural_match, no_coverage)] @@ -320,17 +321,13 @@ pub struct AssertParamIsEq<T: Eq + ?Sized> { /// ``` /// use std::cmp::Ordering; /// -/// let result = 1.cmp(&2); -/// assert_eq!(Ordering::Less, result); +/// assert_eq!(1.cmp(&2), Ordering::Less); /// -/// let result = 1.cmp(&1); -/// assert_eq!(Ordering::Equal, result); +/// assert_eq!(1.cmp(&1), Ordering::Equal); /// -/// let result = 2.cmp(&1); -/// assert_eq!(Ordering::Greater, result); +/// assert_eq!(2.cmp(&1), Ordering::Greater); /// ``` -#[derive(Clone, Copy, Eq, Debug, Hash)] -#[derive_const(PartialOrd, Ord, PartialEq)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] #[stable(feature = "rust1", since = "1.0.0")] #[repr(i8)] pub enum Ordering { @@ -600,8 +597,7 @@ impl Ordering { pub struct Reverse<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T); #[stable(feature = "reverse_cmp_key", since = "1.19.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -impl<T: ~const PartialOrd> const PartialOrd for Reverse<T> { +impl<T: PartialOrd> PartialOrd for Reverse<T> { #[inline] fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> { other.0.partial_cmp(&self.0) @@ -759,7 +755,6 @@ impl<T: Clone> Clone for Reverse<T> { #[doc(alias = ">=")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Ord"] -#[const_trait] pub trait Ord: Eq + PartialOrd<Self> { /// This method returns an [`Ordering`] between `self` and `other`. /// @@ -786,8 +781,8 @@ pub trait Ord: Eq + PartialOrd<Self> { /// # Examples /// /// ``` - /// assert_eq!(2, 1.max(2)); - /// assert_eq!(2, 2.max(2)); + /// assert_eq!(1.max(2), 2); + /// assert_eq!(2.max(2), 2); /// ``` #[stable(feature = "ord_max_min", since = "1.21.0")] #[inline] @@ -795,7 +790,6 @@ pub trait Ord: Eq + PartialOrd<Self> { fn max(self, other: Self) -> Self where Self: Sized, - Self: ~const Destruct, { max_by(self, other, Ord::cmp) } @@ -807,8 +801,8 @@ pub trait Ord: Eq + PartialOrd<Self> { /// # Examples /// /// ``` - /// assert_eq!(1, 1.min(2)); - /// assert_eq!(2, 2.min(2)); + /// assert_eq!(1.min(2), 1); + /// assert_eq!(2.min(2), 2); /// ``` #[stable(feature = "ord_max_min", since = "1.21.0")] #[inline] @@ -816,7 +810,6 @@ pub trait Ord: Eq + PartialOrd<Self> { fn min(self, other: Self) -> Self where Self: Sized, - Self: ~const Destruct, { min_by(self, other, Ord::cmp) } @@ -833,17 +826,16 @@ pub trait Ord: Eq + PartialOrd<Self> { /// # Examples /// /// ``` - /// assert!((-3).clamp(-2, 1) == -2); - /// assert!(0.clamp(-2, 1) == 0); - /// assert!(2.clamp(-2, 1) == 1); + /// assert_eq!((-3).clamp(-2, 1), -2); + /// assert_eq!(0.clamp(-2, 1), 0); + /// assert_eq!(2.clamp(-2, 1), 1); /// ``` #[must_use] #[stable(feature = "clamp", since = "1.50.0")] fn clamp(self, min: Self, max: Self) -> Self where Self: Sized, - Self: ~const Destruct, - Self: ~const PartialOrd, + Self: PartialOrd, { assert!(min <= max); if self < min { @@ -856,7 +848,8 @@ pub trait Ord: Eq + PartialOrd<Self> { } } -/// Derive macro generating an impl of the trait `Ord`. +/// Derive macro generating an impl of the trait [`Ord`]. +/// The behavior of this macro is described in detail [here](Ord#derivable). #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] @@ -1030,7 +1023,6 @@ pub macro Ord($item:item) { label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", append_const_msg )] -#[const_trait] #[rustc_diagnostic_item = "PartialOrd"] pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { /// This method returns an ordering between `self` and `other` values if one exists. @@ -1065,11 +1057,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { /// # Examples /// /// ``` - /// let result = 1.0 < 2.0; - /// assert_eq!(result, true); - /// - /// let result = 2.0 < 1.0; - /// assert_eq!(result, false); + /// assert_eq!(1.0 < 1.0, false); + /// assert_eq!(1.0 < 2.0, true); + /// assert_eq!(2.0 < 1.0, false); /// ``` #[inline] #[must_use] @@ -1084,11 +1074,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { /// # Examples /// /// ``` - /// let result = 1.0 <= 2.0; - /// assert_eq!(result, true); - /// - /// let result = 2.0 <= 2.0; - /// assert_eq!(result, true); + /// assert_eq!(1.0 <= 1.0, true); + /// assert_eq!(1.0 <= 2.0, true); + /// assert_eq!(2.0 <= 1.0, false); /// ``` #[inline] #[must_use] @@ -1102,11 +1090,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { /// # Examples /// /// ``` - /// let result = 1.0 > 2.0; - /// assert_eq!(result, false); - /// - /// let result = 2.0 > 2.0; - /// assert_eq!(result, false); + /// assert_eq!(1.0 > 1.0, false); + /// assert_eq!(1.0 > 2.0, false); + /// assert_eq!(2.0 > 1.0, true); /// ``` #[inline] #[must_use] @@ -1121,11 +1107,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { /// # Examples /// /// ``` - /// let result = 2.0 >= 1.0; - /// assert_eq!(result, true); - /// - /// let result = 2.0 >= 2.0; - /// assert_eq!(result, true); + /// assert_eq!(1.0 >= 1.0, true); + /// assert_eq!(1.0 >= 2.0, false); + /// assert_eq!(2.0 >= 1.0, true); /// ``` #[inline] #[must_use] @@ -1135,7 +1119,8 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { } } -/// Derive macro generating an impl of the trait `PartialOrd`. +/// Derive macro generating an impl of the trait [`PartialOrd`]. +/// The behavior of this macro is described in detail [here](PartialOrd#derivable). #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] @@ -1154,15 +1139,14 @@ pub macro PartialOrd($item:item) { /// ``` /// use std::cmp; /// -/// assert_eq!(1, cmp::min(1, 2)); -/// assert_eq!(2, cmp::min(2, 2)); +/// assert_eq!(cmp::min(1, 2), 1); +/// assert_eq!(cmp::min(2, 2), 2); /// ``` #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] #[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")] -pub const fn min<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T { +pub fn min<T: Ord>(v1: T, v2: T) -> T { v1.min(v2) } @@ -1175,18 +1159,16 @@ pub const fn min<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T { /// ``` /// use std::cmp; /// -/// assert_eq!(cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 1); -/// assert_eq!(cmp::min_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2); +/// let result = cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())); +/// assert_eq!(result, 1); +/// +/// let result = cmp::min_by(-2, 3, |x: &i32, y: &i32| x.abs().cmp(&y.abs())); +/// assert_eq!(result, -2); /// ``` #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -pub const fn min_by<T, F: ~const FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T -where - T: ~const Destruct, - F: ~const Destruct, -{ +pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T { match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v1, Ordering::Greater => v2, @@ -1202,20 +1184,17 @@ where /// ``` /// use std::cmp; /// -/// assert_eq!(cmp::min_by_key(-2, 1, |x: &i32| x.abs()), 1); -/// assert_eq!(cmp::min_by_key(-2, 2, |x: &i32| x.abs()), -2); +/// let result = cmp::min_by_key(-2, 1, |x: &i32| x.abs()); +/// assert_eq!(result, 1); +/// +/// let result = cmp::min_by_key(-2, 2, |x: &i32| x.abs()); +/// assert_eq!(result, -2); /// ``` #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -pub const fn min_by_key<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(v1: T, v2: T, mut f: F) -> T -where - T: ~const Destruct, - F: ~const Destruct, - K: ~const Destruct, -{ - min_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2))) +pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T { + min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) } /// Compares and returns the maximum of two values. @@ -1229,15 +1208,14 @@ where /// ``` /// use std::cmp; /// -/// assert_eq!(2, cmp::max(1, 2)); -/// assert_eq!(2, cmp::max(2, 2)); +/// assert_eq!(cmp::max(1, 2), 2); +/// assert_eq!(cmp::max(2, 2), 2); /// ``` #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] #[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")] -pub const fn max<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T { +pub fn max<T: Ord>(v1: T, v2: T) -> T { v1.max(v2) } @@ -1250,18 +1228,16 @@ pub const fn max<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T { /// ``` /// use std::cmp; /// -/// assert_eq!(cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2); -/// assert_eq!(cmp::max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 2); +/// let result = cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())); +/// assert_eq!(result, -2); +/// +/// let result = cmp::max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())) ; +/// assert_eq!(result, 2); /// ``` #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -pub const fn max_by<T, F: ~const FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T -where - T: ~const Destruct, - F: ~const Destruct, -{ +pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T { match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v2, Ordering::Greater => v1, @@ -1277,20 +1253,17 @@ where /// ``` /// use std::cmp; /// -/// assert_eq!(cmp::max_by_key(-2, 1, |x: &i32| x.abs()), -2); -/// assert_eq!(cmp::max_by_key(-2, 2, |x: &i32| x.abs()), 2); +/// let result = cmp::max_by_key(-2, 1, |x: &i32| x.abs()); +/// assert_eq!(result, -2); +/// +/// let result = cmp::max_by_key(-2, 2, |x: &i32| x.abs()); +/// assert_eq!(result, 2); /// ``` #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -pub const fn max_by_key<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(v1: T, v2: T, mut f: F) -> T -where - T: ~const Destruct, - F: ~const Destruct, - K: ~const Destruct, -{ - max_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2))) +pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T { + max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types @@ -1301,8 +1274,7 @@ mod impls { macro_rules! partial_eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialEq for $t { + impl PartialEq for $t { #[inline] fn eq(&self, other: &$t) -> bool { (*self) == (*other) } #[inline] @@ -1312,8 +1284,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialEq for () { + impl PartialEq for () { #[inline] fn eq(&self, _other: &()) -> bool { true @@ -1340,8 +1311,7 @@ mod impls { macro_rules! partial_ord_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialOrd for $t { + impl PartialOrd for $t { #[inline] fn partial_cmp(&self, other: &$t) -> Option<Ordering> { match (*self <= *other, *self >= *other) { @@ -1351,21 +1321,20 @@ mod impls { (true, true) => Some(Equal), } } - #[inline] + #[inline(always)] fn lt(&self, other: &$t) -> bool { (*self) < (*other) } - #[inline] + #[inline(always)] fn le(&self, other: &$t) -> bool { (*self) <= (*other) } - #[inline] + #[inline(always)] fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } - #[inline] + #[inline(always)] fn gt(&self, other: &$t) -> bool { (*self) > (*other) } } )*) } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialOrd for () { + impl PartialOrd for () { #[inline] fn partial_cmp(&self, _: &()) -> Option<Ordering> { Some(Equal) @@ -1373,8 +1342,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialOrd for bool { + impl PartialOrd for bool { #[inline] fn partial_cmp(&self, other: &bool) -> Option<Ordering> { Some(self.cmp(other)) @@ -1386,25 +1354,23 @@ mod impls { macro_rules! ord_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialOrd for $t { + impl PartialOrd for $t { #[inline] fn partial_cmp(&self, other: &$t) -> Option<Ordering> { Some(self.cmp(other)) } - #[inline] + #[inline(always)] fn lt(&self, other: &$t) -> bool { (*self) < (*other) } - #[inline] + #[inline(always)] fn le(&self, other: &$t) -> bool { (*self) <= (*other) } - #[inline] + #[inline(always)] fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } - #[inline] + #[inline(always)] fn gt(&self, other: &$t) -> bool { (*self) > (*other) } } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const Ord for $t { + impl Ord for $t { #[inline] fn cmp(&self, other: &$t) -> Ordering { // The order here is important to generate more optimal assembly. @@ -1418,8 +1384,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const Ord for () { + impl Ord for () { #[inline] fn cmp(&self, _other: &()) -> Ordering { Equal @@ -1427,8 +1392,7 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const Ord for bool { + impl Ord for bool { #[inline] fn cmp(&self, other: &bool) -> Ordering { // Casting to i8's and converting the difference to an Ordering generates @@ -1447,8 +1411,8 @@ mod impls { ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[unstable(feature = "never_type", issue = "35121")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialEq for ! { + impl PartialEq for ! { + #[inline] fn eq(&self, _: &!) -> bool { *self } @@ -1458,16 +1422,16 @@ mod impls { impl Eq for ! {} #[unstable(feature = "never_type", issue = "35121")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const PartialOrd for ! { + impl PartialOrd for ! { + #[inline] fn partial_cmp(&self, _: &!) -> Option<Ordering> { *self } } #[unstable(feature = "never_type", issue = "35121")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl const Ord for ! { + impl Ord for ! { + #[inline] fn cmp(&self, _: &!) -> Ordering { *self } @@ -1476,10 +1440,9 @@ mod impls { // & pointers #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl<A: ?Sized, B: ?Sized> const PartialEq<&B> for &A + impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A where - A: ~const PartialEq<B>, + A: PartialEq<B>, { #[inline] fn eq(&self, other: &&B) -> bool { @@ -1491,10 +1454,9 @@ mod impls { } } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl<A: ?Sized, B: ?Sized> const PartialOrd<&B> for &A + impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A where - A: ~const PartialOrd<B>, + A: PartialOrd<B>, { #[inline] fn partial_cmp(&self, other: &&B) -> Option<Ordering> { diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs new file mode 100644 index 00000000000..2548d9e24c9 --- /dev/null +++ b/library/core/src/cmp/bytewise.rs @@ -0,0 +1,83 @@ +use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; +use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; + +/// Types where `==` & `!=` are equivalent to comparing their underlying bytes. +/// +/// Importantly, this means no floating-point types, as those have different +/// byte representations (like `-0` and `+0`) which compare as the same. +/// Since byte arrays are `Eq`, that implies that these types are probably also +/// `Eq`, but that's not technically required to use this trait. +/// +/// `Rhs` is *de facto* always `Self`, but the separate parameter is important +/// to avoid the `specializing impl repeats parameter` error when consuming this. +/// +/// # Safety +/// +/// - `Self` and `Rhs` have no padding. +/// - `Self` and `Rhs` have the same layout (size and alignment). +/// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct. +/// - `<Self as PartialEq<Rhs>>::{eq,ne}` are equivalent to comparing the bytes. +#[rustc_specialization_trait] +pub(crate) unsafe trait BytewiseEq<Rhs = Self>: PartialEq<Rhs> + Sized {} + +macro_rules! is_bytewise_comparable { + ($($t:ty),+ $(,)?) => {$( + unsafe impl BytewiseEq for $t {} + )+}; +} + +// SAFETY: All the ordinary integer types have no padding, and are not pointers. +is_bytewise_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +// SAFETY: These have *niches*, but no *padding* and no *provenance*, +// so we can compare them directly. +is_bytewise_comparable!(bool, char, super::Ordering); + +// SAFETY: Similarly, the non-zero types have a niche, but no undef and no pointers, +// and they compare like their underlying numeric type. +is_bytewise_comparable!( + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroUsize, + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroIsize, +); + +// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus +// are also safe to equality-compare bitwise inside an `Option`. +// The way `PartialOrd` is defined for `Option` means that this wouldn't work +// for `<` or `>` on the signed types, but since we only do `==` it's fine. +is_bytewise_comparable!( + Option<NonZeroU8>, + Option<NonZeroU16>, + Option<NonZeroU32>, + Option<NonZeroU64>, + Option<NonZeroU128>, + Option<NonZeroUsize>, + Option<NonZeroI8>, + Option<NonZeroI16>, + Option<NonZeroI32>, + Option<NonZeroI64>, + Option<NonZeroI128>, + Option<NonZeroIsize>, +); + +macro_rules! is_bytewise_comparable_array_length { + ($($n:literal),+ $(,)?) => {$( + // SAFETY: Arrays have no padding between elements, so if the elements are + // `BytewiseEq`, then the whole array can be too. + unsafe impl<T: BytewiseEq<U>, U> BytewiseEq<[U; $n]> for [T; $n] {} + )+}; +} + +// Frustratingly, this can't be made const-generic as it gets +// error: specializing impl repeats parameter `N` +// so just do it for a couple of plausibly-common ones. +is_bytewise_comparable_array_length!(0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64); diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index f95b880df34..38a6d1ccdb5 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -214,7 +214,6 @@ pub const fn identity<T>(x: T) -> T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "AsRef")] -#[const_trait] pub trait AsRef<T: ?Sized> { /// Converts this type into a shared reference of the (usually inferred) input type. #[stable(feature = "rust1", since = "1.0.0")] @@ -366,7 +365,6 @@ pub trait AsRef<T: ?Sized> { /// `&mut Vec<u8>`, for example, is the better choice (callers need to pass the correct type then). #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")] -#[const_trait] pub trait AsMut<T: ?Sized> { /// Converts this type into a mutable reference of the (usually inferred) input type. #[stable(feature = "rust1", since = "1.0.0")] @@ -443,7 +441,6 @@ pub trait AsMut<T: ?Sized> { /// [`Vec`]: ../../std/vec/struct.Vec.html #[rustc_diagnostic_item = "Into"] #[stable(feature = "rust1", since = "1.0.0")] -#[const_trait] pub trait Into<T>: Sized { /// Converts this type into the (usually inferred) input type. #[must_use] @@ -539,10 +536,9 @@ pub trait Into<T>: Sized { all(_Self = "&str", T = "std::string::String"), note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix", ))] -#[const_trait] pub trait From<T>: Sized { /// Converts to this type from the input type. - #[lang = "from"] + #[rustc_diagnostic_item = "from_fn"] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn from(value: T) -> Self; @@ -564,7 +560,6 @@ pub trait From<T>: Sized { /// [`Into`], see there for details. #[rustc_diagnostic_item = "TryInto"] #[stable(feature = "try_from", since = "1.34.0")] -#[const_trait] pub trait TryInto<T>: Sized { /// The type returned in the event of a conversion error. #[stable(feature = "try_from", since = "1.34.0")] @@ -641,7 +636,6 @@ pub trait TryInto<T>: Sized { /// [`try_from`]: TryFrom::try_from #[rustc_diagnostic_item = "TryFrom"] #[stable(feature = "try_from", since = "1.34.0")] -#[const_trait] pub trait TryFrom<T>: Sized { /// The type returned in the event of a conversion error. #[stable(feature = "try_from", since = "1.34.0")] @@ -658,10 +652,9 @@ pub trait TryFrom<T>: Sized { // As lifts over & #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T: ?Sized, U: ?Sized> const AsRef<U> for &T +impl<T: ?Sized, U: ?Sized> AsRef<U> for &T where - T: ~const AsRef<U>, + T: AsRef<U>, { #[inline] fn as_ref(&self) -> &U { @@ -671,10 +664,9 @@ where // As lifts over &mut #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T: ?Sized, U: ?Sized> const AsRef<U> for &mut T +impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T where - T: ~const AsRef<U>, + T: AsRef<U>, { #[inline] fn as_ref(&self) -> &U { @@ -692,10 +684,9 @@ where // AsMut lifts over &mut #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T: ?Sized, U: ?Sized> const AsMut<U> for &mut T +impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T where - T: ~const AsMut<U>, + T: AsMut<U>, { #[inline] fn as_mut(&mut self) -> &mut U { @@ -713,15 +704,15 @@ where // From implies Into #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T, U> const Into<U> for T +impl<T, U> Into<U> for T where - U: ~const From<T>, + U: From<T>, { /// Calls `U::from(self)`. /// /// That is, this conversion is whatever the implementation of /// <code>[From]<T> for U</code> chooses to do. + #[inline] fn into(self) -> U { U::from(self) } @@ -729,8 +720,7 @@ where // From (and thus Into) is reflexive #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<T> for T { +impl<T> From<T> for T { /// Returns the argument unchanged. #[inline(always)] fn from(t: T) -> T { @@ -747,8 +737,7 @@ impl<T> const From<T> for T { #[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead. #[rustc_reservation_impl = "permitting this impl would forbid us from adding \ `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<!> for T { +impl<T> From<!> for T { fn from(t: !) -> T { t } @@ -756,13 +745,13 @@ impl<T> const From<!> for T { // TryFrom implies TryInto #[stable(feature = "try_from", since = "1.34.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T, U> const TryInto<U> for T +impl<T, U> TryInto<U> for T where - U: ~const TryFrom<T>, + U: TryFrom<T>, { type Error = U::Error; + #[inline] fn try_into(self) -> Result<U, U::Error> { U::try_from(self) } @@ -771,13 +760,13 @@ where // Infallible conversions are semantically equivalent to fallible conversions // with an uninhabited error type. #[stable(feature = "try_from", since = "1.34.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T, U> const TryFrom<U> for T +impl<T, U> TryFrom<U> for T where - U: ~const Into<T>, + U: Into<T>, { type Error = Infallible; + #[inline] fn try_from(value: U) -> Result<Self, Self::Error> { Ok(U::into(value)) } @@ -873,8 +862,7 @@ impl AsMut<str> for str { pub enum Infallible {} #[stable(feature = "convert_infallible", since = "1.34.0")] -#[rustc_const_unstable(feature = "const_clone", issue = "91805")] -impl const Clone for Infallible { +impl Clone for Infallible { fn clone(&self) -> Infallible { match *self {} } @@ -926,8 +914,8 @@ impl Ord for Infallible { } #[stable(feature = "convert_infallible", since = "1.34.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl const From<!> for Infallible { +impl From<!> for Infallible { + #[inline] fn from(x: !) -> Self { x } diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 4da7c323492..56ab63be27d 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -44,8 +44,7 @@ impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize); macro_rules! impl_from { ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { #[$attr] - #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] - impl const From<$Small> for $Large { + impl From<$Small> for $Large { // Rustdocs on the impl block show a "[+] show undocumented items" toggle. // Rustdocs on functions do not. #[doc = $doc] @@ -170,18 +169,38 @@ impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0" // bool -> Float #[stable(feature = "float_from_bool", since = "1.68.0")] -#[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] -impl const From<bool> for f32 { - /// Converts `bool` to `f32` losslessly. +impl From<bool> for f32 { + /// Converts `bool` to `f32` losslessly. The resulting value is positive + /// `0.0` for `false` and `1.0` for `true` values. + /// + /// # Examples + /// ``` + /// let x: f32 = false.into(); + /// assert_eq!(x, 0.0); + /// assert!(x.is_sign_positive()); + /// + /// let y: f32 = true.into(); + /// assert_eq!(y, 1.0); + /// ``` #[inline] fn from(small: bool) -> Self { small as u8 as Self } } #[stable(feature = "float_from_bool", since = "1.68.0")] -#[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] -impl const From<bool> for f64 { - /// Converts `bool` to `f64` losslessly. +impl From<bool> for f64 { + /// Converts `bool` to `f64` losslessly. The resulting value is positive + /// `0.0` for `false` and `1.0` for `true` values. + /// + /// # Examples + /// ``` + /// let x: f64 = false.into(); + /// assert_eq!(x, 0.0); + /// assert!(x.is_sign_positive()); + /// + /// let y: f64 = true.into(); + /// assert_eq!(y, 1.0); + /// ``` #[inline] fn from(small: bool) -> Self { small as u8 as Self @@ -192,8 +211,7 @@ impl const From<bool> for f64 { macro_rules! try_from_unbounded { ($source:ty, $($target:ty),*) => {$( #[stable(feature = "try_from", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] - impl const TryFrom<$source> for $target { + impl TryFrom<$source> for $target { type Error = TryFromIntError; /// Try to create the target number type from a source @@ -211,8 +229,7 @@ macro_rules! try_from_unbounded { macro_rules! try_from_lower_bounded { ($source:ty, $($target:ty),*) => {$( #[stable(feature = "try_from", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] - impl const TryFrom<$source> for $target { + impl TryFrom<$source> for $target { type Error = TryFromIntError; /// Try to create the target number type from a source @@ -234,8 +251,7 @@ macro_rules! try_from_lower_bounded { macro_rules! try_from_upper_bounded { ($source:ty, $($target:ty),*) => {$( #[stable(feature = "try_from", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] - impl const TryFrom<$source> for $target { + impl TryFrom<$source> for $target { type Error = TryFromIntError; /// Try to create the target number type from a source @@ -257,8 +273,7 @@ macro_rules! try_from_upper_bounded { macro_rules! try_from_both_bounded { ($source:ty, $($target:ty),*) => {$( #[stable(feature = "try_from", since = "1.34.0")] - #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] - impl const TryFrom<$source> for $target { + impl TryFrom<$source> for $target { type Error = TryFromIntError; /// Try to create the target number type from a source @@ -409,8 +424,7 @@ use crate::num::NonZeroUsize; macro_rules! nzint_impl_from { ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { #[$attr] - #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] - impl const From<$Small> for $Large { + impl From<$Small> for $Large { // Rustdocs on the impl block show a "[+] show undocumented items" toggle. // Rustdocs on functions do not. #[doc = $doc] diff --git a/library/core/src/default.rs b/library/core/src/default.rs index d96b53de0a3..09dbc95810f 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -99,7 +99,6 @@ /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Default")] #[stable(feature = "rust1", since = "1.0.0")] -#[const_trait] pub trait Default: Sized { /// Returns the "default value" for a type. /// @@ -190,8 +189,7 @@ pub macro Default($item:item) { macro_rules! default_impl { ($t:ty, $v:expr, $doc:tt) => { #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] - impl const Default for $t { + impl Default for $t { #[inline] #[doc = $doc] fn default() -> $t { diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 571bc4bcfd1..11cb0827578 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -28,7 +28,7 @@ use crate::fmt::{Debug, Display}; #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Error")] #[rustc_has_incoherent_inherent_impls] -#[cfg_attr(not(bootstrap), allow(multiple_supertrait_upcastable))] +#[allow(multiple_supertrait_upcastable)] pub trait Error: Debug + Display { /// The lower-level source of this error, if any. /// @@ -489,7 +489,7 @@ impl Error for crate::char::CharTryFromError { #[stable(feature = "duration_checked_float", since = "1.66.0")] impl Error for crate::time::TryFromFloatSecsError {} -#[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] impl Error for crate::ffi::FromBytesUntilNulError {} #[unstable(feature = "get_many_mut", issue = "104642")] diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs new file mode 100644 index 00000000000..20ac3cf027f --- /dev/null +++ b/library/core/src/escape.rs @@ -0,0 +1,99 @@ +//! Helper code for character escaping. + +use crate::num::NonZeroUsize; +use crate::ops::Range; + +const HEX_DIGITS: [u8; 16] = *b"0123456789abcdef"; + +/// Escapes a byte into provided buffer; returns length of escaped +/// representation. +pub(crate) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range<u8> { + let (data, len) = match byte { + b'\t' => ([b'\\', b't', 0, 0], 2), + b'\r' => ([b'\\', b'r', 0, 0], 2), + b'\n' => ([b'\\', b'n', 0, 0], 2), + b'\\' => ([b'\\', b'\\', 0, 0], 2), + b'\'' => ([b'\\', b'\'', 0, 0], 2), + b'"' => ([b'\\', b'"', 0, 0], 2), + b'\x20'..=b'\x7e' => ([byte, 0, 0, 0], 1), + _ => { + let hi = HEX_DIGITS[usize::from(byte >> 4)]; + let lo = HEX_DIGITS[usize::from(byte & 0xf)]; + ([b'\\', b'x', hi, lo], 4) + } + }; + *output = data; + 0..(len as u8) +} + +/// Escapes a character into provided buffer using `\u{NNNN}` representation. +pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8> { + output[9] = b'}'; + + let ch = ch as u32; + output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize]; + output[4] = HEX_DIGITS[((ch >> 16) & 15) as usize]; + output[5] = HEX_DIGITS[((ch >> 12) & 15) as usize]; + output[6] = HEX_DIGITS[((ch >> 8) & 15) as usize]; + output[7] = HEX_DIGITS[((ch >> 4) & 15) as usize]; + output[8] = HEX_DIGITS[((ch >> 0) & 15) as usize]; + + // or-ing 1 ensures that for ch==0 the code computes that one digit should + // be printed. + let start = (ch | 1).leading_zeros() as usize / 4 - 2; + output[start..start + 3].copy_from_slice(b"\\u{"); + + (start as u8)..10 +} + +/// An iterator over an fixed-size array. +/// +/// This is essentially equivalent to array’s IntoIter except that indexes are +/// limited to u8 to reduce size of the structure. +#[derive(Clone, Debug)] +pub(crate) struct EscapeIterInner<const N: usize> { + // Invariant: data[alive] is all ASCII. + pub(crate) data: [u8; N], + + // Invariant: alive.start <= alive.end <= N. + pub(crate) alive: Range<u8>, +} + +impl<const N: usize> EscapeIterInner<N> { + pub fn new(data: [u8; N], alive: Range<u8>) -> Self { + const { assert!(N < 256) }; + debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}"); + let this = Self { data, alive }; + debug_assert!(this.as_bytes().is_ascii(), "Expected ASCII, got {:?}", this.as_bytes()); + this + } + + fn as_bytes(&self) -> &[u8] { + &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)] + } + + pub fn as_str(&self) -> &str { + // SAFETY: self.data[self.alive] is all ASCII characters. + unsafe { crate::str::from_utf8_unchecked(self.as_bytes()) } + } + + pub fn len(&self) -> usize { + usize::from(self.alive.end - self.alive.start) + } + + pub fn next(&mut self) -> Option<u8> { + self.alive.next().map(|i| self.data[usize::from(i)]) + } + + pub fn next_back(&mut self) -> Option<u8> { + self.alive.next_back().map(|i| self.data[usize::from(i)]) + } + + pub fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.alive.advance_by(n) + } + + pub fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.alive.advance_back_by(n) + } +} diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index cd00fd0daf9..07b11814f96 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -79,9 +79,9 @@ use crate::str; /// /// [str]: prim@str "str" #[derive(Hash)] -#[cfg_attr(not(test), rustc_diagnostic_item = "CStr")] #[stable(feature = "core_c_str", since = "1.64.0")] #[rustc_has_incoherent_inherent_impls] +#[cfg_attr(not(bootstrap), lang = "CStr")] // FIXME: // `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies // on `CStr` being layout-compatible with `[u8]`. @@ -153,10 +153,10 @@ impl Error for FromBytesWithNulError { /// This error is created by the [`CStr::from_bytes_until_nul`] method. /// #[derive(Clone, PartialEq, Eq, Debug)] -#[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] pub struct FromBytesUntilNulError(()); -#[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] impl fmt::Display for FromBytesUntilNulError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "data provided does not contain a nul") @@ -172,6 +172,7 @@ impl fmt::Debug for CStr { #[stable(feature = "cstr_default", since = "1.10.0")] impl Default for &CStr { + #[inline] fn default() -> Self { const SLICE: &[c_char] = &[0]; // SAFETY: `SLICE` is indeed pointing to a valid nul-terminated string. @@ -323,14 +324,15 @@ impl CStr { /// assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA"); /// ``` /// - #[rustc_allow_const_fn_unstable(const_slice_index)] - #[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] + #[rustc_const_stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> { let nul_pos = memchr::memchr(0, bytes); match nul_pos { Some(nul_pos) => { - let subslice = &bytes[..nul_pos + 1]; + // FIXME(const-hack) replace with range index + // SAFETY: nul_pos + 1 <= bytes.len() + let subslice = unsafe { crate::slice::from_raw_parts(bytes.as_ptr(), nul_pos + 1) }; // SAFETY: We know there is a nul byte at nul_pos, so this slice // (ending at the nul byte) is a well-formed C string. Ok(unsafe { CStr::from_bytes_with_nul_unchecked(subslice) }) @@ -457,6 +459,10 @@ impl CStr { /// to a contiguous region of memory terminated with a 0 byte to represent /// the end of the string. /// + /// The type of the returned pointer is + /// [`*const c_char`][crate::ffi::c_char], and whether it's + /// an alias for `*const i8` or `*const u8` is platform-specific. + /// /// **WARNING** /// /// The returned pointer is read-only; writing to it (including passing it @@ -470,6 +476,7 @@ impl CStr { /// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)] /// use std::ffi::CString; /// + /// // Do not do this: /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr(); /// unsafe { /// // `ptr` is dangling @@ -530,7 +537,8 @@ impl CStr { pub const fn is_empty(&self) -> bool { // SAFETY: We know there is at least one byte; for empty strings it // is the NUL terminator. - (unsafe { self.inner.get_unchecked(0) }) == &0 + // FIXME(const-hack): use get_unchecked + unsafe { *self.inner.as_ptr() == 0 } } /// Converts this C string to a byte slice. @@ -554,8 +562,7 @@ impl CStr { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] - pub const fn to_bytes(&self) -> &[u8] { + pub fn to_bytes(&self) -> &[u8] { let bytes = self.to_bytes_with_nul(); // SAFETY: to_bytes_with_nul returns slice with length at least 1 unsafe { bytes.get_unchecked(..bytes.len() - 1) } @@ -606,8 +613,7 @@ impl CStr { /// assert_eq!(cstr.to_str(), Ok("foo")); /// ``` #[stable(feature = "cstr_to_str", since = "1.4.0")] - #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] - pub const fn to_str(&self) -> Result<&str, str::Utf8Error> { + pub fn to_str(&self) -> Result<&str, str::Utf8Error> { // N.B., when `CStr` is changed to perform the length check in `.to_bytes()` // instead of in `from_ptr()`, it may be worth considering if this should // be rewritten to do the UTF-8 check inline with the length calculation @@ -618,6 +624,7 @@ impl CStr { #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for CStr { + #[inline] fn eq(&self, other: &CStr) -> bool { self.to_bytes().eq(other.to_bytes()) } @@ -626,12 +633,14 @@ impl PartialEq for CStr { impl Eq for CStr {} #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for CStr { + #[inline] fn partial_cmp(&self, other: &CStr) -> Option<Ordering> { self.to_bytes().partial_cmp(&other.to_bytes()) } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for CStr { + #[inline] fn cmp(&self, other: &CStr) -> Ordering { self.to_bytes().cmp(&other.to_bytes()) } @@ -641,6 +650,7 @@ impl Ord for CStr { impl ops::Index<ops::RangeFrom<usize>> for CStr { type Output = CStr; + #[inline] fn index(&self, index: ops::RangeFrom<usize>) -> &CStr { let bytes = self.to_bytes_with_nul(); // we need to manually check the starting index to account for the null diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 76daceecd7b..b85894259f1 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -143,7 +143,11 @@ mod c_char_definition { target_arch = "powerpc" ) ), - all(target_os = "fuchsia", target_arch = "aarch64"), + all( + target_os = "fuchsia", + any(target_arch = "aarch64", target_arch = "riscv64") + ), + all(target_os = "nto", target_arch = "aarch64"), target_os = "horizon" ))] { pub type c_char = u8; @@ -198,6 +202,7 @@ mod c_long_definition { // would be uninhabited and at least dereferencing such pointers would // be UB. #[doc = include_str!("c_void.md")] +#[cfg_attr(not(bootstrap), lang = "c_void")] #[repr(u8)] #[stable(feature = "core_c_void", since = "1.30.0")] pub enum c_void { @@ -614,12 +619,15 @@ impl<'f> Drop for VaListImpl<'f> { extern "rust-intrinsic" { /// Destroy the arglist `ap` after initialization with `va_start` or /// `va_copy`. + #[rustc_nounwind] fn va_end(ap: &mut VaListImpl<'_>); /// Copies the current location of arglist `src` to the arglist `dst`. + #[rustc_nounwind] fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>); /// Loads an argument of type `T` from the `va_list` `ap` and increment the /// argument `ap` points to. + #[rustc_nounwind] fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T; } diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 7da49b04aaa..36f49d51ca6 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -60,7 +60,7 @@ impl fmt::Write for PadAdapter<'_, '_> { /// } /// /// impl fmt::Debug for Foo { -/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_struct("Foo") /// .field("bar", &self.bar) /// .field("baz", &self.baz) @@ -109,14 +109,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// .field("bar", &self.bar) // We add `bar` field. /// .field("another", &self.another) // We add `another` field. /// // We even add a field which doesn't exist (because why not?). - /// .field("not_existing_field", &1) + /// .field("nonexistent_field", &1) /// .finish() // We're good to go! /// } /// } /// /// assert_eq!( /// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }), - /// "Bar { bar: 10, another: \"Hello World\", not_existing_field: 1 }", + /// "Bar { bar: 10, another: \"Hello World\", nonexistent_field: 1 }", /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -249,7 +249,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// struct Foo(i32, String); /// /// impl fmt::Debug for Foo { -/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_tuple("Foo") /// .field(&self.0) /// .field(&self.1) @@ -418,7 +418,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { /// struct Foo(Vec<i32>); /// /// impl fmt::Debug for Foo { -/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_set().entries(self.0.iter()).finish() /// } /// } @@ -548,7 +548,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// struct Foo(Vec<i32>); /// /// impl fmt::Debug for Foo { -/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_list().entries(self.0.iter()).finish() /// } /// } @@ -678,7 +678,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// struct Foo(Vec<(String, i32)>); /// /// impl fmt::Debug for Foo { -/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() /// } /// } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index c9821bf8109..bac2f31878b 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -18,6 +18,7 @@ mod float; #[cfg(no_fp_fmt_parse)] mod nofloat; mod num; +mod rt; #[stable(feature = "fmt_flags_align", since = "1.28.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Alignment")] @@ -38,12 +39,6 @@ pub enum Alignment { #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; -#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] -#[doc(hidden)] -pub mod rt { - pub mod v1; -} - /// The type returned by formatter methods. /// /// # Examples @@ -227,7 +222,7 @@ impl<W: Write + ?Sized> Write for &mut W { pub struct Formatter<'a> { flags: u32, fill: char, - align: rt::v1::Alignment, + align: rt::Alignment, width: Option<usize>, precision: Option<usize>, @@ -248,7 +243,7 @@ impl<'a> Formatter<'a> { Formatter { flags: 0, fill: ' ', - align: rt::v1::Alignment::Unknown, + align: rt::Alignment::Unknown, width: None, precision: None, buf, @@ -256,149 +251,60 @@ impl<'a> Formatter<'a> { } } -// NB. Argument is essentially an optimized partially applied formatting function, -// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`. - -extern "C" { - type Opaque; -} - -/// This struct represents the generic "argument" which is taken by the Xprintf -/// family of functions. It contains a function to format the given value. At -/// compile time it is ensured that the function and the value have the correct -/// types, and then this struct is used to canonicalize arguments to one type. -#[cfg_attr(not(bootstrap), lang = "format_argument")] +/// This structure represents a safely precompiled version of a format string +/// and its arguments. This cannot be generated at runtime because it cannot +/// safely be done, so no constructors are given and the fields are private +/// to prevent modification. +/// +/// The [`format_args!`] macro will safely create an instance of this structure. +/// The macro validates the format string at compile-time so usage of the +/// [`write()`] and [`format()`] functions can be safely performed. +/// +/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` +/// and `Display` contexts as seen below. The example also shows that `Debug` +/// and `Display` format to the same thing: the interpolated format string +/// in `format_args!`. +/// +/// ```rust +/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); +/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); +/// assert_eq!("1 foo 2", display); +/// assert_eq!(display, debug); +/// ``` +/// +/// [`format()`]: ../../std/fmt/fn.format.html +#[lang = "format_arguments"] +#[stable(feature = "rust1", since = "1.0.0")] #[derive(Copy, Clone)] -#[allow(missing_debug_implementations)] -#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] -#[doc(hidden)] -pub struct ArgumentV1<'a> { - value: &'a Opaque, - formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, -} - -/// This struct represents the unsafety of constructing an `Arguments`. -/// It exists, rather than an unsafe function, in order to simplify the expansion -/// of `format_args!(..)` and reduce the scope of the `unsafe` block. -#[cfg_attr(not(bootstrap), lang = "format_unsafe_arg")] -#[allow(missing_debug_implementations)] -#[doc(hidden)] -#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] -pub struct UnsafeArg { - _private: (), -} +pub struct Arguments<'a> { + // Format string pieces to print. + pieces: &'a [&'static str], -impl UnsafeArg { - /// See documentation where `UnsafeArg` is required to know when it is safe to - /// create and use `UnsafeArg`. - #[doc(hidden)] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] - #[inline(always)] - pub unsafe fn new() -> Self { - Self { _private: () } - } -} + // Placeholder specs, or `None` if all specs are default (as in "{}{}"). + fmt: Option<&'a [rt::Placeholder]>, -// This guarantees a single stable value for the function pointer associated with -// indices/counts in the formatting infrastructure. -// -// Note that a function defined as such would not be correct as functions are -// always tagged unnamed_addr with the current lowering to LLVM IR, so their -// address is not considered important to LLVM and as such the as_usize cast -// could have been miscompiled. In practice, we never call as_usize on non-usize -// containing data (as a matter of static generation of the formatting -// arguments), so this is merely an additional check. -// -// We primarily want to ensure that the function pointer at `USIZE_MARKER` has -// an address corresponding *only* to functions that also take `&usize` as their -// first argument. The read_volatile here ensures that we can safely ready out a -// usize from the passed reference and that this address does not point at a -// non-usize taking function. -#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] -static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| { - // SAFETY: ptr is a reference - let _v: usize = unsafe { crate::ptr::read_volatile(ptr) }; - loop {} -}; - -macro_rules! arg_new { - ($f: ident, $t: ident) => { - #[doc(hidden)] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] - #[inline] - pub fn $f<'b, T: $t>(x: &'b T) -> ArgumentV1<'_> { - Self::new(x, $t::fmt) - } - }; + // Dynamic arguments for interpolation, to be interleaved with string + // pieces. (Every argument is preceded by a string piece.) + args: &'a [rt::Argument<'a>], } -#[rustc_diagnostic_item = "ArgumentV1Methods"] -impl<'a> ArgumentV1<'a> { - #[doc(hidden)] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] +/// Used by the format_args!() macro to create a fmt::Arguments object. +#[doc(hidden)] +#[unstable(feature = "fmt_internals", issue = "none")] +impl<'a> Arguments<'a> { #[inline] - pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> { - // SAFETY: `mem::transmute(x)` is safe because - // 1. `&'b T` keeps the lifetime it originated with `'b` - // (so as to not have an unbounded lifetime) - // 2. `&'b T` and `&'b Opaque` have the same memory layout - // (when `T` is `Sized`, as it is here) - // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result` - // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI - // (as long as `T` is `Sized`) - unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } } - } - - arg_new!(new_display, Display); - arg_new!(new_debug, Debug); - arg_new!(new_octal, Octal); - arg_new!(new_lower_hex, LowerHex); - arg_new!(new_upper_hex, UpperHex); - arg_new!(new_pointer, Pointer); - arg_new!(new_binary, Binary); - arg_new!(new_lower_exp, LowerExp); - arg_new!(new_upper_exp, UpperExp); - - #[doc(hidden)] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] - pub fn from_usize(x: &usize) -> ArgumentV1<'_> { - ArgumentV1::new(x, USIZE_MARKER) - } - - fn as_usize(&self) -> Option<usize> { - // We are type punning a bit here: USIZE_MARKER only takes an &usize but - // formatter takes an &Opaque. Rust understandably doesn't think we should compare - // the function pointers if they don't have the same signature, so we cast to - // usizes to tell it that we just want to compare addresses. - if self.formatter as usize == USIZE_MARKER as usize { - // SAFETY: The `formatter` field is only set to USIZE_MARKER if - // the value is a usize, so this is safe - Some(unsafe { *(self.value as *const _ as *const usize) }) - } else { - None + #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] + pub const fn new_const(pieces: &'a [&'static str]) -> Self { + if pieces.len() > 1 { + panic!("invalid args"); } + Arguments { pieces, fmt: None, args: &[] } } -} -// flags available in the v1 format of format_args -#[derive(Copy, Clone)] -enum FlagV1 { - SignPlus, - SignMinus, - Alternate, - SignAwareZeroPad, - DebugLowerHex, - DebugUpperHex, -} - -impl<'a> Arguments<'a> { /// When using the format_args!() macro, this function is used to generate the /// Arguments structure. - #[doc(hidden)] #[inline] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] - #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] - pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { + pub fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> { if pieces.len() < args.len() || pieces.len() > args.len() + 1 { panic!("invalid args"); } @@ -407,22 +313,17 @@ impl<'a> Arguments<'a> { /// This function is used to specify nonstandard formatting parameters. /// - /// An `UnsafeArg` is required because the following invariants must be held + /// An `rt::UnsafeArg` is required because the following invariants must be held /// in order for this function to be safe: /// 1. The `pieces` slice must be at least as long as `fmt`. - /// 2. Every [`rt::v1::Argument::position`] value within `fmt` must be a - /// valid index of `args`. - /// 3. Every [`rt::v1::Count::Param`] within `fmt` must contain a valid index of - /// `args`. - #[doc(hidden)] + /// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`. + /// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`. #[inline] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] - #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] - pub const fn new_v1_formatted( + pub fn new_v1_formatted( pieces: &'a [&'static str], - args: &'a [ArgumentV1<'a>], - fmt: &'a [rt::v1::Argument], - _unsafe_arg: UnsafeArg, + args: &'a [rt::Argument<'a>], + fmt: &'a [rt::Placeholder], + _unsafe_arg: rt::UnsafeArg, ) -> Arguments<'a> { Arguments { pieces, fmt: Some(fmt), args } } @@ -431,9 +332,7 @@ impl<'a> Arguments<'a> { /// /// This is intended to be used for setting initial `String` capacity /// when using `format!`. Note: this is neither the lower nor upper bound. - #[doc(hidden)] #[inline] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] pub fn estimated_capacity(&self) -> usize { let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum(); @@ -453,43 +352,6 @@ impl<'a> Arguments<'a> { } } -/// This structure represents a safely precompiled version of a format string -/// and its arguments. This cannot be generated at runtime because it cannot -/// safely be done, so no constructors are given and the fields are private -/// to prevent modification. -/// -/// The [`format_args!`] macro will safely create an instance of this structure. -/// The macro validates the format string at compile-time so usage of the -/// [`write()`] and [`format()`] functions can be safely performed. -/// -/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` -/// and `Display` contexts as seen below. The example also shows that `Debug` -/// and `Display` format to the same thing: the interpolated format string -/// in `format_args!`. -/// -/// ```rust -/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); -/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); -/// assert_eq!("1 foo 2", display); -/// assert_eq!(display, debug); -/// ``` -/// -/// [`format()`]: ../../std/fmt/fn.format.html -#[cfg_attr(not(bootstrap), lang = "format_arguments")] -#[stable(feature = "rust1", since = "1.0.0")] -#[derive(Copy, Clone)] -pub struct Arguments<'a> { - // Format string pieces to print. - pieces: &'a [&'static str], - - // Placeholder specs, or `None` if all specs are default (as in "{}{}"). - fmt: Option<&'a [rt::v1::Argument]>, - - // Dynamic arguments for interpolation, to be interleaved with string - // pieces. (Every argument is preceded by a string piece.) - args: &'a [ArgumentV1<'a>], -} - impl<'a> Arguments<'a> { /// Get the formatted string, if it has no arguments to be formatted at runtime. /// @@ -519,7 +381,7 @@ impl<'a> Arguments<'a> { /// /// fn write_str(_: &str) { /* ... */ } /// - /// fn write_fmt(args: &Arguments) { + /// fn write_fmt(args: &Arguments<'_>) { /// if let Some(s) = args.as_str() { /// write_str(s) /// } else { @@ -1229,7 +1091,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { if !piece.is_empty() { formatter.buf.write_str(*piece)?; } - (arg.formatter)(arg.value, &mut formatter)?; + arg.fmt(&mut formatter)?; idx += 1; } } @@ -1259,15 +1121,15 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { Ok(()) } -unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result { - fmt.fill = arg.format.fill; - fmt.align = arg.format.align; - fmt.flags = arg.format.flags; +unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result { + fmt.fill = arg.fill; + fmt.align = arg.align; + fmt.flags = arg.flags; // SAFETY: arg and args come from the same Arguments, // which guarantees the indexes are always within bounds. unsafe { - fmt.width = getcount(args, &arg.format.width); - fmt.precision = getcount(args, &arg.format.precision); + fmt.width = getcount(args, &arg.width); + fmt.precision = getcount(args, &arg.precision); } // Extract the correct argument @@ -1277,14 +1139,14 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV let value = unsafe { args.get_unchecked(arg.position) }; // Then actually do some printing - (value.formatter)(value.value, fmt) + value.fmt(fmt) } -unsafe fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> { +unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize> { match *cnt { - rt::v1::Count::Is(n) => Some(n), - rt::v1::Count::Implied => None, - rt::v1::Count::Param(i) => { + rt::Count::Is(n) => Some(n), + rt::Count::Implied => None, + rt::Count::Param(i) => { debug_assert!(i < args.len()); // SAFETY: cnt and args come from the same Arguments, // which guarantees this index is always within bounds. @@ -1366,7 +1228,7 @@ impl<'a> Formatter<'a> { /// } /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// // We need to remove "-" from the number output. /// let tmp = self.nb.abs().to_string(); /// @@ -1427,9 +1289,9 @@ impl<'a> Formatter<'a> { // is zero Some(min) if self.sign_aware_zero_pad() => { let old_fill = crate::mem::replace(&mut self.fill, '0'); - let old_align = crate::mem::replace(&mut self.align, rt::v1::Alignment::Right); + let old_align = crate::mem::replace(&mut self.align, rt::Alignment::Right); write_prefix(self, sign, prefix)?; - let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?; + let post_padding = self.padding(min - width, Alignment::Right)?; self.buf.write_str(buf)?; post_padding.write(self)?; self.fill = old_fill; @@ -1438,7 +1300,7 @@ impl<'a> Formatter<'a> { } // Otherwise, the sign and prefix goes after the padding Some(min) => { - let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?; + let post_padding = self.padding(min - width, Alignment::Right)?; write_prefix(self, sign, prefix)?; self.buf.write_str(buf)?; post_padding.write(self) @@ -1466,7 +1328,7 @@ impl<'a> Formatter<'a> { /// struct Foo; /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// formatter.pad("Foo") /// } /// } @@ -1513,7 +1375,7 @@ impl<'a> Formatter<'a> { // If we're under both the maximum and the minimum width, then fill // up the minimum width with the specified string + some alignment. else { - let align = rt::v1::Alignment::Left; + let align = Alignment::Left; let post_padding = self.padding(width - chars_count, align)?; self.buf.write_str(s)?; post_padding.write(self) @@ -1528,17 +1390,19 @@ impl<'a> Formatter<'a> { pub(crate) fn padding( &mut self, padding: usize, - default: rt::v1::Alignment, + default: Alignment, ) -> result::Result<PostPadding, Error> { let align = match self.align { - rt::v1::Alignment::Unknown => default, - _ => self.align, + rt::Alignment::Unknown => default, + rt::Alignment::Left => Alignment::Left, + rt::Alignment::Right => Alignment::Right, + rt::Alignment::Center => Alignment::Center, }; let (pre_pad, post_pad) = match align { - rt::v1::Alignment::Left => (0, padding), - rt::v1::Alignment::Right | rt::v1::Alignment::Unknown => (padding, 0), - rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2), + Alignment::Left => (0, padding), + Alignment::Right => (padding, 0), + Alignment::Center => (padding / 2, (padding + 1) / 2), }; for _ in 0..pre_pad { @@ -1558,7 +1422,6 @@ impl<'a> Formatter<'a> { let mut formatted = formatted.clone(); let old_fill = self.fill; let old_align = self.align; - let mut align = old_align; if self.sign_aware_zero_pad() { // a sign always goes first let sign = formatted.sign; @@ -1567,9 +1430,8 @@ impl<'a> Formatter<'a> { // remove the sign from the formatted parts formatted.sign = ""; width = width.saturating_sub(sign.len()); - align = rt::v1::Alignment::Right; self.fill = '0'; - self.align = rt::v1::Alignment::Right; + self.align = rt::Alignment::Right; } // remaining parts go through the ordinary padding process. @@ -1578,7 +1440,7 @@ impl<'a> Formatter<'a> { // no padding self.write_formatted_parts(&formatted) } else { - let post_padding = self.padding(width - len, align)?; + let post_padding = self.padding(width - len, Alignment::Right)?; self.write_formatted_parts(&formatted)?; post_padding.write(self) }; @@ -1648,7 +1510,7 @@ impl<'a> Formatter<'a> { /// struct Foo; /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// formatter.write_str("Foo") /// // This is equivalent to: /// // write!(formatter, "Foo") @@ -1673,7 +1535,7 @@ impl<'a> Formatter<'a> { /// struct Foo(i32); /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// formatter.write_fmt(format_args!("Foo {}", self.0)) /// } /// } @@ -1708,7 +1570,7 @@ impl<'a> Formatter<'a> { /// struct Foo; /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// let c = formatter.fill(); /// if let Some(width) = formatter.width() { /// for _ in 0..width { @@ -1736,14 +1598,12 @@ impl<'a> Formatter<'a> { /// # Examples /// /// ``` - /// extern crate core; - /// /// use std::fmt::{self, Alignment}; /// /// struct Foo; /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// let s = if let Some(s) = formatter.align() { /// match s { /// Alignment::Left => "left", @@ -1766,10 +1626,10 @@ impl<'a> Formatter<'a> { #[stable(feature = "fmt_flags_align", since = "1.28.0")] pub fn align(&self) -> Option<Alignment> { match self.align { - rt::v1::Alignment::Left => Some(Alignment::Left), - rt::v1::Alignment::Right => Some(Alignment::Right), - rt::v1::Alignment::Center => Some(Alignment::Center), - rt::v1::Alignment::Unknown => None, + rt::Alignment::Left => Some(Alignment::Left), + rt::Alignment::Right => Some(Alignment::Right), + rt::Alignment::Center => Some(Alignment::Center), + rt::Alignment::Unknown => None, } } @@ -1783,7 +1643,7 @@ impl<'a> Formatter<'a> { /// struct Foo(i32); /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// if let Some(width) = formatter.width() { /// // If we received a width, we use it /// write!(formatter, "{:width$}", format!("Foo({})", self.0), width = width) @@ -1814,7 +1674,7 @@ impl<'a> Formatter<'a> { /// struct Foo(f32); /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// if let Some(precision) = formatter.precision() { /// // If we received a precision, we use it. /// write!(formatter, "Foo({1:.*})", precision, self.0) @@ -1844,7 +1704,7 @@ impl<'a> Formatter<'a> { /// struct Foo(i32); /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// if formatter.sign_plus() { /// write!(formatter, /// "Foo({}{})", @@ -1863,7 +1723,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_plus(&self) -> bool { - self.flags & (1 << FlagV1::SignPlus as u32) != 0 + self.flags & (1 << rt::Flag::SignPlus as u32) != 0 } /// Determines if the `-` flag was specified. @@ -1876,7 +1736,7 @@ impl<'a> Formatter<'a> { /// struct Foo(i32); /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// if formatter.sign_minus() { /// // You want a minus sign? Have one! /// write!(formatter, "-Foo({})", self.0) @@ -1892,7 +1752,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_minus(&self) -> bool { - self.flags & (1 << FlagV1::SignMinus as u32) != 0 + self.flags & (1 << rt::Flag::SignMinus as u32) != 0 } /// Determines if the `#` flag was specified. @@ -1905,7 +1765,7 @@ impl<'a> Formatter<'a> { /// struct Foo(i32); /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// if formatter.alternate() { /// write!(formatter, "Foo({})", self.0) /// } else { @@ -1920,7 +1780,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn alternate(&self) -> bool { - self.flags & (1 << FlagV1::Alternate as u32) != 0 + self.flags & (1 << rt::Flag::Alternate as u32) != 0 } /// Determines if the `0` flag was specified. @@ -1933,7 +1793,7 @@ impl<'a> Formatter<'a> { /// struct Foo(i32); /// /// impl fmt::Display for Foo { - /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// assert!(formatter.sign_aware_zero_pad()); /// assert_eq!(formatter.width(), Some(4)); /// // We ignore the formatter's options. @@ -1946,17 +1806,17 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_aware_zero_pad(&self) -> bool { - self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0 + self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 } // FIXME: Decide what public API we want for these two flags. // https://github.com/rust-lang/rust/issues/48584 fn debug_lower_hex(&self) -> bool { - self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 + self.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0 } fn debug_upper_hex(&self) -> bool { - self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 + self.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0 } /// Creates a [`DebugStruct`] builder designed to assist with creation of @@ -1977,7 +1837,7 @@ impl<'a> Formatter<'a> { /// } /// /// impl fmt::Debug for Foo { - /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_struct("Foo") /// .field("bar", &self.bar) /// .field("baz", &self.baz) @@ -2135,7 +1995,7 @@ impl<'a> Formatter<'a> { /// struct Foo<T>(i32, String, PhantomData<T>); /// /// impl<T> fmt::Debug for Foo<T> { - /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_tuple("Foo") /// .field(&self.0) /// .field(&self.1) @@ -2267,7 +2127,7 @@ impl<'a> Formatter<'a> { /// struct Foo(Vec<i32>); /// /// impl fmt::Debug for Foo { - /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_list().entries(self.0.iter()).finish() /// } /// } @@ -2290,7 +2150,7 @@ impl<'a> Formatter<'a> { /// struct Foo(Vec<i32>); /// /// impl fmt::Debug for Foo { - /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_set().entries(self.0.iter()).finish() /// } /// } @@ -2306,14 +2166,14 @@ impl<'a> Formatter<'a> { /// ```rust /// use std::fmt; /// - /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R)); - /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V); + /// struct Arm<'a, L, R>(&'a (L, R)); + /// struct Table<'a, K, V>(&'a [(K, V)], V); /// /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R> /// where /// L: 'a + fmt::Debug, R: 'a + fmt::Debug /// { - /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// L::fmt(&(self.0).0, fmt)?; /// fmt.write_str(" => ")?; /// R::fmt(&(self.0).1, fmt) @@ -2324,7 +2184,7 @@ impl<'a> Formatter<'a> { /// where /// K: 'a + fmt::Debug, V: 'a + fmt::Debug /// { - /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_set() /// .entries(self.0.iter().map(Arm)) /// .entry(&Arm(&(format_args!("_"), &self.1))) @@ -2348,7 +2208,7 @@ impl<'a> Formatter<'a> { /// struct Foo(Vec<(String, i32)>); /// /// impl fmt::Debug for Foo { - /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish() /// } /// } @@ -2407,6 +2267,7 @@ fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperEx #[unstable(feature = "never_type", issue = "35121")] impl Debug for ! { + #[inline] fn fmt(&self, _: &mut Formatter<'_>) -> Result { *self } @@ -2414,6 +2275,7 @@ impl Debug for ! { #[unstable(feature = "never_type", issue = "35121")] impl Display for ! { + #[inline] fn fmt(&self, _: &mut Formatter<'_>) -> Result { *self } @@ -2516,13 +2378,13 @@ pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Resul // or not to zero extend, and then unconditionally set it to get the // prefix. if f.alternate() { - f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); + f.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32); if f.width.is_none() { f.width = Some((usize::BITS / 4) as usize + 2); } } - f.flags |= 1 << (FlagV1::Alternate as u32); + f.flags |= 1 << (rt::Flag::Alternate as u32); let ret = LowerHex::fmt(&ptr_addr, f); diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs new file mode 100644 index 00000000000..d37888c27bd --- /dev/null +++ b/library/core/src/fmt/rt.rs @@ -0,0 +1,212 @@ +#![allow(missing_debug_implementations)] +#![unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] + +//! These are the lang items used by format_args!(). + +use super::*; + +#[lang = "format_placeholder"] +#[derive(Copy, Clone)] +pub struct Placeholder { + pub position: usize, + pub fill: char, + pub align: Alignment, + pub flags: u32, + pub precision: Count, + pub width: Count, +} + +impl Placeholder { + #[inline(always)] + pub const fn new( + position: usize, + fill: char, + align: Alignment, + flags: u32, + precision: Count, + width: Count, + ) -> Self { + Self { position, fill, align, flags, precision, width } + } +} + +#[lang = "format_alignment"] +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum Alignment { + Left, + Right, + Center, + Unknown, +} + +/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) +/// and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers. +#[lang = "format_count"] +#[derive(Copy, Clone)] +pub enum Count { + /// Specified with a literal number, stores the value + Is(usize), + /// Specified using `$` and `*` syntaxes, stores the index into `args` + Param(usize), + /// Not specified + Implied, +} + +// This needs to match the order of flags in compiler/rustc_ast_lowering/src/format.rs. +#[derive(Copy, Clone)] +pub(super) enum Flag { + SignPlus, + SignMinus, + Alternate, + SignAwareZeroPad, + DebugLowerHex, + DebugUpperHex, +} + +/// This struct represents the generic "argument" which is taken by format_args!(). +/// It contains a function to format the given value. At compile time it is ensured that the +/// function and the value have the correct types, and then this struct is used to canonicalize +/// arguments to one type. +/// +/// Argument is essentially an optimized partially applied formatting function, +/// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`. +#[lang = "format_argument"] +#[derive(Copy, Clone)] +pub struct Argument<'a> { + value: &'a Opaque, + formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, +} + +#[rustc_diagnostic_item = "ArgumentMethods"] +impl<'a> Argument<'a> { + #[inline(always)] + fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> { + // SAFETY: `mem::transmute(x)` is safe because + // 1. `&'b T` keeps the lifetime it originated with `'b` + // (so as to not have an unbounded lifetime) + // 2. `&'b T` and `&'b Opaque` have the same memory layout + // (when `T` is `Sized`, as it is here) + // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result` + // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI + // (as long as `T` is `Sized`) + unsafe { Argument { formatter: mem::transmute(f), value: mem::transmute(x) } } + } + + #[inline(always)] + pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'_> { + Self::new(x, Display::fmt) + } + #[inline(always)] + pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'_> { + Self::new(x, Debug::fmt) + } + #[inline(always)] + pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> { + Self::new(x, Octal::fmt) + } + #[inline(always)] + pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'_> { + Self::new(x, LowerHex::fmt) + } + #[inline(always)] + pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'_> { + Self::new(x, UpperHex::fmt) + } + #[inline(always)] + pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'_> { + Self::new(x, Pointer::fmt) + } + #[inline(always)] + pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'_> { + Self::new(x, Binary::fmt) + } + #[inline(always)] + pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'_> { + Self::new(x, LowerExp::fmt) + } + #[inline(always)] + pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'_> { + Self::new(x, UpperExp::fmt) + } + #[inline(always)] + pub fn from_usize(x: &usize) -> Argument<'_> { + Self::new(x, USIZE_MARKER) + } + + #[inline(always)] + pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result { + (self.formatter)(self.value, f) + } + + #[inline(always)] + pub(super) fn as_usize(&self) -> Option<usize> { + // We are type punning a bit here: USIZE_MARKER only takes an &usize but + // formatter takes an &Opaque. Rust understandably doesn't think we should compare + // the function pointers if they don't have the same signature, so we cast to + // usizes to tell it that we just want to compare addresses. + if self.formatter as usize == USIZE_MARKER as usize { + // SAFETY: The `formatter` field is only set to USIZE_MARKER if + // the value is a usize, so this is safe + Some(unsafe { *(self.value as *const _ as *const usize) }) + } else { + None + } + } + + /// Used by `format_args` when all arguments are gone after inlining, + /// when using `&[]` would incorrectly allow for a bigger lifetime. + /// + /// This fails without format argument inlining, and that shouldn't be different + /// when the argument is inlined: + /// + /// ```compile_fail,E0716 + /// let f = format_args!("{}", "a"); + /// println!("{f}"); + /// ``` + #[inline(always)] + pub fn none() -> [Self; 0] { + [] + } +} + +/// This struct represents the unsafety of constructing an `Arguments`. +/// It exists, rather than an unsafe function, in order to simplify the expansion +/// of `format_args!(..)` and reduce the scope of the `unsafe` block. +#[lang = "format_unsafe_arg"] +pub struct UnsafeArg { + _private: (), +} + +impl UnsafeArg { + /// See documentation where `UnsafeArg` is required to know when it is safe to + /// create and use `UnsafeArg`. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _private: () } + } +} + +extern "C" { + type Opaque; +} + +// This guarantees a single stable value for the function pointer associated with +// indices/counts in the formatting infrastructure. +// +// Note that a function defined as such would not be correct as functions are +// always tagged unnamed_addr with the current lowering to LLVM IR, so their +// address is not considered important to LLVM and as such the as_usize cast +// could have been miscompiled. In practice, we never call as_usize on non-usize +// containing data (as a matter of static generation of the formatting +// arguments), so this is merely an additional check. +// +// We primarily want to ensure that the function pointer at `USIZE_MARKER` has +// an address corresponding *only* to functions that also take `&usize` as their +// first argument. The read_volatile here ensures that we can safely ready out a +// usize from the passed reference and that this address does not point at a +// non-usize taking function. +static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| { + // SAFETY: ptr is a reference + let _v: usize = unsafe { crate::ptr::read_volatile(ptr) }; + loop {} +}; diff --git a/library/core/src/fmt/rt/v1.rs b/library/core/src/fmt/rt/v1.rs deleted file mode 100644 index 11a50951a75..00000000000 --- a/library/core/src/fmt/rt/v1.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! This is an internal module used by the ifmt! runtime. These structures are -//! emitted to static arrays to precompile format strings ahead of time. -//! -//! These definitions are similar to their `ct` equivalents, but differ in that -//! these can be statically allocated and are slightly optimized for the runtime -#![allow(missing_debug_implementations)] - -#[cfg_attr(not(bootstrap), lang = "format_placeholder")] -#[derive(Copy, Clone)] -// FIXME: Rename this to Placeholder -pub struct Argument { - pub position: usize, - pub format: FormatSpec, -} - -#[derive(Copy, Clone)] -pub struct FormatSpec { - pub fill: char, - pub align: Alignment, - pub flags: u32, - pub precision: Count, - pub width: Count, -} - -impl Argument { - #[inline(always)] - pub const fn new( - position: usize, - fill: char, - align: Alignment, - flags: u32, - precision: Count, - width: Count, - ) -> Self { - Self { position, format: FormatSpec { fill, align, flags, precision, width } } - } -} - -/// Possible alignments that can be requested as part of a formatting directive. -#[cfg_attr(not(bootstrap), lang = "format_alignment")] -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum Alignment { - /// Indication that contents should be left-aligned. - Left, - /// Indication that contents should be right-aligned. - Right, - /// Indication that contents should be center-aligned. - Center, - /// No alignment was requested. - Unknown, -} - -/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers. -#[cfg_attr(not(bootstrap), lang = "format_count")] -#[derive(Copy, Clone)] -pub enum Count { - /// Specified with a literal number, stores the value - Is(usize), - /// Specified using `$` and `*` syntaxes, stores the index into `args` - Param(usize), - /// Not specified - Implied, -} diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs index 649b4338772..38c654e76b4 100644 --- a/library/core/src/future/into_future.rs +++ b/library/core/src/future/into_future.rs @@ -99,6 +99,7 @@ use crate::future::Future; /// } /// ``` #[stable(feature = "into_future", since = "1.64.0")] +#[rustc_diagnostic_item = "IntoFuture"] pub trait IntoFuture { /// The output that the future will produce on completion. #[stable(feature = "into_future", since = "1.64.0")] diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 46cbcd43530..089493d3766 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -66,15 +66,3 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { // that fulfills all the requirements for a mutable reference. unsafe { &mut *cx.0.as_ptr().cast() } } - -// FIXME(swatinem): This fn is currently needed to work around shortcomings -// in type and lifetime inference. -// See the comment at the bottom of `LoweringContext::make_async_expr` and -// <https://github.com/rust-lang/rust/issues/104826>. -#[doc(hidden)] -#[unstable(feature = "gen_future", issue = "50547")] -#[inline] -#[lang = "identity_future"] -pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut { - f -} diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 71a0d1825ef..a73b5b610a4 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -86,8 +86,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::fmt; -use crate::intrinsics::const_eval_select; -use crate::marker::{self, Destruct}; +use crate::marker; #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] @@ -158,7 +157,7 @@ mod sip; /// /// Implementations of `hash` should ensure that the data they /// pass to the `Hasher` are prefix-free. That is, -/// unequal values should cause two different sequences of values to be written, +/// values which are not equal should cause two different sequences of values to be written, /// and neither of the two sequences should be a prefix of the other. /// /// For example, the standard implementation of [`Hash` for `&str`][impl] passes an extra @@ -184,7 +183,6 @@ mod sip; /// [impl]: ../../std/primitive.str.html#impl-Hash-for-str #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Hash"] -#[const_trait] pub trait Hash { /// Feeds this value into the given [`Hasher`]. /// @@ -199,7 +197,7 @@ pub trait Hash { /// println!("Hash is {:x}!", hasher.finish()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn hash<H: ~const Hasher>(&self, state: &mut H); + fn hash<H: Hasher>(&self, state: &mut H); /// Feeds a slice of this type into the given [`Hasher`]. /// @@ -236,25 +234,13 @@ pub trait Hash { /// [`hash`]: Hash::hash /// [`hash_slice`]: Hash::hash_slice #[stable(feature = "hash_slice", since = "1.3.0")] - fn hash_slice<H: ~const Hasher>(data: &[Self], state: &mut H) + fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized, { - //FIXME(const_trait_impl): revert to only a for loop - fn rt<T: Hash, H: Hasher>(data: &[T], state: &mut H) { - for piece in data { - piece.hash(state) - } - } - const fn ct<T: ~const Hash, H: ~const Hasher>(data: &[T], state: &mut H) { - let mut i = 0; - while i < data.len() { - data[i].hash(state); - i += 1; - } + for piece in data { + piece.hash(state) } - // SAFETY: same behavior, CT just uses while instead of for - unsafe { const_eval_select((data, state), ct, rt) }; } } @@ -327,7 +313,6 @@ pub use macros::Hash; /// [`write_u8`]: Hasher::write_u8 /// [`write_u32`]: Hasher::write_u32 #[stable(feature = "rust1", since = "1.0.0")] -#[const_trait] pub trait Hasher { /// Returns the hash value for the values written so far. /// @@ -573,8 +558,7 @@ pub trait Hasher { } #[stable(feature = "indirect_hasher_impl", since = "1.22.0")] -#[rustc_const_unstable(feature = "const_hash", issue = "104061")] -impl<H: ~const Hasher + ?Sized> const Hasher for &mut H { +impl<H: Hasher + ?Sized> Hasher for &mut H { fn finish(&self) -> u64 { (**self).finish() } @@ -654,7 +638,6 @@ impl<H: ~const Hasher + ?Sized> const Hasher for &mut H { /// [`build_hasher`]: BuildHasher::build_hasher /// [`HashMap`]: ../../std/collections/struct.HashMap.html #[stable(since = "1.7.0", feature = "build_hasher")] -#[const_trait] pub trait BuildHasher { /// Type of the hasher that will be created. #[stable(since = "1.7.0", feature = "build_hasher")] @@ -715,10 +698,10 @@ pub trait BuildHasher { /// ); /// ``` #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")] - fn hash_one<T: ~const Hash + ~const Destruct>(&self, x: T) -> u64 + fn hash_one<T: Hash>(&self, x: T) -> u64 where Self: Sized, - Self::Hasher: ~const Hasher + ~const Destruct, + Self::Hasher: Hasher, { let mut hasher = self.build_hasher(); x.hash(&mut hasher); @@ -782,8 +765,7 @@ impl<H> fmt::Debug for BuildHasherDefault<H> { } #[stable(since = "1.7.0", feature = "build_hasher")] -#[rustc_const_unstable(feature = "const_hash", issue = "104061")] -impl<H: ~const Default + Hasher> const BuildHasher for BuildHasherDefault<H> { +impl<H: Default + Hasher> BuildHasher for BuildHasherDefault<H> { type Hasher = H; fn build_hasher(&self) -> H { @@ -799,8 +781,7 @@ impl<H> Clone for BuildHasherDefault<H> { } #[stable(since = "1.7.0", feature = "build_hasher")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<H> const Default for BuildHasherDefault<H> { +impl<H> Default for BuildHasherDefault<H> { fn default() -> BuildHasherDefault<H> { BuildHasherDefault(marker::PhantomData) } @@ -825,16 +806,15 @@ mod impls { macro_rules! impl_write { ($(($ty:ident, $meth:ident),)*) => {$( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl const Hash for $ty { + impl Hash for $ty { #[inline] - fn hash<H: ~const Hasher>(&self, state: &mut H) { + fn hash<H: Hasher>(&self, state: &mut H) { state.$meth(*self) } #[inline] - fn hash_slice<H: ~const Hasher>(data: &[$ty], state: &mut H) { - let newlen = data.len() * mem::size_of::<$ty>(); + fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) { + let newlen = mem::size_of_val(data); let ptr = data.as_ptr() as *const u8; // SAFETY: `ptr` is valid and aligned, as this macro is only used // for numeric primitives which have no padding. The new slice only @@ -862,37 +842,33 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl const Hash for bool { + impl Hash for bool { #[inline] - fn hash<H: ~const Hasher>(&self, state: &mut H) { + fn hash<H: Hasher>(&self, state: &mut H) { state.write_u8(*self as u8) } } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl const Hash for char { + impl Hash for char { #[inline] - fn hash<H: ~const Hasher>(&self, state: &mut H) { + fn hash<H: Hasher>(&self, state: &mut H) { state.write_u32(*self as u32) } } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl const Hash for str { + impl Hash for str { #[inline] - fn hash<H: ~const Hasher>(&self, state: &mut H) { + fn hash<H: Hasher>(&self, state: &mut H) { state.write_str(self); } } #[stable(feature = "never_hash", since = "1.29.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl const Hash for ! { + impl Hash for ! { #[inline] - fn hash<H: ~const Hasher>(&self, _: &mut H) { + fn hash<H: Hasher>(&self, _: &mut H) { *self } } @@ -900,10 +876,9 @@ mod impls { macro_rules! impl_hash_tuple { () => ( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl const Hash for () { + impl Hash for () { #[inline] - fn hash<H: ~const Hasher>(&self, _state: &mut H) {} + fn hash<H: Hasher>(&self, _state: &mut H) {} } ); @@ -911,11 +886,10 @@ mod impls { maybe_tuple_doc! { $($name)+ @ #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl<$($name: ~const Hash),+> const Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { + impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized { #[allow(non_snake_case)] #[inline] - fn hash<S: ~const Hasher>(&self, state: &mut S) { + fn hash<S: Hasher>(&self, state: &mut S) { let ($(ref $name,)+) = *self; $($name.hash(state);)+ } @@ -958,29 +932,26 @@ mod impls { impl_hash_tuple! { T B C D E F G H I J K L } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl<T: ~const Hash> const Hash for [T] { + impl<T: Hash> Hash for [T] { #[inline] - fn hash<H: ~const Hasher>(&self, state: &mut H) { + fn hash<H: Hasher>(&self, state: &mut H) { state.write_length_prefix(self.len()); Hash::hash_slice(self, state) } } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl<T: ?Sized + ~const Hash> const Hash for &T { + impl<T: ?Sized + Hash> Hash for &T { #[inline] - fn hash<H: ~const Hasher>(&self, state: &mut H) { + fn hash<H: Hasher>(&self, state: &mut H) { (**self).hash(state); } } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - impl<T: ?Sized + ~const Hash> const Hash for &mut T { + impl<T: ?Sized + Hash> Hash for &mut T { #[inline] - fn hash<H: ~const Hasher>(&self, state: &mut H) { + fn hash<H: Hasher>(&self, state: &mut H) { (**self).hash(state); } } diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 7f8287bf56f..6b9f2e84257 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -118,7 +118,7 @@ macro_rules! load_int_le { /// Safety: this performs unchecked indexing of `buf` at `start..start+len`, so /// that must be in-bounds. #[inline] -const unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { debug_assert!(len < 8); let mut i = 0; // current byte index (from LSB) in the output u64 let mut out = 0; @@ -225,8 +225,7 @@ impl<S: Sip> Hasher<S> { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_hash", issue = "104061")] -impl const super::Hasher for SipHasher { +impl super::Hasher for SipHasher { #[inline] fn write(&mut self, msg: &[u8]) { self.0.hasher.write(msg) @@ -244,8 +243,7 @@ impl const super::Hasher for SipHasher { } #[unstable(feature = "hashmap_internals", issue = "none")] -#[rustc_const_unstable(feature = "const_hash", issue = "104061")] -impl const super::Hasher for SipHasher13 { +impl super::Hasher for SipHasher13 { #[inline] fn write(&mut self, msg: &[u8]) { self.hasher.write(msg) @@ -262,7 +260,7 @@ impl const super::Hasher for SipHasher13 { } } -impl<S: ~const Sip> const super::Hasher for Hasher<S> { +impl<S: Sip> super::Hasher for Hasher<S> { // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined // for this type. We could add them, copy the `short_write` implementation // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*` @@ -342,7 +340,7 @@ impl<S: ~const Sip> const super::Hasher for Hasher<S> { } } -impl<S: Sip> const Clone for Hasher<S> { +impl<S: Sip> Clone for Hasher<S> { #[inline] fn clone(&self) -> Hasher<S> { Hasher { @@ -366,7 +364,6 @@ impl<S: Sip> Default for Hasher<S> { } #[doc(hidden)] -#[const_trait] trait Sip { fn c_rounds(_: &mut State); fn d_rounds(_: &mut State); @@ -375,7 +372,7 @@ trait Sip { #[derive(Debug, Clone, Default)] struct Sip13Rounds; -impl const Sip for Sip13Rounds { +impl Sip for Sip13Rounds { #[inline] fn c_rounds(state: &mut State) { compress!(state); @@ -392,7 +389,7 @@ impl const Sip for Sip13Rounds { #[derive(Debug, Clone, Default)] struct Sip24Rounds; -impl const Sip for Sip24Rounds { +impl Sip for Sip24Rounds { #[inline] fn c_rounds(state: &mut State) { compress!(state); diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index ee13dae60b1..75c104ce2fa 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -73,8 +73,8 @@ use crate::intrinsics; /// ``` /// /// While using `unreachable_unchecked()` is perfectly sound in the following -/// example, the compiler is able to prove that a division by zero is not -/// possible. Benchmarking reveals that `unreachable_unchecked()` provides +/// example, as the compiler is able to prove that a division by zero is not +/// possible, benchmarking reveals that `unreachable_unchecked()` provides /// no benefit over using [`unreachable!`], while the latter does not introduce /// the possibility of Undefined Behavior. /// @@ -217,18 +217,15 @@ pub fn spin_loop() { /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The /// extent to which it can block optimisations may vary depending upon the platform and code-gen /// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the -/// identity function. +/// identity function. As such, it **must not be relied upon to control critical program behavior.** +/// This _immediately_ precludes any direct use of this function for cryptographic or security +/// purposes. /// /// [`std::convert::identity`]: crate::convert::identity /// /// # When is this useful? /// -/// First and foremost: `black_box` does _not_ guarantee any exact behavior and, in some cases, may -/// do nothing at all. As such, it **must not be relied upon to control critical program behavior.** -/// This _immediately_ precludes any direct use of this function for cryptographic or security -/// purposes. -/// -/// While not suitable in those mission-critical cases, `back_box`'s functionality can generally be +/// While not suitable in those mission-critical cases, `black_box`'s functionality can generally be /// relied upon for benchmarking, and should be used there. It will try to ensure that the /// compiler doesn't optimize away part of the intended test code based on context. For /// example: diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs index 5d4c9ba7395..5774107f520 100644 --- a/library/core/src/internal_macros.rs +++ b/library/core/src/internal_macros.rs @@ -1,23 +1,10 @@ // implements the unary operator "op &T" // based on "op T" where T is expected to be `Copy`able macro_rules! forward_ref_unop { - (impl const $imp:ident, $method:ident for $t:ty) => { - forward_ref_unop!(impl const $imp, $method for $t, + (impl $imp:ident, $method:ident for $t:ty) => { + forward_ref_unop!(impl $imp, $method for $t, #[stable(feature = "rust1", since = "1.0.0")]); }; - // Equivalent to the non-const version, with the addition of `rustc_const_unstable` - (impl const $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { - #[$attr] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const $imp for &$t { - type Output = <$t as $imp>::Output; - - #[inline] - fn $method(self) -> <$t as $imp>::Output { - $imp::$method(*self) - } - } - }; (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { #[$attr] impl $imp for &$t { @@ -34,45 +21,10 @@ macro_rules! forward_ref_unop { // implements binary operators "&T op U", "T op &U", "&T op &U" // based on "T op U" where T and U are expected to be `Copy`able macro_rules! forward_ref_binop { - (impl const $imp:ident, $method:ident for $t:ty, $u:ty) => { - forward_ref_binop!(impl const $imp, $method for $t, $u, + (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { + forward_ref_binop!(impl $imp, $method for $t, $u, #[stable(feature = "rust1", since = "1.0.0")]); }; - // Equivalent to the non-const version, with the addition of `rustc_const_unstable` - (impl const $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { - #[$attr] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl<'a> const $imp<$u> for &'a $t { - type Output = <$t as $imp<$u>>::Output; - - #[inline] - fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { - $imp::$method(*self, other) - } - } - - #[$attr] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const $imp<&$u> for $t { - type Output = <$t as $imp<$u>>::Output; - - #[inline] - fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { - $imp::$method(self, *other) - } - } - - #[$attr] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const $imp<&$u> for &$t { - type Output = <$t as $imp<$u>>::Output; - - #[inline] - fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { - $imp::$method(*self, *other) - } - } - }; (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { #[$attr] impl<'a> $imp<$u> for &'a $t { @@ -113,21 +65,6 @@ macro_rules! forward_ref_op_assign { forward_ref_op_assign!(impl $imp, $method for $t, $u, #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]); }; - (impl const $imp:ident, $method:ident for $t:ty, $u:ty) => { - forward_ref_op_assign!(impl const $imp, $method for $t, $u, - #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]); - }; - // Equivalent to the non-const version, with the addition of `rustc_const_unstable` - (impl const $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { - #[$attr] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const $imp<&$u> for $t { - #[inline] - fn $method(&mut self, other: &$u) { - $imp::$method(self, *other); - } - } - }; (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { #[$attr] impl $imp<&$u> for $t { diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index b1ed3b31e43..23ded42fa66 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -84,6 +84,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Relaxed`] as both the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -91,6 +92,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -98,6 +100,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -105,6 +108,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -112,6 +116,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Acquire`] as both the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -119,6 +124,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -126,6 +132,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -133,6 +140,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -140,6 +148,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -147,6 +156,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -154,6 +164,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -161,6 +172,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -168,6 +180,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -175,6 +188,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -182,6 +196,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange` method by passing /// [`Ordering::SeqCst`] as both the success and failure parameters. /// For example, [`AtomicBool::compare_exchange`]. + #[rustc_nounwind] pub fn atomic_cxchg_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. @@ -190,6 +205,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Relaxed`] as both the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -197,6 +213,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -204,6 +221,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -211,6 +229,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -218,6 +237,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Acquire`] as both the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -225,6 +245,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -232,6 +253,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -239,6 +261,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -246,6 +269,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -253,6 +277,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -260,6 +285,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -267,6 +293,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -274,6 +301,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -281,6 +309,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// @@ -288,6 +317,7 @@ extern "rust-intrinsic" { /// [`atomic`] types via the `compare_exchange_weak` method by passing /// [`Ordering::SeqCst`] as both the success and failure parameters. /// For example, [`AtomicBool::compare_exchange_weak`]. + #[rustc_nounwind] pub fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Loads the current value of the pointer. @@ -295,19 +325,23 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`]. + #[rustc_nounwind] pub fn atomic_load_seqcst<T: Copy>(src: *const T) -> T; /// Loads the current value of the pointer. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`]. + #[rustc_nounwind] pub fn atomic_load_acquire<T: Copy>(src: *const T) -> T; /// Loads the current value of the pointer. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`]. + #[rustc_nounwind] pub fn atomic_load_relaxed<T: Copy>(src: *const T) -> T; + #[rustc_nounwind] pub fn atomic_load_unordered<T: Copy>(src: *const T) -> T; /// Stores the value at the specified memory location. @@ -315,19 +349,23 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `store` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`]. + #[rustc_nounwind] pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T); /// Stores the value at the specified memory location. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `store` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`]. + #[rustc_nounwind] pub fn atomic_store_release<T: Copy>(dst: *mut T, val: T); /// Stores the value at the specified memory location. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `store` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::store`]. + #[rustc_nounwind] pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T); + #[rustc_nounwind] pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T); /// Stores the value at the specified memory location, returning the old value. @@ -335,30 +373,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`]. + #[rustc_nounwind] pub fn atomic_xchg_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`]. + #[rustc_nounwind] pub fn atomic_xchg_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`]. + #[rustc_nounwind] pub fn atomic_xchg_release<T: Copy>(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::swap`]. + #[rustc_nounwind] pub fn atomic_xchg_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::swap`]. + #[rustc_nounwind] pub fn atomic_xchg_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. @@ -366,30 +409,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`]. + #[rustc_nounwind] pub fn atomic_xadd_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`]. + #[rustc_nounwind] pub fn atomic_xadd_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`]. + #[rustc_nounwind] pub fn atomic_xadd_release<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_add`]. + #[rustc_nounwind] pub fn atomic_xadd_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_add`]. + #[rustc_nounwind] pub fn atomic_xadd_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. @@ -397,30 +445,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. + #[rustc_nounwind] pub fn atomic_xsub_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. + #[rustc_nounwind] pub fn atomic_xsub_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. + #[rustc_nounwind] pub fn atomic_xsub_release<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. + #[rustc_nounwind] pub fn atomic_xsub_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. + #[rustc_nounwind] pub fn atomic_xsub_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. @@ -428,30 +481,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`]. + #[rustc_nounwind] pub fn atomic_and_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`]. + #[rustc_nounwind] pub fn atomic_and_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`]. + #[rustc_nounwind] pub fn atomic_and_release<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_and`]. + #[rustc_nounwind] pub fn atomic_and_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_and`]. + #[rustc_nounwind] pub fn atomic_and_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. @@ -459,30 +517,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`]. + #[rustc_nounwind] pub fn atomic_nand_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`]. + #[rustc_nounwind] pub fn atomic_nand_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`]. + #[rustc_nounwind] pub fn atomic_nand_release<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_nand`]. + #[rustc_nounwind] pub fn atomic_nand_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_nand`]. + #[rustc_nounwind] pub fn atomic_nand_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. @@ -490,30 +553,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`]. + #[rustc_nounwind] pub fn atomic_or_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`]. + #[rustc_nounwind] pub fn atomic_or_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`]. + #[rustc_nounwind] pub fn atomic_or_release<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_or`]. + #[rustc_nounwind] pub fn atomic_or_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_or`]. + #[rustc_nounwind] pub fn atomic_or_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. @@ -521,30 +589,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`]. + #[rustc_nounwind] pub fn atomic_xor_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`]. + #[rustc_nounwind] pub fn atomic_xor_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`]. + #[rustc_nounwind] pub fn atomic_xor_release<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_xor`]. + #[rustc_nounwind] pub fn atomic_xor_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_xor`]. + #[rustc_nounwind] pub fn atomic_xor_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. @@ -552,30 +625,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_max_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_max_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_max_release<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_max_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_max_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. @@ -583,18 +661,21 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_min_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_min_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_min_release<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// @@ -607,6 +688,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_min_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. @@ -614,30 +696,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_umin_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_umin_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_umin_release<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_umin_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_min`]. + #[rustc_nounwind] pub fn atomic_umin_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. @@ -645,30 +732,35 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_umax_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_umax_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_umax_release<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_umax_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`]. + #[rustc_nounwind] pub fn atomic_umax_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// An atomic fence. @@ -676,24 +768,28 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available in /// [`atomic::fence`] by passing [`Ordering::SeqCst`] /// as the `order`. + #[rustc_nounwind] pub fn atomic_fence_seqcst(); /// An atomic fence. /// /// The stabilized version of this intrinsic is available in /// [`atomic::fence`] by passing [`Ordering::Acquire`] /// as the `order`. + #[rustc_nounwind] pub fn atomic_fence_acquire(); /// An atomic fence. /// /// The stabilized version of this intrinsic is available in /// [`atomic::fence`] by passing [`Ordering::Release`] /// as the `order`. + #[rustc_nounwind] pub fn atomic_fence_release(); /// An atomic fence. /// /// The stabilized version of this intrinsic is available in /// [`atomic::fence`] by passing [`Ordering::AcqRel`] /// as the `order`. + #[rustc_nounwind] pub fn atomic_fence_acqrel(); /// A compiler-only memory barrier. @@ -706,6 +802,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available in /// [`atomic::compiler_fence`] by passing [`Ordering::SeqCst`] /// as the `order`. + #[rustc_nounwind] pub fn atomic_singlethreadfence_seqcst(); /// A compiler-only memory barrier. /// @@ -717,6 +814,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available in /// [`atomic::compiler_fence`] by passing [`Ordering::Acquire`] /// as the `order`. + #[rustc_nounwind] pub fn atomic_singlethreadfence_acquire(); /// A compiler-only memory barrier. /// @@ -728,6 +826,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available in /// [`atomic::compiler_fence`] by passing [`Ordering::Release`] /// as the `order`. + #[rustc_nounwind] pub fn atomic_singlethreadfence_release(); /// A compiler-only memory barrier. /// @@ -739,6 +838,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is available in /// [`atomic::compiler_fence`] by passing [`Ordering::AcqRel`] /// as the `order`. + #[rustc_nounwind] pub fn atomic_singlethreadfence_acqrel(); /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction @@ -750,6 +850,7 @@ extern "rust-intrinsic" { /// ranging from (0) - no locality, to (3) - extremely local keep in cache. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn prefetch_read_data<T>(data: *const T, locality: i32); /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction /// if supported; otherwise, it is a no-op. @@ -760,6 +861,7 @@ extern "rust-intrinsic" { /// ranging from (0) - no locality, to (3) - extremely local keep in cache. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn prefetch_write_data<T>(data: *const T, locality: i32); /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction /// if supported; otherwise, it is a no-op. @@ -770,6 +872,7 @@ extern "rust-intrinsic" { /// ranging from (0) - no locality, to (3) - extremely local keep in cache. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn prefetch_read_instruction<T>(data: *const T, locality: i32); /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction /// if supported; otherwise, it is a no-op. @@ -780,6 +883,7 @@ extern "rust-intrinsic" { /// ranging from (0) - no locality, to (3) - extremely local keep in cache. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn prefetch_write_instruction<T>(data: *const T, locality: i32); /// Magic intrinsic that derives its meaning from attributes @@ -792,6 +896,7 @@ extern "rust-intrinsic" { /// /// This intrinsic should not be used outside of the compiler. #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn rustc_peek<T>(_: T) -> T; /// Aborts the execution of the process. @@ -810,6 +915,7 @@ extern "rust-intrinsic" { /// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or /// `SIGBUS`. The precise behaviour is not guaranteed and not stable. #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn abort() -> !; /// Informs the optimizer that this point in the code is not reachable, @@ -821,6 +927,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`]. #[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")] + #[rustc_nounwind] pub fn unreachable() -> !; /// Informs the optimizer that a condition is always true. @@ -834,6 +941,7 @@ extern "rust-intrinsic" { /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_assume", issue = "76972")] + #[rustc_nounwind] pub fn assume(b: bool); /// Hints to the compiler that branch condition is likely to be true. @@ -849,6 +957,7 @@ extern "rust-intrinsic" { /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_likely", issue = "none")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn likely(b: bool) -> bool; /// Hints to the compiler that branch condition is likely to be false. @@ -864,11 +973,13 @@ extern "rust-intrinsic" { /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_likely", issue = "none")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn unlikely(b: bool) -> bool; /// Executes a breakpoint trap, for inspection by a debugger. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn breakpoint(); /// The size of a type in bytes. @@ -884,6 +995,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is [`core::mem::size_of`]. #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn size_of<T>() -> usize; /// The minimum alignment of a type. @@ -896,23 +1008,27 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is [`core::mem::align_of`]. #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn min_align_of<T>() -> usize; /// The preferred alignment of a type. /// /// This intrinsic does not have a stable counterpart. /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971). #[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")] + #[rustc_nounwind] pub fn pref_align_of<T>() -> usize; /// The size of the referenced value in bytes. /// /// The stabilized version of this intrinsic is [`mem::size_of_val`]. #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] + #[rustc_nounwind] pub fn size_of_val<T: ?Sized>(_: *const T) -> usize; /// The required alignment of the referenced value. /// /// The stabilized version of this intrinsic is [`core::mem::align_of_val`]. #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")] + #[rustc_nounwind] pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize; /// Gets a static string slice containing the name of a type. @@ -925,6 +1041,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is [`core::any::type_name`]. #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn type_name<T: ?Sized>() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This @@ -939,6 +1056,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. #[rustc_const_unstable(feature = "const_type_id", issue = "77125")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn type_id<T: ?Sized + 'static>() -> u64; /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: @@ -947,6 +1065,7 @@ extern "rust-intrinsic" { /// This intrinsic does not have a stable counterpart. #[rustc_const_stable(feature = "const_assert_type", since = "1.59.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn assert_inhabited<T>(); /// A guard for unsafe functions that cannot ever be executed if `T` does not permit @@ -955,6 +1074,7 @@ extern "rust-intrinsic" { /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn assert_zero_valid<T>(); /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. @@ -962,6 +1082,7 @@ extern "rust-intrinsic" { /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn assert_mem_uninitialized_valid<T>(); /// Gets a reference to a static `Location` indicating where it was called. @@ -974,6 +1095,7 @@ extern "rust-intrinsic" { /// Consider using [`core::panic::Location::caller`] instead. #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn caller_location() -> &'static crate::panic::Location<'static>; /// Moves a value out of scope without running drop glue. @@ -987,6 +1109,7 @@ extern "rust-intrinsic" { /// any safety invariants. #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn forget<T: ?Sized>(_: T); /// Reinterprets the bits of a value of one type as another type. @@ -1064,7 +1187,7 @@ extern "rust-intrinsic" { /// Below are common applications of `transmute` which can be replaced with safer /// constructs. /// - /// Turning raw bytes (`&[u8]`) into `u32`, `f64`, etc.: + /// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.: /// /// ``` /// let raw_bytes = [0x78, 0x56, 0x34, 0x12]; @@ -1250,8 +1373,23 @@ extern "rust-intrinsic" { #[rustc_allowed_through_unstable_modules] #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] #[rustc_diagnostic_item = "transmute"] + #[rustc_nounwind] pub fn transmute<Src, Dst>(src: Src) -> Dst; + /// Like [`transmute`], but even less checked at compile-time: rather than + /// giving an error for `size_of::<Src>() != size_of::<Dst>()`, it's + /// **Undefined Behaviour** at runtime. + /// + /// Prefer normal `transmute` where possible, for the extra checking, since + /// both do exactly the same thing at runtime, if they both compile. + /// + /// This is not expected to ever be exposed directly to users, rather it + /// may eventually be exposed through some more-constrained API. + #[cfg(not(bootstrap))] + #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] + #[rustc_nounwind] + pub fn transmute_unchecked<Src, Dst>(src: Src) -> Dst; + /// Returns `true` if the actual type given as `T` requires drop /// glue; returns `false` if the actual type provided for `T` /// implements `Copy`. @@ -1267,6 +1405,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn needs_drop<T: ?Sized>() -> bool; /// Calculates the offset from a pointer. @@ -1274,6 +1413,10 @@ extern "rust-intrinsic" { /// This is implemented as an intrinsic to avoid converting to and from an /// integer, since the conversion would throw away aliasing information. /// + /// This can only be used with `Ptr` as a raw pointer type (`*mut` or `*const`) + /// to a `Sized` pointee and with `Delta` as `usize` or `isize`. Any other + /// instantiations may arbitrarily misbehave, and that's *not* a compiler bug. + /// /// # Safety /// /// Both the starting and resulting pointer must be either in bounds or one @@ -1282,8 +1425,17 @@ extern "rust-intrinsic" { /// returned value will result in undefined behavior. /// /// The stabilized version of this intrinsic is [`pointer::offset`]. + #[cfg(not(bootstrap))] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[rustc_nounwind] + pub fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr; + + /// The bootstrap version of this is more restricted. + #[cfg(bootstrap)] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[rustc_nounwind] pub fn offset<T>(dst: *const T, offset: isize) -> *const T; /// Calculates the offset from a pointer, potentially wrapping. @@ -1301,6 +1453,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] + #[rustc_nounwind] pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T; /// Masks out bits of the pointer according to a mask. @@ -1312,6 +1465,7 @@ extern "rust-intrinsic" { /// /// Consider using [`pointer::mask`] instead. #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T; /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with @@ -1322,6 +1476,7 @@ extern "rust-intrinsic" { /// unless size is equal to zero. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize); /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with /// a size of `count * size_of::<T>()` and an alignment of @@ -1331,6 +1486,7 @@ extern "rust-intrinsic" { /// unless size is equal to zero. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize); /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a /// size of `count * size_of::<T>()` and an alignment of @@ -1340,158 +1496,187 @@ extern "rust-intrinsic" { /// unless size is equal to zero. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize); /// Performs a volatile load from the `src` pointer. /// /// The stabilized version of this intrinsic is [`core::ptr::read_volatile`]. + #[rustc_nounwind] pub fn volatile_load<T>(src: *const T) -> T; /// Performs a volatile store to the `dst` pointer. /// /// The stabilized version of this intrinsic is [`core::ptr::write_volatile`]. + #[rustc_nounwind] pub fn volatile_store<T>(dst: *mut T, val: T); /// Performs a volatile load from the `src` pointer /// The pointer is not required to be aligned. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn unaligned_volatile_load<T>(src: *const T) -> T; /// Performs a volatile store to the `dst` pointer. /// The pointer is not required to be aligned. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn unaligned_volatile_store<T>(dst: *mut T, val: T); /// Returns the square root of an `f32` /// /// The stabilized version of this intrinsic is /// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt) + #[rustc_nounwind] pub fn sqrtf32(x: f32) -> f32; /// Returns the square root of an `f64` /// /// The stabilized version of this intrinsic is /// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt) + #[rustc_nounwind] pub fn sqrtf64(x: f64) -> f64; /// Raises an `f32` to an integer power. /// /// The stabilized version of this intrinsic is /// [`f32::powi`](../../std/primitive.f32.html#method.powi) + #[rustc_nounwind] pub fn powif32(a: f32, x: i32) -> f32; /// Raises an `f64` to an integer power. /// /// The stabilized version of this intrinsic is /// [`f64::powi`](../../std/primitive.f64.html#method.powi) + #[rustc_nounwind] pub fn powif64(a: f64, x: i32) -> f64; /// Returns the sine of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::sin`](../../std/primitive.f32.html#method.sin) + #[rustc_nounwind] pub fn sinf32(x: f32) -> f32; /// Returns the sine of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::sin`](../../std/primitive.f64.html#method.sin) + #[rustc_nounwind] pub fn sinf64(x: f64) -> f64; /// Returns the cosine of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::cos`](../../std/primitive.f32.html#method.cos) + #[rustc_nounwind] pub fn cosf32(x: f32) -> f32; /// Returns the cosine of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::cos`](../../std/primitive.f64.html#method.cos) + #[rustc_nounwind] pub fn cosf64(x: f64) -> f64; /// Raises an `f32` to an `f32` power. /// /// The stabilized version of this intrinsic is /// [`f32::powf`](../../std/primitive.f32.html#method.powf) + #[rustc_nounwind] pub fn powf32(a: f32, x: f32) -> f32; /// Raises an `f64` to an `f64` power. /// /// The stabilized version of this intrinsic is /// [`f64::powf`](../../std/primitive.f64.html#method.powf) + #[rustc_nounwind] pub fn powf64(a: f64, x: f64) -> f64; /// Returns the exponential of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::exp`](../../std/primitive.f32.html#method.exp) + #[rustc_nounwind] pub fn expf32(x: f32) -> f32; /// Returns the exponential of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::exp`](../../std/primitive.f64.html#method.exp) + #[rustc_nounwind] pub fn expf64(x: f64) -> f64; /// Returns 2 raised to the power of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::exp2`](../../std/primitive.f32.html#method.exp2) + #[rustc_nounwind] pub fn exp2f32(x: f32) -> f32; /// Returns 2 raised to the power of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::exp2`](../../std/primitive.f64.html#method.exp2) + #[rustc_nounwind] pub fn exp2f64(x: f64) -> f64; /// Returns the natural logarithm of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::ln`](../../std/primitive.f32.html#method.ln) + #[rustc_nounwind] pub fn logf32(x: f32) -> f32; /// Returns the natural logarithm of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::ln`](../../std/primitive.f64.html#method.ln) + #[rustc_nounwind] pub fn logf64(x: f64) -> f64; /// Returns the base 10 logarithm of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::log10`](../../std/primitive.f32.html#method.log10) + #[rustc_nounwind] pub fn log10f32(x: f32) -> f32; /// Returns the base 10 logarithm of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::log10`](../../std/primitive.f64.html#method.log10) + #[rustc_nounwind] pub fn log10f64(x: f64) -> f64; /// Returns the base 2 logarithm of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::log2`](../../std/primitive.f32.html#method.log2) + #[rustc_nounwind] pub fn log2f32(x: f32) -> f32; /// Returns the base 2 logarithm of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::log2`](../../std/primitive.f64.html#method.log2) + #[rustc_nounwind] pub fn log2f64(x: f64) -> f64; /// Returns `a * b + c` for `f32` values. /// /// The stabilized version of this intrinsic is /// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) + #[rustc_nounwind] pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values. /// /// The stabilized version of this intrinsic is /// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) + #[rustc_nounwind] pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; /// Returns the absolute value of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::abs`](../../std/primitive.f32.html#method.abs) + #[rustc_nounwind] pub fn fabsf32(x: f32) -> f32; /// Returns the absolute value of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::abs`](../../std/primitive.f64.html#method.abs) + #[rustc_nounwind] pub fn fabsf64(x: f64) -> f64; /// Returns the minimum of two `f32` values. @@ -1504,6 +1689,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is /// [`f32::min`] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn minnumf32(x: f32, y: f32) -> f32; /// Returns the minimum of two `f64` values. /// @@ -1515,6 +1701,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is /// [`f64::min`] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn minnumf64(x: f64, y: f64) -> f64; /// Returns the maximum of two `f32` values. /// @@ -1526,6 +1713,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is /// [`f32::max`] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn maxnumf32(x: f32, y: f32) -> f32; /// Returns the maximum of two `f64` values. /// @@ -1537,113 +1725,153 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is /// [`f64::max`] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn maxnumf64(x: f64, y: f64) -> f64; /// Copies the sign from `y` to `x` for `f32` values. /// /// The stabilized version of this intrinsic is /// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) + #[rustc_nounwind] pub fn copysignf32(x: f32, y: f32) -> f32; /// Copies the sign from `y` to `x` for `f64` values. /// /// The stabilized version of this intrinsic is /// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) + #[rustc_nounwind] pub fn copysignf64(x: f64, y: f64) -> f64; /// Returns the largest integer less than or equal to an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::floor`](../../std/primitive.f32.html#method.floor) + #[rustc_nounwind] pub fn floorf32(x: f32) -> f32; /// Returns the largest integer less than or equal to an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::floor`](../../std/primitive.f64.html#method.floor) + #[rustc_nounwind] pub fn floorf64(x: f64) -> f64; /// Returns the smallest integer greater than or equal to an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::ceil`](../../std/primitive.f32.html#method.ceil) + #[rustc_nounwind] pub fn ceilf32(x: f32) -> f32; /// Returns the smallest integer greater than or equal to an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::ceil`](../../std/primitive.f64.html#method.ceil) + #[rustc_nounwind] pub fn ceilf64(x: f64) -> f64; /// Returns the integer part of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::trunc`](../../std/primitive.f32.html#method.trunc) + #[rustc_nounwind] pub fn truncf32(x: f32) -> f32; /// Returns the integer part of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::trunc`](../../std/primitive.f64.html#method.trunc) + #[rustc_nounwind] pub fn truncf64(x: f64) -> f64; /// Returns the nearest integer to an `f32`. May raise an inexact floating-point exception /// if the argument is not an integer. + /// + /// The stabilized version of this intrinsic is + /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) + #[rustc_nounwind] pub fn rintf32(x: f32) -> f32; /// Returns the nearest integer to an `f64`. May raise an inexact floating-point exception /// if the argument is not an integer. + /// + /// The stabilized version of this intrinsic is + /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) + #[rustc_nounwind] pub fn rintf64(x: f64) -> f64; /// Returns the nearest integer to an `f32`. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn nearbyintf32(x: f32) -> f32; /// Returns the nearest integer to an `f64`. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn nearbyintf64(x: f64) -> f64; /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. /// /// The stabilized version of this intrinsic is /// [`f32::round`](../../std/primitive.f32.html#method.round) + #[rustc_nounwind] pub fn roundf32(x: f32) -> f32; /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. /// /// The stabilized version of this intrinsic is /// [`f64::round`](../../std/primitive.f64.html#method.round) + #[rustc_nounwind] pub fn roundf64(x: f64) -> f64; + /// Returns the nearest integer to an `f32`. Rounds half-way cases to the number + /// with an even least significant digit. + /// + /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] + pub fn roundevenf32(x: f32) -> f32; + /// Returns the nearest integer to an `f64`. Rounds half-way cases to the number + /// with an even least significant digit. + /// + /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] + pub fn roundevenf64(x: f64) -> f64; + /// Float addition that allows optimizations based on algebraic rules. /// May assume inputs are finite. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn fadd_fast<T: Copy>(a: T, b: T) -> T; /// Float subtraction that allows optimizations based on algebraic rules. /// May assume inputs are finite. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn fsub_fast<T: Copy>(a: T, b: T) -> T; /// Float multiplication that allows optimizations based on algebraic rules. /// May assume inputs are finite. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn fmul_fast<T: Copy>(a: T, b: T) -> T; /// Float division that allows optimizations based on algebraic rules. /// May assume inputs are finite. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn fdiv_fast<T: Copy>(a: T, b: T) -> T; /// Float remainder that allows optimizations based on algebraic rules. /// May assume inputs are finite. /// /// This intrinsic does not have a stable counterpart. + #[rustc_nounwind] pub fn frem_fast<T: Copy>(a: T, b: T) -> T; /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range /// (<https://github.com/rust-lang/rust/issues/10184>) /// /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. + #[rustc_nounwind] pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; /// Returns the number of bits set in an integer type `T` @@ -1658,6 +1886,7 @@ extern "rust-intrinsic" { /// [`u32::count_ones`] #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn ctpop<T: Copy>(x: T) -> T; /// Returns the number of leading unset bits (zeroes) in an integer type `T`. @@ -1696,6 +1925,7 @@ extern "rust-intrinsic" { /// ``` #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn ctlz<T: Copy>(x: T) -> T; /// Like `ctlz`, but extra-unsafe as it returns `undef` when @@ -1715,6 +1945,7 @@ extern "rust-intrinsic" { /// assert_eq!(num_leading, 3); /// ``` #[rustc_const_stable(feature = "constctlz", since = "1.50.0")] + #[rustc_nounwind] pub fn ctlz_nonzero<T: Copy>(x: T) -> T; /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. @@ -1753,6 +1984,7 @@ extern "rust-intrinsic" { /// ``` #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn cttz<T: Copy>(x: T) -> T; /// Like `cttz`, but extra-unsafe as it returns `undef` when @@ -1772,6 +2004,7 @@ extern "rust-intrinsic" { /// assert_eq!(num_trailing, 3); /// ``` #[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")] + #[rustc_nounwind] pub fn cttz_nonzero<T: Copy>(x: T) -> T; /// Reverses the bytes in an integer type `T`. @@ -1786,6 +2019,7 @@ extern "rust-intrinsic" { /// [`u32::swap_bytes`] #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn bswap<T: Copy>(x: T) -> T; /// Reverses the bits in an integer type `T`. @@ -1800,6 +2034,7 @@ extern "rust-intrinsic" { /// [`u32::reverse_bits`] #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn bitreverse<T: Copy>(x: T) -> T; /// Performs checked integer addition. @@ -1814,6 +2049,7 @@ extern "rust-intrinsic" { /// [`u32::overflowing_add`] #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool); /// Performs checked integer subtraction @@ -1828,6 +2064,7 @@ extern "rust-intrinsic" { /// [`u32::overflowing_sub`] #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool); /// Performs checked integer multiplication @@ -1842,6 +2079,7 @@ extern "rust-intrinsic" { /// [`u32::overflowing_mul`] #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool); /// Performs an exact division, resulting in undefined behavior where @@ -1849,6 +2087,7 @@ extern "rust-intrinsic" { /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_exact_div", issue = "none")] + #[rustc_nounwind] pub fn exact_div<T: Copy>(x: T, y: T) -> T; /// Performs an unchecked division, resulting in undefined behavior @@ -1858,6 +2097,7 @@ extern "rust-intrinsic" { /// primitives via the `checked_div` method. For example, /// [`u32::checked_div`] #[rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0")] + #[rustc_nounwind] pub fn unchecked_div<T: Copy>(x: T, y: T) -> T; /// Returns the remainder of an unchecked division, resulting in /// undefined behavior when `y == 0` or `x == T::MIN && y == -1` @@ -1866,6 +2106,7 @@ extern "rust-intrinsic" { /// primitives via the `checked_rem` method. For example, /// [`u32::checked_rem`] #[rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0")] + #[rustc_nounwind] pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T; /// Performs an unchecked left shift, resulting in undefined behavior when @@ -1875,6 +2116,7 @@ extern "rust-intrinsic" { /// primitives via the `checked_shl` method. For example, /// [`u32::checked_shl`] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] + #[rustc_nounwind] pub fn unchecked_shl<T: Copy>(x: T, y: T) -> T; /// Performs an unchecked right shift, resulting in undefined behavior when /// `y < 0` or `y >= N`, where N is the width of T in bits. @@ -1883,6 +2125,7 @@ extern "rust-intrinsic" { /// primitives via the `checked_shr` method. For example, /// [`u32::checked_shr`] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] + #[rustc_nounwind] pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T; /// Returns the result of an unchecked addition, resulting in @@ -1890,6 +2133,7 @@ extern "rust-intrinsic" { /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] + #[rustc_nounwind] pub fn unchecked_add<T: Copy>(x: T, y: T) -> T; /// Returns the result of an unchecked subtraction, resulting in @@ -1897,6 +2141,7 @@ extern "rust-intrinsic" { /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] + #[rustc_nounwind] pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T; /// Returns the result of an unchecked multiplication, resulting in @@ -1904,6 +2149,7 @@ extern "rust-intrinsic" { /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] + #[rustc_nounwind] pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T; /// Performs rotate left. @@ -1918,6 +2164,7 @@ extern "rust-intrinsic" { /// [`u32::rotate_left`] #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn rotate_left<T: Copy>(x: T, y: T) -> T; /// Performs rotate right. @@ -1932,6 +2179,7 @@ extern "rust-intrinsic" { /// [`u32::rotate_right`] #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn rotate_right<T: Copy>(x: T, y: T) -> T; /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits. @@ -1946,6 +2194,7 @@ extern "rust-intrinsic" { /// [`u32::wrapping_add`] #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn wrapping_add<T: Copy>(a: T, b: T) -> T; /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits. /// @@ -1959,6 +2208,7 @@ extern "rust-intrinsic" { /// [`u32::wrapping_sub`] #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T; /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits. /// @@ -1972,6 +2222,7 @@ extern "rust-intrinsic" { /// [`u32::wrapping_mul`] #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T; /// Computes `a + b`, saturating at numeric bounds. @@ -1986,6 +2237,7 @@ extern "rust-intrinsic" { /// [`u32::saturating_add`] #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn saturating_add<T: Copy>(a: T, b: T) -> T; /// Computes `a - b`, saturating at numeric bounds. /// @@ -1999,8 +2251,30 @@ extern "rust-intrinsic" { /// [`u32::saturating_sub`] #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn saturating_sub<T: Copy>(a: T, b: T) -> T; + /// This is an implementation detail of [`crate::ptr::read`] and should + /// not be used anywhere else. See its comments for why this exists. + /// + /// This intrinsic can *only* be called where the pointer is a local without + /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it + /// trivially obeys runtime-MIR rules about derefs in operands. + #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")] + #[rustc_nounwind] + pub fn read_via_copy<T>(ptr: *const T) -> T; + + /// This is an implementation detail of [`crate::ptr::write`] and should + /// not be used anywhere else. See its comments for why this exists. + /// + /// This intrinsic can *only* be called where the pointer is a local without + /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so + /// that it trivially obeys runtime-MIR rules about derefs in operands. + #[cfg(not(bootstrap))] + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_nounwind] + pub fn write_via_move<T>(ptr: *mut T, value: T); + /// Returns the value of the discriminant for the variant in 'v'; /// if `T` has no discriminant, returns `0`. /// @@ -2012,6 +2286,7 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant; /// Returns the number of variants of the type `T` cast to a `usize`; @@ -2025,6 +2300,7 @@ extern "rust-intrinsic" { /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`]. #[rustc_const_unstable(feature = "variant_count", issue = "73662")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn variant_count<T>() -> usize; /// Rust's "try catch" construct which invokes the function pointer `try_fn` @@ -2034,18 +2310,24 @@ extern "rust-intrinsic" { /// takes the data pointer and a pointer to the target-specific exception /// object that was caught. For more information see the compiler's /// source as well as std's catch implementation. + /// + /// `catch_fn` must not unwind. + #[rustc_nounwind] pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32; /// Emits a `!nontemporal` store according to LLVM (see their docs). /// Probably will never become stable. + #[rustc_nounwind] pub fn nontemporal_store<T>(ptr: *mut T, val: T); /// See documentation of `<*const T>::offset_from` for details. #[rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0")] + #[rustc_nounwind] pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize; /// See documentation of `<*const T>::sub_ptr` for details. #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[rustc_nounwind] pub fn ptr_offset_from_unsigned<T>(ptr: *const T, base: *const T) -> usize; /// See documentation of `<*const T>::guaranteed_eq` for details. @@ -2059,6 +2341,7 @@ extern "rust-intrinsic" { /// any safety invariants. #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8; /// Allocates a block of memory at compile time. @@ -2070,6 +2353,7 @@ extern "rust-intrinsic" { /// - At compile time, a compile error occurs if this constraint is violated. /// - At runtime, it is not checked. #[rustc_const_unstable(feature = "const_heap", issue = "79597")] + #[rustc_nounwind] pub fn const_allocate(size: usize, align: usize) -> *mut u8; /// Deallocates a memory which allocated by `intrinsics::const_allocate` at compile time. @@ -2083,6 +2367,7 @@ extern "rust-intrinsic" { /// - If the `ptr` is created in an another const, this intrinsic doesn't deallocate it. /// - If the `ptr` is pointing to a local variable, this intrinsic doesn't deallocate it. #[rustc_const_unstable(feature = "const_heap", issue = "79597")] + #[rustc_nounwind] pub fn const_deallocate(ptr: *mut u8, size: usize, align: usize); /// Determines whether the raw bytes of the two values are equal. @@ -2093,6 +2378,10 @@ extern "rust-intrinsic" { /// Above some backend-decided threshold this will emit calls to `memcmp`, /// like slice equality does, instead of causing massive code size. /// + /// Since this works by comparing the underlying bytes, the actual `T` is + /// not particularly important. It will be used for its size and alignment, + /// but any validity restrictions will be ignored, not enforced. + /// /// # Safety /// /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized or carry a @@ -2103,6 +2392,7 @@ extern "rust-intrinsic" { /// (The implementation is allowed to branch on the results of comparisons, /// which is UB if any of their inputs are `undef`.) #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")] + #[rustc_nounwind] pub fn raw_eq<T>(a: &T, b: &T) -> bool; /// See documentation of [`std::hint::black_box`] for details. @@ -2110,14 +2400,17 @@ extern "rust-intrinsic" { /// [`std::hint::black_box`]: crate::hint::black_box #[rustc_const_unstable(feature = "const_black_box", issue = "none")] #[rustc_safe_intrinsic] + #[rustc_nounwind] pub fn black_box<T>(dummy: T) -> T; /// `ptr` must point to a vtable. /// The intrinsic will return the size stored in that vtable. + #[rustc_nounwind] pub fn vtable_size(ptr: *const ()) -> usize; /// `ptr` must point to a vtable. /// The intrinsic will return the alignment stored in that vtable. + #[rustc_nounwind] pub fn vtable_align(ptr: *const ()) -> usize; /// Selects which function to call depending on the context. @@ -2181,6 +2474,12 @@ extern "rust-intrinsic" { where G: FnOnce<ARG, Output = RET>, F: FnOnce<ARG, Output = RET>; + + /// This method creates a pointer to any `Some` value. If the argument is + /// `None`, an invalid within-bounds pointer (that is still acceptable for + /// constructing an empty slice) is returned. + #[rustc_nounwind] + pub fn option_payload_ptr<T>(arg: *const Option<T>) -> *const T; } // Some functions are defined here because they accidentally got made @@ -2194,7 +2493,7 @@ extern "rust-intrinsic" { /// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)` /// where the names specified will be moved into the macro as captured variables, and defines an item /// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics -/// for the function declaractions and can be omitted if there is no generics. +/// for the function declarations and can be omitted if there is no generics. /// /// # Safety /// @@ -2224,6 +2523,7 @@ macro_rules! assert_unsafe_precondition { } } #[allow(non_snake_case)] + #[inline] const fn comptime$(<$($tt)*>)?($(_:$ty),*) {} ::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime); @@ -2253,7 +2553,9 @@ pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool { pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool { let src_usize = src.addr(); let dst_usize = dst.addr(); - let size = mem::size_of::<T>().checked_mul(count).unwrap(); + let size = mem::size_of::<T>() + .checked_mul(count) + .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize"); let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize }; // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. @@ -2353,6 +2655,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) - pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_nounwind] pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); } @@ -2443,13 +2746,14 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_nounwind] fn copy<T>(src: *const T, dst: *mut T, count: usize); } // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { assert_unsafe_precondition!( - "ptr::copy requires that both pointer arguments are aligned aligned and non-null", + "ptr::copy requires that both pointer arguments are aligned and non-null", [T](src: *const T, dst: *mut T) => is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) ); @@ -2515,6 +2819,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_nounwind] fn write_bytes<T>(dst: *mut T, val: u8, count: usize); } @@ -2527,3 +2832,24 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { write_bytes(dst, val, count) } } + +/// Polyfill for bootstrap +#[cfg(bootstrap)] +pub const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst { + use crate::mem::*; + // SAFETY: It's a transmute -- the caller promised it's fine. + unsafe { transmute_copy(&ManuallyDrop::new(src)) } +} + +/// Polyfill for bootstrap +#[cfg(bootstrap)] +pub const unsafe fn write_via_move<T>(ptr: *mut T, value: T) { + use crate::mem::*; + // SAFETY: the caller must guarantee that `dst` is valid for writes. + // `dst` cannot overlap `src` because the caller has mutable access + // to `dst` while `src` is owned by this function. + unsafe { + copy_nonoverlapping::<T>(&value, ptr, 1); + forget(value); + } +} diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 995d66dca56..19f8b944c1f 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -8,14 +8,13 @@ //! //! The documentation for this module describes how to use this feature. If you are interested in //! hacking on the implementation, most of that documentation lives at -//! `rustc_mir_building/src/build/custom/mod.rs`. +//! `rustc_mir_build/src/build/custom/mod.rs`. //! //! Typical usage will look like this: //! //! ```rust //! #![feature(core_intrinsics, custom_mir)] //! -//! extern crate core; //! use core::intrinsics::mir::*; //! //! #[custom_mir(dialect = "built")] @@ -42,13 +41,15 @@ //! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect //! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]` //! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect = -//! "runtime", phase = "optimized")] if you don't. +//! "runtime", phase = "optimized")]` if you don't. //! //! [dialect docs]: //! https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html //! //! The input to the [`mir!`] macro is: //! +//! - An optional return type annotation in the form of `type RET = ...;`. This may be required +//! if the compiler cannot infer the type of RET. //! - A possibly empty list of local declarations. Locals can also be declared inline on //! assignments via `let`. Type inference generally works. Shadowing does not. //! - A list of basic blocks. The first of these is the start block and is where execution begins. @@ -63,7 +64,6 @@ //! ```rust //! #![feature(core_intrinsics, custom_mir)] //! -//! extern crate core; //! use core::intrinsics::mir::*; //! //! #[custom_mir(dialect = "built")] @@ -124,6 +124,18 @@ //! } //! ) //! } +//! +//! #[custom_mir(dialect = "runtime", phase = "optimized")] +//! fn annotated_return_type() -> (i32, bool) { +//! mir!( +//! type RET = (i32, bool); +//! { +//! RET.0 = 1; +//! RET.1 = true; +//! Return() +//! } +//! ) +//! } //! ``` //! //! We can also set off compilation failures that happen in sufficiently late stages of the @@ -218,6 +230,7 @@ //! - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue. //! - [`Discriminant`] and [`Len`] have associated functions. //! - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc. +//! - The binary operation `Offset` can be created via [`Offset`]. //! - Checked binary operations are represented by wrapping the associated binop in [`Checked`]. //! - Array repetition syntax (`[foo; 10]`) creates the associated rvalue. //! @@ -227,12 +240,12 @@ //! are no resume and abort terminators, and terminators that might unwind do not have any way to //! indicate the unwind block. //! -//! - [`Goto`], [`Return`], [`Unreachable`], [`Drop`](Drop()), and [`DropAndReplace`] have associated functions. +//! - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions. //! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block` //! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the //! otherwise branch. //! - [`Call`] has an associated function as well. The third argument of this function is a normal -//! function call expresion, for example `my_other_function(a, 5)`. +//! function call expression, for example `my_other_function(a, 5)`. //! #![unstable( @@ -250,6 +263,7 @@ pub struct BasicBlock; macro_rules! define { ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => { #[rustc_diagnostic_item = $name] + #[inline] $( #[ $meta ] )* pub fn $($sig)* { panic!() } } @@ -259,7 +273,6 @@ define!("mir_return", fn Return() -> BasicBlock); define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_unreachable", fn Unreachable() -> BasicBlock); define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock)); -define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: BasicBlock)); define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T)); define!("mir_storage_live", fn StorageLive<T>(local: T)); define!("mir_storage_dead", fn StorageDead<T>(local: T)); @@ -276,6 +289,7 @@ define!( fn Discriminant<T>(place: T) -> <T as ::core::marker::DiscriminantKind>::Discriminant ); define!("mir_set_discriminant", fn SetDiscriminant<T>(place: T, index: u32)); +define!("mir_offset", fn Offset<T, U>(ptr: T, count: U) -> T); define!( "mir_field", /// Access the field with the given index of some place. @@ -302,7 +316,6 @@ define!( /// ```rust /// #![feature(custom_mir, core_intrinsics)] /// - /// extern crate core; /// use core::intrinsics::mir::*; /// /// #[custom_mir(dialect = "built")] @@ -331,6 +344,14 @@ define!( fn Variant<T>(place: T, index: u32) -> () ); define!( + "mir_cast_transmute", + /// Emits a `CastKind::Transmute` cast. + /// + /// Needed to test the UB when `sizeof(T) != sizeof(U)`, which can't be + /// generated via the normal `mem::transmute`. + fn CastTransmute<T, U>(operand: T) -> U +); +define!( "mir_make_place", #[doc(hidden)] fn __internal_make_place<T>(place: T) -> *mut T @@ -343,6 +364,7 @@ define!( #[rustc_macro_transparency = "transparent"] pub macro mir { ( + $(type RET = $ret_ty:ty ;)? $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)* { @@ -363,7 +385,7 @@ pub macro mir { { // Now all locals #[allow(non_snake_case)] - let RET; + let RET $(: $ret_ty)?; $( let $local_decl $(: $local_decl_ty)? ; )* diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index 477e7117c3e..4e0e19ddc78 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,3 +1,4 @@ +use crate::num::NonZeroUsize; use crate::ops::{NeverShortCircuit, Try}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. @@ -26,7 +27,7 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { I::advance_by(self.0, n) } @@ -62,7 +63,7 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { I::advance_back_by(self.0, n) } diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index 60eb3a6da3a..26aa959e6da 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -1,4 +1,5 @@ use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// An iterator that links two iterators together, in a chain. @@ -14,7 +15,7 @@ use crate::ops::Try; /// /// let a1 = [1, 2, 3]; /// let a2 = [4, 5, 6]; -/// let iter: Chain<Iter<_>, Iter<_>> = a1.iter().chain(a2.iter()); +/// let iter: Chain<Iter<'_, _>, Iter<'_, _>> = a1.iter().chain(a2.iter()); /// ``` #[derive(Clone, Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] @@ -95,38 +96,33 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let mut rem = n; - + fn advance_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> { if let Some(ref mut a) = self.a { - match a.advance_by(rem) { + n = match a.advance_by(n) { Ok(()) => return Ok(()), - Err(k) => rem -= k, - } + Err(k) => k.get(), + }; self.a = None; } if let Some(ref mut b) = self.b { - match b.advance_by(rem) { - Ok(()) => return Ok(()), - Err(k) => rem -= k, - } + return b.advance_by(n); // we don't fuse the second iterator } - if rem == 0 { Ok(()) } else { Err(n - rem) } + NonZeroUsize::new(n).map_or(Ok(()), Err) } #[inline] fn nth(&mut self, mut n: usize) -> Option<Self::Item> { if let Some(ref mut a) = self.a { - match a.advance_by(n) { + n = match a.advance_by(n) { Ok(()) => match a.next() { - None => n = 0, + None => 0, x => return x, }, - Err(k) => n -= k, - } + Err(k) => k.get(), + }; self.a = None; } @@ -186,38 +182,33 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - let mut rem = n; - + fn advance_back_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> { if let Some(ref mut b) = self.b { - match b.advance_back_by(rem) { + n = match b.advance_back_by(n) { Ok(()) => return Ok(()), - Err(k) => rem -= k, - } + Err(k) => k.get(), + }; self.b = None; } if let Some(ref mut a) = self.a { - match a.advance_back_by(rem) { - Ok(()) => return Ok(()), - Err(k) => rem -= k, - } + return a.advance_back_by(n); // we don't fuse the second iterator } - if rem == 0 { Ok(()) } else { Err(n - rem) } + NonZeroUsize::new(n).map_or(Ok(()), Err) } #[inline] fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> { if let Some(ref mut b) = self.b { - match b.advance_back_by(n) { + n = match b.advance_back_by(n) { Ok(()) => match b.next_back() { - None => n = 0, + None => 0, x => return x, }, - Err(k) => n -= k, - } + Err(k) => k.get(), + }; self.b = None; } @@ -282,6 +273,28 @@ where { } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<A: Default, B: Default> Default for Chain<A, B> { + /// Creates a `Chain` from the default values for `A` and `B`. + /// + /// ``` + /// # use core::iter::Chain; + /// # use core::slice; + /// # use std::collections::{btree_set, BTreeSet}; + /// # use std::mem; + /// struct Foo<'a>(Chain<slice::Iter<'a, u8>, btree_set::Iter<'a, u8>>); + /// + /// let set = BTreeSet::<u8>::new(); + /// let slice: &[u8] = &[]; + /// let mut foo = Foo(slice.iter().chain(set.iter())); + /// + /// // take requires `Default` + /// let _: Chain<_, _> = mem::take(&mut foo.0); + fn default() -> Self { + Chain::new(Default::default(), Default::default()) + } +} + #[inline] fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> { let x = f(opt.as_mut()?); diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index 914ff86c1a9..d3cceb8d4ad 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -153,3 +153,17 @@ where item.clone() } } + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Cloned<I> { + /// Creates a `Cloned` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Cloned; + /// let iter: Cloned<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Self::new(Default::default()) + } +} diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 62d3afb8160..8f6b2904eae 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -4,6 +4,7 @@ use crate::iter::adapters::{ use crate::iter::{FusedIterator, TrustedLen}; use crate::mem::MaybeUninit; use crate::mem::SizedTypeProperties; +use crate::num::NonZeroUsize; use crate::ops::Try; use crate::{array, ptr}; @@ -89,7 +90,7 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.it.advance_by(n) } @@ -130,7 +131,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.it.advance_back_by(n) } } @@ -240,3 +241,17 @@ where } } } + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Copied<I> { + /// Creates a `Copied` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Copied; + /// let iter: Copied<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Self::new(Default::default()) + } +} diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs index 02b5939072e..51bd09b6eff 100644 --- a/library/core/src/iter/adapters/cycle.rs +++ b/library/core/src/iter/adapters/cycle.rs @@ -1,3 +1,4 @@ +use crate::num::NonZeroUsize; use crate::{iter::FusedIterator, ops::Try}; /// An iterator that repeats endlessly. @@ -81,23 +82,22 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let mut rem = n; - match self.iter.advance_by(rem) { - ret @ Ok(_) => return ret, - Err(advanced) => rem -= advanced, - } + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let mut n = match self.iter.advance_by(n) { + Ok(()) => return Ok(()), + Err(rem) => rem.get(), + }; - while rem > 0 { + while n > 0 { self.iter = self.orig.clone(); - match self.iter.advance_by(rem) { - ret @ Ok(_) => return ret, - Err(0) => return Err(n - rem), - Err(advanced) => rem -= advanced, - } + n = match self.iter.advance_by(n) { + Ok(()) => return Ok(()), + e @ Err(rem) if rem.get() == n => return e, + Err(rem) => rem.get(), + }; } - Ok(()) + NonZeroUsize::new(n).map_or(Ok(()), Err) } // No `fold` override, because `fold` doesn't make much sense for `Cycle`, diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 14a12695111..00c1c377bf9 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -2,6 +2,7 @@ use crate::iter::adapters::{ zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// An iterator that yields the current count and the element during iteration. @@ -114,17 +115,14 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - match self.iter.advance_by(n) { - ret @ Ok(_) => { - self.count += n; - ret - } - ret @ Err(advanced) => { - self.count += advanced; - ret - } - } + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let remaining = self.iter.advance_by(n); + let advanced = match remaining { + Ok(()) => n, + Err(rem) => n - rem.get(), + }; + self.count += advanced; + remaining } #[rustc_inherit_overflow_checks] @@ -208,7 +206,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // we do not need to update the count since that only tallies the number of items // consumed from the front. consuming items from the back can never reduce that. self.iter.advance_back_by(n) @@ -264,3 +262,17 @@ where #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl<I: InPlaceIterable> InPlaceIterable for Enumerate<I> {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Enumerate<I> { + /// Creates an `Enumerate` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use std::iter::Enumerate; + /// let iter: Enumerate<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Enumerate::new(Default::default()) + } +} diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index b040a0ea901..2568aaf34f3 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,5 +1,6 @@ use crate::fmt; use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator that maps each element to an iterator, and yields the elements @@ -75,7 +76,7 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.inner.advance_by(n) } @@ -120,7 +121,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.inner.advance_back_by(n) } } @@ -135,26 +136,12 @@ where } #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<T, I, F, const N: usize> TrustedLen for FlatMap<I, [T; N], F> +unsafe impl<I, U, F> TrustedLen for FlatMap<I, U, F> where - I: TrustedLen, - F: FnMut(I::Item) -> [T; N], -{ -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap<I, &'a [T; N], F> -where - I: TrustedLen, - F: FnMut(I::Item) -> &'a [T; N], -{ -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap<I, &'a mut [T; N], F> -where - I: TrustedLen, - F: FnMut(I::Item) -> &'a mut [T; N], + I: Iterator, + U: IntoIterator, + F: FnMut(I::Item) -> U, + FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>: TrustedLen, { } @@ -236,7 +223,7 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.inner.advance_by(n) } @@ -281,7 +268,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.inner.advance_back_by(n) } } @@ -297,14 +284,33 @@ where #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<I> TrustedLen for Flatten<I> where - I: TrustedLen, - <I as Iterator>::Item: TrustedConstSize, + I: Iterator<Item: IntoIterator>, + FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>: TrustedLen, +{ +} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I> Default for Flatten<I> +where + I: Default + Iterator<Item: IntoIterator>, { + /// Creates a `Flatten` iterator from the default value of `I`. + /// + /// ``` + /// # use core::slice; + /// # use std::iter::Flatten; + /// let iter: Flatten<slice::Iter<'_, [u8; 4]>> = Default::default(); + /// assert_eq!(iter.count(), 0); + /// ``` + fn default() -> Self { + Flatten::new(Default::default()) + } } /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. #[derive(Clone, Debug)] +#[unstable(feature = "trusted_len", issue = "37572")] struct FlattenCompat<I, U> { iter: Fuse<I>, frontiter: Option<U>, @@ -458,6 +464,7 @@ where } } +#[unstable(feature = "trusted_len", issue = "37572")] impl<I, U> Iterator for FlattenCompat<I, U> where I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>, @@ -534,18 +541,18 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { #[inline] #[rustc_inherit_overflow_checks] fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> { match iter.advance_by(n) { Ok(()) => ControlFlow::Break(()), - Err(advanced) => ControlFlow::Continue(n - advanced), + Err(remaining) => ControlFlow::Continue(remaining.get()), } } match self.iter_try_fold(n, advance) { - ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining), + ControlFlow::Continue(remaining) => NonZeroUsize::new(remaining).map_or(Ok(()), Err), _ => Ok(()), } } @@ -572,6 +579,7 @@ where } } +#[unstable(feature = "trusted_len", issue = "37572")] impl<I, U> DoubleEndedIterator for FlattenCompat<I, U> where I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>, @@ -624,23 +632,47 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { #[inline] #[rustc_inherit_overflow_checks] fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> { match iter.advance_back_by(n) { Ok(()) => ControlFlow::Break(()), - Err(advanced) => ControlFlow::Continue(n - advanced), + Err(remaining) => ControlFlow::Continue(remaining.get()), } } match self.iter_try_rfold(n, advance) { - ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining), + ControlFlow::Continue(remaining) => NonZeroUsize::new(remaining).map_or(Ok(()), Err), _ => Ok(()), } } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<const N: usize, I, T> TrustedLen + for FlattenCompat<I, <[T; N] as IntoIterator>::IntoIter> +where + I: TrustedLen<Item = [T; N]>, +{ +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, const N: usize, I, T> TrustedLen + for FlattenCompat<I, <&'a [T; N] as IntoIterator>::IntoIter> +where + I: TrustedLen<Item = &'a [T; N]>, +{ +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, const N: usize, I, T> TrustedLen + for FlattenCompat<I, <&'a mut [T; N] as IntoIterator>::IntoIter> +where + I: TrustedLen<Item = &'a mut [T; N]>, +{ +} + trait ConstSizeIntoIterator: IntoIterator { // FIXME(#31844): convert to an associated const once specialization supports that fn size() -> Option<usize>; @@ -677,19 +709,6 @@ impl<T, const N: usize> ConstSizeIntoIterator for &mut [T; N] { } } -#[doc(hidden)] -#[unstable(feature = "std_internals", issue = "none")] -// FIXME(#20400): Instead of this helper trait there should be multiple impl TrustedLen for Flatten<> -// blocks with different bounds on Iterator::Item but the compiler erroneously considers them overlapping -pub unsafe trait TrustedConstSize: IntoIterator {} - -#[unstable(feature = "std_internals", issue = "none")] -unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {} -#[unstable(feature = "std_internals", issue = "none")] -unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {} -#[unstable(feature = "std_internals", issue = "none")] -unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {} - #[inline] fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> { let x = f(opt.as_mut()?); diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index c9314454203..b1fa4f92117 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -181,6 +181,21 @@ where } } +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Fuse<I> { + /// Creates a `Fuse` iterator from the default value of `I`. + /// + /// ``` + /// # use core::slice; + /// # use std::iter::Fuse; + /// let iter: Fuse<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Fuse { iter: Default::default() } + } +} + #[unstable(feature = "trusted_len", issue = "37572")] // SAFETY: `TrustedLen` requires that an accurate length is reported via `size_hint()`. As `Fuse` // is just forwarding this to the wrapped iterator `I` this property is preserved and it is safe to diff --git a/library/core/src/iter/adapters/rev.rs b/library/core/src/iter/adapters/rev.rs index 139fb7bbdd9..4aaf7c61f50 100644 --- a/library/core/src/iter/adapters/rev.rs +++ b/library/core/src/iter/adapters/rev.rs @@ -1,4 +1,5 @@ use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// A double-ended iterator with the direction inverted. @@ -38,7 +39,7 @@ where } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.iter.advance_back_by(n) } @@ -83,7 +84,7 @@ where } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.iter.advance_by(n) } @@ -135,3 +136,17 @@ impl<I> FusedIterator for Rev<I> where I: FusedIterator + DoubleEndedIterator {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<I> TrustedLen for Rev<I> where I: TrustedLen + DoubleEndedIterator {} + +#[stable(feature = "default_iters", since = "1.70.0")] +impl<I: Default> Default for Rev<I> { + /// Creates a `Rev` iterator from the default value of `I` + /// ``` + /// # use core::slice; + /// # use core::iter::Rev; + /// let iter: Rev<slice::Iter<'_, u8>> = Default::default(); + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + Rev::new(Default::default()) + } +} diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index c6334880db5..306338bc7cc 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -1,5 +1,6 @@ use crate::intrinsics::unlikely; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator that skips over `n` elements of `iter`. @@ -128,34 +129,27 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let mut rem = n; - let step_one = self.n.saturating_add(rem); - - match self.iter.advance_by(step_one) { - Ok(_) => { - rem -= step_one - self.n; - self.n = 0; - } - Err(advanced) => { - let advanced_without_skip = advanced.saturating_sub(self.n); - self.n = self.n.saturating_sub(advanced); - return if n == 0 { Ok(()) } else { Err(advanced_without_skip) }; - } - } + fn advance_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> { + let skip_inner = self.n; + let skip_and_advance = skip_inner.saturating_add(n); - // step_one calculation may have saturated - if unlikely(rem > 0) { - return match self.iter.advance_by(rem) { - ret @ Ok(_) => ret, - Err(advanced) => { - rem -= advanced; - Err(n - rem) - } - }; + let remainder = match self.iter.advance_by(skip_and_advance) { + Ok(()) => 0, + Err(n) => n.get(), + }; + let advanced_inner = skip_and_advance - remainder; + n -= advanced_inner.saturating_sub(skip_inner); + self.n = self.n.saturating_sub(advanced_inner); + + // skip_and_advance may have saturated + if unlikely(remainder == 0 && n > 0) { + n = match self.iter.advance_by(n) { + Ok(()) => 0, + Err(n) => n.get(), + } } - Ok(()) + NonZeroUsize::new(n).map_or(Ok(()), Err) } } @@ -209,13 +203,11 @@ where impl_fold_via_try_fold! { rfold -> try_rfold } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let min = crate::cmp::min(self.len(), n); - return match self.iter.advance_back_by(min) { - ret @ Ok(_) if n <= min => ret, - Ok(_) => Err(min), - _ => panic!("ExactSizeIterator contract violation"), - }; + let rem = self.iter.advance_back_by(min); + assert!(rem.is_ok(), "ExactSizeIterator contract violation"); + NonZeroUsize::new(n - min).map_or(Ok(()), Err) } } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index d947c7b0e30..ce18bffe714 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -1,5 +1,6 @@ use crate::cmp; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator that only iterates over the first `n` iterations of `iter`. @@ -121,18 +122,15 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let min = self.n.min(n); - match self.iter.advance_by(min) { - Ok(_) => { - self.n -= min; - if min < n { Err(min) } else { Ok(()) } - } - ret @ Err(advanced) => { - self.n -= advanced; - ret - } - } + let rem = match self.iter.advance_by(min) { + Ok(()) => 0, + Err(rem) => rem.get(), + }; + let advanced = min - rem; + self.n -= advanced; + NonZeroUsize::new(n - advanced).map_or(Ok(()), Err) } } @@ -223,7 +221,7 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // The amount by which the inner iterator needs to be shortened for it to be // at most as long as the take() amount. let trim_inner = self.iter.len().saturating_sub(self.n); @@ -232,12 +230,14 @@ where // about having to advance more than usize::MAX here. let advance_by = trim_inner.saturating_add(n); - let advanced = match self.iter.advance_back_by(advance_by) { - Ok(_) => advance_by - trim_inner, - Err(advanced) => advanced - trim_inner, + let remainder = match self.iter.advance_back_by(advance_by) { + Ok(()) => 0, + Err(rem) => rem.get(), }; - self.n -= advanced; - return if advanced < n { Err(advanced) } else { Ok(()) }; + let advanced_by_inner = advance_by - remainder; + let advanced_by = advanced_by_inner - trim_inner; + self.n -= advanced_by; + NonZeroUsize::new(n - advanced_by).map_or(Ok(()), Err) } } diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 156b925de77..de638552fa3 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -278,6 +278,7 @@ //! //! ``` //! # #![allow(unused_must_use)] +//! # #![allow(map_unit_fn)] //! let v = vec![1, 2, 3, 4, 5]; //! v.iter().map(|x| println!("{x}")); //! ``` diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 78e27d73065..0171d89812f 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1,5 +1,6 @@ use crate::convert::TryFrom; use crate::mem; +use crate::num::NonZeroUsize; use crate::ops::{self, Try}; use super::{ @@ -520,12 +521,12 @@ trait RangeIteratorImpl { // Iterator fn spec_next(&mut self) -> Option<Self::Item>; fn spec_nth(&mut self, n: usize) -> Option<Self::Item>; - fn spec_advance_by(&mut self, n: usize) -> Result<(), usize>; + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize>; // DoubleEndedIterator fn spec_next_back(&mut self) -> Option<Self::Item>; fn spec_nth_back(&mut self, n: usize) -> Option<Self::Item>; - fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>; + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>; } impl<A: Step> RangeIteratorImpl for ops::Range<A> { @@ -557,7 +558,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> { } #[inline] - default fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> { + default fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let available = if self.start <= self.end { Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) } else { @@ -569,7 +570,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> { self.start = Step::forward_checked(self.start.clone(), taken).expect("`Step` invariants not upheld"); - if taken < n { Err(taken) } else { Ok(()) } + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) } #[inline] @@ -598,7 +599,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> { } #[inline] - default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> { + default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let available = if self.start <= self.end { Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) } else { @@ -610,7 +611,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> { self.end = Step::backward_checked(self.end.clone(), taken).expect("`Step` invariants not upheld"); - if taken < n { Err(taken) } else { Ok(()) } + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) } } @@ -641,7 +642,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> { } #[inline] - fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> { + fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let available = if self.start <= self.end { Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) } else { @@ -656,7 +657,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> { // Otherwise 0 is returned which always safe to use. self.start = unsafe { Step::forward_unchecked(self.start.clone(), taken) }; - if taken < n { Err(taken) } else { Ok(()) } + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) } #[inline] @@ -685,7 +686,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> { } #[inline] - fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let available = if self.start <= self.end { Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) } else { @@ -697,7 +698,7 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> { // SAFETY: same as the spec_advance_by() implementation self.end = unsafe { Step::backward_unchecked(self.end.clone(), taken) }; - if taken < n { Err(taken) } else { Ok(()) } + NonZeroUsize::new(n - taken).map_or(Ok(()), Err) } } @@ -731,12 +732,18 @@ impl<A: Step> Iterator for ops::Range<A> { } #[inline] - fn min(mut self) -> Option<A> { + fn min(mut self) -> Option<A> + where + A: Ord, + { self.next() } #[inline] - fn max(mut self) -> Option<A> { + fn max(mut self) -> Option<A> + where + A: Ord, + { self.next_back() } @@ -746,7 +753,7 @@ impl<A: Step> Iterator for ops::Range<A> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.spec_advance_by(n) } @@ -824,7 +831,7 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.spec_advance_back_by(n) } } @@ -1157,12 +1164,18 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> { } #[inline] - fn min(mut self) -> Option<A> { + fn min(mut self) -> Option<A> + where + A: Ord, + { self.next() } #[inline] - fn max(mut self) -> Option<A> { + fn max(mut self) -> Option<A> + where + A: Ord, + { self.next_back() } diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs index 617dfd12383..243df015f9a 100644 --- a/library/core/src/iter/sources/empty.rs +++ b/library/core/src/iter/sources/empty.rs @@ -81,8 +81,7 @@ impl<T> Clone for Empty<T> { // not #[derive] because that adds a Default bound on T, // which isn't necessary. #[stable(feature = "iter_empty", since = "1.2.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T> const Default for Empty<T> { +impl<T> Default for Empty<T> { fn default() -> Empty<T> { Empty(marker::PhantomData) } diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index 733142ed011..67051f6e97b 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs @@ -1,4 +1,5 @@ use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZeroUsize; /// Creates a new iterator that endlessly repeats a single element. /// @@ -80,7 +81,7 @@ impl<A: Clone> Iterator for Repeat<A> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // Advancing an infinite iterator of a single element is a no-op. let _ = n; Ok(()) @@ -109,7 +110,7 @@ impl<A: Clone> DoubleEndedIterator for Repeat<A> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { // Advancing an infinite iterator of a single element is a no-op. let _ = n; Ok(()) diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index dc61d6065b8..0b0445850bf 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -1,5 +1,6 @@ use crate::iter::{FusedIterator, TrustedLen}; use crate::mem::ManuallyDrop; +use crate::num::NonZeroUsize; /// Creates a new iterator that repeats a single element a given number of times. /// @@ -137,7 +138,7 @@ impl<A: Clone> Iterator for RepeatN<A> { } #[inline] - fn advance_by(&mut self, skip: usize) -> Result<(), usize> { + fn advance_by(&mut self, skip: usize) -> Result<(), NonZeroUsize> { let len = self.count; if skip >= len { @@ -145,7 +146,8 @@ impl<A: Clone> Iterator for RepeatN<A> { } if skip > len { - Err(len) + // SAFETY: we just checked that the difference is positive + Err(unsafe { NonZeroUsize::new_unchecked(skip - len) }) } else { self.count = len - skip; Ok(()) @@ -178,7 +180,7 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { self.advance_by(n) } diff --git a/library/core/src/iter/sources/repeat_with.rs b/library/core/src/iter/sources/repeat_with.rs index 3f34105a3e0..d3cd74a4483 100644 --- a/library/core/src/iter/sources/repeat_with.rs +++ b/library/core/src/iter/sources/repeat_with.rs @@ -19,7 +19,6 @@ use crate::ops::Try; /// please open a GitHub issue explaining your use case. /// /// [`repeat()`]: crate::iter::repeat -/// [`DoubleEndedIterator`]: crate::iter::DoubleEndedIterator /// /// # Examples /// diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index e31669b3924..f9c7eb8f938 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -164,12 +164,13 @@ where /// element is encountered: /// /// ``` + /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) }; /// let v = vec![1, 2]; - /// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32| - /// if x < 0 { Err("Negative element found") } - /// else { Ok(x) } - /// ).sum(); + /// let res: Result<i32, _> = v.iter().map(f).sum(); /// assert_eq!(res, Ok(3)); + /// let v = vec![1, -2]; + /// let res: Result<i32, _> = v.iter().map(f).sum(); + /// assert_eq!(res, Err("Negative element found")); /// ``` fn sum<I>(iter: I) -> Result<T, E> where @@ -187,6 +188,20 @@ where /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further /// elements are taken, and the [`Err`] is returned. Should no [`Err`] /// occur, the product of all elements is returned. + /// + /// # Examples + /// + /// This multiplies each number in a vector of strings, + /// if a string could not be parsed the operation returns `Err`: + /// + /// ``` + /// let nums = vec!["5", "10", "1", "2"]; + /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product(); + /// assert_eq!(total, Ok(100)); + /// let nums = vec!["5", "10", "one", "2"]; + /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product(); + /// assert!(total.is_err()); + /// ``` fn product<I>(iter: I) -> Result<T, E> where I: Iterator<Item = Result<U, E>>, @@ -213,6 +228,9 @@ where /// let words = vec!["have", "a", "great", "day"]; /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum(); /// assert_eq!(total, Some(5)); + /// let words = vec!["have", "a", "good", "day"]; + /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum(); + /// assert_eq!(total, None); /// ``` fn sum<I>(iter: I) -> Option<T> where @@ -230,6 +248,20 @@ where /// Takes each element in the [`Iterator`]: if it is a [`None`], no further /// elements are taken, and the [`None`] is returned. Should no [`None`] /// occur, the product of all elements is returned. + /// + /// # Examples + /// + /// This multiplies each number in a vector of strings, + /// if a string could not be parsed the operation returns `None`: + /// + /// ``` + /// let nums = vec!["5", "10", "1", "2"]; + /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product(); + /// assert_eq!(total, Some(100)); + /// let nums = vec!["5", "10", "one", "2"]; + /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product(); + /// assert_eq!(total, None); + /// ``` fn product<I>(iter: I) -> Option<T> where I: Iterator<Item = Option<U>>, diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index e099700e3e7..76b3a32880d 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -228,7 +228,6 @@ pub trait FromIterator<A>: Sized { #[rustc_diagnostic_item = "IntoIterator"] #[rustc_skip_array_during_method_dispatch] #[stable(feature = "rust1", since = "1.0.0")] -#[const_trait] pub trait IntoIterator { /// The type of the elements being iterated over. #[stable(feature = "rust1", since = "1.0.0")] @@ -264,7 +263,7 @@ pub trait IntoIterator { #[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")] #[stable(feature = "rust1", since = "1.0.0")] -impl<I: Iterator> const IntoIterator for I { +impl<I: Iterator> IntoIterator for I { type Item = I::Item; type IntoIter = I; diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index ed23873cdde..182d9f758ad 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,3 +1,4 @@ +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator able to yield elements from both ends. @@ -98,10 +99,11 @@ pub trait DoubleEndedIterator: Iterator { /// eagerly skip `n` elements starting from the back by calling [`next_back`] up /// to `n` times until [`None`] is encountered. /// - /// `advance_back_by(n)` will return [`Ok(())`] if the iterator successfully advances by - /// `n` elements, or [`Err(k)`] if [`None`] is encountered, where `k` is the number of - /// elements the iterator is advanced by before running out of elements (i.e. the length - /// of the iterator). Note that `k` is always less than `n`. + /// `advance_back_by(n)` will return `Ok(())` if the iterator successfully advances by + /// `n` elements, or a `Err(NonZeroUsize)` with value `k` if [`None`] is encountered, where `k` + /// is remaining number of steps that could not be advanced because the iterator ran out. + /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`. + /// Otherwise, `k` is always less than `n`. /// /// Calling `advance_back_by(0)` can do meaningful work, for example [`Flatten`] can advance its /// outer iterator until it finds an inner iterator that is not empty, which then often @@ -118,22 +120,26 @@ pub trait DoubleEndedIterator: Iterator { /// ``` /// #![feature(iter_advance_by)] /// + /// use std::num::NonZeroUsize; /// let a = [3, 4, 5, 6]; /// let mut iter = a.iter(); /// /// assert_eq!(iter.advance_back_by(2), Ok(())); /// assert_eq!(iter.next_back(), Some(&4)); /// assert_eq!(iter.advance_back_by(0), Ok(())); - /// assert_eq!(iter.advance_back_by(100), Err(1)); // only `&3` was skipped + /// assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&3` was skipped /// ``` /// /// [`Ok(())`]: Ok /// [`Err(k)`]: Err #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { for i in 0..n { - self.next_back().ok_or(i)?; + if self.next_back().is_none() { + // SAFETY: `i` is always less than `n`. + return Err(unsafe { NonZeroUsize::new_unchecked(n - i) }); + } } Ok(()) } @@ -182,7 +188,9 @@ pub trait DoubleEndedIterator: Iterator { #[inline] #[stable(feature = "iter_nth_back", since = "1.37.0")] fn nth_back(&mut self, n: usize) -> Option<Self::Item> { - self.advance_back_by(n).ok()?; + if self.advance_back_by(n).is_err() { + return None; + } self.next_back() } @@ -365,7 +373,7 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() } - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { (**self).advance_back_by(n) } fn nth_back(&mut self, n: usize) -> Option<I::Item> { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 9e3e13e7004..dabfce14474 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1,5 +1,6 @@ use crate::array; use crate::cmp::{self, Ordering}; +use crate::num::NonZeroUsize; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; use super::super::try_process; @@ -141,6 +142,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_next_chunk", reason = "recently added", issue = "98326")] + #[rustc_do_not_const_check] fn next_chunk<const N: usize>( &mut self, ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> @@ -218,6 +220,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn size_hint(&self) -> (usize, Option<usize>) { (0, None) } @@ -255,6 +258,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn count(self) -> usize where Self: Sized, @@ -285,6 +289,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn last(self) -> Option<Self::Item> where Self: Sized, @@ -302,10 +307,11 @@ pub trait Iterator { /// This method will eagerly skip `n` elements by calling [`next`] up to `n` /// times until [`None`] is encountered. /// - /// `advance_by(n)` will return [`Ok(())`][Ok] if the iterator successfully advances by - /// `n` elements, or [`Err(k)`][Err] if [`None`] is encountered, where `k` is the number - /// of elements the iterator is advanced by before running out of elements (i.e. the - /// length of the iterator). Note that `k` is always less than `n`. + /// `advance_by(n)` will return `Ok(())` if the iterator successfully advances by + /// `n` elements, or a `Err(NonZeroUsize)` with value `k` if [`None`] is encountered, + /// where `k` is remaining number of steps that could not be advanced because the iterator ran out. + /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`. + /// Otherwise, `k` is always less than `n`. /// /// Calling `advance_by(0)` can do meaningful work, for example [`Flatten`] /// can advance its outer iterator until it finds an inner iterator that is not empty, which @@ -321,19 +327,24 @@ pub trait Iterator { /// ``` /// #![feature(iter_advance_by)] /// + /// use std::num::NonZeroUsize; /// let a = [1, 2, 3, 4]; /// let mut iter = a.iter(); /// /// assert_eq!(iter.advance_by(2), Ok(())); /// assert_eq!(iter.next(), Some(&3)); /// assert_eq!(iter.advance_by(0), Ok(())); - /// assert_eq!(iter.advance_by(100), Err(1)); // only `&4` was skipped + /// assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&4` was skipped /// ``` #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + #[rustc_do_not_const_check] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { for i in 0..n { - self.next().ok_or(i)?; + if self.next().is_none() { + // SAFETY: `i` is always less than `n`. + return Err(unsafe { NonZeroUsize::new_unchecked(n - i) }); + } } Ok(()) } @@ -379,6 +390,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn nth(&mut self, n: usize) -> Option<Self::Item> { self.advance_by(n).ok()?; self.next() @@ -431,6 +443,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_step_by", since = "1.28.0")] + #[rustc_do_not_const_check] fn step_by(self, step: usize) -> StepBy<Self> where Self: Sized, @@ -502,6 +515,7 @@ pub trait Iterator { /// [`OsStr`]: ../../std/ffi/struct.OsStr.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> where Self: Sized, @@ -620,6 +634,7 @@ pub trait Iterator { /// [`zip`]: crate::iter::zip #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> where Self: Sized, @@ -662,6 +677,7 @@ pub trait Iterator { /// [`intersperse_with`]: Iterator::intersperse_with #[inline] #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + #[rustc_do_not_const_check] fn intersperse(self, separator: Self::Item) -> Intersperse<Self> where Self: Sized, @@ -720,6 +736,7 @@ pub trait Iterator { /// [`intersperse`]: Iterator::intersperse #[inline] #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] + #[rustc_do_not_const_check] fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> where Self: Sized, @@ -746,7 +763,6 @@ pub trait Iterator { /// more idiomatic to use [`for`] than `map()`. /// /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for - /// [`FnMut`]: crate::ops::FnMut /// /// # Examples /// @@ -777,8 +793,10 @@ pub trait Iterator { /// println!("{x}"); /// } /// ``` + #[rustc_diagnostic_item = "IteratorMap"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn map<B, F>(self, f: F) -> Map<Self, F> where Self: Sized, @@ -824,6 +842,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_for_each", since = "1.21.0")] + #[rustc_do_not_const_check] fn for_each<F>(self, f: F) where Self: Sized, @@ -899,6 +918,7 @@ pub trait Iterator { /// Note that `iter.filter(f).next()` is equivalent to `iter.find(f)`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn filter<P>(self, predicate: P) -> Filter<Self, P> where Self: Sized, @@ -944,6 +964,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where Self: Sized, @@ -990,6 +1011,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn enumerate(self) -> Enumerate<Self> where Self: Sized, @@ -1061,6 +1083,7 @@ pub trait Iterator { /// [`next`]: Iterator::next #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn peekable(self) -> Peekable<Self> where Self: Sized, @@ -1126,6 +1149,7 @@ pub trait Iterator { #[inline] #[doc(alias = "drop_while")] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where Self: Sized, @@ -1207,6 +1231,7 @@ pub trait Iterator { /// the iteration should stop, but wasn't placed back into the iterator. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where Self: Sized, @@ -1295,6 +1320,7 @@ pub trait Iterator { /// [`fuse`]: Iterator::fuse #[inline] #[stable(feature = "iter_map_while", since = "1.57.0")] + #[rustc_do_not_const_check] fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> where Self: Sized, @@ -1326,6 +1352,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn skip(self, n: usize) -> Skip<Self> where Self: Sized, @@ -1379,6 +1406,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn take(self, n: usize) -> Take<Self> where Self: Sized, @@ -1428,6 +1456,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> where Self: Sized, @@ -1468,6 +1497,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> where Self: Sized, @@ -1552,6 +1582,7 @@ pub trait Iterator { /// [`flat_map()`]: Iterator::flat_map #[inline] #[stable(feature = "iterator_flatten", since = "1.29.0")] + #[rustc_do_not_const_check] fn flatten(self) -> Flatten<Self> where Self: Sized, @@ -1620,6 +1651,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn fuse(self) -> Fuse<Self> where Self: Sized, @@ -1704,6 +1736,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn inspect<F>(self, f: F) -> Inspect<Self, F> where Self: Sized, @@ -1734,6 +1767,7 @@ pub trait Iterator { /// assert_eq!(of_rust, vec!["of", "Rust"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn by_ref(&mut self) -> &mut Self where Self: Sized, @@ -1853,6 +1887,7 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")] + #[rustc_do_not_const_check] fn collect<B: FromIterator<Self::Item>>(self) -> B where Self: Sized, @@ -1931,6 +1966,7 @@ pub trait Iterator { /// [`collect`]: Iterator::collect #[inline] #[unstable(feature = "iterator_try_collect", issue = "94047")] + #[rustc_do_not_const_check] fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B> where Self: Sized, @@ -1966,7 +2002,7 @@ pub trait Iterator { /// a.iter().map(|&x| x * 2).collect_into(&mut vec); /// a.iter().map(|&x| x * 10).collect_into(&mut vec); /// - /// assert_eq!(vec![0, 1, 2, 4, 6, 10, 20, 30], vec); + /// assert_eq!(vec, vec![0, 1, 2, 4, 6, 10, 20, 30]); /// ``` /// /// `Vec` can have a manual set capacity to avoid reallocating it: @@ -1981,7 +2017,7 @@ pub trait Iterator { /// a.iter().map(|&x| x * 10).collect_into(&mut vec); /// /// assert_eq!(6, vec.capacity()); - /// println!("{:?}", vec); + /// assert_eq!(vec, vec![2, 4, 6, 10, 20, 30]); /// ``` /// /// The returned mutable reference can be used to continue the call chain: @@ -1995,15 +2031,16 @@ pub trait Iterator { /// let count = a.iter().collect_into(&mut vec).iter().count(); /// /// assert_eq!(count, vec.len()); - /// println!("Vec len is {}", count); + /// assert_eq!(vec, vec![1, 2, 3]); /// /// let count = a.iter().collect_into(&mut vec).iter().count(); /// /// assert_eq!(count, vec.len()); - /// println!("Vec len now is {}", count); + /// assert_eq!(vec, vec![1, 2, 3, 1, 2, 3]); /// ``` #[inline] #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")] + #[rustc_do_not_const_check] fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E where Self: Sized, @@ -2038,6 +2075,7 @@ pub trait Iterator { /// assert_eq!(odd, vec![1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, @@ -2075,8 +2113,8 @@ pub trait Iterator { /// /// # Current implementation /// - /// Current algorithms tries finding the first element for which the predicate evaluates - /// to false, and the last element for which it evaluates to true and repeatedly swaps them. + /// The current algorithm tries to find the first element for which the predicate evaluates + /// to false and the last element for which it evaluates to true, and repeatedly swaps them. /// /// Time complexity: *O*(*n*) /// @@ -2100,6 +2138,7 @@ pub trait Iterator { /// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds /// ``` #[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")] + #[rustc_do_not_const_check] fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize where Self: Sized + DoubleEndedIterator<Item = &'a mut T>, @@ -2157,6 +2196,7 @@ pub trait Iterator { /// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase)); /// ``` #[unstable(feature = "iter_is_partitioned", reason = "new API", issue = "62544")] + #[rustc_do_not_const_check] fn is_partitioned<P>(mut self, mut predicate: P) -> bool where Self: Sized, @@ -2251,6 +2291,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] + #[rustc_do_not_const_check] fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where Self: Sized, @@ -2309,6 +2350,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] + #[rustc_do_not_const_check] fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, @@ -2428,6 +2470,7 @@ pub trait Iterator { #[doc(alias = "inject", alias = "foldl")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn fold<B, F>(mut self, init: B, mut f: F) -> B where Self: Sized, @@ -2465,6 +2508,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_fold_self", since = "1.51.0")] + #[rustc_do_not_const_check] fn reduce<F>(mut self, f: F) -> Option<Self::Item> where Self: Sized, @@ -2536,6 +2580,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")] + #[rustc_do_not_const_check] fn try_reduce<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<R::Output>> where Self: Sized, @@ -2593,6 +2638,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn all<F>(&mut self, f: F) -> bool where Self: Sized, @@ -2646,6 +2692,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn any<F>(&mut self, f: F) -> bool where Self: Sized, @@ -2709,6 +2756,7 @@ pub trait Iterator { /// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, @@ -2740,6 +2788,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_find_map", since = "1.30.0")] + #[rustc_do_not_const_check] fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, @@ -2796,6 +2845,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "try_find", reason = "new API", issue = "63178")] + #[rustc_do_not_const_check] fn try_find<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<Self::Item>> where Self: Sized, @@ -2878,6 +2928,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, @@ -2935,6 +2986,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, @@ -2986,6 +3038,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn max(self) -> Option<Self::Item> where Self: Sized, @@ -3024,6 +3077,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn min(self) -> Option<Self::Item> where Self: Sized, @@ -3046,6 +3100,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] + #[rustc_do_not_const_check] fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item> where Self: Sized, @@ -3079,6 +3134,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_max_by", since = "1.15.0")] + #[rustc_do_not_const_check] fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, @@ -3106,6 +3162,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] + #[rustc_do_not_const_check] fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item> where Self: Sized, @@ -3139,6 +3196,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_min_by", since = "1.15.0")] + #[rustc_do_not_const_check] fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, @@ -3176,6 +3234,7 @@ pub trait Iterator { #[inline] #[doc(alias = "reverse")] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn rev(self) -> Rev<Self> where Self: Sized + DoubleEndedIterator, @@ -3214,6 +3273,7 @@ pub trait Iterator { /// assert_eq!(z, [3, 6]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, @@ -3246,6 +3306,7 @@ pub trait Iterator { /// assert_eq!(v_map, vec![1, 2, 3]); /// ``` #[stable(feature = "iter_copied", since = "1.36.0")] + #[rustc_do_not_const_check] fn copied<'a, T: 'a>(self) -> Copied<Self> where Self: Sized + Iterator<Item = &'a T>, @@ -3293,6 +3354,7 @@ pub trait Iterator { /// assert_eq!(&[vec![23]], &faster[..]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_do_not_const_check] fn cloned<'a, T: 'a>(self) -> Cloned<Self> where Self: Sized + Iterator<Item = &'a T>, @@ -3327,6 +3389,7 @@ pub trait Iterator { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[rustc_do_not_const_check] fn cycle(self) -> Cycle<Self> where Self: Sized + Clone, @@ -3370,6 +3433,7 @@ pub trait Iterator { /// ``` #[track_caller] #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] + #[rustc_do_not_const_check] fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> where Self: Sized, @@ -3383,6 +3447,9 @@ pub trait Iterator { /// /// An empty iterator returns the zero value of the type. /// + /// `sum()` can be used to sum any type implementing [`Sum`][`core::iter::Sum`], + /// including [`Option`][`Option::sum`] and [`Result`][`Result::sum`]. + /// /// # Panics /// /// When calling `sum()` and a primitive integer type is being returned, this @@ -3400,6 +3467,7 @@ pub trait Iterator { /// assert_eq!(sum, 6); /// ``` #[stable(feature = "iter_arith", since = "1.11.0")] + #[rustc_do_not_const_check] fn sum<S>(self) -> S where Self: Sized, @@ -3412,6 +3480,9 @@ pub trait Iterator { /// /// An empty iterator returns the one value of the type. /// + /// `product()` can be used to multiply any type implementing [`Product`][`core::iter::Product`], + /// including [`Option`][`Option::product`] and [`Result`][`Result::product`]. + /// /// # Panics /// /// When calling `product()` and a primitive integer type is being returned, @@ -3429,6 +3500,7 @@ pub trait Iterator { /// assert_eq!(factorial(5), 120); /// ``` #[stable(feature = "iter_arith", since = "1.11.0")] + #[rustc_do_not_const_check] fn product<P>(self) -> P where Self: Sized, @@ -3450,6 +3522,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_do_not_const_check] fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, @@ -3479,6 +3552,7 @@ pub trait Iterator { /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_do_not_const_check] fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, @@ -3535,6 +3609,7 @@ pub trait Iterator { /// ``` /// #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_do_not_const_check] fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, @@ -3573,6 +3648,7 @@ pub trait Iterator { /// ); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_do_not_const_check] fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, @@ -3606,6 +3682,7 @@ pub trait Iterator { /// assert_eq!([1].iter().eq([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_do_not_const_check] fn eq<I>(self, other: I) -> bool where I: IntoIterator, @@ -3631,6 +3708,7 @@ pub trait Iterator { /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_do_not_const_check] fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, @@ -3653,7 +3731,7 @@ pub trait Iterator { } } - /// Determines if the elements of this [`Iterator`] are unequal to those of + /// Determines if the elements of this [`Iterator`] are not equal to those of /// another. /// /// # Examples @@ -3663,6 +3741,7 @@ pub trait Iterator { /// assert_eq!([1].iter().ne([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_do_not_const_check] fn ne<I>(self, other: I) -> bool where I: IntoIterator, @@ -3684,6 +3763,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().lt([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_do_not_const_check] fn lt<I>(self, other: I) -> bool where I: IntoIterator, @@ -3705,6 +3785,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().le([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_do_not_const_check] fn le<I>(self, other: I) -> bool where I: IntoIterator, @@ -3726,6 +3807,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().gt([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_do_not_const_check] fn gt<I>(self, other: I) -> bool where I: IntoIterator, @@ -3747,6 +3829,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().ge([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_do_not_const_check] fn ge<I>(self, other: I) -> bool where I: IntoIterator, @@ -3778,6 +3861,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[rustc_do_not_const_check] fn is_sorted(self) -> bool where Self: Sized, @@ -3806,6 +3890,7 @@ pub trait Iterator { /// /// [`is_sorted`]: Iterator::is_sorted #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[rustc_do_not_const_check] fn is_sorted_by<F>(mut self, compare: F) -> bool where Self: Sized, @@ -3852,6 +3937,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] + #[rustc_do_not_const_check] fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, @@ -3867,6 +3953,7 @@ pub trait Iterator { #[inline] #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] + #[rustc_do_not_const_check] unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> Self::Item where Self: TrustedRandomAccessNoCoerce, @@ -3925,7 +4012,7 @@ impl<I: Iterator + ?Sized> Iterator for &mut I { fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() } - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { (**self).advance_by(n) } fn nth(&mut self, n: usize) -> Option<Self::Item> { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index dc0702c467a..0af04fac909 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -95,22 +95,25 @@ #![warn(missing_docs)] #![allow(explicit_outlives_requirements)] #![allow(incomplete_features)] -#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))] +#![warn(multiple_supertrait_upcastable)] // // Library features: -#![feature(const_align_offset)] +// tidy-alphabetical-start +#![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] +#![feature(const_align_offset)] #![feature(const_alloc_layout)] #![feature(const_arguments_as_str)] +#![feature(const_array_from_ref)] #![feature(const_array_into_iter_constructors)] +#![feature(const_assume)] #![feature(const_bigint_helper_methods)] #![feature(const_black_box)] #![feature(const_caller_location)] #![feature(const_cell_into_inner)] #![feature(const_char_from_u32_unchecked)] -#![feature(const_clone)] -#![feature(const_cmp)] +#![feature(const_cstr_methods)] #![feature(const_discriminant)] #![feature(const_eval_select)] #![feature(const_exact_div)] @@ -119,48 +122,51 @@ #![feature(const_fmt_arguments_new)] #![feature(const_hash)] #![feature(const_heap)] -#![feature(const_convert)] #![feature(const_index_range_slice_index)] #![feature(const_inherent_unchecked_arith)] #![feature(const_int_unchecked_arith)] #![feature(const_intrinsic_forget)] +#![feature(const_ipv4)] +#![feature(const_ipv6)] #![feature(const_likely)] -#![feature(const_maybe_uninit_uninit_array)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init)] +#![feature(const_maybe_uninit_uninit_array)] #![feature(const_nonnull_new)] -#![feature(const_num_from_num)] -#![feature(const_ops)] +#![feature(const_num_midpoint)] #![feature(const_option)] #![feature(const_option_ext)] #![feature(const_pin)] +#![feature(const_pointer_byte_offsets)] #![feature(const_pointer_is_aligned)] -#![feature(const_ptr_sub_ptr)] -#![feature(const_replace)] -#![feature(const_result_drop)] #![feature(const_ptr_as_ref)] #![feature(const_ptr_is_null)] -#![feature(const_ptr_read)] +#![feature(const_ptr_sub_ptr)] #![feature(const_ptr_write)] #![feature(const_raw_ptr_comparison)] +#![feature(const_replace)] #![feature(const_size_of_val)] #![feature(const_size_of_val_raw)] #![feature(const_slice_from_raw_parts_mut)] +#![feature(const_slice_from_ref)] +#![feature(const_slice_index)] +#![feature(const_slice_is_ascii)] #![feature(const_slice_ptr_len)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_swap)] -#![feature(const_trait_impl)] +#![feature(const_transmute_copy)] #![feature(const_try)] #![feature(const_type_id)] #![feature(const_type_name)] -#![feature(const_default_impls)] #![feature(const_unicode_case_lookup)] #![feature(const_unsafecell_get_mut)] #![feature(const_waker)] #![feature(core_panic)] -#![feature(char_indices_offset)] #![feature(duration_consts_float)] +#![feature(internal_impls_macro)] +#![feature(ip)] +#![feature(is_ascii_octdigit)] #![feature(maybe_uninit_uninit_array)] #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] @@ -168,24 +174,21 @@ #![feature(slice_ptr_get)] #![feature(slice_split_at_unchecked)] #![feature(str_internals)] -#![feature(str_split_remainder)] #![feature(str_split_inclusive_remainder)] +#![feature(str_split_remainder)] #![feature(strict_provenance)] #![feature(utf16_extra)] #![feature(utf16_extra_const)] #![feature(variant_count)] -#![feature(const_array_from_ref)] -#![feature(const_slice_from_ref)] -#![feature(const_slice_index)] -#![feature(const_is_char_boundary)] -#![feature(const_cstr_methods)] -#![feature(is_ascii_octdigit)] +// tidy-alphabetical-end // // Language features: +// tidy-alphabetical-start #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] +#![feature(asm_const)] #![feature(associated_type_bounds)] #![feature(auto_traits)] #![feature(c_unwind)] @@ -194,19 +197,20 @@ #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(const_closures)] #![feature(const_fn_floating_point_arithmetic)] +#![feature(const_for)] #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_refs_to_cell)] +#![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] -#![feature(derive_const)] #![feature(doc_cfg)] +#![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] -#![feature(rustdoc_internals)] #![feature(exhaustive_patterns)] -#![feature(doc_cfg_hide)] #![feature(extern_types)] #![feature(fundamental)] +#![feature(generic_arg_infer)] #![feature(if_let_guard)] #![feature(inline_const)] #![feature(intra_doc_pointers)] @@ -215,6 +219,7 @@ #![feature(link_llvm_intrinsics)] #![feature(macro_metavar_expr)] #![feature(min_specialization)] +#![feature(multiple_supertrait_upcastable)] #![feature(must_not_suspend)] #![feature(negative_impls)] #![feature(never_type)] @@ -225,6 +230,7 @@ #![feature(repr_simd)] #![feature(rustc_allow_const_fn_unstable)] #![feature(rustc_attrs)] +#![feature(rustdoc_internals)] #![feature(simd_ffi)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] @@ -234,14 +240,12 @@ #![feature(try_blocks)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] -#![feature(asm_const)] -#![feature(const_transmute_copy)] -#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))] +// tidy-alphabetical-end // // Target features: +// tidy-alphabetical-start #![feature(arm_target_feature)] #![feature(avx512_target_feature)] -#![feature(cmpxchg16b_target_feature)] #![feature(hexagon_target_feature)] #![feature(mips_target_feature)] #![feature(powerpc_target_feature)] @@ -250,6 +254,7 @@ #![feature(sse4a_target_feature)] #![feature(tbm_target_feature)] #![feature(wasm_target_feature)] +// tidy-alphabetical-end // allow using `core::` in intra-doc links #[allow(unused_extern_crates)] @@ -348,6 +353,7 @@ pub mod cell; pub mod char; pub mod ffi; pub mod iter; +pub mod net; pub mod option; pub mod panic; pub mod panicking; @@ -373,6 +379,7 @@ pub mod alloc; // note: does not need to be public mod bool; +mod escape; mod tuple; mod unit; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3b026bc0e0f..b24882ddb17 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -340,9 +340,9 @@ pub macro debug_assert_matches($($arg:tt)*) { #[stable(feature = "matches_macro", since = "1.42.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")] macro_rules! matches { - ($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => { + ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => { match $expression { - $( $pattern )|+ $( if $guard )? => true, + $pattern $(if $guard)? => true, _ => false } }; @@ -498,7 +498,6 @@ macro_rules! r#try { /// In a `no_std` setup you are responsible for the implementation details of the components. /// /// ```no_run -/// # extern crate core; /// use core::fmt::Write; /// /// struct Example; @@ -712,8 +711,8 @@ macro_rules! unimplemented { /// Indicates unfinished code. /// -/// This can be useful if you are prototyping and are just looking to have your -/// code typecheck. +/// This can be useful if you are prototyping and just +/// want a placeholder to let your code pass type analysis. /// /// The difference between [`unimplemented!`] and `todo!` is that while `todo!` conveys /// an intent of implementing the functionality later and the message is "not yet diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index 98fb7e9e41d..8b549e187ba 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -42,7 +42,7 @@ the successful result of some computation, `Ok(T)`, or error types that represent an anticipated runtime failure mode of that computation, `Err(E)`. `Result` is used alongside user defined types which represent the various anticipated runtime failure modes that the associated computation could -encounter. `Result` must be propagated manually, often with the the help of the +encounter. `Result` must be propagated manually, often with the help of the `?` operator and `Try` trait, and they must be reported manually, often with the help of the `Error` trait. diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 520ae0edb09..01606086fca 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -12,6 +12,60 @@ use crate::fmt::Debug; use crate::hash::Hash; use crate::hash::Hasher; +/// Implements a given marker trait for multiple types at the same time. +/// +/// The basic syntax looks like this: +/// ```ignore private macro +/// marker_impls! { MarkerTrait for u8, i8 } +/// ``` +/// You can also implement `unsafe` traits +/// ```ignore private macro +/// marker_impls! { unsafe MarkerTrait for u8, i8 } +/// ``` +/// Add attributes to all impls: +/// ```ignore private macro +/// marker_impls! { +/// #[allow(lint)] +/// #[unstable(feature = "marker_trait", issue = "none")] +/// MarkerTrait for u8, i8 +/// } +/// ``` +/// And use generics: +/// ```ignore private macro +/// marker_impls! { +/// MarkerTrait for +/// u8, i8, +/// {T: ?Sized} *const T, +/// {T: ?Sized} *mut T, +/// {T: MarkerTrait} PhantomData<T>, +/// u32, +/// } +/// ``` +#[unstable(feature = "internal_impls_macro", issue = "none")] +macro marker_impls { + ( $(#[$($meta:tt)*])* $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => { + // This inner macro is needed because... idk macros are weird. + // It allows repeating `meta` on all impls. + #[unstable(feature = "internal_impls_macro", issue = "none")] + macro _impl { + ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => { + $(#[$($meta)*])* impl<$$($$($$bounds_)*)?> $Trait for $$T_ {} + } + } + $( _impl! { $({$($bounds)*})? $T } )+ + }, + ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => { + #[unstable(feature = "internal_impls_macro", issue = "none")] + macro _impl { + ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => { + $(#[$($meta)*])* unsafe impl<$$($$($$bounds_)*)?> $Trait for $$T_ {} + } + } + + $( _impl! { $({$($bounds)*})? $T } )+ + }, +} + /// Types that can be transferred across thread boundaries. /// /// This trait is automatically implemented when the compiler determines it's @@ -24,7 +78,7 @@ use crate::hash::Hasher; /// operations. Its cousin [`sync::Arc`][arc] does use atomic operations (incurring /// some overhead) and thus is `Send`. /// -/// See [the Nomicon](../../nomicon/send-and-sync.html) for more details. +/// See [the Nomicon](../../nomicon/send-and-sync.html) and the [`Sync`] trait for more details. /// /// [`Rc`]: ../../std/rc/struct.Rc.html /// [arc]: ../../std/sync/struct.Arc.html @@ -97,7 +151,7 @@ unsafe impl<T: Sync + ?Sized> Send for &T {} #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable #[rustc_specialization_trait] #[rustc_deny_explicit_impl] -#[cfg_attr(not(bootstrap), rustc_coinductive)] +#[rustc_coinductive] pub trait Sized { // Empty. } @@ -214,6 +268,20 @@ pub trait StructuralEq { // Empty. } +// FIXME: Remove special cases of these types from the compiler pattern checking code and always check `T: StructuralEq` instead +marker_impls! { + #[unstable(feature = "structural_match", issue = "31434")] + StructuralEq for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, + str /* Technically requires `[u8]: StructuralEq` */, + {T, const N: usize} [T; N], + {T} [T], + {T: ?Sized} &T, +} + /// Types whose values can be duplicated simply by copying bits. /// /// By default, variable bindings have 'move semantics.' In other @@ -324,7 +392,7 @@ pub trait StructuralEq { /// attempt to derive a `Copy` implementation, we'll get an error: /// /// ```text -/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy` +/// the trait `Copy` cannot be implemented for this type; field `points` does not implement `Copy` /// ``` /// /// Shared references (`&T`) are also `Copy`, so a type can be `Copy`, even when it holds @@ -401,6 +469,30 @@ pub macro Copy($item:item) { /* compiler built-in */ } +// Implementations of `Copy` for primitive types. +// +// Implementations that cannot be described in Rust +// are implemented in `traits::SelectionContext::copy_clone_conditions()` +// in `rustc_trait_selection`. +marker_impls! { + #[stable(feature = "rust1", since = "1.0.0")] + Copy for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + f32, f64, + bool, char, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + +} + +#[unstable(feature = "never_type", issue = "35121")] +impl Copy for ! {} + +/// Shared references can be copied, but mutable references *cannot*! +#[stable(feature = "rust1", since = "1.0.0")] +impl<T: ?Sized> Copy for &T {} + /// Types for which it is safe to share references between threads. /// /// This trait is automatically implemented when the compiler determines @@ -426,6 +518,11 @@ pub macro Copy($item:item) { /// becomes read-only, as if it were a `& &T`. Hence there is no risk /// of a data race. /// +/// A shorter overview of how [`Sync`] and [`Send`] relate to referencing: +/// * `&T` is [`Send`] if and only if `T` is [`Sync`] +/// * `&mut T` is [`Send`] if and only if `T` is [`Send`] +/// * `&T` and `&mut T` are [`Sync`] if and only if `T` is [`Sync`] +/// /// Types that are not `Sync` are those that have "interior /// mutability" in a non-thread-safe form, such as [`Cell`][cell] /// and [`RefCell`][refcell]. These types allow for mutation of @@ -591,7 +688,7 @@ impl<T: ?Sized> !Sync for *mut T {} /// use std::marker::PhantomData; /// /// # #[allow(dead_code)] -/// struct Slice<'a, T: 'a> { +/// struct Slice<'a, T> { /// start: *const T, /// end: *const T, /// phantom: PhantomData<&'a T>, @@ -607,7 +704,7 @@ impl<T: ?Sized> !Sync for *mut T {} /// ``` /// # #![allow(dead_code)] /// # use std::marker::PhantomData; -/// # struct Slice<'a, T: 'a> { +/// # struct Slice<'a, T> { /// # start: *const T, /// # end: *const T, /// # phantom: PhantomData<&'a T>, @@ -669,16 +766,11 @@ impl<T: ?Sized> !Sync for *mut T {} /// /// ## Ownership and the drop check /// -/// Adding a field of type `PhantomData<T>` indicates that your -/// type owns data of type `T`. This in turn implies that when your -/// type is dropped, it may drop one or more instances of the type -/// `T`. This has bearing on the Rust compiler's [drop check] -/// analysis. +/// The exact interaction of `PhantomData` with drop check **may change in the future**. /// -/// If your struct does not in fact *own* the data of type `T`, it is -/// better to use a reference type, like `PhantomData<&'a T>` -/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so -/// as not to indicate ownership. +/// Currently, adding a field of type `PhantomData<T>` indicates that your type *owns* data of type +/// `T` in very rare circumstances. This in turn has effects on the Rust compiler's [drop check] +/// analysis. For the exact rules, see the [drop check] documentation. /// /// ## Layout /// @@ -686,7 +778,7 @@ impl<T: ?Sized> !Sync for *mut T {} /// * `size_of::<PhantomData<T>>() == 0` /// * `align_of::<PhantomData<T>>() == 1` /// -/// [drop check]: ../../nomicon/dropck.html +/// [drop check]: Drop#drop-check #[lang = "phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] pub struct PhantomData<T: ?Sized>; @@ -732,8 +824,7 @@ impl<T: ?Sized> Clone for PhantomData<T> { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T: ?Sized> const Default for PhantomData<T> { +impl<T: ?Sized> Default for PhantomData<T> { fn default() -> Self { Self } @@ -774,11 +865,14 @@ pub trait DiscriminantKind { pub(crate) unsafe auto trait Freeze {} impl<T: ?Sized> !Freeze for UnsafeCell<T> {} -unsafe impl<T: ?Sized> Freeze for PhantomData<T> {} -unsafe impl<T: ?Sized> Freeze for *const T {} -unsafe impl<T: ?Sized> Freeze for *mut T {} -unsafe impl<T: ?Sized> Freeze for &T {} -unsafe impl<T: ?Sized> Freeze for &mut T {} +marker_impls! { + unsafe Freeze for + {T: ?Sized} PhantomData<T>, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} /// Types that can be safely moved after being pinned. /// @@ -823,7 +917,7 @@ unsafe impl<T: ?Sized> Freeze for &mut T {} /// [`pin` module]: crate::pin #[stable(feature = "pin", since = "1.33.0")] #[rustc_on_unimplemented( - note = "consider using `Box::pin`", + note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope", message = "`{Self}` cannot be unpinned" )] #[lang = "unpin"] @@ -839,17 +933,19 @@ pub struct PhantomPinned; #[stable(feature = "pin", since = "1.33.0")] impl !Unpin for PhantomPinned {} -#[stable(feature = "pin", since = "1.33.0")] -impl<'a, T: ?Sized + 'a> Unpin for &'a T {} - -#[stable(feature = "pin", since = "1.33.0")] -impl<'a, T: ?Sized + 'a> Unpin for &'a mut T {} - -#[stable(feature = "pin_raw", since = "1.38.0")] -impl<T: ?Sized> Unpin for *const T {} +marker_impls! { + #[stable(feature = "pin", since = "1.33.0")] + Unpin for + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} -#[stable(feature = "pin_raw", since = "1.38.0")] -impl<T: ?Sized> Unpin for *mut T {} +marker_impls! { + #[stable(feature = "pin_raw", since = "1.38.0")] + Unpin for + {T: ?Sized} *const T, + {T: ?Sized} *mut T, +} /// A marker for types that can be dropped. /// @@ -858,8 +954,8 @@ impl<T: ?Sized> Unpin for *mut T {} #[unstable(feature = "const_trait_impl", issue = "67792")] #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] -#[const_trait] #[rustc_deny_explicit_impl] +#[const_trait] pub trait Destruct {} /// A marker for tuple types. @@ -877,49 +973,44 @@ pub trait Tuple {} /// All types that have the same size and alignment as a `usize` or /// `*const ()` automatically implement this trait. #[unstable(feature = "pointer_like_trait", issue = "none")] -#[cfg_attr(bootstrap, lang = "pointer_sized")] -#[cfg_attr(not(bootstrap), lang = "pointer_like")] +#[lang = "pointer_like"] #[rustc_on_unimplemented( - message = "`{Self}` needs to have the same alignment and size as a pointer", + message = "`{Self}` needs to have the same ABI as a pointer", label = "`{Self}` needs to be a pointer-like type" )] pub trait PointerLike {} -/// Implementations of `Copy` for primitive types. -/// -/// Implementations that cannot be described in Rust -/// are implemented in `traits::SelectionContext::copy_clone_conditions()` -/// in `rustc_trait_selection`. -mod copy_impls { - - use super::Copy; - - macro_rules! impl_copy { - ($($t:ty)*) => { - $( - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for $t {} - )* - } - } - - impl_copy! { - usize u8 u16 u32 u64 u128 - isize i8 i16 i32 i64 i128 - f32 f64 - bool char - } - - #[unstable(feature = "never_type", issue = "35121")] - impl Copy for ! {} - - #[stable(feature = "rust1", since = "1.0.0")] - impl<T: ?Sized> Copy for *const T {} - - #[stable(feature = "rust1", since = "1.0.0")] - impl<T: ?Sized> Copy for *mut T {} +/// A marker for types which can be used as types of `const` generic parameters. +#[cfg_attr(not(bootstrap), lang = "const_param_ty")] +#[unstable(feature = "adt_const_params", issue = "95174")] +#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] +pub trait ConstParamTy: StructuralEq {} + +// FIXME(generic_const_parameter_types): handle `ty::FnDef`/`ty::Closure` +// FIXME(generic_const_parameter_types): handle `ty::Tuple` +marker_impls! { + #[unstable(feature = "adt_const_params", issue = "95174")] + ConstParamTy for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, + str /* Technically requires `[u8]: ConstParamTy` */, + {T: ConstParamTy, const N: usize} [T; N], + {T: ConstParamTy} [T], + {T: ?Sized + ConstParamTy} &T, +} - /// Shared references can be copied, but mutable references *cannot*! - #[stable(feature = "rust1", since = "1.0.0")] - impl<T: ?Sized> Copy for &T {} +/// A common trait implemented by all function pointers. +#[unstable( + feature = "fn_ptr_trait", + issue = "none", + reason = "internal trait for implementing various traits for all function pointers" +)] +#[lang = "fn_ptr_trait"] +#[rustc_deny_explicit_impl] +pub trait FnPtr: Copy + Clone { + /// Returns the address of the function pointer. + #[lang = "fn_ptr_addr"] + fn addr(self) -> *const (); } diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 3d719afe49e..5f3d66e3773 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -146,8 +146,7 @@ impl<T: ?Sized> ManuallyDrop<T> { } #[stable(feature = "manually_drop", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_deref", issue = "88955")] -impl<T: ?Sized> const Deref for ManuallyDrop<T> { +impl<T: ?Sized> Deref for ManuallyDrop<T> { type Target = T; #[inline(always)] fn deref(&self) -> &T { @@ -156,8 +155,7 @@ impl<T: ?Sized> const Deref for ManuallyDrop<T> { } #[stable(feature = "manually_drop", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_deref", issue = "88955")] -impl<T: ?Sized> const DerefMut for ManuallyDrop<T> { +impl<T: ?Sized> DerefMut for ManuallyDrop<T> { #[inline(always)] fn deref_mut(&mut self) -> &mut T { &mut self.value diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 3f491836551..d09a24b4b1d 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -945,14 +945,10 @@ impl<T> MaybeUninit<T> { // * `MaybeUninit<T>` and T are guaranteed to have the same layout // * `MaybeUninit` does not drop, so there are no double-frees // And thus the conversion is safe - let ret = unsafe { + unsafe { intrinsics::assert_inhabited::<[T; N]>(); - (&array as *const _ as *const [T; N]).read() - }; - - // FIXME: required to avoid `~const Destruct` bound - super::forget(array); - ret + intrinsics::transmute_unchecked(array) + } } /// Assuming all the elements are initialized, get a slice to them. @@ -1241,13 +1237,9 @@ impl<T> MaybeUninit<T> { /// ``` #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] { + let bytes = mem::size_of_val(this); // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes - unsafe { - slice::from_raw_parts( - this.as_ptr() as *const MaybeUninit<u8>, - this.len() * mem::size_of::<T>(), - ) - } + unsafe { slice::from_raw_parts(this.as_ptr() as *const MaybeUninit<u8>, bytes) } } /// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of @@ -1274,13 +1266,9 @@ impl<T> MaybeUninit<T> { /// ``` #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")] pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] { + let bytes = mem::size_of_val(this); // SAFETY: MaybeUninit<u8> is always valid, even for padding bytes - unsafe { - slice::from_raw_parts_mut( - this.as_mut_ptr() as *mut MaybeUninit<u8>, - this.len() * mem::size_of::<T>(), - ) - } + unsafe { slice::from_raw_parts_mut(this.as_mut_ptr() as *mut MaybeUninit<u8>, bytes) } } } @@ -1299,7 +1287,7 @@ impl<T, const N: usize> MaybeUninit<[T; N]> { #[inline] pub const fn transpose(self) -> [MaybeUninit<T>; N] { // SAFETY: T and MaybeUninit<T> have the same layout - unsafe { super::transmute_copy(&ManuallyDrop::new(self)) } + unsafe { intrinsics::transmute_unchecked(self) } } } @@ -1319,6 +1307,6 @@ impl<T, const N: usize> [MaybeUninit<T>; N] { #[inline] pub const fn transpose(self) -> MaybeUninit<[T; N]> { // SAFETY: T and MaybeUninit<T> have the same layout - unsafe { super::transmute_copy(&ManuallyDrop::new(self)) } + unsafe { intrinsics::transmute_unchecked(self) } } } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index a67df7ed557..289305253ec 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -170,7 +170,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) { /// /// The following table gives the size for primitives. /// -/// Type | size_of::\<Type>() +/// Type | `size_of::<Type>()` /// ---- | --------------- /// () | 0 /// bool | 1 @@ -190,8 +190,8 @@ pub fn forget_unsized<T: ?Sized>(t: T) { /// /// Furthermore, `usize` and `isize` have the same size. /// -/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have -/// the same size. If `T` is Sized, all of those types have the same size as `usize`. +/// The types [`*const T`], `&T`, [`Box<T>`], [`Option<&T>`], and `Option<Box<T>>` all have +/// the same size. If `T` is `Sized`, all of those types have the same size as `usize`. /// /// The mutability of a pointer does not change its size. As such, `&T` and `&mut T` /// have the same size. Likewise for `*const T` and `*mut T`. @@ -203,7 +203,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) { /// /// ## Size of Structs /// -/// For `structs`, the size is determined by the following algorithm. +/// For `struct`s, the size is determined by the following algorithm. /// /// For each field in the struct ordered by declaration order: /// @@ -299,6 +299,10 @@ pub fn forget_unsized<T: ?Sized>(t: T) { /// ``` /// /// [alignment]: align_of +/// [`*const T`]: primitive@pointer +/// [`Box<T>`]: ../../std/boxed/struct.Box.html +/// [`Option<&T>`]: crate::option::Option +/// #[inline(always)] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] @@ -311,7 +315,7 @@ pub const fn size_of<T>() -> usize { /// Returns the size of the pointed-to value in bytes. /// -/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no +/// This is usually the same as [`size_of::<T>()`]. However, when `T` *has* no /// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], /// then `size_of_val` can be used to get the dynamically-known size. /// @@ -328,6 +332,8 @@ pub const fn size_of<T>() -> usize { /// let y: &[u8] = &x; /// assert_eq!(13, mem::size_of_val(y)); /// ``` +/// +/// [`size_of::<T>()`]: size_of #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] @@ -340,7 +346,7 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize { /// Returns the size of the pointed-to value in bytes. /// -/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no +/// This is usually the same as [`size_of::<T>()`]. However, when `T` *has* no /// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], /// then `size_of_val_raw` can be used to get the dynamically-known size. /// @@ -363,6 +369,7 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize { /// [`size_of_val`] on a reference to a type with an extern type tail. /// - otherwise, it is conservatively not allowed to call this function. /// +/// [`size_of::<T>()`]: size_of /// [trait object]: ../../book/ch17-02-trait-objects.html /// [extern type]: ../../unstable-book/language-features/extern-types.html /// @@ -961,6 +968,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T { /// Integers and other types implementing [`Copy`] are unaffected by `drop`. /// /// ``` +/// # #![cfg_attr(not(bootstrap), allow(drop_copy))] /// #[derive(Copy, Clone)] /// struct Foo(u8); /// @@ -1272,3 +1280,45 @@ pub trait SizedTypeProperties: Sized { #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] impl<T> SizedTypeProperties for T {} + +/// Expands to the offset in bytes of a field from the beginning of the given type. +/// +/// Only structs, unions and tuples are supported. +/// +/// Nested field accesses may be used, but not array indexes like in `C`'s `offsetof`. +/// +/// Note that the output of this macro is not stable, except for `#[repr(C)]` types. +/// +/// # Examples +/// +/// ``` +/// #![feature(offset_of)] +/// +/// use std::mem; +/// #[repr(C)] +/// struct FieldStruct { +/// first: u8, +/// second: u16, +/// third: u8 +/// } +/// +/// assert_eq!(mem::offset_of!(FieldStruct, first), 0); +/// assert_eq!(mem::offset_of!(FieldStruct, second), 2); +/// assert_eq!(mem::offset_of!(FieldStruct, third), 4); +/// +/// #[repr(C)] +/// struct NestedA { +/// b: NestedB +/// } +/// +/// #[repr(C)] +/// struct NestedB(u8); +/// +/// assert_eq!(mem::offset_of!(NestedA, b.0), 0); +/// ``` +#[cfg(not(bootstrap))] +#[unstable(feature = "offset_of", issue = "106655")] +#[allow_internal_unstable(builtin_syntax)] +pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) { + builtin # offset_of($Container, $($fields).+) +} diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index 3b98efff293..87ae30619c6 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -5,10 +5,6 @@ /// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_trait"] -#[rustc_on_unimplemented( - message = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`.", - label = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`." -)] pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }> where Src: ?Sized, @@ -85,8 +81,7 @@ impl Assume { // FIXME(jswrenn): This const op is not actually usable. Why? // https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926 #[unstable(feature = "transmutability", issue = "99571")] -#[rustc_const_unstable(feature = "transmutability", issue = "99571")] -impl const core::ops::Add for Assume { +impl core::ops::Add for Assume { type Output = Assume; fn add(self, other_assumptions: Assume) -> Assume { @@ -97,8 +92,7 @@ impl const core::ops::Add for Assume { // FIXME(jswrenn): This const op is not actually usable. Why? // https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926 #[unstable(feature = "transmutability", issue = "99571")] -#[rustc_const_unstable(feature = "transmutability", issue = "99571")] -impl const core::ops::Sub for Assume { +impl core::ops::Sub for Assume { type Output = Assume; fn sub(self, other_assumptions: Assume) -> Assume { diff --git a/library/std/src/net/display_buffer.rs b/library/core/src/net/display_buffer.rs index 7aadf06e92f..7aadf06e92f 100644 --- a/library/std/src/net/display_buffer.rs +++ b/library/core/src/net/display_buffer.rs diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs new file mode 100644 index 00000000000..954d88d548e --- /dev/null +++ b/library/core/src/net/ip_addr.rs @@ -0,0 +1,2070 @@ +use crate::cmp::Ordering; +use crate::fmt::{self, Write}; +use crate::mem::transmute; + +use super::display_buffer::DisplayBuffer; + +/// 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(not(test), rustc_diagnostic_item = "IpAddr")] +#[stable(feature = "ip_addr", since = "1.7.0")] +#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] +pub enum IpAddr { + /// An IPv4 address. + #[stable(feature = "ip_addr", since = "1.7.0")] + V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr), + /// An IPv6 address. + #[stable(feature = "ip_addr", since = "1.7.0")] + V6(#[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`]: crate::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)] +#[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`]: crate::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)] +#[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)] +#[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ip", issue = "76205")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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 + /// ); + /// ``` + #[rustc_const_unstable(feature = "const_ip", issue = "76205")] + #[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); + /// ``` + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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"] + #[rustc_const_unstable(feature = "const_ip", issue = "76205")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] + #[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)); + /// ``` + #[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")] + #[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)); + /// ``` + #[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]); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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. + /// ``` + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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) + /// ); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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)); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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] } + } +} + +#[stable(feature = "ip_addr", since = "1.7.0")] +impl fmt::Display for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + IpAddr::V4(ip) => ip.fmt(fmt), + IpAddr::V6(ip) => ip.fmt(fmt), + } + } +} + +#[stable(feature = "ip_addr", since = "1.7.0")] +impl fmt::Debug for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[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) + } +} + +#[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) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Ipv4Addr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let octets = self.octets(); + + // If there are no alignment requirements, write the IP address directly to `f`. + // Otherwise, write it to a local buffer and then use `f.pad`. + if fmt.precision().is_none() && fmt.width().is_none() { + write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]) + } else { + const LONGEST_IPV4_ADDR: &str = "255.255.255.255"; + + let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new(); + // Buffer is long enough for the longest possible IPv4 address, so this should never fail. + write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap(); + + fmt.pad(buf.as_str()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Ipv4Addr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[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, + } + } +} + +#[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, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Ipv4Addr { + #[inline] + fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[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), + } + } +} + +#[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), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Ipv4Addr { + #[inline] + fn cmp(&self, other: &Ipv4Addr) -> Ordering { + self.octets.cmp(&other.octets) + } +} + +#[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) + } +} + +#[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() } + } +} + +#[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 } + } +} + +#[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] + #[stable(feature = "rust1", since = "1.0.0")] + #[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")] + #[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")] + #[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]); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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. + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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); + /// ``` + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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's 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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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))); + /// ``` + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] + #[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); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[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]); + /// ``` + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] + #[stable(feature = "ipv6_to_octets", since = "1.12.0")] + #[must_use] + #[inline] + pub const fn octets(&self) -> [u8; 16] { + self.octets + } +} + +/// Write an Ipv6Addr, conforming to the canonical style described by +/// [RFC 5952](https://tools.ietf.org/html/rfc5952). +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Ipv6Addr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If there are no alignment requirements, write the IP address directly to `f`. + // Otherwise, write it to a local buffer and then use `f.pad`. + if f.precision().is_none() && f.width().is_none() { + let segments = self.segments(); + + // Special case for :: and ::1; otherwise they get written with the + // IPv4 formatter + if self.is_unspecified() { + f.write_str("::") + } else if self.is_loopback() { + f.write_str("::1") + } else if let Some(ipv4) = self.to_ipv4() { + match segments[5] { + // IPv4 Compatible address + 0 => write!(f, "::{}", ipv4), + // IPv4 Mapped address + 0xffff => write!(f, "::ffff:{}", ipv4), + _ => unreachable!(), + } + } else { + #[derive(Copy, Clone, Default)] + struct Span { + start: usize, + len: usize, + } + + // Find the inner 0 span + let zeroes = { + let mut longest = Span::default(); + let mut current = Span::default(); + + for (i, &segment) in segments.iter().enumerate() { + if segment == 0 { + if current.len == 0 { + current.start = i; + } + + current.len += 1; + + if current.len > longest.len { + longest = current; + } + } else { + current = Span::default(); + } + } + + longest + }; + + /// Write a colon-separated part of the address + #[inline] + fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result { + if let Some((first, tail)) = chunk.split_first() { + write!(f, "{:x}", first)?; + for segment in tail { + f.write_char(':')?; + write!(f, "{:x}", segment)?; + } + } + Ok(()) + } + + if zeroes.len > 1 { + fmt_subslice(f, &segments[..zeroes.start])?; + f.write_str("::")?; + fmt_subslice(f, &segments[zeroes.start + zeroes.len..]) + } else { + fmt_subslice(f, &segments) + } + } + } else { + const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; + + let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new(); + // Buffer is long enough for the longest possible IPv6 address, so this should never fail. + write!(buf, "{}", self).unwrap(); + + f.pad(buf.as_str()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Ipv6Addr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[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, + } + } +} + +#[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, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Ipv6Addr { + #[inline] + fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[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), + } + } +} + +#[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), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Ipv6Addr { + #[inline] + fn cmp(&self, other: &Ipv6Addr) -> Ordering { + self.segments().cmp(&other.segments()) + } +} + +#[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) + } +} +#[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()) + } +} + +#[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 } + } +} + +#[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) + } +} + +#[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)) + } +} + +#[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/library/core/src/net/mod.rs b/library/core/src/net/mod.rs new file mode 100644 index 00000000000..31f5f5d3c22 --- /dev/null +++ b/library/core/src/net/mod.rs @@ -0,0 +1,24 @@ +//! Networking primitives for IP communication. +//! +//! This module provides types for IP and socket addresses. +//! +//! # Organization +//! +//! * [`IpAddr`] represents IP addresses of either IPv4 or IPv6; [`Ipv4Addr`] and +//! [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses +//! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`] +//! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses + +#![unstable(feature = "ip_in_core", issue = "108443")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::parser::AddrParseError; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6}; + +mod display_buffer; +mod ip_addr; +mod parser; +mod socket_addr; diff --git a/library/std/src/net/parser.rs b/library/core/src/net/parser.rs index a38031c48c8..b9a1924d668 100644 --- a/library/std/src/net/parser.rs +++ b/library/core/src/net/parser.rs @@ -3,15 +3,13 @@ //! This module is "publicly exported" through the `FromStr` implementations //! below. -#[cfg(test)] -mod tests; - +use crate::convert::TryInto; use crate::error::Error; use crate::fmt; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use crate::str::FromStr; -trait ReadNumberHelper: crate::marker::Sized { +trait ReadNumberHelper: Sized { const ZERO: Self; fn checked_mul(&self, other: u32) -> Option<Self>; fn checked_add(&self, other: u32) -> Option<Self>; diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs new file mode 100644 index 00000000000..8396aecf947 --- /dev/null +++ b/library/core/src/net/socket_addr.rs @@ -0,0 +1,691 @@ +use crate::cmp::Ordering; +use crate::fmt::{self, Write}; +use crate::hash; +use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + +use super::display_buffer::DisplayBuffer; + +/// 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)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum SocketAddr { + /// An IPv4 socket address. + #[stable(feature = "rust1", since = "1.0.0")] + V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4), + /// An IPv6 socket address. + #[stable(feature = "rust1", since = "1.0.0")] + V6(#[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)] +#[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)] +#[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); + /// ``` + #[stable(feature = "ip_addr", since = "1.7.0")] + #[must_use] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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] + #[stable(feature = "ip_addr", since = "1.7.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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))); + /// ``` + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[inline] + 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] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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); + /// ``` + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[inline] + 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] + #[stable(feature = "sockaddr_checker", since = "1.16.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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] + #[stable(feature = "sockaddr_checker", since = "1.16.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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)); + /// ``` + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[inline] + 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] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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); + /// ``` + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[inline] + 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); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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)); + /// ``` + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[inline] + 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] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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); + /// ``` + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[inline] + 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] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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); + /// ``` + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[inline] + 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] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")] + #[inline] + 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); + /// ``` + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + #[inline] + pub fn set_scope_id(&mut self, new_scope_id: u32) { + self.scope_id = new_scope_id; + } +} + +#[stable(feature = "ip_from_ip", since = "1.16.0")] +impl From<SocketAddrV4> for SocketAddr { + /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`]. + #[inline] + fn from(sock4: SocketAddrV4) -> SocketAddr { + SocketAddr::V4(sock4) + } +} + +#[stable(feature = "ip_from_ip", since = "1.16.0")] +impl From<SocketAddrV6> for SocketAddr { + /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`]. + #[inline] + fn from(sock6: SocketAddrV6) -> SocketAddr { + SocketAddr::V6(sock6) + } +} + +#[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) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + SocketAddr::V4(ref a) => a.fmt(f), + SocketAddr::V6(ref a) => a.fmt(f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV4 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If there are no alignment requirements, write the socket address directly to `f`. + // Otherwise, write it to a local buffer and then use `f.pad`. + if f.precision().is_none() && f.width().is_none() { + write!(f, "{}:{}", self.ip(), self.port()) + } else { + const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65536"; + + let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new(); + // Buffer is long enough for the longest possible IPv4 socket address, so this should never fail. + write!(buf, "{}:{}", self.ip(), self.port()).unwrap(); + + f.pad(buf.as_str()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV4 { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV6 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If there are no alignment requirements, write the socket address directly to `f`. + // Otherwise, write it to a local buffer and then use `f.pad`. + if f.precision().is_none() && f.width().is_none() { + match self.scope_id() { + 0 => write!(f, "[{}]:{}", self.ip(), self.port()), + scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()), + } + } else { + const LONGEST_IPV6_SOCKET_ADDR: &str = + "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967296]:65536"; + + let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new(); + match self.scope_id() { + 0 => write!(buf, "[{}]:{}", self.ip(), self.port()), + scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()), + } + // Buffer is long enough for the longest possible IPv6 socket address, so this should never fail. + .unwrap(); + + f.pad(buf.as_str()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV6 { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "socketaddr_ordering", since = "1.45.0")] +impl PartialOrd for SocketAddrV4 { + #[inline] + fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[stable(feature = "socketaddr_ordering", since = "1.45.0")] +impl PartialOrd for SocketAddrV6 { + #[inline] + fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[stable(feature = "socketaddr_ordering", since = "1.45.0")] +impl Ord for SocketAddrV4 { + #[inline] + fn cmp(&self, other: &SocketAddrV4) -> Ordering { + self.ip().cmp(other.ip()).then(self.port().cmp(&other.port())) + } +} + +#[stable(feature = "socketaddr_ordering", since = "1.45.0")] +impl Ord for SocketAddrV6 { + #[inline] + fn cmp(&self, other: &SocketAddrV6) -> Ordering { + self.ip().cmp(other.ip()).then(self.port().cmp(&other.port())) + } +} + +#[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) + } +} +#[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/library/core/src/num/dec2flt/common.rs b/library/core/src/num/dec2flt/common.rs index 17957d7e770..11a62648519 100644 --- a/library/core/src/num/dec2flt/common.rs +++ b/library/core/src/num/dec2flt/common.rs @@ -1,165 +1,60 @@ //! Common utilities, for internal use only. -use crate::ptr; - /// Helper methods to process immutable bytes. -pub(crate) trait ByteSlice: AsRef<[u8]> { - unsafe fn first_unchecked(&self) -> u8 { - debug_assert!(!self.is_empty()); - // SAFETY: safe as long as self is not empty - unsafe { *self.as_ref().get_unchecked(0) } - } - - /// Get if the slice contains no elements. - fn is_empty(&self) -> bool { - self.as_ref().is_empty() - } - - /// Check if the slice at least `n` length. - fn check_len(&self, n: usize) -> bool { - n <= self.as_ref().len() - } - - /// Check if the first character in the slice is equal to c. - fn first_is(&self, c: u8) -> bool { - self.as_ref().first() == Some(&c) - } - - /// Check if the first character in the slice is equal to c1 or c2. - fn first_is2(&self, c1: u8, c2: u8) -> bool { - if let Some(&c) = self.as_ref().first() { c == c1 || c == c2 } else { false } - } - - /// Bounds-checked test if the first character in the slice is a digit. - fn first_isdigit(&self) -> bool { - if let Some(&c) = self.as_ref().first() { c.is_ascii_digit() } else { false } - } - - /// Check if self starts with u with a case-insensitive comparison. - fn starts_with_ignore_case(&self, u: &[u8]) -> bool { - debug_assert!(self.as_ref().len() >= u.len()); - let iter = self.as_ref().iter().zip(u.iter()); - let d = iter.fold(0, |i, (&x, &y)| i | (x ^ y)); - d == 0 || d == 32 - } - - /// Get the remaining slice after the first N elements. - fn advance(&self, n: usize) -> &[u8] { - &self.as_ref()[n..] - } - - /// Get the slice after skipping all leading characters equal c. - fn skip_chars(&self, c: u8) -> &[u8] { - let mut s = self.as_ref(); - while s.first_is(c) { - s = s.advance(1); - } - s - } - - /// Get the slice after skipping all leading characters equal c1 or c2. - fn skip_chars2(&self, c1: u8, c2: u8) -> &[u8] { - let mut s = self.as_ref(); - while s.first_is2(c1, c2) { - s = s.advance(1); - } - s - } - +pub(crate) trait ByteSlice { /// Read 8 bytes as a 64-bit integer in little-endian order. - unsafe fn read_u64_unchecked(&self) -> u64 { - debug_assert!(self.check_len(8)); - let src = self.as_ref().as_ptr() as *const u64; - // SAFETY: safe as long as self is at least 8 bytes - u64::from_le(unsafe { ptr::read_unaligned(src) }) - } + fn read_u64(&self) -> u64; - /// Try to read the next 8 bytes from the slice. - fn read_u64(&self) -> Option<u64> { - if self.check_len(8) { - // SAFETY: self must be at least 8 bytes. - Some(unsafe { self.read_u64_unchecked() }) - } else { - None - } - } - - /// Calculate the offset of slice from another. - fn offset_from(&self, other: &Self) -> isize { - other.as_ref().len() as isize - self.as_ref().len() as isize - } -} - -impl ByteSlice for [u8] {} - -/// Helper methods to process mutable bytes. -pub(crate) trait ByteSliceMut: AsMut<[u8]> { /// Write a 64-bit integer as 8 bytes in little-endian order. - unsafe fn write_u64_unchecked(&mut self, value: u64) { - debug_assert!(self.as_mut().len() >= 8); - let dst = self.as_mut().as_mut_ptr() as *mut u64; - // NOTE: we must use `write_unaligned`, since dst is not - // guaranteed to be properly aligned. Miri will warn us - // if we use `write` instead of `write_unaligned`, as expected. - // SAFETY: safe as long as self is at least 8 bytes - unsafe { - ptr::write_unaligned(dst, u64::to_le(value)); - } - } -} + fn write_u64(&mut self, value: u64); -impl ByteSliceMut for [u8] {} + /// Calculate the offset of a slice from another. + fn offset_from(&self, other: &Self) -> isize; -/// Bytes wrapper with specialized methods for ASCII characters. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub(crate) struct AsciiStr<'a> { - slc: &'a [u8], + /// Iteratively parse and consume digits from bytes. + /// Returns the same bytes with consumed digits being + /// elided. + fn parse_digits(&self, func: impl FnMut(u8)) -> &Self; } -impl<'a> AsciiStr<'a> { - pub fn new(slc: &'a [u8]) -> Self { - Self { slc } +impl ByteSlice for [u8] { + #[inline(always)] // inlining this is crucial to remove bound checks + fn read_u64(&self) -> u64 { + let mut tmp = [0; 8]; + tmp.copy_from_slice(&self[..8]); + u64::from_le_bytes(tmp) } - /// Advance the view by n, advancing it in-place to (n..). - pub unsafe fn step_by(&mut self, n: usize) -> &mut Self { - // SAFETY: safe as long n is less than the buffer length - self.slc = unsafe { self.slc.get_unchecked(n..) }; - self + #[inline(always)] // inlining this is crucial to remove bound checks + fn write_u64(&mut self, value: u64) { + self[..8].copy_from_slice(&value.to_le_bytes()) } - /// Advance the view by n, advancing it in-place to (1..). - pub unsafe fn step(&mut self) -> &mut Self { - // SAFETY: safe as long as self is not empty - unsafe { self.step_by(1) } + #[inline] + fn offset_from(&self, other: &Self) -> isize { + other.len() as isize - self.len() as isize } - /// Iteratively parse and consume digits from bytes. - pub fn parse_digits(&mut self, mut func: impl FnMut(u8)) { - while let Some(&c) = self.as_ref().first() { + #[inline] + fn parse_digits(&self, mut func: impl FnMut(u8)) -> &Self { + let mut s = self; + + // FIXME: Can't use s.split_first() here yet, + // see https://github.com/rust-lang/rust/issues/109328 + while let [c, s_next @ ..] = s { let c = c.wrapping_sub(b'0'); if c < 10 { func(c); - // SAFETY: self cannot be empty - unsafe { - self.step(); - } + s = s_next; } else { break; } } - } -} -impl<'a> AsRef<[u8]> for AsciiStr<'a> { - #[inline] - fn as_ref(&self) -> &[u8] { - self.slc + s } } -impl<'a> ByteSlice for AsciiStr<'a> {} - /// Determine if 8 bytes are all decimal digits. /// This does not care about the order in which the bytes were loaded. pub(crate) fn is_8digits(v: u64) -> bool { @@ -168,19 +63,6 @@ pub(crate) fn is_8digits(v: u64) -> bool { (a | b) & 0x8080_8080_8080_8080 == 0 } -/// Iteratively parse and consume digits from bytes. -pub(crate) fn parse_digits(s: &mut &[u8], mut f: impl FnMut(u8)) { - while let Some(&c) = s.get(0) { - let c = c.wrapping_sub(b'0'); - if c < 10 { - f(c); - *s = s.advance(1); - } else { - break; - } - } -} - /// A custom 64-bit floating point type, representing `f * 2^e`. /// e is biased, so it be directly shifted into the exponent bits. #[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] @@ -192,6 +74,7 @@ pub struct BiasedFp { } impl BiasedFp { + #[inline] pub const fn zero_pow2(e: i32) -> Self { Self { f: 0, e } } diff --git a/library/core/src/num/dec2flt/decimal.rs b/library/core/src/num/dec2flt/decimal.rs index 2019f71e69b..350f64bb4f7 100644 --- a/library/core/src/num/dec2flt/decimal.rs +++ b/library/core/src/num/dec2flt/decimal.rs @@ -9,7 +9,7 @@ //! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion", //! available online: <https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html>. -use crate::num::dec2flt::common::{is_8digits, parse_digits, ByteSlice, ByteSliceMut}; +use crate::num::dec2flt::common::{is_8digits, ByteSlice}; #[derive(Clone)] pub struct Decimal { @@ -205,29 +205,32 @@ impl Decimal { pub fn parse_decimal(mut s: &[u8]) -> Decimal { let mut d = Decimal::default(); let start = s; - s = s.skip_chars(b'0'); - parse_digits(&mut s, |digit| d.try_add_digit(digit)); - if s.first_is(b'.') { - s = s.advance(1); + + while let Some((&b'0', s_next)) = s.split_first() { + s = s_next; + } + + s = s.parse_digits(|digit| d.try_add_digit(digit)); + + if let Some((b'.', s_next)) = s.split_first() { + s = s_next; let first = s; // Skip leading zeros. if d.num_digits == 0 { - s = s.skip_chars(b'0'); + while let Some((&b'0', s_next)) = s.split_first() { + s = s_next; + } } while s.len() >= 8 && d.num_digits + 8 < Decimal::MAX_DIGITS { - // SAFETY: s is at least 8 bytes. - let v = unsafe { s.read_u64_unchecked() }; + let v = s.read_u64(); if !is_8digits(v) { break; } - // SAFETY: d.num_digits + 8 is less than d.digits.len() - unsafe { - d.digits[d.num_digits..].write_u64_unchecked(v - 0x3030_3030_3030_3030); - } + d.digits[d.num_digits..].write_u64(v - 0x3030_3030_3030_3030); d.num_digits += 8; - s = s.advance(8); + s = &s[8..]; } - parse_digits(&mut s, |digit| d.try_add_digit(digit)); + s = s.parse_digits(|digit| d.try_add_digit(digit)); d.decimal_point = s.len() as i32 - first.len() as i32; } if d.num_digits != 0 { @@ -248,22 +251,26 @@ pub fn parse_decimal(mut s: &[u8]) -> Decimal { d.num_digits = Decimal::MAX_DIGITS; } } - if s.first_is2(b'e', b'E') { - s = s.advance(1); - let mut neg_exp = false; - if s.first_is(b'-') { - neg_exp = true; - s = s.advance(1); - } else if s.first_is(b'+') { - s = s.advance(1); - } - let mut exp_num = 0_i32; - parse_digits(&mut s, |digit| { - if exp_num < 0x10000 { - exp_num = 10 * exp_num + digit as i32; + if let Some((&ch, s_next)) = s.split_first() { + if ch == b'e' || ch == b'E' { + s = s_next; + let mut neg_exp = false; + if let Some((&ch, s_next)) = s.split_first() { + neg_exp = ch == b'-'; + if ch == b'-' || ch == b'+' { + s = s_next; + } } - }); - d.decimal_point += if neg_exp { -exp_num } else { exp_num }; + let mut exp_num = 0_i32; + + s.parse_digits(|digit| { + if exp_num < 0x10000 { + exp_num = 10 * exp_num + digit as i32; + } + }); + + d.decimal_point += if neg_exp { -exp_num } else { exp_num }; + } } for i in d.num_digits..Decimal::MAX_DIGITS_WITHOUT_OVERFLOW { d.digits[i] = 0; diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs index 5921c5ed472..1c9d68999d6 100644 --- a/library/core/src/num/dec2flt/float.rs +++ b/library/core/src/num/dec2flt/float.rs @@ -118,11 +118,13 @@ impl RawFloat for f32 { const SMALLEST_POWER_OF_TEN: i32 = -65; const LARGEST_POWER_OF_TEN: i32 = 38; + #[inline] fn from_u64(v: u64) -> Self { debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH); v as _ } + #[inline] fn from_u64_bits(v: u64) -> Self { f32::from_bits((v & 0xFFFFFFFF) as u32) } @@ -169,11 +171,13 @@ impl RawFloat for f64 { const SMALLEST_POWER_OF_TEN: i32 = -342; const LARGEST_POWER_OF_TEN: i32 = 308; + #[inline] fn from_u64(v: u64) -> Self { debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH); v as _ } + #[inline] fn from_u64_bits(v: u64) -> Self { f64::from_bits(v) } diff --git a/library/core/src/num/dec2flt/lemire.rs b/library/core/src/num/dec2flt/lemire.rs index 9f7594460a1..3bc052df7a6 100644 --- a/library/core/src/num/dec2flt/lemire.rs +++ b/library/core/src/num/dec2flt/lemire.rs @@ -118,10 +118,12 @@ pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp { /// This uses a pre-computed integer approximation for /// log2(10), where 217706 / 2^16 is accurate for the /// entire range of non-finite decimal exponents. +#[inline] fn power(q: i32) -> i32 { (q.wrapping_mul(152_170 + 65536) >> 16) + 63 } +#[inline] fn full_multiplication(a: u64, b: u64) -> (u64, u64) { let r = (a as u128) * (b as u128); (r as u64, (r >> 64) as u64) diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index f8d493e8b62..a4bc8b1c9b0 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -79,7 +79,7 @@ use crate::error::Error; use crate::fmt; use crate::str::FromStr; -use self::common::{BiasedFp, ByteSlice}; +use self::common::BiasedFp; use self::float::RawFloat; use self::lemire::compute_float; use self::parse::{parse_inf_nan, parse_number}; @@ -147,7 +147,13 @@ macro_rules! from_str_float_impl { /// representable floating-point number to the number represented /// by `src` (following the same rules for rounding as for the /// results of primitive operations). - #[inline] + // We add the `#[inline(never)]` attribute, since its content will + // be filled with that of `dec2flt`, which has #[inline(always)]. + // Since `dec2flt` is generic, a normal inline attribute on this function + // with `dec2flt` having no attributes results in heavily repeated + // generation of `dec2flt`, despite the fact only a maximum of 2 + // possible instances can ever exist. Adding #[inline(never)] avoids this. + #[inline(never)] fn from_str(src: &str) -> Result<Self, ParseFloatError> { dec2flt(src) } @@ -202,12 +208,14 @@ impl fmt::Display for ParseFloatError { } } +#[inline] pub(super) fn pfe_empty() -> ParseFloatError { ParseFloatError { kind: FloatErrorKind::Empty } } // Used in unit tests, keep public. // This is much better than making FloatErrorKind and ParseFloatError::kind public. +#[inline] pub fn pfe_invalid() -> ParseFloatError { ParseFloatError { kind: FloatErrorKind::Invalid } } @@ -220,6 +228,7 @@ fn biased_fp_to_float<T: RawFloat>(x: BiasedFp) -> T { } /// Converts a decimal string into a floating point number. +#[inline(always)] // Will be inlined into a function with `#[inline(never)]`, see above pub fn dec2flt<F: RawFloat>(s: &str) -> Result<F, ParseFloatError> { let mut s = s.as_bytes(); let c = if let Some(&c) = s.first() { @@ -229,17 +238,18 @@ pub fn dec2flt<F: RawFloat>(s: &str) -> Result<F, ParseFloatError> { }; let negative = c == b'-'; if c == b'-' || c == b'+' { - s = s.advance(1); + s = &s[1..]; } if s.is_empty() { return Err(pfe_invalid()); } - let num = match parse_number(s, negative) { + let mut num = match parse_number(s) { Some(r) => r, None if let Some(value) = parse_inf_nan(s, negative) => return Ok(value), None => return Err(pfe_invalid()), }; + num.negative = negative; if let Some(value) = num.try_fast_path::<F>() { return Ok(value); } diff --git a/library/core/src/num/dec2flt/number.rs b/library/core/src/num/dec2flt/number.rs index 405f7e7b613..8589e2bbd4f 100644 --- a/library/core/src/num/dec2flt/number.rs +++ b/library/core/src/num/dec2flt/number.rs @@ -33,6 +33,7 @@ pub struct Number { impl Number { /// Detect if the float can be accurately reconstructed from native floats. + #[inline] fn is_fast_path<F: RawFloat>(&self) -> bool { F::MIN_EXPONENT_FAST_PATH <= self.exponent && self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH diff --git a/library/core/src/num/dec2flt/parse.rs b/library/core/src/num/dec2flt/parse.rs index 1a90e0d206f..b0a23835c5b 100644 --- a/library/core/src/num/dec2flt/parse.rs +++ b/library/core/src/num/dec2flt/parse.rs @@ -1,6 +1,6 @@ //! Functions to parse floating-point numbers. -use crate::num::dec2flt::common::{is_8digits, AsciiStr, ByteSlice}; +use crate::num::dec2flt::common::{is_8digits, ByteSlice}; use crate::num::dec2flt::float::RawFloat; use crate::num::dec2flt::number::Number; @@ -26,24 +26,39 @@ fn parse_8digits(mut v: u64) -> u64 { } /// Parse digits until a non-digit character is found. -fn try_parse_digits(s: &mut AsciiStr<'_>, x: &mut u64) { +fn try_parse_digits(mut s: &[u8], mut x: u64) -> (&[u8], u64) { // may cause overflows, to be handled later - s.parse_digits(|digit| { - *x = x.wrapping_mul(10).wrapping_add(digit as _); + + while s.len() >= 8 { + let num = s.read_u64(); + if is_8digits(num) { + x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(num)); + s = &s[8..]; + } else { + break; + } + } + + s = s.parse_digits(|digit| { + x = x.wrapping_mul(10).wrapping_add(digit as _); }); + + (s, x) } /// Parse up to 19 digits (the max that can be stored in a 64-bit integer). -fn try_parse_19digits(s: &mut AsciiStr<'_>, x: &mut u64) { +fn try_parse_19digits(s_ref: &mut &[u8], x: &mut u64) { + let mut s = *s_ref; + while *x < MIN_19DIGIT_INT { - if let Some(&c) = s.as_ref().first() { + // FIXME: Can't use s.split_first() here yet, + // see https://github.com/rust-lang/rust/issues/109328 + if let [c, s_next @ ..] = s { let digit = c.wrapping_sub(b'0'); + if digit < 10 { *x = (*x * 10) + digit as u64; // no overflows here - // SAFETY: cannot be empty - unsafe { - s.step(); - } + s = s_next; } else { break; } @@ -51,46 +66,26 @@ fn try_parse_19digits(s: &mut AsciiStr<'_>, x: &mut u64) { break; } } -} -/// Try to parse 8 digits at a time, using an optimized algorithm. -fn try_parse_8digits(s: &mut AsciiStr<'_>, x: &mut u64) { - // may cause overflows, to be handled later - if let Some(v) = s.read_u64() { - if is_8digits(v) { - *x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(v)); - // SAFETY: already ensured the buffer was >= 8 bytes in read_u64. - unsafe { - s.step_by(8); - } - if let Some(v) = s.read_u64() { - if is_8digits(v) { - *x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(v)); - // SAFETY: already ensured the buffer was >= 8 bytes in try_read_u64. - unsafe { - s.step_by(8); - } - } - } - } - } + *s_ref = s; } /// Parse the scientific notation component of a float. -fn parse_scientific(s: &mut AsciiStr<'_>) -> Option<i64> { - let mut exponent = 0_i64; +fn parse_scientific(s_ref: &mut &[u8]) -> Option<i64> { + let mut exponent = 0i64; let mut negative = false; - if let Some(&c) = s.as_ref().get(0) { + + let mut s = *s_ref; + + if let Some((&c, s_next)) = s.split_first() { negative = c == b'-'; if c == b'-' || c == b'+' { - // SAFETY: s cannot be empty - unsafe { - s.step(); - } + s = s_next; } } - if s.first_isdigit() { - s.parse_digits(|digit| { + + if matches!(s.first(), Some(&x) if x.is_ascii_digit()) { + *s_ref = s.parse_digits(|digit| { // no overflows here, saturate well before overflow if exponent < 0x10000 { exponent = 10 * exponent + digit as i64; @@ -98,6 +93,7 @@ fn parse_scientific(s: &mut AsciiStr<'_>) -> Option<i64> { }); if negative { Some(-exponent) } else { Some(exponent) } } else { + *s_ref = s; None } } @@ -106,28 +102,29 @@ fn parse_scientific(s: &mut AsciiStr<'_>) -> Option<i64> { /// /// This creates a representation of the float as the /// significant digits and the decimal exponent. -fn parse_partial_number(s: &[u8], negative: bool) -> Option<(Number, usize)> { - let mut s = AsciiStr::new(s); - let start = s; +fn parse_partial_number(mut s: &[u8]) -> Option<(Number, usize)> { debug_assert!(!s.is_empty()); // parse initial digits before dot let mut mantissa = 0_u64; - let digits_start = s; - try_parse_digits(&mut s, &mut mantissa); - let mut n_digits = s.offset_from(&digits_start); + let start = s; + let tmp = try_parse_digits(s, mantissa); + s = tmp.0; + mantissa = tmp.1; + let mut n_digits = s.offset_from(start); // handle dot with the following digits let mut n_after_dot = 0; let mut exponent = 0_i64; let int_end = s; - if s.first_is(b'.') { - // SAFETY: s cannot be empty due to first_is - unsafe { s.step() }; + + if let Some((&b'.', s_next)) = s.split_first() { + s = s_next; let before = s; - try_parse_8digits(&mut s, &mut mantissa); - try_parse_digits(&mut s, &mut mantissa); - n_after_dot = s.offset_from(&before); + let tmp = try_parse_digits(s, mantissa); + s = tmp.0; + mantissa = tmp.1; + n_after_dot = s.offset_from(before); exponent = -n_after_dot as i64; } @@ -138,65 +135,60 @@ fn parse_partial_number(s: &[u8], negative: bool) -> Option<(Number, usize)> { // handle scientific format let mut exp_number = 0_i64; - if s.first_is2(b'e', b'E') { - // SAFETY: s cannot be empty - unsafe { - s.step(); + if let Some((&c, s_next)) = s.split_first() { + if c == b'e' || c == b'E' { + s = s_next; + // If None, we have no trailing digits after exponent, or an invalid float. + exp_number = parse_scientific(&mut s)?; + exponent += exp_number; } - // If None, we have no trailing digits after exponent, or an invalid float. - exp_number = parse_scientific(&mut s)?; - exponent += exp_number; } - let len = s.offset_from(&start) as _; + let len = s.offset_from(start) as _; // handle uncommon case with many digits if n_digits <= 19 { - return Some((Number { exponent, mantissa, negative, many_digits: false }, len)); + return Some((Number { exponent, mantissa, negative: false, many_digits: false }, len)); } n_digits -= 19; let mut many_digits = false; - let mut p = digits_start; - while p.first_is2(b'0', b'.') { - // SAFETY: p cannot be empty due to first_is2 - unsafe { - // '0' = b'.' + 2 - n_digits -= p.first_unchecked().saturating_sub(b'0' - 1) as isize; - p.step(); + let mut p = start; + while let Some((&c, p_next)) = p.split_first() { + if c == b'.' || c == b'0' { + n_digits -= c.saturating_sub(b'0' - 1) as isize; + p = p_next; + } else { + break; } } if n_digits > 0 { // at this point we have more than 19 significant digits, let's try again many_digits = true; mantissa = 0; - let mut s = digits_start; + let mut s = start; try_parse_19digits(&mut s, &mut mantissa); exponent = if mantissa >= MIN_19DIGIT_INT { // big int - int_end.offset_from(&s) + int_end.offset_from(s) } else { - // SAFETY: the next byte must be present and be '.' - // We know this is true because we had more than 19 - // digits previously, so we overflowed a 64-bit integer, - // but parsing only the integral digits produced less - // than 19 digits. That means we must have a decimal - // point, and at least 1 fractional digit. - unsafe { s.step() }; + s = &s[1..]; let before = s; try_parse_19digits(&mut s, &mut mantissa); - -s.offset_from(&before) + -s.offset_from(before) } as i64; // add back the explicit part exponent += exp_number; } - Some((Number { exponent, mantissa, negative, many_digits }, len)) + Some((Number { exponent, mantissa, negative: false, many_digits }, len)) } -/// Try to parse a non-special floating point number. -pub fn parse_number(s: &[u8], negative: bool) -> Option<Number> { - if let Some((float, rest)) = parse_partial_number(s, negative) { +/// Try to parse a non-special floating point number, +/// as well as two slices with integer and fractional parts +/// and the parsed exponent. +pub fn parse_number(s: &[u8]) -> Option<Number> { + if let Some((float, rest)) = parse_partial_number(s) { if rest == s.len() { return Some(float); } @@ -204,30 +196,48 @@ pub fn parse_number(s: &[u8], negative: bool) -> Option<Number> { None } -/// Parse a partial representation of a special, non-finite float. -fn parse_partial_inf_nan<F: RawFloat>(s: &[u8]) -> Option<(F, usize)> { - fn parse_inf_rest(s: &[u8]) -> usize { - if s.len() >= 8 && s[3..].as_ref().starts_with_ignore_case(b"inity") { 8 } else { 3 } - } - if s.len() >= 3 { - if s.starts_with_ignore_case(b"nan") { - return Some((F::NAN, 3)); - } else if s.starts_with_ignore_case(b"inf") { - return Some((F::INFINITY, parse_inf_rest(s))); - } - } - None -} - /// Try to parse a special, non-finite float. -pub fn parse_inf_nan<F: RawFloat>(s: &[u8], negative: bool) -> Option<F> { - if let Some((mut float, rest)) = parse_partial_inf_nan::<F>(s) { - if rest == s.len() { - if negative { - float = -float; - } - return Some(float); - } +pub(crate) fn parse_inf_nan<F: RawFloat>(s: &[u8], negative: bool) -> Option<F> { + // Since a valid string has at most the length 8, we can load + // all relevant characters into a u64 and work from there. + // This also generates much better code. + + let mut register; + let len: usize; + + // All valid strings are either of length 8 or 3. + if s.len() == 8 { + register = s.read_u64(); + len = 8; + } else if s.len() == 3 { + let a = s[0] as u64; + let b = s[1] as u64; + let c = s[2] as u64; + register = (c << 16) | (b << 8) | a; + len = 3; + } else { + return None; } - None + + // Clear out the bits which turn ASCII uppercase characters into + // lowercase characters. The resulting string is all uppercase. + // What happens to other characters is irrelevant. + register &= 0xDFDFDFDFDFDFDFDF; + + // u64 values corresponding to relevant cases + const INF_3: u64 = 0x464E49; // "INF" + const INF_8: u64 = 0x5954494E49464E49; // "INFINITY" + const NAN: u64 = 0x4E414E; // "NAN" + + // Match register value to constant to parse string. + // Also match on the string length to catch edge cases + // like "inf\0\0\0\0\0". + let float = match (register, len) { + (INF_3, 3) => F::INFINITY, + (INF_8, 8) => F::INFINITY, + (NAN, 3) => F::NAN, + _ => return None, + }; + + if negative { Some(-float) } else { Some(float) } } diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index 1bae4efe7d9..14e99578a7c 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -26,15 +26,15 @@ impl Error for TryFromIntError { } #[stable(feature = "try_from", since = "1.34.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl const From<Infallible> for TryFromIntError { +impl From<Infallible> for TryFromIntError { fn from(x: Infallible) -> TryFromIntError { match x {} } } #[unstable(feature = "never_type", issue = "35121")] -impl const From<!> for TryFromIntError { +impl From<!> for TryFromIntError { + #[inline] fn from(never: !) -> TryFromIntError { // Match rather than coerce to make sure that code like // `From<Infallible> for TryFromIntError` above will keep working diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 1308b0770b8..4a035ad61e1 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -940,6 +940,42 @@ impl f32 { } } + /// Calculates the middle point of `self` and `rhs`. + /// + /// This returns NaN when *either* argument is NaN or if a combination of + /// +inf and -inf is provided as arguments. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + /// assert_eq!(1f32.midpoint(4.0), 2.5); + /// assert_eq!((-5.5f32).midpoint(8.0), 1.25); + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + pub fn midpoint(self, other: f32) -> f32 { + const LO: f32 = f32::MIN_POSITIVE * 2.; + const HI: f32 = f32::MAX / 2.; + + let (a, b) = (self, other); + let abs_a = a.abs_private(); + let abs_b = b.abs_private(); + + if abs_a <= HI && abs_b <= HI { + // Overflow is impossible + (a + b) / 2. + } else if abs_a < LO { + // Not safe to halve a + a + (b / 2.) + } else if abs_b < LO { + // Not safe to halve b + (a / 2.) + b + } else { + // Not safe to halve a and b + (a / 2.) + (b / 2.) + } + } + /// Rounds toward zero and converts to any primitive integer type, /// assuming that the value is finite and fits in that type. /// @@ -1391,7 +1427,7 @@ impl f32 { #[stable(feature = "clamp", since = "1.50.0")] #[inline] pub fn clamp(mut self, min: f32, max: f32) -> f32 { - assert!(min <= max); + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); if self < min { self = min; } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 2a22c4302b9..3aafc435f1e 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -951,6 +951,42 @@ impl f64 { } } + /// Calculates the middle point of `self` and `rhs`. + /// + /// This returns NaN when *either* argument is NaN or if a combination of + /// +inf and -inf is provided as arguments. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + /// assert_eq!(1f64.midpoint(4.0), 2.5); + /// assert_eq!((-5.5f64).midpoint(8.0), 1.25); + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + pub fn midpoint(self, other: f64) -> f64 { + const LO: f64 = f64::MIN_POSITIVE * 2.; + const HI: f64 = f64::MAX / 2.; + + let (a, b) = (self, other); + let abs_a = a.abs_private(); + let abs_b = b.abs_private(); + + if abs_a <= HI && abs_b <= HI { + // Overflow is impossible + (a + b) / 2. + } else if abs_a < LO { + // Not safe to halve a + a + (b / 2.) + } else if abs_b < LO { + // Not safe to halve b + (a / 2.) + b + } else { + // Not safe to halve a and b + (a / 2.) + (b / 2.) + } + } + /// Rounds toward zero and converts to any primitive integer type, /// assuming that the value is finite and fits in that type. /// @@ -1389,7 +1425,7 @@ impl f64 { #[stable(feature = "clamp", since = "1.50.0")] #[inline] pub fn clamp(mut self, min: f64, max: f64) -> f64 { - assert!(min <= max); + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); if self < min { self = min; } diff --git a/library/core/src/num/flt2dec/strategy/grisu.rs b/library/core/src/num/flt2dec/strategy/grisu.rs index ed3e0edaff2..b9f0d114c6a 100644 --- a/library/core/src/num/flt2dec/strategy/grisu.rs +++ b/library/core/src/num/flt2dec/strategy/grisu.rs @@ -487,6 +487,22 @@ pub fn format_exact_opt<'a>( let vint = (v.f >> e) as u32; let vfrac = v.f & ((1 << e) - 1); + let requested_digits = buf.len(); + + const POW10_UP_TO_9: [u32; 10] = + [1, 10, 100, 1000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000]; + + // We deviate from the original algorithm here and do some early checks to determine if we can satisfy requested_digits. + // If we determine that we can't, we exit early and avoid most of the heavy lifting that the algorithm otherwise does. + // + // When vfrac is zero, we can easily determine if vint can satisfy requested digits: + // If requested_digits >= 11, vint is not able to exhaust the count by itself since 10^(11 -1) > u32 max value >= vint. + // If vint < 10^(requested_digits - 1), vint cannot exhaust the count. + // Otherwise, vint might be able to exhaust the count and we need to execute the rest of the code. + if (vfrac == 0) && ((requested_digits >= 11) || (vint < POW10_UP_TO_9[requested_digits - 1])) { + return None; + } + // both old `v` and new `v` (scaled by `10^-k`) has an error of < 1 ulp (Theorem 5.1). // as we don't know the error is positive or negative, we use two approximations // spaced equally and have the maximal error of 2 ulps (same to the shortest case). diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 479f8ffb78d..1199d09b563 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1,9 +1,29 @@ macro_rules! int_impl { - ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $BITS_MINUS_ONE:expr, $Min:expr, $Max:expr, - $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, - $reversed:expr, $le_bytes:expr, $be_bytes:expr, - $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr, - $bound_condition:expr) => { + ( + Self = $SelfT:ty, + ActualT = $ActualT:ident, + UnsignedT = $UnsignedT:ty, + + // There are all for use *only* in doc comments. + // As such, they're all passed as literals -- passing them as a string + // literal is fine if they need to be multiple code tokens. + // In non-comments, use the associated constants rather than these. + BITS = $BITS:literal, + BITS_MINUS_ONE = $BITS_MINUS_ONE:literal, + Min = $Min:literal, + Max = $Max:literal, + rot = $rot:literal, + rot_op = $rot_op:literal, + rot_result = $rot_result:literal, + swap_op = $swap_op:literal, + swapped = $swapped:literal, + reversed = $reversed:literal, + le_bytes = $le_bytes:literal, + be_bytes = $be_bytes:literal, + to_xe_bytes_doc = $to_xe_bytes_doc:expr, + from_xe_bytes_doc = $from_xe_bytes_doc:expr, + bound_condition = $bound_condition:literal, + ) => { /// The smallest value that can be represented by this integer type #[doc = concat!("(−2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ").")] /// @@ -15,7 +35,7 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")] /// ``` #[stable(feature = "assoc_int_consts", since = "1.43.0")] - pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self; + pub const MIN: Self = !Self::MAX; /// The largest value that can be represented by this integer type #[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> − 1", $bound_condition, ").")] @@ -28,7 +48,7 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")] /// ``` #[stable(feature = "assoc_int_consts", since = "1.43.0")] - pub const MAX: Self = !Self::MIN; + pub const MAX: Self = (<$UnsignedT>::MAX >> 1) as Self; /// The size of this integer type in bits. /// @@ -38,7 +58,7 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")] /// ``` #[stable(feature = "int_bits_const", since = "1.53.0")] - pub const BITS: u32 = $BITS; + pub const BITS: u32 = <$UnsignedT>::BITS; /// Converts a string slice in a given base to an integer. /// @@ -765,7 +785,7 @@ macro_rules! int_impl { // SAFETY: the caller must uphold the safety contract for // `unchecked_shl`. // Any legal shift amount is losslessly representable in the self type. - unsafe { intrinsics::unchecked_shl(self, rhs.try_into().ok().unwrap_unchecked()) } + unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } } /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is @@ -813,7 +833,7 @@ macro_rules! int_impl { // SAFETY: the caller must uphold the safety contract for // `unchecked_shr`. // Any legal shift amount is losslessly representable in the self type. - unsafe { intrinsics::unchecked_shr(self, rhs.try_into().ok().unwrap_unchecked()) } + unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } } /// Checked absolute value. Computes `self.abs()`, returning `None` if @@ -1365,7 +1385,7 @@ macro_rules! int_impl { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds unsafe { - self.unchecked_shl(rhs & ($BITS - 1)) + self.unchecked_shl(rhs & (Self::BITS - 1)) } } @@ -1395,7 +1415,7 @@ macro_rules! int_impl { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds unsafe { - self.unchecked_shr(rhs & ($BITS - 1)) + self.unchecked_shr(rhs & (Self::BITS - 1)) } } @@ -1901,7 +1921,7 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) + (self.wrapping_shl(rhs), rhs >= Self::BITS) } /// Shifts self right by `rhs` bits. @@ -1924,7 +1944,7 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) + (self.wrapping_shr(rhs), rhs >= Self::BITS) } /// Computes the absolute value of `self`. @@ -2312,6 +2332,44 @@ macro_rules! int_impl { } } + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards negative infinity and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-1), -1);")] + #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(0), -1);")] + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] + #[rustc_allow_const_fn_unstable(const_num_midpoint)] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: Self) -> Self { + const U: $UnsignedT = <$SelfT>::MIN.unsigned_abs(); + + // Map an $SelfT to an $UnsignedT + // ex: i8 [-128; 127] to [0; 255] + const fn map(a: $SelfT) -> $UnsignedT { + (a as $UnsignedT) ^ U + } + + // Map an $UnsignedT to an $SelfT + // ex: u8 [0; 255] to [-128; 127] + const fn demap(a: $UnsignedT) -> $SelfT { + (a ^ U) as $SelfT + } + + demap(<$UnsignedT>::midpoint(map(self), map(rhs))) + } + /// Returns the logarithm of the number with respect to an arbitrary base, /// rounded down. /// @@ -2583,13 +2641,16 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[rustc_allow_const_fn_unstable(const_cmp)] pub const fn signum(self) -> Self { // Picking the right way to phrase this is complicated // (<https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign>) // so delegate it to `Ord` which is already producing -1/0/+1 // exactly like we need and can be the place to deal with the complexity. - self.cmp(&0) as _ + + // FIXME(const-hack): replace with cmp + if self < 0 { -1 } + else if self == 0 { 0 } + else { 1 } } /// Returns `true` if `self` is positive and `false` if the number is zero or diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 0497416745f..c9baa09f407 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -95,6 +95,57 @@ depending on the target pointer size. }; } +macro_rules! midpoint_impl { + ($SelfT:ty, unsigned) => { + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards negative infinity and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: $SelfT) -> $SelfT { + // Use the well known branchless algorthim from Hacker's Delight to compute + // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`. + ((self ^ rhs) >> 1) + (self & rhs) + } + }; + ($SelfT:ty, $WideT:ty, unsigned) => { + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards negative infinity and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: $SelfT) -> $SelfT { + ((self as $WideT + rhs as $WideT) / 2) as $SelfT + } + }; +} + macro_rules! widening_impl { ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => { /// Calculates the complete product `self * rhs` without the possibility to overflow. @@ -225,74 +276,237 @@ macro_rules! widening_impl { }; } +macro_rules! conv_rhs_for_unchecked_shift { + ($SelfT:ty, $x:expr) => {{ + #[inline] + fn conv(x: u32) -> $SelfT { + // FIXME(const-hack) replace with `.try_into().ok().unwrap_unchecked()`. + // SAFETY: Any legal shift amount must be losslessly representable in the self type. + unsafe { x.try_into().ok().unwrap_unchecked() } + } + #[inline] + const fn const_conv(x: u32) -> $SelfT { + x as _ + } + + intrinsics::const_eval_select(($x,), const_conv, conv) + }}; +} + impl i8 { - int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", - "[0x12]", "[0x12]", "", "", "" } + int_impl! { + Self = i8, + ActualT = i8, + UnsignedT = u8, + BITS = 8, + BITS_MINUS_ONE = 7, + Min = -128, + Max = 127, + rot = 2, + rot_op = "-0x7e", + rot_result = "0xa", + swap_op = "0x12", + swapped = "0x12", + reversed = "0x48", + le_bytes = "[0x12]", + be_bytes = "[0x12]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } } impl i16 { - int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", - "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "", "" } + int_impl! { + Self = i16, + ActualT = i16, + UnsignedT = u16, + BITS = 16, + BITS_MINUS_ONE = 15, + Min = -32768, + Max = 32767, + rot = 4, + rot_op = "-0x5ffd", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", + le_bytes = "[0x34, 0x12]", + be_bytes = "[0x12, 0x34]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } } impl i32 { - int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", - "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78]", "", "", "" } + int_impl! { + Self = i32, + ActualT = i32, + UnsignedT = u32, + BITS = 32, + BITS_MINUS_ONE = 31, + Min = -2147483648, + Max = 2147483647, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", + le_bytes = "[0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } } impl i64 { - int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12, - "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", - "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "", "" } + int_impl! { + Self = i64, + ActualT = i64, + UnsignedT = u64, + BITS = 64, + BITS_MINUS_ONE = 63, + Min = -9223372036854775808, + Max = 9223372036854775807, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", + le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } } impl i128 { - int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728, - 170141183460469231731687303715884105727, 16, - "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", - "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", - "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ - 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "", "" } + int_impl! { + Self = i128, + ActualT = i128, + UnsignedT = u128, + BITS = 128, + BITS_MINUS_ONE = 127, + Min = -170141183460469231731687303715884105728, + Max = 170141183460469231731687303715884105727, + rot = 16, + rot_op = "0x13f40000000000000000000000004f76", + rot_result = "0x4f7613f4", + swap_op = "0x12345678901234567890123456789012", + swapped = "0x12907856341290785634129078563412", + reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", + le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ + 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } } #[cfg(target_pointer_width = "16")] impl isize { - int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", - "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(), - " on 16-bit targets" } + int_impl! { + Self = isize, + ActualT = i16, + UnsignedT = usize, + BITS = 16, + BITS_MINUS_ONE = 15, + Min = -32768, + Max = 32767, + rot = 4, + rot_op = "-0x5ffd", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", + le_bytes = "[0x34, 0x12]", + be_bytes = "[0x12, 0x34]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 16-bit targets", + } } #[cfg(target_pointer_width = "32")] impl isize { - int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", - "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(), - " on 32-bit targets" } + int_impl! { + Self = isize, + ActualT = i32, + UnsignedT = usize, + BITS = 32, + BITS_MINUS_ONE = 31, + Min = -2147483648, + Max = 2147483647, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", + le_bytes = "[0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 32-bit targets", + } } #[cfg(target_pointer_width = "64")] impl isize { - int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807, - 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", - "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(), - " on 64-bit targets" } + int_impl! { + Self = isize, + ActualT = i64, + UnsignedT = usize, + BITS = 64, + BITS_MINUS_ONE = 63, + Min = -9223372036854775808, + Max = 9223372036854775807, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", + le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 64-bit targets", + } } -/// If 6th bit set ascii is upper case. +/// If 6th bit is set ascii is lower case. const ASCII_CASE_MASK: u8 = 0b0010_0000; impl u8 { - uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", - "[0x12]", "", "", "" } + uint_impl! { + Self = u8, + ActualT = u8, + SignedT = i8, + NonZeroT = NonZeroU8, + BITS = 8, + MAX = 255, + rot = 2, + rot_op = "0x82", + rot_result = "0xa", + swap_op = "0x12", + swapped = "0x12", + reversed = "0x48", + le_bytes = "[0x12]", + be_bytes = "[0x12]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } widening_impl! { u8, u16, 8, unsigned } + midpoint_impl! { u8, u16, unsigned } /// Checks if the value is within the ASCII range. /// @@ -310,7 +524,16 @@ impl u8 { #[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")] #[inline] pub const fn is_ascii(&self) -> bool { - *self & 128 == 0 + *self <= 127 + } + + /// If the value of this byte is within the ASCII range, returns it as an + /// [ASCII character](ascii::Char). Otherwise, returns `None`. + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn as_ascii(&self) -> Option<ascii::Char> { + ascii::Char::from_u8(*self) } /// Makes a copy of the value in its ASCII upper case equivalent. @@ -875,9 +1098,27 @@ impl u8 { } impl u16 { - uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", - "[0x34, 0x12]", "[0x12, 0x34]", "", "", "" } + uint_impl! { + Self = u16, + ActualT = u16, + SignedT = i16, + NonZeroT = NonZeroU16, + BITS = 16, + MAX = 65535, + rot = 4, + rot_op = "0xa003", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", + le_bytes = "[0x34, 0x12]", + be_bytes = "[0x12, 0x34]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } widening_impl! { u16, u32, 16, unsigned } + midpoint_impl! { u16, u32, unsigned } /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`]. /// @@ -906,57 +1147,151 @@ impl u16 { } impl u32 { - uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", - "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "", "" } + uint_impl! { + Self = u32, + ActualT = u32, + SignedT = i32, + NonZeroT = NonZeroU32, + BITS = 32, + MAX = 4294967295, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", + le_bytes = "[0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } widening_impl! { u32, u64, 32, unsigned } + midpoint_impl! { u32, u64, unsigned } } impl u64 { - uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", - "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", - "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", - "", "", ""} + uint_impl! { + Self = u64, + ActualT = u64, + SignedT = i64, + NonZeroT = NonZeroU64, + BITS = 64, + MAX = 18446744073709551615, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", + le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } widening_impl! { u64, u128, 64, unsigned } + midpoint_impl! { u64, u128, unsigned } } impl u128 { - uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16, - "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", - "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", - "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ - 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", - "", "", ""} + uint_impl! { + Self = u128, + ActualT = u128, + SignedT = i128, + NonZeroT = NonZeroU128, + BITS = 128, + MAX = 340282366920938463463374607431768211455, + rot = 16, + rot_op = "0x13f40000000000000000000000004f76", + rot_result = "0x4f7613f4", + swap_op = "0x12345678901234567890123456789012", + swapped = "0x12907856341290785634129078563412", + reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", + le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ + 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + to_xe_bytes_doc = "", + from_xe_bytes_doc = "", + bound_condition = "", + } + midpoint_impl! { u128, unsigned } } #[cfg(target_pointer_width = "16")] impl usize { - uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", - "[0x34, 0x12]", "[0x12, 0x34]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(), - " on 16-bit targets" } + uint_impl! { + Self = usize, + ActualT = u16, + SignedT = isize, + NonZeroT = NonZeroUsize, + BITS = 16, + MAX = 65535, + rot = 4, + rot_op = "0xa003", + rot_result = "0x3a", + swap_op = "0x1234", + swapped = "0x3412", + reversed = "0x2c48", + le_bytes = "[0x34, 0x12]", + be_bytes = "[0x12, 0x34]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 16-bit targets", + } widening_impl! { usize, u32, 16, unsigned } + midpoint_impl! { usize, u32, unsigned } } + #[cfg(target_pointer_width = "32")] impl usize { - uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", - "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(), - " on 32-bit targets" } + uint_impl! { + Self = usize, + ActualT = u32, + SignedT = isize, + NonZeroT = NonZeroUsize, + BITS = 32, + MAX = 4294967295, + rot = 8, + rot_op = "0x10000b3", + rot_result = "0xb301", + swap_op = "0x12345678", + swapped = "0x78563412", + reversed = "0x1e6a2c48", + le_bytes = "[0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 32-bit targets", + } widening_impl! { usize, u64, 32, unsigned } + midpoint_impl! { usize, u64, unsigned } } #[cfg(target_pointer_width = "64")] impl usize { - uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", - "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", - "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(), - " on 64-bit targets" } + uint_impl! { + Self = usize, + ActualT = u64, + SignedT = isize, + NonZeroT = NonZeroUsize, + BITS = 64, + MAX = 18446744073709551615, + rot = 12, + rot_op = "0xaa00000000006e1", + rot_result = "0x6e10aa", + swap_op = "0x1234567890123456", + swapped = "0x5634129078563412", + reversed = "0x6a2c48091e6a2c48", + le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(), + from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(), + bound_condition = " on 64-bit targets", + } widening_impl! { usize, u128, 64, unsigned } + midpoint_impl! { usize, u128, unsigned } } impl usize { diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index fbda8f82b1b..6a3b9c5287a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1,7 +1,7 @@ //! Definitions of integer that is known not to equal zero. use crate::fmt; -use crate::ops::{BitOr, BitOrAssign, Div, Rem}; +use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem}; use crate::str::FromStr; use super::from_str_radix; @@ -34,6 +34,13 @@ macro_rules! nonzero_integers { /// use std::mem::size_of; #[doc = concat!("assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int), ">());")] /// ``` + /// + /// # Layout + /// + #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] + /// with the exception that `0` is not a valid instance. + #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] + /// including in FFI. #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] @@ -89,8 +96,7 @@ macro_rules! nonzero_integers { } #[stable(feature = "from_nonzero", since = "1.31.0")] - #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] - impl const From<$Ty> for $Int { + impl From<$Ty> for $Int { #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] #[inline] fn from(nonzero: $Ty) -> Self { @@ -99,8 +105,7 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOr for $Ty { + impl BitOr for $Ty { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self::Output { @@ -111,8 +116,7 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOr<$Int> for $Ty { + impl BitOr<$Int> for $Ty { type Output = Self; #[inline] fn bitor(self, rhs: $Int) -> Self::Output { @@ -124,8 +128,7 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOr<$Ty> for $Int { + impl BitOr<$Ty> for $Int { type Output = $Ty; #[inline] fn bitor(self, rhs: $Ty) -> Self::Output { @@ -137,8 +140,7 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOrAssign for $Ty { + impl BitOrAssign for $Ty { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = *self | rhs; @@ -146,8 +148,7 @@ macro_rules! nonzero_integers { } #[stable(feature = "nonzero_bitor", since = "1.45.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOrAssign<$Int> for $Ty { + impl BitOrAssign<$Int> for $Ty { #[inline] fn bitor_assign(&mut self, rhs: $Int) { *self = *self | rhs; @@ -269,8 +270,7 @@ macro_rules! nonzero_integers_div { ( $( $Ty: ident($Int: ty); )+ ) => { $( #[stable(feature = "nonzero_div", since = "1.51.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Div<$Ty> for $Int { + impl Div<$Ty> for $Int { type Output = $Int; /// This operation rounds towards zero, /// truncating any fractional part of the exact result, and cannot panic. @@ -283,8 +283,7 @@ macro_rules! nonzero_integers_div { } #[stable(feature = "nonzero_div", since = "1.51.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Rem<$Ty> for $Int { + impl Rem<$Ty> for $Int { type Output = $Int; /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. #[inline] @@ -494,6 +493,43 @@ macro_rules! nonzero_unsigned_operations { pub const fn ilog10(self) -> u32 { super::int_log10::$Int(self.0) } + + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards negative infinity and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + /// + /// assert_eq!(one.midpoint(four), two); + /// assert_eq!(four.midpoint(one), two); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] + #[rustc_allow_const_fn_unstable(const_num_midpoint)] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: Self) -> Self { + // SAFETY: The only way to get `0` with midpoint is to have two opposite or + // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because + // of the unsignedness of this number and also because $Ty is guaranteed to + // never being 0. + unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } + } } )+ } @@ -665,8 +701,7 @@ macro_rules! nonzero_signed_operations { /// assert_eq!(pos, pos.wrapping_abs()); /// assert_eq!(pos, neg.wrapping_abs()); /// assert_eq!(min, min.wrapping_abs()); - /// # // FIXME: add once Neg is implemented? - /// # // assert_eq!(max, (-max).wrapping_abs()); + /// assert_eq!(max, (-max).wrapping_abs()); /// # Some(()) /// # } /// ``` @@ -715,6 +750,32 @@ macro_rules! nonzero_signed_operations { unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } } + /// Returns `true` if `self` is positive and `false` if the + /// number is negative. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(pos_five.is_positive()); + /// assert!(!neg_five.is_positive()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] + pub const fn is_positive(self) -> bool { + self.get().is_positive() + } + /// Returns `true` if `self` is negative and `false` if the /// number is positive. /// @@ -869,6 +930,20 @@ macro_rules! nonzero_signed_operations { unsafe { $Ty::new_unchecked(result) } } } + + #[stable(feature = "signed_nonzero_neg", since = "CURRENT_RUSTC_VERSION")] + impl Neg for $Ty { + type Output = $Ty; + + #[inline] + fn neg(self) -> $Ty { + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().neg()) } + } + } + + forward_ref_unop! { impl Neg, neg for $Ty, + #[stable(feature = "signed_nonzero_neg", since = "CURRENT_RUSTC_VERSION")] } )+ } } @@ -1147,12 +1222,10 @@ macro_rules! nonzero_min_max_unsigned { /// # Examples /// /// ``` - /// #![feature(nonzero_min_max)] - /// #[doc = concat!("# use std::num::", stringify!($Ty), ";")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")] /// ``` - #[unstable(feature = "nonzero_min_max", issue = "89065")] + #[stable(feature = "nonzero_min_max", since = "1.70.0")] pub const MIN: Self = Self::new(1).unwrap(); /// The largest value that can be represented by this non-zero @@ -1162,12 +1235,10 @@ macro_rules! nonzero_min_max_unsigned { /// # Examples /// /// ``` - /// #![feature(nonzero_min_max)] - /// #[doc = concat!("# use std::num::", stringify!($Ty), ";")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] /// ``` - #[unstable(feature = "nonzero_min_max", issue = "89065")] + #[stable(feature = "nonzero_min_max", since = "1.70.0")] pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); } )+ @@ -1189,12 +1260,10 @@ macro_rules! nonzero_min_max_signed { /// # Examples /// /// ``` - /// #![feature(nonzero_min_max)] - /// #[doc = concat!("# use std::num::", stringify!($Ty), ";")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")] /// ``` - #[unstable(feature = "nonzero_min_max", issue = "89065")] + #[stable(feature = "nonzero_min_max", since = "1.70.0")] pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); /// The largest value that can be represented by this non-zero @@ -1208,12 +1277,10 @@ macro_rules! nonzero_min_max_signed { /// # Examples /// /// ``` - /// #![feature(nonzero_min_max)] - /// #[doc = concat!("# use std::num::", stringify!($Ty), ";")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] /// ``` - #[unstable(feature = "nonzero_min_max", issue = "89065")] + #[stable(feature = "nonzero_min_max", since = "1.70.0")] pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); } )+ diff --git a/library/core/src/num/shells/u16.rs b/library/core/src/num/shells/u16.rs index b203806f460..7394977e507 100644 --- a/library/core/src/num/shells/u16.rs +++ b/library/core/src/num/shells/u16.rs @@ -1,4 +1,4 @@ -//! Redundant constants module for the [`i16` primitive type][i16]. +//! Redundant constants module for the [`u16` primitive type][u16]. //! //! New code should use the associated constants directly on the primitive type. diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 495c44bd859..6f6b6dbb80b 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1,10 +1,28 @@ macro_rules! uint_impl { - ($SelfT:ty, $ActualT:ident, $SignedT:ident, $NonZeroT:ident, - $BITS:expr, $MaxV:expr, - $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, - $reversed:expr, $le_bytes:expr, $be_bytes:expr, - $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr, - $bound_condition:expr) => { + ( + Self = $SelfT:ty, + ActualT = $ActualT:ident, + SignedT = $SignedT:ident, + NonZeroT = $NonZeroT:ident, + + // There are all for use *only* in doc comments. + // As such, they're all passed as literals -- passing them as a string + // literal is fine if they need to be multiple code tokens. + // In non-comments, use the associated constants rather than these. + BITS = $BITS:literal, + MAX = $MaxV:literal, + rot = $rot:literal, + rot_op = $rot_op:literal, + rot_result = $rot_result:literal, + swap_op = $swap_op:literal, + swapped = $swapped:literal, + reversed = $reversed:literal, + le_bytes = $le_bytes:literal, + be_bytes = $be_bytes:literal, + to_xe_bytes_doc = $to_xe_bytes_doc:expr, + from_xe_bytes_doc = $from_xe_bytes_doc:expr, + bound_condition = $bound_condition:literal, + ) => { /// The smallest value that can be represented by this integer type. /// /// # Examples @@ -38,7 +56,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")] /// ``` #[stable(feature = "int_bits_const", since = "1.53.0")] - pub const BITS: u32 = $BITS; + pub const BITS: u32 = Self::MAX.count_ones(); /// Converts a string slice in a given base to an integer. /// @@ -921,7 +939,7 @@ macro_rules! uint_impl { // SAFETY: the caller must uphold the safety contract for // `unchecked_shl`. // Any legal shift amount is losslessly representable in the self type. - unsafe { intrinsics::unchecked_shl(self, rhs.try_into().ok().unwrap_unchecked()) } + unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } } /// Checked shift right. Computes `self >> rhs`, returning `None` @@ -969,7 +987,7 @@ macro_rules! uint_impl { // SAFETY: the caller must uphold the safety contract for // `unchecked_shr`. // Any legal shift amount is losslessly representable in the self type. - unsafe { intrinsics::unchecked_shr(self, rhs.try_into().ok().unwrap_unchecked()) } + unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } } /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if @@ -1345,12 +1363,11 @@ macro_rules! uint_impl { /// /// Basic usage: /// - /// Please note that this example is shared between integer types. - /// Which explains why `i8` is used here. - /// /// ``` - /// assert_eq!(100i8.wrapping_neg(), -100); - /// assert_eq!((-128i8).wrapping_neg(), -128); + #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".wrapping_neg(), 0);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_neg(), 1);")] + #[doc = concat!("assert_eq!(13_", stringify!($SelfT), ".wrapping_neg(), (!13) + 1);")] + #[doc = concat!("assert_eq!(42_", stringify!($SelfT), ".wrapping_neg(), !(42 - 1));")] /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] @@ -1390,7 +1407,7 @@ macro_rules! uint_impl { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds unsafe { - self.unchecked_shl(rhs & ($BITS - 1)) + self.unchecked_shl(rhs & (Self::BITS - 1)) } } @@ -1423,7 +1440,7 @@ macro_rules! uint_impl { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds unsafe { - self.unchecked_shr(rhs & ($BITS - 1)) + self.unchecked_shr(rhs & (Self::BITS - 1)) } } @@ -1847,7 +1864,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline(always)] pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) + (self.wrapping_shl(rhs), rhs >= Self::BITS) } /// Shifts self right by `rhs` bits. @@ -1872,7 +1889,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline(always)] pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) + (self.wrapping_shr(rhs), rhs >= Self::BITS) } /// Raises self to the power of `exp`, using exponentiation by squaring. diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs index 5353d900e76..ed354a2e50b 100644 --- a/library/core/src/num/wrapping.rs +++ b/library/core/src/num/wrapping.rs @@ -87,8 +87,7 @@ impl<T: fmt::UpperHex> fmt::UpperHex for Wrapping<T> { macro_rules! sh_impl_signed { ($t:ident, $f:ident) => { #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Shl<$f> for Wrapping<$t> { + impl Shl<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -100,22 +99,20 @@ macro_rules! sh_impl_signed { } } } - forward_ref_binop! { impl const Shl, shl for Wrapping<$t>, $f, + forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const ShlAssign<$f> for Wrapping<$t> { + impl ShlAssign<$f> for Wrapping<$t> { #[inline] fn shl_assign(&mut self, other: $f) { *self = *self << other; } } - forward_ref_op_assign! { impl const ShlAssign, shl_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Shr<$f> for Wrapping<$t> { + impl Shr<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -127,26 +124,24 @@ macro_rules! sh_impl_signed { } } } - forward_ref_binop! { impl const Shr, shr for Wrapping<$t>, $f, + forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const ShrAssign<$f> for Wrapping<$t> { + impl ShrAssign<$f> for Wrapping<$t> { #[inline] fn shr_assign(&mut self, other: $f) { *self = *self >> other; } } - forward_ref_op_assign! { impl const ShrAssign, shr_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } }; } macro_rules! sh_impl_unsigned { ($t:ident, $f:ident) => { #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Shl<$f> for Wrapping<$t> { + impl Shl<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -154,22 +149,20 @@ macro_rules! sh_impl_unsigned { Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32)) } } - forward_ref_binop! { impl const Shl, shl for Wrapping<$t>, $f, + forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const ShlAssign<$f> for Wrapping<$t> { + impl ShlAssign<$f> for Wrapping<$t> { #[inline] fn shl_assign(&mut self, other: $f) { *self = *self << other; } } - forward_ref_op_assign! { impl const ShlAssign, shl_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Shr<$f> for Wrapping<$t> { + impl Shr<$f> for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -177,18 +170,17 @@ macro_rules! sh_impl_unsigned { Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32)) } } - forward_ref_binop! { impl const Shr, shr for Wrapping<$t>, $f, + forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const ShrAssign<$f> for Wrapping<$t> { + impl ShrAssign<$f> for Wrapping<$t> { #[inline] fn shr_assign(&mut self, other: $f) { *self = *self >> other; } } - forward_ref_op_assign! { impl const ShrAssign, shr_assign for Wrapping<$t>, $f } + forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } }; } @@ -217,8 +209,7 @@ sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } macro_rules! wrapping_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Add for Wrapping<$t> { + impl Add for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -226,32 +217,29 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_add(other.0)) } } - forward_ref_binop! { impl const Add, add for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const AddAssign for Wrapping<$t> { + impl AddAssign for Wrapping<$t> { #[inline] fn add_assign(&mut self, other: Wrapping<$t>) { *self = *self + other; } } - forward_ref_op_assign! { impl const AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const AddAssign<$t> for Wrapping<$t> { + impl AddAssign<$t> for Wrapping<$t> { #[inline] fn add_assign(&mut self, other: $t) { *self = *self + Wrapping(other); } } - forward_ref_op_assign! { impl const AddAssign, add_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, $t } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Sub for Wrapping<$t> { + impl Sub for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -259,32 +247,29 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_sub(other.0)) } } - forward_ref_binop! { impl const Sub, sub for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const SubAssign for Wrapping<$t> { + impl SubAssign for Wrapping<$t> { #[inline] fn sub_assign(&mut self, other: Wrapping<$t>) { *self = *self - other; } } - forward_ref_op_assign! { impl const SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const SubAssign<$t> for Wrapping<$t> { + impl SubAssign<$t> for Wrapping<$t> { #[inline] fn sub_assign(&mut self, other: $t) { *self = *self - Wrapping(other); } } - forward_ref_op_assign! { impl const SubAssign, sub_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, $t } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Mul for Wrapping<$t> { + impl Mul for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -296,28 +281,25 @@ macro_rules! wrapping_impl { #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const MulAssign for Wrapping<$t> { + impl MulAssign for Wrapping<$t> { #[inline] fn mul_assign(&mut self, other: Wrapping<$t>) { *self = *self * other; } } - forward_ref_op_assign! { impl const MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const MulAssign<$t> for Wrapping<$t> { + impl MulAssign<$t> for Wrapping<$t> { #[inline] fn mul_assign(&mut self, other: $t) { *self = *self * Wrapping(other); } } - forward_ref_op_assign! { impl const MulAssign, mul_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, $t } #[stable(feature = "wrapping_div", since = "1.3.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Div for Wrapping<$t> { + impl Div for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -325,32 +307,29 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_div(other.0)) } } - forward_ref_binop! { impl const Div, div for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const DivAssign for Wrapping<$t> { + impl DivAssign for Wrapping<$t> { #[inline] fn div_assign(&mut self, other: Wrapping<$t>) { *self = *self / other; } } - forward_ref_op_assign! { impl const DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const DivAssign<$t> for Wrapping<$t> { + impl DivAssign<$t> for Wrapping<$t> { #[inline] fn div_assign(&mut self, other: $t) { *self = *self / Wrapping(other); } } - forward_ref_op_assign! { impl const DivAssign, div_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, $t } #[stable(feature = "wrapping_impls", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Rem for Wrapping<$t> { + impl Rem for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -358,32 +337,29 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_rem(other.0)) } } - forward_ref_binop! { impl const Rem, rem for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const RemAssign for Wrapping<$t> { + impl RemAssign for Wrapping<$t> { #[inline] fn rem_assign(&mut self, other: Wrapping<$t>) { *self = *self % other; } } - forward_ref_op_assign! { impl const RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const RemAssign<$t> for Wrapping<$t> { + impl RemAssign<$t> for Wrapping<$t> { #[inline] fn rem_assign(&mut self, other: $t) { *self = *self % Wrapping(other); } } - forward_ref_op_assign! { impl const RemAssign, rem_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, $t } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Not for Wrapping<$t> { + impl Not for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -391,12 +367,11 @@ macro_rules! wrapping_impl { Wrapping(!self.0) } } - forward_ref_unop! { impl const Not, not for Wrapping<$t>, + forward_ref_unop! { impl Not, not for Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitXor for Wrapping<$t> { + impl BitXor for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -404,32 +379,29 @@ macro_rules! wrapping_impl { Wrapping(self.0 ^ other.0) } } - forward_ref_binop! { impl const BitXor, bitxor for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitXorAssign for Wrapping<$t> { + impl BitXorAssign for Wrapping<$t> { #[inline] fn bitxor_assign(&mut self, other: Wrapping<$t>) { *self = *self ^ other; } } - forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitXorAssign<$t> for Wrapping<$t> { + impl BitXorAssign<$t> for Wrapping<$t> { #[inline] fn bitxor_assign(&mut self, other: $t) { *self = *self ^ Wrapping(other); } } - forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, $t } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOr for Wrapping<$t> { + impl BitOr for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -437,32 +409,29 @@ macro_rules! wrapping_impl { Wrapping(self.0 | other.0) } } - forward_ref_binop! { impl const BitOr, bitor for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOrAssign for Wrapping<$t> { + impl BitOrAssign for Wrapping<$t> { #[inline] fn bitor_assign(&mut self, other: Wrapping<$t>) { *self = *self | other; } } - forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOrAssign<$t> for Wrapping<$t> { + impl BitOrAssign<$t> for Wrapping<$t> { #[inline] fn bitor_assign(&mut self, other: $t) { *self = *self | Wrapping(other); } } - forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, $t } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitAnd for Wrapping<$t> { + impl BitAnd for Wrapping<$t> { type Output = Wrapping<$t>; #[inline] @@ -470,39 +439,36 @@ macro_rules! wrapping_impl { Wrapping(self.0 & other.0) } } - forward_ref_binop! { impl const BitAnd, bitand for Wrapping<$t>, Wrapping<$t>, + forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitAndAssign for Wrapping<$t> { + impl BitAndAssign for Wrapping<$t> { #[inline] fn bitand_assign(&mut self, other: Wrapping<$t>) { *self = *self & other; } } - forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "wrapping_int_assign_impl", since = "1.60.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitAndAssign<$t> for Wrapping<$t> { + impl BitAndAssign<$t> for Wrapping<$t> { #[inline] fn bitand_assign(&mut self, other: $t) { *self = *self & Wrapping(other); } } - forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for Wrapping<$t>, $t } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, $t } #[stable(feature = "wrapping_neg", since = "1.10.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Neg for Wrapping<$t> { + impl Neg for Wrapping<$t> { type Output = Self; #[inline] fn neg(self) -> Self { Wrapping(0) - self } } - forward_ref_unop! { impl const Neg, neg for Wrapping<$t>, + forward_ref_unop! { impl Neg, neg for Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } )*) diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 0c7ee9630c6..840c8cd2fe8 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -73,7 +73,6 @@ append_const_msg )] #[doc(alias = "+")] -#[const_trait] pub trait Add<Rhs = Self> { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -95,8 +94,7 @@ pub trait Add<Rhs = Self> { macro_rules! add_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Add for $t { + impl Add for $t { type Output = $t; #[inline] @@ -104,7 +102,7 @@ macro_rules! add_impl { fn add(self, other: $t) -> $t { self + other } } - forward_ref_binop! { impl const Add, add for $t, $t } + forward_ref_binop! { impl Add, add for $t, $t } )*) } @@ -183,7 +181,6 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } append_const_msg )] #[doc(alias = "-")] -#[const_trait] pub trait Sub<Rhs = Self> { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -205,8 +202,7 @@ pub trait Sub<Rhs = Self> { macro_rules! sub_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Sub for $t { + impl Sub for $t { type Output = $t; #[inline] @@ -214,7 +210,7 @@ macro_rules! sub_impl { fn sub(self, other: $t) -> $t { self - other } } - forward_ref_binop! { impl const Sub, sub for $t, $t } + forward_ref_binop! { impl Sub, sub for $t, $t } )*) } @@ -314,7 +310,6 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } label = "no implementation for `{Self} * {Rhs}`" )] #[doc(alias = "*")] -#[const_trait] pub trait Mul<Rhs = Self> { /// The resulting type after applying the `*` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -336,8 +331,7 @@ pub trait Mul<Rhs = Self> { macro_rules! mul_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Mul for $t { + impl Mul for $t { type Output = $t; #[inline] @@ -345,7 +339,7 @@ macro_rules! mul_impl { fn mul(self, other: $t) -> $t { self * other } } - forward_ref_binop! { impl const Mul, mul for $t, $t } + forward_ref_binop! { impl Mul, mul for $t, $t } )*) } @@ -449,7 +443,6 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } label = "no implementation for `{Self} / {Rhs}`" )] #[doc(alias = "/")] -#[const_trait] pub trait Div<Rhs = Self> { /// The resulting type after applying the `/` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -477,15 +470,14 @@ macro_rules! div_impl_integer { /// #[doc = $panic] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Div for $t { + impl Div for $t { type Output = $t; #[inline] fn div(self, other: $t) -> $t { self / other } } - forward_ref_binop! { impl const Div, div for $t, $t } + forward_ref_binop! { impl Div, div for $t, $t } )*)*) } @@ -497,15 +489,14 @@ div_impl_integer! { macro_rules! div_impl_float { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Div for $t { + impl Div for $t { type Output = $t; #[inline] fn div(self, other: $t) -> $t { self / other } } - forward_ref_binop! { impl const Div, div for $t, $t } + forward_ref_binop! { impl Div, div for $t, $t } )*) } @@ -526,7 +517,7 @@ div_impl_float! { f32 f64 } /// use std::ops::Rem; /// /// #[derive(PartialEq, Debug)] -/// struct SplitSlice<'a, T: 'a> { +/// struct SplitSlice<'a, T> { /// slice: &'a [T], /// } /// @@ -553,7 +544,6 @@ div_impl_float! { f32 f64 } label = "no implementation for `{Self} % {Rhs}`" )] #[doc(alias = "%")] -#[const_trait] pub trait Rem<Rhs = Self> { /// The resulting type after applying the `%` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -581,15 +571,14 @@ macro_rules! rem_impl_integer { /// #[doc = $panic] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Rem for $t { + impl Rem for $t { type Output = $t; #[inline] fn rem(self, other: $t) -> $t { self % other } } - forward_ref_binop! { impl const Rem, rem for $t, $t } + forward_ref_binop! { impl Rem, rem for $t, $t } )*)*) } @@ -616,15 +605,14 @@ macro_rules! rem_impl_float { /// assert_eq!(x % y, remainder); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Rem for $t { + impl Rem for $t { type Output = $t; #[inline] fn rem(self, other: $t) -> $t { self % other } } - forward_ref_binop! { impl const Rem, rem for $t, $t } + forward_ref_binop! { impl Rem, rem for $t, $t } )*) } @@ -669,7 +657,6 @@ rem_impl_float! { f32 f64 } #[lang = "neg"] #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "-")] -#[const_trait] pub trait Neg { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -692,8 +679,7 @@ pub trait Neg { macro_rules! neg_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Neg for $t { + impl Neg for $t { type Output = $t; #[inline] @@ -701,7 +687,7 @@ macro_rules! neg_impl { fn neg(self) -> $t { -self } } - forward_ref_unop! { impl const Neg, neg for $t } + forward_ref_unop! { impl Neg, neg for $t } )*) } @@ -744,7 +730,6 @@ neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "+")] #[doc(alias = "+=")] -#[const_trait] pub trait AddAssign<Rhs = Self> { /// Performs the `+=` operation. /// @@ -762,14 +747,13 @@ pub trait AddAssign<Rhs = Self> { macro_rules! add_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const AddAssign for $t { + impl AddAssign for $t { #[inline] #[rustc_inherit_overflow_checks] fn add_assign(&mut self, other: $t) { *self += other } } - forward_ref_op_assign! { impl const AddAssign, add_assign for $t, $t } + forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t } )+) } @@ -812,7 +796,6 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "-")] #[doc(alias = "-=")] -#[const_trait] pub trait SubAssign<Rhs = Self> { /// Performs the `-=` operation. /// @@ -830,14 +813,13 @@ pub trait SubAssign<Rhs = Self> { macro_rules! sub_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const SubAssign for $t { + impl SubAssign for $t { #[inline] #[rustc_inherit_overflow_checks] fn sub_assign(&mut self, other: $t) { *self -= other } } - forward_ref_op_assign! { impl const SubAssign, sub_assign for $t, $t } + forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t } )+) } @@ -871,7 +853,6 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "*")] #[doc(alias = "*=")] -#[const_trait] pub trait MulAssign<Rhs = Self> { /// Performs the `*=` operation. /// @@ -889,14 +870,13 @@ pub trait MulAssign<Rhs = Self> { macro_rules! mul_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const MulAssign for $t { + impl MulAssign for $t { #[inline] #[rustc_inherit_overflow_checks] fn mul_assign(&mut self, other: $t) { *self *= other } } - forward_ref_op_assign! { impl const MulAssign, mul_assign for $t, $t } + forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t } )+) } @@ -930,7 +910,6 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "/")] #[doc(alias = "/=")] -#[const_trait] pub trait DivAssign<Rhs = Self> { /// Performs the `/=` operation. /// @@ -948,13 +927,12 @@ pub trait DivAssign<Rhs = Self> { macro_rules! div_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const DivAssign for $t { + impl DivAssign for $t { #[inline] fn div_assign(&mut self, other: $t) { *self /= other } } - forward_ref_op_assign! { impl const DivAssign, div_assign for $t, $t } + forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t } )+) } @@ -992,7 +970,6 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } )] #[doc(alias = "%")] #[doc(alias = "%=")] -#[const_trait] pub trait RemAssign<Rhs = Self> { /// Performs the `%=` operation. /// @@ -1010,13 +987,12 @@ pub trait RemAssign<Rhs = Self> { macro_rules! rem_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const RemAssign for $t { + impl RemAssign for $t { #[inline] fn rem_assign(&mut self, other: $t) { *self %= other } } - forward_ref_op_assign! { impl const RemAssign, rem_assign for $t, $t } + forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t } )+) } diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index 327009801d1..c70f4a3da2e 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -31,7 +31,6 @@ #[lang = "not"] #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "!")] -#[const_trait] pub trait Not { /// The resulting type after applying the `!` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -55,23 +54,21 @@ pub trait Not { macro_rules! not_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Not for $t { + impl Not for $t { type Output = $t; #[inline] fn not(self) -> $t { !self } } - forward_ref_unop! { impl const Not, not for $t } + forward_ref_unop! { impl Not, not for $t } )*) } not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[stable(feature = "not_never", since = "1.60.0")] -#[rustc_const_unstable(feature = "const_ops", issue = "90080")] -impl const Not for ! { +impl Not for ! { type Output = !; #[inline] @@ -144,7 +141,6 @@ impl const Not for ! { message = "no implementation for `{Self} & {Rhs}`", label = "no implementation for `{Self} & {Rhs}`" )] -#[const_trait] pub trait BitAnd<Rhs = Self> { /// The resulting type after applying the `&` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -168,15 +164,14 @@ pub trait BitAnd<Rhs = Self> { macro_rules! bitand_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitAnd for $t { + impl BitAnd for $t { type Output = $t; #[inline] fn bitand(self, rhs: $t) -> $t { self & rhs } } - forward_ref_binop! { impl const BitAnd, bitand for $t, $t } + forward_ref_binop! { impl BitAnd, bitand for $t, $t } )*) } @@ -246,7 +241,6 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} | {Rhs}`", label = "no implementation for `{Self} | {Rhs}`" )] -#[const_trait] pub trait BitOr<Rhs = Self> { /// The resulting type after applying the `|` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -270,15 +264,14 @@ pub trait BitOr<Rhs = Self> { macro_rules! bitor_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOr for $t { + impl BitOr for $t { type Output = $t; #[inline] fn bitor(self, rhs: $t) -> $t { self | rhs } } - forward_ref_binop! { impl const BitOr, bitor for $t, $t } + forward_ref_binop! { impl BitOr, bitor for $t, $t } )*) } @@ -348,7 +341,6 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} ^ {Rhs}`", label = "no implementation for `{Self} ^ {Rhs}`" )] -#[const_trait] pub trait BitXor<Rhs = Self> { /// The resulting type after applying the `^` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -372,15 +364,14 @@ pub trait BitXor<Rhs = Self> { macro_rules! bitxor_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitXor for $t { + impl BitXor for $t { type Output = $t; #[inline] fn bitxor(self, other: $t) -> $t { self ^ other } } - forward_ref_binop! { impl const BitXor, bitxor for $t, $t } + forward_ref_binop! { impl BitXor, bitxor for $t, $t } )*) } @@ -449,7 +440,6 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} << {Rhs}`", label = "no implementation for `{Self} << {Rhs}`" )] -#[const_trait] pub trait Shl<Rhs = Self> { /// The resulting type after applying the `<<` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -471,8 +461,7 @@ pub trait Shl<Rhs = Self> { macro_rules! shl_impl { ($t:ty, $f:ty) => { #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Shl<$f> for $t { + impl Shl<$f> for $t { type Output = $t; #[inline] @@ -482,7 +471,7 @@ macro_rules! shl_impl { } } - forward_ref_binop! { impl const Shl, shl for $t, $f } + forward_ref_binop! { impl Shl, shl for $t, $f } }; } @@ -569,7 +558,6 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } message = "no implementation for `{Self} >> {Rhs}`", label = "no implementation for `{Self} >> {Rhs}`" )] -#[const_trait] pub trait Shr<Rhs = Self> { /// The resulting type after applying the `>>` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -591,8 +579,7 @@ pub trait Shr<Rhs = Self> { macro_rules! shr_impl { ($t:ty, $f:ty) => { #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const Shr<$f> for $t { + impl Shr<$f> for $t { type Output = $t; #[inline] @@ -602,7 +589,7 @@ macro_rules! shr_impl { } } - forward_ref_binop! { impl const Shr, shr for $t, $f } + forward_ref_binop! { impl Shr, shr for $t, $f } }; } @@ -698,7 +685,6 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } message = "no implementation for `{Self} &= {Rhs}`", label = "no implementation for `{Self} &= {Rhs}`" )] -#[const_trait] pub trait BitAndAssign<Rhs = Self> { /// Performs the `&=` operation. /// @@ -728,13 +714,12 @@ pub trait BitAndAssign<Rhs = Self> { macro_rules! bitand_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitAndAssign for $t { + impl BitAndAssign for $t { #[inline] fn bitand_assign(&mut self, other: $t) { *self &= other } } - forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for $t, $t } + forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t } )+) } @@ -771,7 +756,6 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} |= {Rhs}`", label = "no implementation for `{Self} |= {Rhs}`" )] -#[const_trait] pub trait BitOrAssign<Rhs = Self> { /// Performs the `|=` operation. /// @@ -801,13 +785,12 @@ pub trait BitOrAssign<Rhs = Self> { macro_rules! bitor_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitOrAssign for $t { + impl BitOrAssign for $t { #[inline] fn bitor_assign(&mut self, other: $t) { *self |= other } } - forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for $t, $t } + forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t } )+) } @@ -844,7 +827,6 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} ^= {Rhs}`", label = "no implementation for `{Self} ^= {Rhs}`" )] -#[const_trait] pub trait BitXorAssign<Rhs = Self> { /// Performs the `^=` operation. /// @@ -874,13 +856,12 @@ pub trait BitXorAssign<Rhs = Self> { macro_rules! bitxor_assign_impl { ($($t:ty)+) => ($( #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const BitXorAssign for $t { + impl BitXorAssign for $t { #[inline] fn bitxor_assign(&mut self, other: $t) { *self ^= other } } - forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for $t, $t } + forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t } )+) } @@ -915,7 +896,6 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } message = "no implementation for `{Self} <<= {Rhs}`", label = "no implementation for `{Self} <<= {Rhs}`" )] -#[const_trait] pub trait ShlAssign<Rhs = Self> { /// Performs the `<<=` operation. /// @@ -937,8 +917,7 @@ pub trait ShlAssign<Rhs = Self> { macro_rules! shl_assign_impl { ($t:ty, $f:ty) => { #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const ShlAssign<$f> for $t { + impl ShlAssign<$f> for $t { #[inline] #[rustc_inherit_overflow_checks] fn shl_assign(&mut self, other: $f) { @@ -946,7 +925,7 @@ macro_rules! shl_assign_impl { } } - forward_ref_op_assign! { impl const ShlAssign, shl_assign for $t, $f } + forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f } }; } @@ -999,7 +978,6 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } message = "no implementation for `{Self} >>= {Rhs}`", label = "no implementation for `{Self} >>= {Rhs}`" )] -#[const_trait] pub trait ShrAssign<Rhs = Self> { /// Performs the `>>=` operation. /// @@ -1021,8 +999,7 @@ pub trait ShrAssign<Rhs = Self> { macro_rules! shr_assign_impl { ($t:ty, $f:ty) => { #[stable(feature = "op_assign_traits", since = "1.8.0")] - #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl const ShrAssign<$f> for $t { + impl ShrAssign<$f> for $t { #[inline] #[rustc_inherit_overflow_checks] fn shr_assign(&mut self, other: $f) { @@ -1030,7 +1007,7 @@ macro_rules! shr_assign_impl { } } - forward_ref_op_assign! { impl const ShrAssign, shr_assign for $t, $f } + forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f } }; } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 117706fb4b2..e10c438ef43 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -97,8 +97,7 @@ pub enum ControlFlow<B, C = ()> { } #[unstable(feature = "try_trait_v2", issue = "84277")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<B, C> const ops::Try for ControlFlow<B, C> { +impl<B, C> ops::Try for ControlFlow<B, C> { type Output = C; type Residual = ControlFlow<B, convert::Infallible>; @@ -117,8 +116,7 @@ impl<B, C> const ops::Try for ControlFlow<B, C> { } #[unstable(feature = "try_trait_v2", issue = "84277")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<B, C> const ops::FromResidual for ControlFlow<B, C> { +impl<B, C> ops::FromResidual for ControlFlow<B, C> { #[inline] fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self { match residual { @@ -128,8 +126,7 @@ impl<B, C> const ops::FromResidual for ControlFlow<B, C> { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -#[rustc_const_unstable(feature = "const_try", issue = "74935")] -impl<B, C> const ops::Residual<C> for ControlFlow<B, convert::Infallible> { +impl<B, C> ops::Residual<C> for ControlFlow<B, convert::Infallible> { type TryType = ControlFlow<B, C>; } diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index c67867f4436..08c35b6dac3 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -61,7 +61,6 @@ #[doc(alias = "&*")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Deref"] -#[const_trait] pub trait Deref { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] @@ -77,8 +76,7 @@ pub trait Deref { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_deref", issue = "88955")] -impl<T: ?Sized> const Deref for &T { +impl<T: ?Sized> Deref for &T { type Target = T; #[rustc_diagnostic_item = "noop_method_deref"] @@ -91,8 +89,7 @@ impl<T: ?Sized> const Deref for &T { impl<T: ?Sized> !DerefMut for &T {} #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_deref", issue = "88955")] -impl<T: ?Sized> const Deref for &mut T { +impl<T: ?Sized> Deref for &mut T { type Target = T; fn deref(&self) -> &T { @@ -170,7 +167,6 @@ impl<T: ?Sized> const Deref for &mut T { #[lang = "deref_mut"] #[doc(alias = "*")] #[stable(feature = "rust1", since = "1.0.0")] -#[const_trait] pub trait DerefMut: Deref { /// Mutably dereferences the value. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index a2c3d978cc4..9ebf426be95 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -132,6 +132,74 @@ /// are `Copy` get implicitly duplicated by the compiler, making it very /// hard to predict when, and how often destructors will be executed. As such, /// these types cannot have destructors. +/// +/// ## Drop check +/// +/// Dropping interacts with the borrow checker in subtle ways: when a type `T` is being implicitly +/// dropped as some variable of this type goes out of scope, the borrow checker needs to ensure that +/// calling `T`'s destructor at this moment is safe. In particular, it also needs to be safe to +/// recursively drop all the fields of `T`. For example, it is crucial that code like the following +/// is being rejected: +/// +/// ```compile_fail,E0597 +/// use std::cell::Cell; +/// +/// struct S<'a>(Cell<Option<&'a S<'a>>>, Box<i32>); +/// impl Drop for S<'_> { +/// fn drop(&mut self) { +/// if let Some(r) = self.0.get() { +/// // Print the contents of the `Box` in `r`. +/// println!("{}", r.1); +/// } +/// } +/// } +/// +/// fn main() { +/// // Set up two `S` that point to each other. +/// let s1 = S(Cell::new(None), Box::new(42)); +/// let s2 = S(Cell::new(Some(&s1)), Box::new(42)); +/// s1.0.set(Some(&s2)); +/// // Now they both get dropped. But whichever is the 2nd one +/// // to be dropped will access the `Box` in the first one, +/// // which is a use-after-free! +/// } +/// ``` +/// +/// The Nomicon discusses the need for [drop check in more detail][drop check]. +/// +/// To reject such code, the "drop check" analysis determines which types and lifetimes need to +/// still be live when `T` gets dropped. The exact details of this analysis are not yet +/// stably guaranteed and **subject to change**. Currently, the analysis works as follows: +/// - If `T` has no drop glue, then trivially nothing is required to be live. This is the case if +/// neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`] +/// and [`ManuallyDrop`] are considered to never have a destructor, no matter their field type. +/// - If `T` has drop glue, then, for all types `U` that are *owned* by any field of `T`, +/// recursively add the types and lifetimes that need to be live when `U` gets dropped. The set of +/// owned types is determined by recursively traversing `T`: +/// - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (including arrays of +/// length 0). +/// - Stop at reference and raw pointer types as well as function pointers and function items; +/// they do not own anything. +/// - Stop at non-composite types (type parameters that remain generic in the current context and +/// base types such as integers and `bool`); these types are owned. +/// - When hitting an ADT with `impl Drop`, stop there; this type is owned. +/// - When hitting an ADT without `impl Drop`, recursively descend to its fields. (For an `enum`, +/// consider all fields of all variants.) +/// - Furthermore, if `T` implements `Drop`, then all generic (lifetime and type) parameters of `T` +/// must be live. +/// +/// In the above example, the last clause implies that `'a` must be live when `S<'a>` is dropped, +/// and hence the example is rejected. If we remove the `impl Drop`, the liveness requirement +/// disappears and the example is accepted. +/// +/// There exists an unstable way for a type to opt-out of the last clause; this is called "drop +/// check eyepatch" or `may_dangle`. For more details on this nightly-only feature, see the +/// [discussion in the Nomicon][nomicon]. +/// +/// [`ManuallyDrop`]: crate::mem::ManuallyDrop +/// [`PhantomData`]: crate::marker::PhantomData +/// [drop check]: ../../nomicon/dropck.html +/// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] #[const_trait] diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index b7e1aee9d84..67c8245f0bf 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -254,10 +254,9 @@ mod impls { use crate::marker::Tuple; #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A: Tuple, F: ?Sized> const Fn<A> for &F + impl<A: Tuple, F: ?Sized> Fn<A> for &F where - F: ~const Fn<A>, + F: Fn<A>, { extern "rust-call" fn call(&self, args: A) -> F::Output { (**self).call(args) @@ -265,10 +264,9 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A: Tuple, F: ?Sized> const FnMut<A> for &F + impl<A: Tuple, F: ?Sized> FnMut<A> for &F where - F: ~const Fn<A>, + F: Fn<A>, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (**self).call(args) @@ -276,10 +274,9 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F + impl<A: Tuple, F: ?Sized> FnOnce<A> for &F where - F: ~const Fn<A>, + F: Fn<A>, { type Output = F::Output; @@ -289,10 +286,9 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F + impl<A: Tuple, F: ?Sized> FnMut<A> for &mut F where - F: ~const FnMut<A>, + F: FnMut<A>, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (*self).call_mut(args) @@ -300,10 +296,9 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F + impl<A: Tuple, F: ?Sized> FnOnce<A> for &mut F where - F: ~const FnMut<A>, + F: FnMut<A>, { type Output = F::Output; extern "rust-call" fn call_once(self, args: A) -> F::Output { diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs index 228efb0bc0a..1f1784ec9b2 100644 --- a/library/core/src/ops/index.rs +++ b/library/core/src/ops/index.rs @@ -55,10 +55,10 @@ #[doc(alias = "]")] #[doc(alias = "[")] #[doc(alias = "[]")] -#[const_trait] pub trait Index<Idx: ?Sized> { /// The returned type after indexing. #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "IndexOutput"] type Output: ?Sized; /// Performs the indexing (`container[index]`) operation. @@ -164,8 +164,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind #[doc(alias = "[")] #[doc(alias = "]")] #[doc(alias = "[]")] -#[const_trait] -pub trait IndexMut<Idx: ?Sized>: ~const Index<Idx> { +pub trait IndexMut<Idx: ?Sized>: Index<Idx> { /// Performs the mutable indexing (`container[index]`) operation. /// /// # Panics diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index 3e06776d2c6..265022a394e 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -1,5 +1,6 @@ use crate::intrinsics::{assert_unsafe_precondition, unchecked_add, unchecked_sub}; use crate::iter::{FusedIterator, TrustedLen}; +use crate::num::NonZeroUsize; /// Like a `Range<usize>`, but with a safety invariant that `start <= end`. /// @@ -132,10 +133,9 @@ impl Iterator for IndexRange { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - let original_len = self.len(); - self.take_prefix(n); - if n > original_len { Err(original_len) } else { Ok(()) } + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let taken = self.take_prefix(n); + NonZeroUsize::new(n - taken.len()).map_or(Ok(()), Err) } } @@ -151,10 +151,9 @@ impl DoubleEndedIterator for IndexRange { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - let original_len = self.len(); - self.take_suffix(n); - if n > original_len { Err(original_len) } else { Ok(()) } + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + let taken = self.take_suffix(n); + NonZeroUsize::new(n - taken.len()).map_or(Ok(()), Err) } } diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index b8ab2656473..ba5e6ddc752 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -96,7 +96,7 @@ impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> { } } -impl<Idx: ~const PartialOrd<Idx>> Range<Idx> { +impl<Idx: PartialOrd<Idx>> Range<Idx> { /// Returns `true` if `item` is contained in the range. /// /// # Examples @@ -116,11 +116,10 @@ impl<Idx: ~const PartialOrd<Idx>> Range<Idx> { /// assert!(!(f32::NAN..1.0).contains(&0.5)); /// ``` #[stable(feature = "range_contains", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] - pub const fn contains<U>(&self, item: &U) -> bool + pub fn contains<U>(&self, item: &U) -> bool where - Idx: ~const PartialOrd<U>, - U: ?Sized + ~const PartialOrd<Idx>, + Idx: PartialOrd<U>, + U: ?Sized + PartialOrd<Idx>, { <Self as RangeBounds<Idx>>::contains(self, item) } @@ -143,8 +142,7 @@ impl<Idx: ~const PartialOrd<Idx>> Range<Idx> { /// assert!( (f32::NAN..5.0).is_empty()); /// ``` #[stable(feature = "range_is_empty", since = "1.47.0")] - #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] - pub const fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { !(self.start < self.end) } } @@ -201,7 +199,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> { } } -impl<Idx: ~const PartialOrd<Idx>> RangeFrom<Idx> { +impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> { /// Returns `true` if `item` is contained in the range. /// /// # Examples @@ -216,11 +214,10 @@ impl<Idx: ~const PartialOrd<Idx>> RangeFrom<Idx> { /// assert!(!(f32::NAN..).contains(&0.5)); /// ``` #[stable(feature = "range_contains", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] - pub const fn contains<U>(&self, item: &U) -> bool + pub fn contains<U>(&self, item: &U) -> bool where - Idx: ~const PartialOrd<U>, - U: ?Sized + ~const PartialOrd<Idx>, + Idx: PartialOrd<U>, + U: ?Sized + PartialOrd<Idx>, { <Self as RangeBounds<Idx>>::contains(self, item) } @@ -283,7 +280,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> { } } -impl<Idx: ~const PartialOrd<Idx>> RangeTo<Idx> { +impl<Idx: PartialOrd<Idx>> RangeTo<Idx> { /// Returns `true` if `item` is contained in the range. /// /// # Examples @@ -298,11 +295,10 @@ impl<Idx: ~const PartialOrd<Idx>> RangeTo<Idx> { /// assert!(!(..f32::NAN).contains(&0.5)); /// ``` #[stable(feature = "range_contains", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] - pub const fn contains<U>(&self, item: &U) -> bool + pub fn contains<U>(&self, item: &U) -> bool where - Idx: ~const PartialOrd<U>, - U: ?Sized + ~const PartialOrd<Idx>, + Idx: PartialOrd<U>, + U: ?Sized + PartialOrd<Idx>, { <Self as RangeBounds<Idx>>::contains(self, item) } @@ -474,7 +470,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> { } } -impl<Idx: ~const PartialOrd<Idx>> RangeInclusive<Idx> { +impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> { /// Returns `true` if `item` is contained in the range. /// /// # Examples @@ -505,11 +501,10 @@ impl<Idx: ~const PartialOrd<Idx>> RangeInclusive<Idx> { /// assert!(!r.contains(&3) && !r.contains(&5)); /// ``` #[stable(feature = "range_contains", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] - pub const fn contains<U>(&self, item: &U) -> bool + pub fn contains<U>(&self, item: &U) -> bool where - Idx: ~const PartialOrd<U>, - U: ?Sized + ~const PartialOrd<Idx>, + Idx: PartialOrd<U>, + U: ?Sized + PartialOrd<Idx>, { <Self as RangeBounds<Idx>>::contains(self, item) } @@ -541,9 +536,8 @@ impl<Idx: ~const PartialOrd<Idx>> RangeInclusive<Idx> { /// assert!(r.is_empty()); /// ``` #[stable(feature = "range_is_empty", since = "1.47.0")] - #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] #[inline] - pub const fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.exhausted || !(self.start <= self.end) } } @@ -605,7 +599,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> { } } -impl<Idx: ~const PartialOrd<Idx>> RangeToInclusive<Idx> { +impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> { /// Returns `true` if `item` is contained in the range. /// /// # Examples @@ -620,11 +614,10 @@ impl<Idx: ~const PartialOrd<Idx>> RangeToInclusive<Idx> { /// assert!(!(..=f32::NAN).contains(&0.5)); /// ``` #[stable(feature = "range_contains", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] - pub const fn contains<U>(&self, item: &U) -> bool + pub fn contains<U>(&self, item: &U) -> bool where - Idx: ~const PartialOrd<U>, - U: ?Sized + ~const PartialOrd<Idx>, + Idx: PartialOrd<U>, + U: ?Sized + PartialOrd<Idx>, { <Self as RangeBounds<Idx>>::contains(self, item) } @@ -765,7 +758,6 @@ impl<T: Clone> Bound<&T> { /// `RangeBounds` is implemented by Rust's built-in range types, produced /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. #[stable(feature = "collections_range", since = "1.28.0")] -#[const_trait] pub trait RangeBounds<T: ?Sized> { /// Start index bound. /// @@ -818,8 +810,8 @@ pub trait RangeBounds<T: ?Sized> { #[stable(feature = "range_contains", since = "1.35.0")] fn contains<U>(&self, item: &U) -> bool where - T: ~const PartialOrd<U>, - U: ?Sized + ~const PartialOrd<T>, + T: PartialOrd<U>, + U: ?Sized + PartialOrd<T>, { (match self.start_bound() { Included(start) => start <= item, @@ -836,8 +828,7 @@ pub trait RangeBounds<T: ?Sized> { use self::Bound::{Excluded, Included, Unbounded}; #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T: ?Sized> const RangeBounds<T> for RangeFull { +impl<T: ?Sized> RangeBounds<T> for RangeFull { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -847,8 +838,7 @@ impl<T: ?Sized> const RangeBounds<T> for RangeFull { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for RangeFrom<T> { +impl<T> RangeBounds<T> for RangeFrom<T> { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -858,8 +848,7 @@ impl<T> const RangeBounds<T> for RangeFrom<T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for RangeTo<T> { +impl<T> RangeBounds<T> for RangeTo<T> { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -869,8 +858,7 @@ impl<T> const RangeBounds<T> for RangeTo<T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for Range<T> { +impl<T> RangeBounds<T> for Range<T> { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -880,8 +868,7 @@ impl<T> const RangeBounds<T> for Range<T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for RangeInclusive<T> { +impl<T> RangeBounds<T> for RangeInclusive<T> { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -897,8 +884,7 @@ impl<T> const RangeBounds<T> for RangeInclusive<T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for RangeToInclusive<T> { +impl<T> RangeBounds<T> for RangeToInclusive<T> { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -908,8 +894,7 @@ impl<T> const RangeBounds<T> for RangeToInclusive<T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for (Bound<T>, Bound<T>) { +impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) { fn start_bound(&self) -> Bound<&T> { match *self { (Included(ref start), _) => Included(start), @@ -928,8 +913,7 @@ impl<T> const RangeBounds<T> for (Bound<T>, Bound<T>) { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<'a, T: ?Sized + 'a> const RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) { +impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) { fn start_bound(&self) -> Bound<&T> { self.0 } @@ -940,8 +924,7 @@ impl<'a, T: ?Sized + 'a> const RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for RangeFrom<&T> { +impl<T> RangeBounds<T> for RangeFrom<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -951,8 +934,7 @@ impl<T> const RangeBounds<T> for RangeFrom<&T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for RangeTo<&T> { +impl<T> RangeBounds<T> for RangeTo<&T> { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -962,8 +944,7 @@ impl<T> const RangeBounds<T> for RangeTo<&T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for Range<&T> { +impl<T> RangeBounds<T> for Range<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -973,8 +954,7 @@ impl<T> const RangeBounds<T> for Range<&T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for RangeInclusive<&T> { +impl<T> RangeBounds<T> for RangeInclusive<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -984,8 +964,7 @@ impl<T> const RangeBounds<T> for RangeInclusive<&T> { } #[stable(feature = "collections_range", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")] -impl<T> const RangeBounds<T> for RangeToInclusive<&T> { +impl<T> RangeBounds<T> for RangeToInclusive<&T> { fn start_bound(&self) -> Bound<&T> { Unbounded } diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 86aa1e4fd20..b4f69d0b213 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -128,8 +128,7 @@ use crate::ops::ControlFlow; )] #[doc(alias = "?")] #[lang = "Try"] -#[const_trait] -pub trait Try: ~const FromResidual { +pub trait Try: FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. #[unstable(feature = "try_trait_v2", issue = "84277")] type Output; @@ -305,7 +304,6 @@ pub trait Try: ~const FromResidual { )] #[rustc_diagnostic_item = "FromResidual"] #[unstable(feature = "try_trait_v2", issue = "84277")] -#[const_trait] pub trait FromResidual<R = <Self as Try>::Residual> { /// Constructs the type from a compatible `Residual` type. /// @@ -358,11 +356,10 @@ where /// and in the other direction, /// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`. #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -#[const_trait] pub trait Residual<O> { /// The "return" type of this meta-function. #[unstable(feature = "try_trait_v2_residual", issue = "91285")] - type TryType: ~const Try<Output = O, Residual = Self>; + type TryType: Try<Output = O, Residual = Self>; } #[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")] @@ -389,23 +386,14 @@ impl<T> NeverShortCircuit<T> { } #[inline] - pub fn wrap_mut_2<A, B>( - mut f: impl ~const FnMut(A, B) -> T, - ) -> impl ~const FnMut(A, B) -> Self { - cfg_if! { - if #[cfg(bootstrap)] { - #[allow(unused_parens)] - (const move |a, b| NeverShortCircuit(f(a, b))) - } else { - const move |a, b| NeverShortCircuit(f(a, b)) - } - } + pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { + move |a, b| NeverShortCircuit(f(a, b)) } } pub(crate) enum NeverShortCircuitResidual {} -impl<T> const Try for NeverShortCircuit<T> { +impl<T> Try for NeverShortCircuit<T> { type Output = T; type Residual = NeverShortCircuitResidual; @@ -420,14 +408,14 @@ impl<T> const Try for NeverShortCircuit<T> { } } -impl<T> const FromResidual for NeverShortCircuit<T> { +impl<T> FromResidual for NeverShortCircuit<T> { #[inline] fn from_residual(never: NeverShortCircuitResidual) -> Self { match never {} } } -impl<T> const Residual<T> for NeverShortCircuitResidual { +impl<T> Residual<T> for NeverShortCircuitResidual { type TryType = NeverShortCircuit<T>; } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 5d5e9559034..ec1ef3cf43d 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -547,17 +547,18 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; -use crate::marker::Destruct; use crate::panicking::{panic, panic_str}; use crate::pin::Pin; use crate::{ cmp, convert, hint, mem, ops::{self, ControlFlow, Deref, DerefMut}, + slice, }; /// The `Option` type. See [the module level documentation](self) for more. #[derive(Copy, PartialOrd, Eq, Ord, Debug, Hash)] #[rustc_diagnostic_item = "Option"] +#[lang = "Option"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Option<T> { /// No value. @@ -603,8 +604,6 @@ impl<T> Option<T> { /// # Examples /// /// ``` - /// #![feature(is_some_and)] - /// /// let x: Option<u32> = Some(2); /// assert_eq!(x.is_some_and(|x| x > 1), true); /// @@ -616,7 +615,7 @@ impl<T> Option<T> { /// ``` #[must_use] #[inline] - #[unstable(feature = "is_some_and", issue = "93050")] + #[stable(feature = "is_some_and", since = "1.70.0")] pub fn is_some_and(self, f: impl FnOnce(T) -> bool) -> bool { match self { None => false, @@ -734,6 +733,119 @@ impl<T> Option<T> { } } + /// Returns a slice of the contained value, if any. If this is `None`, an + /// empty slice is returned. This can be useful to have a single type of + /// iterator over an `Option` or slice. + /// + /// Note: Should you have an `Option<&T>` and wish to get a slice of `T`, + /// you can unpack it via `opt.map_or(&[], std::slice::from_ref)`. + /// + /// # Examples + /// + /// ```rust + /// #![feature(option_as_slice)] + /// + /// assert_eq!( + /// [Some(1234).as_slice(), None.as_slice()], + /// [&[1234][..], &[][..]], + /// ); + /// ``` + /// + /// The inverse of this function is (discounting + /// borrowing) [`[_]::first`](slice::first): + /// + /// ```rust + /// #![feature(option_as_slice)] + /// + /// for i in [Some(1234_u16), None] { + /// assert_eq!(i.as_ref(), i.as_slice().first()); + /// } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "option_as_slice", issue = "108545")] + pub fn as_slice(&self) -> &[T] { + // SAFETY: When the `Option` is `Some`, we're using the actual pointer + // to the payload, with a length of 1, so this is equivalent to + // `slice::from_ref`, and thus is safe. + // When the `Option` is `None`, the length used is 0, so to be safe it + // just needs to be aligned, which it is because `&self` is aligned and + // the offset used is a multiple of alignment. + // + // In the new version, the intrinsic always returns a pointer to an + // in-bounds and correctly aligned position for a `T` (even if in the + // `None` case it's just padding). + unsafe { + slice::from_raw_parts( + crate::intrinsics::option_payload_ptr(crate::ptr::from_ref(self)), + usize::from(self.is_some()), + ) + } + } + + /// Returns a mutable slice of the contained value, if any. If this is + /// `None`, an empty slice is returned. This can be useful to have a + /// single type of iterator over an `Option` or slice. + /// + /// Note: Should you have an `Option<&mut T>` instead of a + /// `&mut Option<T>`, which this method takes, you can obtain a mutable + /// slice via `opt.map_or(&mut [], std::slice::from_mut)`. + /// + /// # Examples + /// + /// ```rust + /// #![feature(option_as_slice)] + /// + /// assert_eq!( + /// [Some(1234).as_mut_slice(), None.as_mut_slice()], + /// [&mut [1234][..], &mut [][..]], + /// ); + /// ``` + /// + /// The result is a mutable slice of zero or one items that points into + /// our original `Option`: + /// + /// ```rust + /// #![feature(option_as_slice)] + /// + /// let mut x = Some(1234); + /// x.as_mut_slice()[0] += 1; + /// assert_eq!(x, Some(1235)); + /// ``` + /// + /// The inverse of this method (discounting borrowing) + /// is [`[_]::first_mut`](slice::first_mut): + /// + /// ```rust + /// #![feature(option_as_slice)] + /// + /// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123)) + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "option_as_slice", issue = "108545")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: When the `Option` is `Some`, we're using the actual pointer + // to the payload, with a length of 1, so this is equivalent to + // `slice::from_mut`, and thus is safe. + // When the `Option` is `None`, the length used is 0, so to be safe it + // just needs to be aligned, which it is because `&self` is aligned and + // the offset used is a multiple of alignment. + // + // In the new version, the intrinsic creates a `*const T` from a + // mutable reference so it is safe to cast back to a mutable pointer + // here. As with `as_slice`, the intrinsic always returns a pointer to + // an in-bounds and correctly aligned position for a `T` (even if in + // the `None` case it's just padding). + unsafe { + slice::from_raw_parts_mut( + crate::intrinsics::option_payload_ptr(crate::ptr::from_mut(self).cast_const()) + .cast_mut(), + usize::from(self.is_some()), + ) + } + } + ///////////////////////////////////////////////////////////////////////// // Getting to contained values ///////////////////////////////////////////////////////////////////////// @@ -840,11 +952,7 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn unwrap_or(self, default: T) -> T - where - T: ~const Destruct, - { + pub fn unwrap_or(self, default: T) -> T { match self { Some(x) => x, None => default, @@ -862,11 +970,9 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn unwrap_or_else<F>(self, f: F) -> T + pub fn unwrap_or_else<F>(self, f: F) -> T where - F: ~const FnOnce() -> T, - F: ~const Destruct, + F: FnOnce() -> T, { match self { Some(x) => x, @@ -895,14 +1001,13 @@ impl<T> Option<T> { /// [`FromStr`]: crate::str::FromStr #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn unwrap_or_default(self) -> T + pub fn unwrap_or_default(self) -> T where - T: ~const Default, + T: Default, { match self { Some(x) => x, - None => Default::default(), + None => T::default(), } } @@ -962,11 +1067,9 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn map<U, F>(self, f: F) -> Option<U> + pub fn map<U, F>(self, f: F) -> Option<U> where - F: ~const FnOnce(T) -> U, - F: ~const Destruct, + F: FnOnce(T) -> U, { match self { Some(x) => Some(f(x)), @@ -991,11 +1094,9 @@ impl<T> Option<T> { /// ``` #[inline] #[unstable(feature = "result_option_inspect", issue = "91345")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn inspect<F>(self, f: F) -> Self + pub fn inspect<F>(self, f: F) -> Self where - F: ~const FnOnce(&T), - F: ~const Destruct, + F: FnOnce(&T), { if let Some(ref x) = self { f(x); @@ -1024,12 +1125,9 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn map_or<U, F>(self, default: U, f: F) -> U + pub fn map_or<U, F>(self, default: U, f: F) -> U where - F: ~const FnOnce(T) -> U, - F: ~const Destruct, - U: ~const Destruct, + F: FnOnce(T) -> U, { match self { Some(t) => f(t), @@ -1053,13 +1151,10 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U + pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U where - D: ~const FnOnce() -> U, - D: ~const Destruct, - F: ~const FnOnce(T) -> U, - F: ~const Destruct, + D: FnOnce() -> U, + F: FnOnce(T) -> U, { match self { Some(t) => f(t), @@ -1090,11 +1185,7 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn ok_or<E>(self, err: E) -> Result<T, E> - where - E: ~const Destruct, - { + pub fn ok_or<E>(self, err: E) -> Result<T, E> { match self { Some(v) => Ok(v), None => Err(err), @@ -1119,11 +1210,9 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn ok_or_else<E, F>(self, err: F) -> Result<T, E> + pub fn ok_or_else<E, F>(self, err: F) -> Result<T, E> where - F: ~const FnOnce() -> E, - F: ~const Destruct, + F: FnOnce() -> E, { match self { Some(v) => Ok(v), @@ -1145,11 +1234,11 @@ impl<T> Option<T> { /// let x: Option<String> = None; /// assert_eq!(x.as_deref(), None); /// ``` + #[inline] #[stable(feature = "option_deref", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn as_deref(&self) -> Option<&T::Target> + pub fn as_deref(&self) -> Option<&T::Target> where - T: ~const Deref, + T: Deref, { match self.as_ref() { Some(t) => Some(t.deref()), @@ -1171,11 +1260,11 @@ impl<T> Option<T> { /// x /// }), Some("HEY".to_owned().as_mut_str())); /// ``` + #[inline] #[stable(feature = "option_deref", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn as_deref_mut(&mut self) -> Option<&mut T::Target> + pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> where - T: ~const DerefMut, + T: DerefMut, { match self.as_mut() { Some(t) => Some(t.deref_mut()), @@ -1259,12 +1348,7 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn and<U>(self, optb: Option<U>) -> Option<U> - where - T: ~const Destruct, - U: ~const Destruct, - { + pub fn and<U>(self, optb: Option<U>) -> Option<U> { match self { Some(_) => optb, None => None, @@ -1301,11 +1385,9 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn and_then<U, F>(self, f: F) -> Option<U> + pub fn and_then<U, F>(self, f: F) -> Option<U> where - F: ~const FnOnce(T) -> Option<U>, - F: ~const Destruct, + F: FnOnce(T) -> Option<U>, { match self { Some(x) => f(x), @@ -1339,12 +1421,9 @@ impl<T> Option<T> { /// [`Some(t)`]: Some #[inline] #[stable(feature = "option_filter", since = "1.27.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn filter<P>(self, predicate: P) -> Self + pub fn filter<P>(self, predicate: P) -> Self where - T: ~const Destruct, - P: ~const FnOnce(&T) -> bool, - P: ~const Destruct, + P: FnOnce(&T) -> bool, { if let Some(x) = self { if predicate(&x) { @@ -1383,11 +1462,7 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn or(self, optb: Option<T>) -> Option<T> - where - T: ~const Destruct, - { + pub fn or(self, optb: Option<T>) -> Option<T> { match self { Some(x) => Some(x), None => optb, @@ -1409,11 +1484,9 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn or_else<F>(self, f: F) -> Option<T> + pub fn or_else<F>(self, f: F) -> Option<T> where - F: ~const FnOnce() -> Option<T>, - F: ~const Destruct, + F: FnOnce() -> Option<T>, { match self { Some(x) => Some(x), @@ -1444,11 +1517,7 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "option_xor", since = "1.37.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn xor(self, optb: Option<T>) -> Option<T> - where - T: ~const Destruct, - { + pub fn xor(self, optb: Option<T>) -> Option<T> { match (self, optb) { (Some(a), None) => Some(a), (None, Some(b)) => Some(b), @@ -1482,11 +1551,7 @@ impl<T> Option<T> { #[must_use = "if you intended to set a value, consider assignment instead"] #[inline] #[stable(feature = "option_insert", since = "1.53.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn insert(&mut self, value: T) -> &mut T - where - T: ~const Destruct, - { + pub fn insert(&mut self, value: T) -> &mut T { *self = Some(value); // SAFETY: the code above just filled the option @@ -1515,11 +1580,7 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "option_entry", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn get_or_insert(&mut self, value: T) -> &mut T - where - T: ~const Destruct, - { + pub fn get_or_insert(&mut self, value: T) -> &mut T { if let None = *self { *self = Some(value); } @@ -1550,16 +1611,11 @@ impl<T> Option<T> { /// ``` #[inline] #[unstable(feature = "option_get_or_insert_default", issue = "82901")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn get_or_insert_default(&mut self) -> &mut T + pub fn get_or_insert_default(&mut self) -> &mut T where - T: ~const Default, + T: Default, { - const fn default<T: ~const Default>() -> T { - T::default() - } - - self.get_or_insert_with(default) + self.get_or_insert_with(T::default) } /// Inserts a value computed from `f` into the option if it is [`None`], @@ -1581,16 +1637,12 @@ impl<T> Option<T> { /// ``` #[inline] #[stable(feature = "option_entry", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn get_or_insert_with<F>(&mut self, f: F) -> &mut T + pub fn get_or_insert_with<F>(&mut self, f: F) -> &mut T where - F: ~const FnOnce() -> T, - F: ~const Destruct, + F: FnOnce() -> T, { - if let None = *self { - // the compiler isn't smart enough to know that we are not dropping a `T` - // here and wants us to ensure `T` can be dropped at compile time. - mem::forget(mem::replace(self, Some(f()))) + if let None = self { + *self = Some(f()); } // SAFETY: a `None` variant for `self` would have been replaced by a `Some` @@ -1649,36 +1701,6 @@ impl<T> Option<T> { mem::replace(self, Some(value)) } - /// Returns `true` if the option is a [`Some`] value containing the given value. - /// - /// # Examples - /// - /// ``` - /// #![feature(option_result_contains)] - /// - /// let x: Option<u32> = Some(2); - /// assert_eq!(x.contains(&2), true); - /// - /// let x: Option<u32> = Some(3); - /// assert_eq!(x.contains(&2), false); - /// - /// let x: Option<u32> = None; - /// assert_eq!(x.contains(&2), false); - /// ``` - #[must_use] - #[inline] - #[unstable(feature = "option_result_contains", issue = "62358")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn contains<U>(&self, x: &U) -> bool - where - U: ~const PartialEq<T>, - { - match self { - Some(y) => x.eq(y), - None => false, - } - } - /// Zips `self` with another `Option`. /// /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`. @@ -1695,12 +1717,7 @@ impl<T> Option<T> { /// assert_eq!(x.zip(z), None); /// ``` #[stable(feature = "option_zip_option", since = "1.46.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn zip<U>(self, other: Option<U>) -> Option<(T, U)> - where - T: ~const Destruct, - U: ~const Destruct, - { + pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)> { match (self, other) { (Some(a), Some(b)) => Some((a, b)), _ => None, @@ -1736,13 +1753,9 @@ impl<T> Option<T> { /// assert_eq!(x.zip_with(None, Point::new), None); /// ``` #[unstable(feature = "option_zip", issue = "70086")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R> + pub fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R> where - F: ~const FnOnce(T, U) -> R, - F: ~const Destruct, - T: ~const Destruct, - U: ~const Destruct, + F: FnOnce(T, U) -> R, { match (self, other) { (Some(a), Some(b)) => Some(f(a, b)), @@ -1768,12 +1781,7 @@ impl<T, U> Option<(T, U)> { /// ``` #[inline] #[stable(feature = "unzip_option", since = "1.66.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] - pub const fn unzip(self) -> (Option<T>, Option<U>) - where - T: ~const Destruct, - U: ~const Destruct, - { + pub fn unzip(self) -> (Option<T>, Option<U>) { match self { Some((a, b)) => (Some(a), Some(b)), None => (None, None), @@ -1823,10 +1831,9 @@ impl<T> Option<&T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")] - pub const fn cloned(self) -> Option<T> + pub fn cloned(self) -> Option<T> where - T: ~const Clone, + T: Clone, { match self { Some(t) => Some(t.clone()), @@ -1875,10 +1882,9 @@ impl<T> Option<&mut T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(since = "1.26.0", feature = "option_ref_mut_cloned")] - #[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")] - pub const fn cloned(self) -> Option<T> + pub fn cloned(self) -> Option<T> where - T: ~const Clone, + T: Clone, { match self { Some(t) => Some(t.clone()), @@ -1931,10 +1937,9 @@ const fn expect_failed(msg: &str) -> ! { ///////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_clone", issue = "91805")] -impl<T> const Clone for Option<T> +impl<T> Clone for Option<T> where - T: ~const Clone + ~const Destruct, + T: Clone, { #[inline] fn clone(&self) -> Self { @@ -1954,8 +1959,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T> const Default for Option<T> { +impl<T> Default for Option<T> { /// Returns [`None`][Option::None]. /// /// # Examples @@ -2015,8 +2019,7 @@ impl<'a, T> IntoIterator for &'a mut Option<T> { } #[stable(since = "1.12.0", feature = "option_from")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<T> for Option<T> { +impl<T> From<T> for Option<T> { /// Moves `val` into a new [`Some`]. /// /// # Examples @@ -2032,8 +2035,7 @@ impl<T> const From<T> for Option<T> { } #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<'a, T> const From<&'a Option<T>> for Option<&'a T> { +impl<'a, T> From<&'a Option<T>> for Option<&'a T> { /// Converts from `&Option<T>` to `Option<&T>`. /// /// # Examples @@ -2060,8 +2062,7 @@ impl<'a, T> const From<&'a Option<T>> for Option<&'a T> { } #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<'a, T> const From<&'a mut Option<T>> for Option<&'a mut T> { +impl<'a, T> From<&'a mut Option<T>> for Option<&'a mut T> { /// Converts from `&mut Option<T>` to `Option<&mut T>` /// /// # Examples @@ -2408,8 +2409,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> { } #[unstable(feature = "try_trait_v2", issue = "84277")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const ops::Try for Option<T> { +impl<T> ops::Try for Option<T> { type Output = T; type Residual = Option<convert::Infallible>; @@ -2428,8 +2428,7 @@ impl<T> const ops::Try for Option<T> { } #[unstable(feature = "try_trait_v2", issue = "84277")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const ops::FromResidual for Option<T> { +impl<T> ops::FromResidual for Option<T> { #[inline] fn from_residual(residual: Option<convert::Infallible>) -> Self { match residual { @@ -2447,8 +2446,7 @@ impl<T> ops::FromResidual<ops::Yeet<()>> for Option<T> { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -#[rustc_const_unstable(feature = "const_try", issue = "74935")] -impl<T> const ops::Residual<T> for Option<convert::Infallible> { +impl<T> ops::Residual<T> for Option<convert::Infallible> { type TryType = Option<T>; } diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 8338a5d7e5a..ebcce79b0f8 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -35,9 +35,11 @@ pub macro panic_2015 { ("{}", $arg:expr $(,)?) => ( $crate::panicking::panic_display(&$arg) ), - ($fmt:expr, $($arg:tt)+) => ( - $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) - ), + ($fmt:expr, $($arg:tt)+) => ({ + // Semicolon to prevent temporaries inside the formatting machinery from + // being considered alive in the caller after the panic_fmt call. + $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)); + }), } #[doc(hidden)] @@ -53,9 +55,11 @@ pub macro panic_2021 { ("{}", $arg:expr $(,)?) => ( $crate::panicking::panic_display(&$arg) ), - ($($t:tt)+) => ( - $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)) - ), + ($($t:tt)+) => ({ + // Semicolon to prevent temporaries inside the formatting machinery from + // being considered alive in the caller after the panic_fmt call. + $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); + }), } #[doc(hidden)] diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 0d385c9d187..06fbe083ca1 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -15,14 +15,10 @@ use crate::panic::Location; /// use std::panic; /// /// panic::set_hook(Box::new(|panic_info| { -/// if let Some(s) = panic_info.payload().downcast_ref::<&str>() { -/// println!("panic occurred: {s:?}"); -/// } else { -/// println!("panic occurred"); -/// } +/// println!("panic occurred: {panic_info}"); /// })); /// -/// panic!("Normal panic"); +/// panic!("critical system failure"); /// ``` #[lang = "panic_info"] #[stable(feature = "panic_hooks", since = "1.10.0")] diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 9a6153f1253..7e7b6b4dbe9 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -28,7 +28,7 @@ use crate::task::{Context, Poll}; /// 2. This broken invariant is then later observed. /// /// Typically in Rust, it is difficult to perform step (2) because catching a -/// panic involves either spawning a thread (which in turns makes it difficult +/// panic involves either spawning a thread (which in turn makes it difficult /// to later witness broken invariants) or using the `catch_unwind` function in this /// module. Additionally, even if an invariant is witnessed, it typically isn't a /// problem in Rust because there are no uninitialized values (like in C or C++). diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 805a1e51ae9..81be3fb22ee 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -29,6 +29,9 @@ use crate::fmt; use crate::panic::{Location, PanicInfo}; +#[cfg(feature = "panic_immediate_abort")] +const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C panic=abort"); + // First we define the two main entry points that all panics go through. // In the end both are just convenience wrappers around `panic_impl`. @@ -111,7 +114,7 @@ pub const fn panic(expr: &'static str) -> ! { // truncation and padding (even though none is used here). Using // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the // output binary, saving up to a few kilobytes. - panic_fmt(fmt::Arguments::new_v1(&[expr], &[])); + panic_fmt(fmt::Arguments::new_const(&[expr])); } /// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize. @@ -120,7 +123,7 @@ pub const fn panic(expr: &'static str) -> ! { #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics #[rustc_nounwind] pub fn panic_nounwind(expr: &'static str) -> ! { - panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[])); + panic_nounwind_fmt(fmt::Arguments::new_const(&[expr])); } #[inline] @@ -159,6 +162,20 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { panic!("index out of bounds: the len is {len} but the index is {index}") } +#[cold] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[track_caller] +#[lang = "panic_misaligned_pointer_dereference"] // needed by codegen for panic on misaligned pointer deref +fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + panic!( + "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}" + ) +} + /// Panic because we cannot unwind out of a function. /// /// This function is called directly by the codegen backend, and must not have diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index febe57dc90b..c4b89a63019 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1003,22 +1003,25 @@ impl<P, U> CoerceUnsized<Pin<U>> for Pin<P> where P: CoerceUnsized<U> {} #[stable(feature = "pin", since = "1.33.0")] impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {} -/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning[^1] a `value: T` _locally_[^2]. +/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning a `value: T` locally. /// -/// Unlike [`Box::pin`], this does not involve a heap allocation. +/// Unlike [`Box::pin`], this does not create a new heap allocation. As explained +/// below, the element might still end up on the heap however. /// -/// [^1]: If the (type `T` of the) given value does not implement [`Unpin`], then this -/// effectively pins the `value` in memory, where it will be unable to be moved. -/// Otherwise, <code>[Pin]<[&mut] T></code> behaves like <code>[&mut] T</code>, and operations such -/// as [`mem::replace()`][crate::mem::replace] will allow extracting that value, and therefore, -/// moving it. -/// See [the `Unpin` section of the `pin` module][self#unpin] for more info. +/// The local pinning performed by this macro is usually dubbed "stack"-pinning. +/// Outside of `async` contexts locals do indeed get stored on the stack. In +/// `async` functions or blocks however, any locals crossing an `.await` point +/// are part of the state captured by the `Future`, and will use the storage of +/// those. That storage can either be on the heap or on the stack. Therefore, +/// local pinning is a more accurate term. /// -/// [^2]: This is usually dubbed "stack"-pinning. And whilst local values are almost always located -/// in the stack (_e.g._, when within the body of a non-`async` function), the truth is that inside -/// the body of an `async fn` or block —more generally, the body of a generator— any locals crossing -/// an `.await` point —a `yield` point— end up being part of the state captured by the `Future` —by -/// the `Generator`—, and thus will be stored wherever that one is. +/// If the type of the given value does not implement [`Unpin`], then this macro +/// pins the value in memory in a way that prevents moves. On the other hand, +/// if the type does implement [`Unpin`], <code>[Pin]<[&mut] T></code> behaves +/// like <code>[&mut] T</code>, and operations such as +/// [`mem::replace()`][crate::mem::replace] or [`mem::take()`](crate::mem::take) +/// will allow moves of the value. +/// See [the `Unpin` section of the `pin` module][self#unpin] for details. /// /// ## Examples /// @@ -1158,9 +1161,9 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {} /// /// If you really need to return a pinned value, consider using [`Box::pin`] instead. /// -/// On the other hand, pinning to the stack[<sup>2</sup>](#fn2) using [`pin!`] is likely to be -/// cheaper than pinning into a fresh heap allocation using [`Box::pin`]. Moreover, by virtue of not -/// even needing an allocator, [`pin!`] is the main non-`unsafe` `#![no_std]`-compatible [`Pin`] +/// On the other hand, local pinning using [`pin!`] is likely to be cheaper than +/// pinning into a fresh heap allocation using [`Box::pin`]. Moreover, by virtue of not +/// requiring an allocator, [`pin!`] is the main non-`unsafe` `#![no_std]`-compatible [`Pin`] /// constructor. /// /// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index d6e9da187e8..8266e899011 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1,7 +1,7 @@ // `library/{std,core}/src/primitive_docs.rs` should have the same contents. // These are different files so that relative links work properly without // having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same. -#[doc(primitive = "bool")] +#[rustc_doc_primitive = "bool"] #[doc(alias = "true")] #[doc(alias = "false")] /// The boolean type. @@ -63,7 +63,7 @@ #[stable(feature = "rust1", since = "1.0.0")] mod prim_bool {} -#[doc(primitive = "never")] +#[rustc_doc_primitive = "never"] #[doc(alias = "!")] // /// The `!` type, also called "never". @@ -274,7 +274,7 @@ mod prim_bool {} #[unstable(feature = "never_type", issue = "35121")] mod prim_never {} -#[doc(primitive = "char")] +#[rustc_doc_primitive = "char"] #[allow(rustdoc::invalid_rust_codeblocks)] /// A character type. /// @@ -398,7 +398,7 @@ mod prim_never {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_char {} -#[doc(primitive = "unit")] +#[rustc_doc_primitive = "unit"] #[doc(alias = "(")] #[doc(alias = ")")] #[doc(alias = "()")] @@ -460,7 +460,7 @@ impl Copy for () { // empty } -#[doc(primitive = "pointer")] +#[rustc_doc_primitive = "pointer"] #[doc(alias = "ptr")] #[doc(alias = "*")] #[doc(alias = "*const")] @@ -550,6 +550,7 @@ impl Copy for () { /// /// ``` /// # #![feature(rustc_private)] +/// #[allow(unused_extern_crates)] /// extern crate libc; /// /// use std::mem; @@ -572,12 +573,11 @@ impl Copy for () { /// [`is_null`]: pointer::is_null /// [`offset`]: pointer::offset #[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))] -/// [`drop`]: mem::drop /// [`write`]: ptr::write #[stable(feature = "rust1", since = "1.0.0")] mod prim_pointer {} -#[doc(primitive = "array")] +#[rustc_doc_primitive = "array"] #[doc(alias = "[]")] #[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases #[doc(alias = "[T; N]")] @@ -587,8 +587,10 @@ mod prim_pointer {} /// There are two syntactic forms for creating an array: /// /// * A list with each element, i.e., `[x, y, z]`. -/// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`. -/// The type of `x` must be [`Copy`]. +/// * A repeat expression `[expr; N]` where `N` is how many times to repeat `expr` in the array. `expr` must either be: +/// +/// * A value of a type implementing the [`Copy`] trait +/// * A `const` value /// /// Note that `[expr; 0]` is allowed, and produces an empty array. /// This will still evaluate `expr`, however, and immediately drop the resulting value, so @@ -609,6 +611,9 @@ mod prim_pointer {} /// if the element type allows it. As a stopgap, trait implementations are /// statically generated up to size 32. /// +/// Arrays of sizes from 1 to 12 (inclusive) implement [`From<Tuple>`], where `Tuple` +/// is a homogenous [prim@tuple] of appropriate length. +/// /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on /// an array. Indeed, this provides most of the API for working with arrays. /// @@ -671,6 +676,13 @@ mod prim_pointer {} /// move_away(roa); /// ``` /// +/// Arrays can be created from homogenous tuples of appropriate length: +/// +/// ``` +/// let tuple: (u32, u32, u32) = (1, 2, 3); +/// let array: [u32; 3] = tuple.into(); +/// ``` +/// /// # Editions /// /// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call @@ -773,10 +785,11 @@ mod prim_pointer {} /// [`Borrow`]: borrow::Borrow /// [`BorrowMut`]: borrow::BorrowMut /// [slice pattern]: ../reference/patterns.html#slice-patterns +/// [`From<Tuple>`]: convert::From #[stable(feature = "rust1", since = "1.0.0")] mod prim_array {} -#[doc(primitive = "slice")] +#[rustc_doc_primitive = "slice"] #[doc(alias = "[")] #[doc(alias = "]")] #[doc(alias = "[]")] @@ -868,7 +881,7 @@ mod prim_array {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_slice {} -#[doc(primitive = "str")] +#[rustc_doc_primitive = "str"] /// String slices. /// /// *[See also the `std::str` module](crate::str).* @@ -935,7 +948,7 @@ mod prim_slice {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_str {} -#[doc(primitive = "tuple")] +#[rustc_doc_primitive = "tuple"] #[doc(alias = "(")] #[doc(alias = ")")] #[doc(alias = "()")] @@ -999,7 +1012,9 @@ mod prim_str {} /// * [`Debug`] /// * [`Default`] /// * [`Hash`] +/// * [`From<[T; N]>`][from] /// +/// [from]: convert::From /// [`Debug`]: fmt::Debug /// [`Hash`]: hash::Hash /// @@ -1015,7 +1030,6 @@ mod prim_str {} /// * [`UnwindSafe`] /// * [`RefUnwindSafe`] /// -/// [`Unpin`]: marker::Unpin /// [`UnwindSafe`]: panic::UnwindSafe /// [`RefUnwindSafe`]: panic::RefUnwindSafe /// @@ -1051,6 +1065,13 @@ mod prim_str {} /// assert_eq!(y, 5); /// ``` /// +/// Homogenous tuples can be created from arrays of appropriate length: +/// +/// ``` +/// let array: [u32; 3] = [1, 2, 3]; +/// let tuple: (u32, u32, u32) = array.into(); +/// ``` +/// #[stable(feature = "rust1", since = "1.0.0")] mod prim_tuple {} @@ -1079,7 +1100,7 @@ impl<T: Copy> Copy for (T,) { // empty } -#[doc(primitive = "f32")] +#[rustc_doc_primitive = "f32"] /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). /// /// This type can represent a wide range of decimal numbers, like `3.5`, `27`, @@ -1108,7 +1129,7 @@ impl<T: Copy> Copy for (T,) { /// - [NaN (not a number)](#associatedconstant.NAN): this value results from /// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected /// behavior: -/// - It is unequal to any float, including itself! This is the reason `f32` +/// - It is not equal to any float, including itself! This is the reason `f32` /// doesn't implement the `Eq` trait. /// - It is also neither smaller nor greater than any float, making it /// impossible to sort by the default comparison operation, which is the @@ -1145,7 +1166,7 @@ impl<T: Copy> Copy for (T,) { #[stable(feature = "rust1", since = "1.0.0")] mod prim_f32 {} -#[doc(primitive = "f64")] +#[rustc_doc_primitive = "f64"] /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008). /// /// This type is very similar to [`f32`], but has increased @@ -1160,67 +1181,67 @@ mod prim_f32 {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_f64 {} -#[doc(primitive = "i8")] +#[rustc_doc_primitive = "i8"] // /// The 8-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i8 {} -#[doc(primitive = "i16")] +#[rustc_doc_primitive = "i16"] // /// The 16-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i16 {} -#[doc(primitive = "i32")] +#[rustc_doc_primitive = "i32"] // /// The 32-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i32 {} -#[doc(primitive = "i64")] +#[rustc_doc_primitive = "i64"] // /// The 64-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i64 {} -#[doc(primitive = "i128")] +#[rustc_doc_primitive = "i128"] // /// The 128-bit signed integer type. #[stable(feature = "i128", since = "1.26.0")] mod prim_i128 {} -#[doc(primitive = "u8")] +#[rustc_doc_primitive = "u8"] // /// The 8-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u8 {} -#[doc(primitive = "u16")] +#[rustc_doc_primitive = "u16"] // /// The 16-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u16 {} -#[doc(primitive = "u32")] +#[rustc_doc_primitive = "u32"] // /// The 32-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u32 {} -#[doc(primitive = "u64")] +#[rustc_doc_primitive = "u64"] // /// The 64-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u64 {} -#[doc(primitive = "u128")] +#[rustc_doc_primitive = "u128"] // /// The 128-bit unsigned integer type. #[stable(feature = "i128", since = "1.26.0")] mod prim_u128 {} -#[doc(primitive = "isize")] +#[rustc_doc_primitive = "isize"] // /// The pointer-sized signed integer type. /// @@ -1230,7 +1251,7 @@ mod prim_u128 {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_isize {} -#[doc(primitive = "usize")] +#[rustc_doc_primitive = "usize"] // /// The pointer-sized unsigned integer type. /// @@ -1240,7 +1261,7 @@ mod prim_isize {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_usize {} -#[doc(primitive = "reference")] +#[rustc_doc_primitive = "reference"] #[doc(alias = "&")] #[doc(alias = "&mut")] // @@ -1336,6 +1357,7 @@ mod prim_usize {} /// * [`Hash`] /// * [`ToSocketAddrs`] /// * [`Send`] \(`&T` references also require <code>T: [Sync]</code>) +/// * [`Sync`] /// /// [`std::fmt`]: fmt /// [`Hash`]: hash::Hash @@ -1371,16 +1393,12 @@ mod prim_usize {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_ref {} -#[doc(primitive = "fn")] +#[rustc_doc_primitive = "fn"] // /// Function pointers, like `fn(usize) -> bool`. /// /// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].* /// -/// [`Fn`]: ops::Fn -/// [`FnMut`]: ops::FnMut -/// [`FnOnce`]: ops::FnOnce -/// /// Function pointers are pointers that point to *code*, not data. They can be called /// just like functions. Like references, function pointers are, among other things, assumed to /// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 2123147c7e4..bbf7199fffa 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -9,8 +9,7 @@ use crate::{cmp, fmt, hash, mem, num}; /// Note that particularly large alignments, while representable in this type, /// are likely not to be supported by actual allocators and linkers. #[unstable(feature = "ptr_alignment_type", issue = "102070")] -#[derive(Copy, Clone, Eq)] -#[derive_const(PartialEq)] +#[derive(Copy, Clone, PartialEq, Eq)] #[repr(transparent)] pub struct Alignment(AlignmentEnum); @@ -41,7 +40,7 @@ impl Alignment { /// Returns the alignment for a type. /// /// This provides the same numerical value as [`mem::align_of`], - /// but in an `Alignment` instead of a `usize. + /// but in an `Alignment` instead of a `usize`. #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const fn of<T>() -> Self { @@ -170,7 +169,7 @@ impl From<Alignment> for usize { #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl const cmp::Ord for Alignment { +impl cmp::Ord for Alignment { #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { self.as_nonzero().get().cmp(&other.as_nonzero().get()) @@ -179,7 +178,7 @@ impl const cmp::Ord for Alignment { #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl const cmp::PartialOrd for Alignment { +impl cmp::PartialOrd for Alignment { #[inline] fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) @@ -201,8 +200,7 @@ type AlignmentEnum = AlignmentEnum32; #[cfg(target_pointer_width = "64")] type AlignmentEnum = AlignmentEnum64; -#[derive(Copy, Clone, Eq)] -#[derive_const(PartialEq)] +#[derive(Copy, Clone, PartialEq, Eq)] #[repr(u16)] enum AlignmentEnum16 { _Align1Shl0 = 1 << 0, @@ -223,8 +221,7 @@ enum AlignmentEnum16 { _Align1Shl15 = 1 << 15, } -#[derive(Copy, Clone, Eq)] -#[derive_const(PartialEq)] +#[derive(Copy, Clone, PartialEq, Eq)] #[repr(u32)] enum AlignmentEnum32 { _Align1Shl0 = 1 << 0, @@ -261,8 +258,7 @@ enum AlignmentEnum32 { _Align1Shl31 = 1 << 31, } -#[derive(Copy, Clone, Eq)] -#[derive_const(PartialEq)] +#[derive(Copy, Clone, PartialEq, Eq)] #[repr(u64)] enum AlignmentEnum64 { _Align1Shl0 = 1 << 0, diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 57e2ffe5d20..5ee1b5e4afc 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -61,14 +61,14 @@ impl<T: ?Sized> *const T { /// Use the pointer value in a new pointer of another type. /// - /// In case `val` is a (fat) pointer to an unsized type, this operation + /// In case `meta` is a (fat) pointer to an unsized type, this operation /// will ignore the pointer part, whereas for (thin) pointers to sized /// types, this has the same effect as a simple cast. /// /// The resulting pointer will have provenance of `self`, i.e., for a fat /// pointer, this operation is semantically the same as creating a new /// fat pointer with the data pointer value of `self` but the metadata of - /// `val`. + /// `meta`. /// /// # Examples /// @@ -132,8 +132,8 @@ impl<T: ?Sized> *const T { /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[deprecated( - since = "1.67", - note = "replaced by the `exposed_addr` method, or update your code \ + since = "1.67.0", + note = "replaced by the `expose_addr` method, or update your code \ to follow the strict provenance rules using its APIs" )] #[inline(always)] @@ -161,7 +161,7 @@ impl<T: ?Sized> *const T { /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[deprecated( - since = "1.67", + since = "1.67.0", note = "replaced by the `ptr::from_exposed_addr` function, or update \ your code to follow the strict provenance rules using its APIs" )] @@ -264,7 +264,7 @@ impl<T: ?Sized> *const T { let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); - // This is the canonical desugarring of this operation + // This is the canonical desugaring of this operation self.wrapping_byte_offset(offset) } @@ -916,8 +916,16 @@ impl<T: ?Sized> *const T { where T: Sized, { + #[cfg(bootstrap)] // SAFETY: the caller must uphold the safety contract for `offset`. - unsafe { self.offset(count as isize) } + unsafe { + self.offset(count as isize) + } + #[cfg(not(bootstrap))] + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { + intrinsics::offset(self, count) + } } /// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`). @@ -1187,7 +1195,7 @@ impl<T: ?Sized> *const T { /// /// [`ptr::read`]: crate::ptr::read() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] + #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn read(self) -> T @@ -1228,7 +1236,7 @@ impl<T: ?Sized> *const T { /// /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] + #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn read_unaligned(self) -> T @@ -1650,11 +1658,10 @@ impl<T> *const [T] { /// } /// ``` #[unstable(feature = "slice_ptr_get", issue = "74265")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub const unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output + pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output where - I: ~const SliceIndex<[T]>, + I: SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. unsafe { index.get_unchecked(self) } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 1ad9af1549a..ecbf4e66fa4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -374,6 +374,7 @@ use crate::hash; use crate::intrinsics::{ self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping, }; +use crate::marker::FnPtr; use crate::mem::{self, MaybeUninit}; @@ -691,7 +692,7 @@ where #[inline(always)] #[must_use] #[unstable(feature = "ptr_from_ref", issue = "106116")] -pub fn from_ref<T: ?Sized>(r: &T) -> *const T { +pub const fn from_ref<T: ?Sized>(r: &T) -> *const T { r } @@ -702,7 +703,7 @@ pub fn from_ref<T: ?Sized>(r: &T) -> *const T { #[inline(always)] #[must_use] #[unstable(feature = "ptr_from_ref", issue = "106116")] -pub fn from_mut<T: ?Sized>(r: &mut T) -> *mut T { +pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T { r } @@ -1132,30 +1133,43 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T { /// [valid]: self#safety #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] +#[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")] +#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn read<T>(src: *const T) -> T { - // We are calling the intrinsics directly to avoid function calls in the generated code - // as `intrinsics::copy_nonoverlapping` is a wrapper function. - extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] - fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); - } + // It would be semantically correct to implement this via `copy_nonoverlapping` + // and `MaybeUninit`, as was done before PR #109035. Calling `assume_init` + // provides enough information to know that this is a typed operation. - let mut tmp = MaybeUninit::<T>::uninit(); - // SAFETY: the caller must guarantee that `src` is valid for reads. - // `src` cannot overlap `tmp` because `tmp` was just allocated on - // the stack as a separate allocated object. + // However, as of March 2023 the compiler was not capable of taking advantage + // of that information. Thus the implementation here switched to an intrinsic, + // which lowers to `_0 = *src` in MIR, to address a few issues: // - // Also, since we just wrote a valid value into `tmp`, it is guaranteed - // to be properly initialized. + // - Using `MaybeUninit::assume_init` after a `copy_nonoverlapping` was not + // turning the untyped copy into a typed load. As such, the generated + // `load` in LLVM didn't get various metadata, such as `!range` (#73258), + // `!nonnull`, and `!noundef`, resulting in poorer optimization. + // - Going through the extra local resulted in multiple extra copies, even + // in optimized MIR. (Ignoring StorageLive/Dead, the intrinsic is one + // MIR statement, while the previous implementation was eight.) LLVM + // could sometimes optimize them away, but because `read` is at the core + // of so many things, not having them in the first place improves what we + // hand off to the backend. For example, `mem::replace::<Big>` previously + // emitted 4 `alloca` and 6 `memcpy`s, but is now 1 `alloc` and 3 `memcpy`s. + // - In general, this approach keeps us from getting any more bugs (like + // #106369) that boil down to "`read(p)` is worse than `*p`", as this + // makes them look identical to the backend (or other MIR consumers). + // + // Future enhancements to MIR optimizations might well allow this to return + // to the previous implementation, rather than using an intrinsic. + + // SAFETY: the caller must guarantee that `src` is valid for reads. unsafe { assert_unsafe_precondition!( "ptr::read requires that the pointer argument is aligned and non-null", [T](src: *const T) => is_aligned_and_not_null(src) ); - copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); - tmp.assume_init() + crate::intrinsics::read_via_copy(src) } } @@ -1236,7 +1250,8 @@ pub const unsafe fn read<T>(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] -#[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] +#[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")] +#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn read_unaligned<T>(src: *const T) -> T { let mut tmp = MaybeUninit::<T>::uninit(); @@ -1336,12 +1351,13 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T { #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write<T>(dst: *mut T, src: T) { - // We are calling the intrinsics directly to avoid function calls in the generated code - // as `intrinsics::copy_nonoverlapping` is a wrapper function. - extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] - fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); - } + // Semantically, it would be fine for this to be implemented as a + // `copy_nonoverlapping` and appropriate drop suppression of `src`. + + // However, implementing via that currently produces more MIR than is ideal. + // Using an intrinsic keeps it down to just the simple `*dst = move src` in + // MIR (11 statements shorter, at the time of writing), and also allows + // `src` to stay an SSA value in codegen_ssa, rather than a memory one. // SAFETY: the caller must guarantee that `dst` is valid for writes. // `dst` cannot overlap `src` because the caller has mutable access @@ -1351,8 +1367,7 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) { "ptr::write requires that the pointer argument is aligned and non-null", [T](dst: *mut T) => is_aligned_and_not_null(dst) ); - copy_nonoverlapping(&src as *const T, dst, 1); - intrinsics::forget(src); + intrinsics::write_via_move(dst, src) } } @@ -1619,8 +1634,8 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <= // 1, where the method versions of these operations are not inlined. use intrinsics::{ - cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_shl, unchecked_shr, - unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub, + assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_shl, + unchecked_shr, unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub, }; /// Calculate multiplicative modular inverse of `x` modulo `m`. @@ -1711,12 +1726,18 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz // in a branch-free way and then bitwise-OR it with whatever result the `-p mod a` // computation produces. + let aligned_address = wrapping_add(addr, a_minus_one) & wrapping_sub(0, a); + let byte_offset = wrapping_sub(aligned_address, addr); + // FIXME: Remove the assume after <https://github.com/llvm/llvm-project/issues/62502> + // SAFETY: Masking by `-a` can only affect the low bits, and thus cannot have reduced + // the value by more than `a-1`, so even though the intermediate values might have + // wrapped, the byte_offset is always in `[0, a)`. + unsafe { assume(byte_offset < a) }; + // SAFETY: `stride == 0` case has been handled by the special case above. let addr_mod_stride = unsafe { unchecked_rem(addr, stride) }; return if addr_mod_stride == 0 { - let aligned_address = wrapping_add(addr, a_minus_one) & wrapping_sub(0, a); - let byte_offset = wrapping_sub(aligned_address, addr); // SAFETY: `stride` is non-zero. This is guaranteed to divide exactly as well, because // addr has been verified to be aligned to the original type’s alignment requirements. unsafe { exact_div(byte_offset, stride) } @@ -1732,7 +1753,12 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz // miracles, given the situations this case has to deal with. // SAFETY: a is power-of-two hence non-zero. stride == 0 case is handled above. - let gcdpow = unsafe { cttz_nonzero(stride).min(cttz_nonzero(a)) }; + // FIXME(const-hack) replace with min + let gcdpow = unsafe { + let x = cttz_nonzero(stride); + let y = cttz_nonzero(a); + if x < y { x } else { y } + }; // SAFETY: gcdpow has an upper-bound that’s at most the number of bits in a usize. let gcd = unsafe { unchecked_shl(1usize, gcdpow) }; // SAFETY: gcd is always greater or equal to 1. @@ -1860,149 +1886,51 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) { hashee.hash(into); } -// If this is a unary fn pointer, it adds a doc comment. -// Otherwise, it hides the docs entirely. -macro_rules! maybe_fnptr_doc { - (@ #[$meta:meta] $item:item) => { - #[doc(hidden)] - #[$meta] - $item - }; - ($a:ident @ #[$meta:meta] $item:item) => { - #[doc(fake_variadic)] - #[doc = "This trait is implemented for function pointers with up to twelve arguments."] - #[$meta] - $item - }; - ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => { - #[doc(hidden)] - #[$meta] - $item - }; +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl<F: FnPtr> PartialEq for F { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.addr() == other.addr() + } } +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl<F: FnPtr> Eq for F {} -// FIXME(strict_provenance_magic): function pointers have buggy codegen that -// necessitates casting to a usize to get the backend to do the right thing. -// for now I will break AVR to silence *a billion* lints. We should probably -// have a proper "opaque function pointer type" to handle this kind of thing. - -// Impls for function pointers -macro_rules! fnptr_impls_safety_abi { - ($FnTy: ty, $($Arg: ident),*) => { - fnptr_impls_safety_abi! { #[stable(feature = "fnptr_impls", since = "1.4.0")] $FnTy, $($Arg),* } - }; - (@c_unwind $FnTy: ty, $($Arg: ident),*) => { - fnptr_impls_safety_abi! { #[unstable(feature = "c_unwind", issue = "74990")] $FnTy, $($Arg),* } - }; - (#[$meta:meta] $FnTy: ty, $($Arg: ident),*) => { - maybe_fnptr_doc! { - $($Arg)* @ - #[$meta] - impl<Ret, $($Arg),*> PartialEq for $FnTy { - #[inline] - fn eq(&self, other: &Self) -> bool { - *self as usize == *other as usize - } - } - } - - maybe_fnptr_doc! { - $($Arg)* @ - #[$meta] - impl<Ret, $($Arg),*> Eq for $FnTy {} - } - - maybe_fnptr_doc! { - $($Arg)* @ - #[$meta] - impl<Ret, $($Arg),*> PartialOrd for $FnTy { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - (*self as usize).partial_cmp(&(*other as usize)) - } - } - } - - maybe_fnptr_doc! { - $($Arg)* @ - #[$meta] - impl<Ret, $($Arg),*> Ord for $FnTy { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - (*self as usize).cmp(&(*other as usize)) - } - } - } - - maybe_fnptr_doc! { - $($Arg)* @ - #[$meta] - impl<Ret, $($Arg),*> hash::Hash for $FnTy { - fn hash<HH: hash::Hasher>(&self, state: &mut HH) { - state.write_usize(*self as usize) - } - } - } - - maybe_fnptr_doc! { - $($Arg)* @ - #[$meta] - impl<Ret, $($Arg),*> fmt::Pointer for $FnTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::pointer_fmt_inner(*self as usize, f) - } - } - } +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl<F: FnPtr> PartialOrd for F { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + self.addr().partial_cmp(&other.addr()) + } +} +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl<F: FnPtr> Ord for F { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.addr().cmp(&other.addr()) + } +} - maybe_fnptr_doc! { - $($Arg)* @ - #[$meta] - impl<Ret, $($Arg),*> fmt::Debug for $FnTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::pointer_fmt_inner(*self as usize, f) - } - } - } +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl<F: FnPtr> hash::Hash for F { + fn hash<HH: hash::Hasher>(&self, state: &mut HH) { + state.write_usize(self.addr() as _) } } -macro_rules! fnptr_impls_args { - ($($Arg: ident),+) => { - fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { extern "C" fn($($Arg),+) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn($($Arg),+) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn($($Arg),+ , ...) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn($($Arg),+) -> Ret, $($Arg),+ } - fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn($($Arg),+ , ...) -> Ret, $($Arg),+ } - }; - () => { - // No variadic functions with 0 parameters - fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, } - fnptr_impls_safety_abi! { extern "C" fn() -> Ret, } - fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn() -> Ret, } - fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, } - fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, } - fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn() -> Ret, } - }; +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl<F: FnPtr> fmt::Pointer for F { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::pointer_fmt_inner(self.addr() as _, f) + } } -fnptr_impls_args! {} -fnptr_impls_args! { T } -fnptr_impls_args! { A, B } -fnptr_impls_args! { A, B, C } -fnptr_impls_args! { A, B, C, D } -fnptr_impls_args! { A, B, C, D, E } -fnptr_impls_args! { A, B, C, D, E, F } -fnptr_impls_args! { A, B, C, D, E, F, G } -fnptr_impls_args! { A, B, C, D, E, F, G, H } -fnptr_impls_args! { A, B, C, D, E, F, G, H, I } -fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J } -fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K } -fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } +#[stable(feature = "fnptr_impls", since = "1.4.0")] +impl<F: FnPtr> fmt::Debug for F { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::pointer_fmt_inner(self.addr() as _, f) + } +} /// Create a `const` raw pointer to a place, without creating an intermediate reference. /// @@ -2034,7 +1962,7 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } /// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2); /// ``` /// -/// See [`addr_of_mut`] for how to create a pointer to unininitialized data. +/// See [`addr_of_mut`] for how to create a pointer to uninitialized data. /// Doing that with `addr_of` would not make much sense since one could only /// read the data, and that would be Undefined Behavior. #[stable(feature = "raw_ref_macros", since = "1.51.0")] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 422d0f2b8f0..5edd291fb76 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -60,14 +60,14 @@ impl<T: ?Sized> *mut T { /// Use the pointer value in a new pointer of another type. /// - /// In case `val` is a (fat) pointer to an unsized type, this operation + /// In case `meta` is a (fat) pointer to an unsized type, this operation /// will ignore the pointer part, whereas for (thin) pointers to sized /// types, this has the same effect as a simple cast. /// /// The resulting pointer will have provenance of `self`, i.e., for a fat /// pointer, this operation is semantically the same as creating a new /// fat pointer with the data pointer value of `self` but the metadata of - /// `val`. + /// `meta`. /// /// # Examples /// @@ -138,8 +138,8 @@ impl<T: ?Sized> *mut T { /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[deprecated( - since = "1.67", - note = "replaced by the `exposed_addr` method, or update your code \ + since = "1.67.0", + note = "replaced by the `expose_addr` method, or update your code \ to follow the strict provenance rules using its APIs" )] #[inline(always)] @@ -167,7 +167,7 @@ impl<T: ?Sized> *mut T { /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[deprecated( - since = "1.67", + since = "1.67.0", note = "replaced by the `ptr::from_exposed_addr_mut` function, or \ update your code to follow the strict provenance rules using its APIs" )] @@ -270,7 +270,7 @@ impl<T: ?Sized> *mut T { let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); - // This is the canonical desugarring of this operation + // This is the canonical desugaring of this operation self.wrapping_byte_offset(offset) } @@ -473,10 +473,20 @@ impl<T: ?Sized> *mut T { where T: Sized, { + #[cfg(bootstrap)] // SAFETY: the caller must uphold the safety contract for `offset`. // The obtained pointer is valid for writes since the caller must // guarantee that it points to the same allocated object as `self`. - unsafe { intrinsics::offset(self, count) as *mut T } + unsafe { + intrinsics::offset(self, count) as *mut T + } + #[cfg(not(bootstrap))] + // SAFETY: the caller must uphold the safety contract for `offset`. + // The obtained pointer is valid for writes since the caller must + // guarantee that it points to the same allocated object as `self`. + unsafe { + intrinsics::offset(self, count) + } } /// Calculates the offset from a pointer in bytes. @@ -1016,8 +1026,16 @@ impl<T: ?Sized> *mut T { where T: Sized, { + #[cfg(bootstrap)] + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { + self.offset(count as isize) + } + #[cfg(not(bootstrap))] // SAFETY: the caller must uphold the safety contract for `offset`. - unsafe { self.offset(count as isize) } + unsafe { + intrinsics::offset(self, count) + } } /// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`). @@ -1287,7 +1305,7 @@ impl<T: ?Sized> *mut T { /// /// [`ptr::read`]: crate::ptr::read() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] + #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn read(self) -> T @@ -1328,7 +1346,7 @@ impl<T: ?Sized> *mut T { /// /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")] + #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn read_unaligned(self) -> T @@ -2036,11 +2054,10 @@ impl<T> *mut [T] { /// } /// ``` #[unstable(feature = "slice_ptr_get", issue = "74265")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline(always)] - pub const unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output + pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output where - I: ~const SliceIndex<[T]>, + I: SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. unsafe { index.get_unchecked_mut(self) } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 8c1a6488605..b492d2f07bc 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -449,6 +449,19 @@ impl<T: ?Sized> NonNull<T> { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } } + + /// See [`pointer::add`] for semantics and safety requirements. + #[inline] + pub(crate) const unsafe fn add(self, delta: usize) -> Self + where + T: Sized, + { + // SAFETY: We require that the delta stays in-bounds of the object, and + // thus it cannot become null, as that would require wrapping the + // address space, which no legal objects are allowed to do. + // And the caller promised the `delta` is sound to add. + unsafe { NonNull { pointer: self.pointer.add(delta) } } + } } impl<T> NonNull<[T]> { @@ -462,8 +475,6 @@ impl<T> NonNull<[T]> { /// # Examples /// /// ```rust - /// #![feature(nonnull_slice_from_raw_parts)] - /// /// use std::ptr::NonNull; /// /// // create a slice pointer when starting out with a pointer to the first element @@ -475,8 +486,8 @@ impl<T> NonNull<[T]> { /// /// (Note that this example artificially demonstrates a use of this method, /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) - #[unstable(feature = "nonnull_slice_from_raw_parts", issue = "71941")] - #[rustc_const_unstable(feature = "const_nonnull_slice_from_raw_parts", issue = "71941")] + #[stable(feature = "nonnull_slice_from_raw_parts", since = "1.70.0")] + #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")] #[must_use] #[inline] pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self { @@ -494,7 +505,6 @@ impl<T> NonNull<[T]> { /// # Examples /// /// ```rust - /// #![feature(nonnull_slice_from_raw_parts)] /// use std::ptr::NonNull; /// /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); @@ -514,7 +524,7 @@ impl<T> NonNull<[T]> { /// # Examples /// /// ```rust - /// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)] + /// #![feature(slice_ptr_get)] /// use std::ptr::NonNull; /// /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); @@ -534,7 +544,7 @@ impl<T> NonNull<[T]> { /// # Examples /// /// ```rust - /// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)] + /// #![feature(slice_ptr_get)] /// use std::ptr::NonNull; /// /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); @@ -668,7 +678,7 @@ impl<T> NonNull<[T]> { /// # Examples /// /// ``` - /// #![feature(slice_ptr_get, nonnull_slice_from_raw_parts)] + /// #![feature(slice_ptr_get)] /// use std::ptr::NonNull; /// /// let x = &mut [1, 2, 4]; @@ -679,11 +689,10 @@ impl<T> NonNull<[T]> { /// } /// ``` #[unstable(feature = "slice_ptr_get", issue = "74265")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub const unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output> + pub unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output> where - I: ~const SliceIndex<[T]>, + I: SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. // As a consequence, the resulting pointer cannot be null. @@ -692,8 +701,7 @@ impl<T> NonNull<[T]> { } #[stable(feature = "nonnull", since = "1.25.0")] -#[rustc_const_unstable(feature = "const_clone", issue = "91805")] -impl<T: ?Sized> const Clone for NonNull<T> { +impl<T: ?Sized> Clone for NonNull<T> { #[inline(always)] fn clone(&self) -> Self { *self @@ -759,8 +767,7 @@ impl<T: ?Sized> hash::Hash for NonNull<T> { } #[unstable(feature = "ptr_internals", issue = "none")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T: ?Sized> const From<Unique<T>> for NonNull<T> { +impl<T: ?Sized> From<Unique<T>> for NonNull<T> { #[inline] fn from(unique: Unique<T>) -> Self { // SAFETY: A Unique pointer cannot be null, so the conditions for @@ -770,8 +777,7 @@ impl<T: ?Sized> const From<Unique<T>> for NonNull<T> { } #[stable(feature = "nonnull", since = "1.25.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T: ?Sized> const From<&mut T> for NonNull<T> { +impl<T: ?Sized> From<&mut T> for NonNull<T> { /// Converts a `&mut T` to a `NonNull<T>`. /// /// This conversion is safe and infallible since references cannot be null. @@ -783,8 +789,7 @@ impl<T: ?Sized> const From<&mut T> for NonNull<T> { } #[stable(feature = "nonnull", since = "1.25.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T: ?Sized> const From<&T> for NonNull<T> { +impl<T: ?Sized> From<&T> for NonNull<T> { /// Converts a `&T` to a `NonNull<T>`. /// /// This conversion is safe and infallible since references cannot be null. diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 64616142b41..a853f15edb7 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -70,7 +70,8 @@ impl<T: Sized> Unique<T> { #[must_use] #[inline] pub const fn dangling() -> Self { - Self::from(NonNull::dangling()) + // FIXME(const-hack) replace with `From` + Unique { pointer: NonNull::dangling(), _marker: PhantomData } } } @@ -134,13 +135,14 @@ impl<T: ?Sized> Unique<T> { #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub const fn cast<U>(self) -> Unique<U> { - Unique::from(self.pointer.cast()) + // FIXME(const-hack): replace with `From` + // SAFETY: is `NonNull` + unsafe { Unique::new_unchecked(self.pointer.cast().as_ptr()) } } } #[unstable(feature = "ptr_internals", issue = "none")] -#[rustc_const_unstable(feature = "const_clone", issue = "91805")] -impl<T: ?Sized> const Clone for Unique<T> { +impl<T: ?Sized> Clone for Unique<T> { #[inline] fn clone(&self) -> Self { *self @@ -171,7 +173,7 @@ impl<T: ?Sized> fmt::Pointer for Unique<T> { } #[unstable(feature = "ptr_internals", issue = "none")] -impl<T: ?Sized> const From<&mut T> for Unique<T> { +impl<T: ?Sized> From<&mut T> for Unique<T> { /// Converts a `&mut T` to a `Unique<T>`. /// /// This conversion is infallible since references cannot be null. @@ -182,7 +184,7 @@ impl<T: ?Sized> const From<&mut T> for Unique<T> { } #[unstable(feature = "ptr_internals", issue = "none")] -impl<T: ?Sized> const From<NonNull<T>> for Unique<T> { +impl<T: ?Sized> From<NonNull<T>> for Unique<T> { /// Converts a `NonNull<T>` to a `Unique<T>`. /// /// This conversion is infallible since `NonNull` cannot be null. diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 208b220c24a..1ee270f4c03 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -489,7 +489,6 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; -use crate::marker::Destruct; use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::{convert, fmt, hint}; @@ -545,8 +544,6 @@ impl<T, E> Result<T, E> { /// # Examples /// /// ``` - /// #![feature(is_some_and)] - /// /// let x: Result<u32, &str> = Ok(2); /// assert_eq!(x.is_ok_and(|x| x > 1), true); /// @@ -558,7 +555,7 @@ impl<T, E> Result<T, E> { /// ``` #[must_use] #[inline] - #[unstable(feature = "is_some_and", issue = "93050")] + #[stable(feature = "is_some_and", since = "1.70.0")] pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool { match self { Err(_) => false, @@ -590,7 +587,6 @@ impl<T, E> Result<T, E> { /// # Examples /// /// ``` - /// #![feature(is_some_and)] /// use std::io::{Error, ErrorKind}; /// /// let x: Result<u32, Error> = Err(Error::new(ErrorKind::NotFound, "!")); @@ -604,7 +600,7 @@ impl<T, E> Result<T, E> { /// ``` #[must_use] #[inline] - #[unstable(feature = "is_some_and", issue = "93050")] + #[stable(feature = "is_some_and", since = "1.70.0")] pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool { match self { Ok(_) => false, @@ -632,16 +628,10 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] - pub const fn ok(self) -> Option<T> - where - E: ~const Destruct, - { + pub fn ok(self) -> Option<T> { match self { Ok(x) => Some(x), - // FIXME: ~const Drop doesn't quite work right yet - #[allow(unused_variables)] - Err(x) => None, + Err(_) => None, } } @@ -661,15 +651,9 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] - pub const fn err(self) -> Option<E> - where - T: ~const Destruct, - { + pub fn err(self) -> Option<E> { match self { - // FIXME: ~const Drop doesn't quite work right yet - #[allow(unused_variables)] - Ok(x) => None, + Ok(_) => None, Err(x) => Some(x), } } @@ -908,6 +892,7 @@ impl<T, E> Result<T, E> { /// let y: Result<&str, &u32> = Err(&42); /// assert_eq!(x.as_deref(), y); /// ``` + #[inline] #[stable(feature = "inner_deref", since = "1.47.0")] pub fn as_deref(&self) -> Result<&T::Target, &E> where @@ -934,6 +919,7 @@ impl<T, E> Result<T, E> { /// let y: Result<&mut str, &mut u32> = Err(&mut i); /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); /// ``` + #[inline] #[stable(feature = "inner_deref", since = "1.47.0")] pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> where @@ -1288,18 +1274,10 @@ impl<T, E> Result<T, E> { /// assert_eq!(x.and(y), Ok("different result type")); /// ``` #[inline] - #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] #[stable(feature = "rust1", since = "1.0.0")] - pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E> - where - T: ~const Destruct, - U: ~const Destruct, - E: ~const Destruct, - { + pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> { match self { - // FIXME: ~const Drop doesn't quite work right yet - #[allow(unused_variables)] - Ok(x) => res, + Ok(_) => res, Err(e) => Err(e), } } @@ -1371,19 +1349,11 @@ impl<T, E> Result<T, E> { /// assert_eq!(x.or(y), Ok(2)); /// ``` #[inline] - #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] #[stable(feature = "rust1", since = "1.0.0")] - pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F> - where - T: ~const Destruct, - E: ~const Destruct, - F: ~const Destruct, - { + pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> { match self { Ok(v) => Ok(v), - // FIXME: ~const Drop doesn't quite work right yet - #[allow(unused_variables)] - Err(e) => res, + Err(_) => res, } } @@ -1431,18 +1401,11 @@ impl<T, E> Result<T, E> { /// assert_eq!(x.unwrap_or(default), default); /// ``` #[inline] - #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] #[stable(feature = "rust1", since = "1.0.0")] - pub const fn unwrap_or(self, default: T) -> T - where - T: ~const Destruct, - E: ~const Destruct, - { + pub fn unwrap_or(self, default: T) -> T { match self { Ok(t) => t, - // FIXME: ~const Drop doesn't quite work right yet - #[allow(unused_variables)] - Err(e) => default, + Err(_) => default, } } @@ -1529,68 +1492,6 @@ impl<T, E> Result<T, E> { Err(e) => e, } } - - ///////////////////////////////////////////////////////////////////////// - // Misc or niche - ///////////////////////////////////////////////////////////////////////// - - /// Returns `true` if the result is an [`Ok`] value containing the given value. - /// - /// # Examples - /// - /// ``` - /// #![feature(option_result_contains)] - /// - /// let x: Result<u32, &str> = Ok(2); - /// assert_eq!(x.contains(&2), true); - /// - /// let x: Result<u32, &str> = Ok(3); - /// assert_eq!(x.contains(&2), false); - /// - /// let x: Result<u32, &str> = Err("Some error message"); - /// assert_eq!(x.contains(&2), false); - /// ``` - #[must_use] - #[inline] - #[unstable(feature = "option_result_contains", issue = "62358")] - pub fn contains<U>(&self, x: &U) -> bool - where - U: PartialEq<T>, - { - match self { - Ok(y) => x == y, - Err(_) => false, - } - } - - /// Returns `true` if the result is an [`Err`] value containing the given value. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_contains_err)] - /// - /// let x: Result<u32, &str> = Ok(2); - /// assert_eq!(x.contains_err(&"Some error message"), false); - /// - /// let x: Result<u32, &str> = Err("Some error message"); - /// assert_eq!(x.contains_err(&"Some error message"), true); - /// - /// let x: Result<u32, &str> = Err("Some other error message"); - /// assert_eq!(x.contains_err(&"Some error message"), false); - /// ``` - #[must_use] - #[inline] - #[unstable(feature = "result_contains_err", issue = "62358")] - pub fn contains_err<F>(&self, f: &F) -> bool - where - F: PartialEq<E>, - { - match self { - Ok(_) => false, - Err(e) => f == e, - } - } } impl<T, E> Result<&T, E> { @@ -1767,11 +1668,10 @@ fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! { ///////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_clone", issue = "91805")] -impl<T, E> const Clone for Result<T, E> +impl<T, E> Clone for Result<T, E> where - T: ~const Clone + ~const Destruct, - E: ~const Clone + ~const Destruct, + T: Clone, + E: Clone, { #[inline] fn clone(&self) -> Self { @@ -2034,8 +1934,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> { } #[unstable(feature = "try_trait_v2", issue = "84277")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T, E> const ops::Try for Result<T, E> { +impl<T, E> ops::Try for Result<T, E> { type Output = T; type Residual = Result<convert::Infallible, E>; @@ -2054,10 +1953,7 @@ impl<T, E> const ops::Try for Result<T, E> { } #[unstable(feature = "try_trait_v2", issue = "84277")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T, E, F: ~const From<E>> const ops::FromResidual<Result<convert::Infallible, E>> - for Result<T, F> -{ +impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Result<T, F> { #[inline] #[track_caller] fn from_residual(residual: Result<convert::Infallible, E>) -> Self { @@ -2076,7 +1972,6 @@ impl<T, E, F: From<E>> ops::FromResidual<ops::Yeet<E>> for Result<T, F> { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -#[rustc_const_unstable(feature = "const_try", issue = "74935")] -impl<T, E> const ops::Residual<T> for Result<convert::Infallible, E> { +impl<T, E> ops::Residual<T> for Result<convert::Infallible, E> { type TryType = Result<T, E>; } diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 5e5399acc1b..f3311f76a7f 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -10,12 +10,43 @@ use crate::ops; impl [u8] { /// Checks if all bytes in this slice are within the ASCII range. #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_unstable(feature = "const_slice_is_ascii", issue = "111090")] #[must_use] #[inline] - pub fn is_ascii(&self) -> bool { + pub const fn is_ascii(&self) -> bool { is_ascii(self) } + /// If this slice [`is_ascii`](Self::is_ascii), returns it as a slice of + /// [ASCII characters](`ascii::Char`), otherwise returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const fn as_ascii(&self) -> Option<&[ascii::Char]> { + if self.is_ascii() { + // SAFETY: Just checked that it's ASCII + Some(unsafe { self.as_ascii_unchecked() }) + } else { + None + } + } + + /// Converts this slice of bytes into a slice of ASCII characters, + /// without checking whether they're valid. + /// + /// # Safety + /// + /// Every byte in the slice must be in `0..=127`, or else this is UB. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char] { + let byte_ptr: *const [u8] = self; + let ascii_ptr = byte_ptr as *const [ascii::Char]; + // SAFETY: The caller promised all the bytes are ASCII + unsafe { &*ascii_ptr } + } + /// Checks that two slices are an ASCII case-insensitive match. /// /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, @@ -232,11 +263,29 @@ impl<'a> fmt::Debug for EscapeAscii<'a> { /// Returns `true` if any byte in the word `v` is nonascii (>= 128). Snarfed /// from `../str/mod.rs`, which does something similar for utf8 validation. #[inline] -fn contains_nonascii(v: usize) -> bool { +const fn contains_nonascii(v: usize) -> bool { const NONASCII_MASK: usize = usize::repeat_u8(0x80); (NONASCII_MASK & v) != 0 } +/// ASCII test *without* the chunk-at-a-time optimizations. +/// +/// This is carefully structured to produce nice small code -- it's smaller in +/// `-O` than what the "obvious" ways produces under `-C opt-level=s`. If you +/// touch it, be sure to run (and update if needed) the assembly test. +#[unstable(feature = "str_internals", issue = "none")] +#[doc(hidden)] +#[inline] +pub const fn is_ascii_simple(mut bytes: &[u8]) -> bool { + while let [rest @ .., last] = bytes { + if !last.is_ascii() { + break; + } + bytes = rest; + } + bytes.is_empty() +} + /// Optimized ASCII test that will use usize-at-a-time operations instead of /// byte-at-a-time operations (when possible). /// @@ -250,7 +299,7 @@ fn contains_nonascii(v: usize) -> bool { /// If any of these loads produces something for which `contains_nonascii` /// (above) returns true, then we know the answer is false. #[inline] -fn is_ascii(s: &[u8]) -> bool { +const fn is_ascii(s: &[u8]) -> bool { const USIZE_SIZE: usize = mem::size_of::<usize>(); let len = s.len(); @@ -262,7 +311,7 @@ fn is_ascii(s: &[u8]) -> bool { // We also do this for architectures where `size_of::<usize>()` isn't // sufficient alignment for `usize`, because it's a weird edge case. if len < USIZE_SIZE || len < align_offset || USIZE_SIZE < mem::align_of::<usize>() { - return s.iter().all(|b| b.is_ascii()); + return is_ascii_simple(s); } // We always read the first word unaligned, which means `align_offset` is @@ -291,18 +340,26 @@ fn is_ascii(s: &[u8]) -> bool { // Paranoia check about alignment, since we're about to do a bunch of // unaligned loads. In practice this should be impossible barring a bug in // `align_offset` though. - debug_assert_eq!(word_ptr.addr() % mem::align_of::<usize>(), 0); + // While this method is allowed to spuriously fail in CTFE, if it doesn't + // have alignment information it should have given a `usize::MAX` for + // `align_offset` earlier, sending things through the scalar path instead of + // this one, so this check should pass if it's reachable. + debug_assert!(word_ptr.is_aligned_to(mem::align_of::<usize>())); // Read subsequent words until the last aligned word, excluding the last // aligned word by itself to be done in tail check later, to ensure that // tail is always one `usize` at most to extra branch `byte_pos == len`. while byte_pos < len - USIZE_SIZE { - debug_assert!( - // Sanity check that the read is in bounds - (word_ptr.addr() + USIZE_SIZE) <= start.addr().wrapping_add(len) && - // And that our assumptions about `byte_pos` hold. - (word_ptr.addr() - start.addr()) == byte_pos - ); + // Sanity check that the read is in bounds + debug_assert!(byte_pos + USIZE_SIZE <= len); + // And that our assumptions about `byte_pos` hold. + debug_assert!(matches!( + word_ptr.cast::<u8>().guaranteed_eq(start.wrapping_add(byte_pos)), + // These are from the same allocation, so will hopefully always be + // known to match even in CTFE, but if it refuses to compare them + // that's ok since it's just a debug check anyway. + None | Some(true), + )); // SAFETY: We know `word_ptr` is properly aligned (because of // `align_offset`), and we know that we have enough bytes between `word_ptr` and the end diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 5e1b218e507..7601dd3c756 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -1,6 +1,6 @@ //! Comparison traits for `[T]`. -use crate::cmp::{self, Ordering}; +use crate::cmp::{self, BytewiseEq, Ordering}; use crate::ffi; use crate::mem; @@ -77,7 +77,7 @@ where // Use memcmp for bytewise equality when the types allow impl<A, B> SlicePartialEq<B> for [A] where - A: BytewiseEquality<B>, + A: BytewiseEq<B>, { fn equal(&self, other: &[B]) -> bool { if self.len() != other.len() { @@ -203,29 +203,6 @@ impl SliceOrd for u8 { } } -// Hack to allow specializing on `Eq` even though `Eq` has a method. -#[rustc_unsafe_specialization_marker] -trait MarkerEq<T>: PartialEq<T> {} - -impl<T: Eq> MarkerEq<T> for T {} - -#[doc(hidden)] -/// Trait implemented for types that can be compared for equality using -/// their bytewise representation -#[rustc_specialization_trait] -trait BytewiseEquality<T>: MarkerEq<T> + Copy {} - -macro_rules! impl_marker_for { - ($traitname:ident, $($ty:ty)*) => { - $( - impl $traitname<$ty> for $ty { } - )* - } -} - -impl_marker_for!(BytewiseEquality, - u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize char bool); - pub(super) trait SliceContains: Sized { fn slice_contains(&self, x: &[Self]) -> bool; } diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index c295a0e0645..6ef9f9c95e8 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -2,14 +2,14 @@ use crate::intrinsics::assert_unsafe_precondition; use crate::intrinsics::const_eval_select; +use crate::intrinsics::unchecked_sub; use crate::ops; use crate::ptr; #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -impl<T, I> const ops::Index<I> for [T] +impl<T, I> ops::Index<I> for [T] where - I: ~const SliceIndex<[T]>, + I: SliceIndex<[T]>, { type Output = I::Output; @@ -20,10 +20,9 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -impl<T, I> const ops::IndexMut<I> for [T] +impl<T, I> ops::IndexMut<I> for [T] where - I: ~const SliceIndex<[T]>, + I: SliceIndex<[T]>, { #[inline] fn index_mut(&mut self, index: I) -> &mut I::Output { @@ -161,7 +160,6 @@ mod private_slice_index { message = "the type `{T}` cannot be indexed by `{Self}`", label = "slice indices are of type `usize` or ranges of `usize`" )] -#[const_trait] pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed { /// The output type returned by methods. #[stable(feature = "slice_get_slice", since = "1.28.0")] @@ -210,7 +208,7 @@ pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed { #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl<T> const SliceIndex<[T]> for usize { +unsafe impl<T> SliceIndex<[T]> for usize { type Output = T; #[inline] @@ -270,7 +268,7 @@ unsafe impl<T> const SliceIndex<[T]> for usize { /// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here /// than there are for a general `Range<usize>` (which might be `100..3`). #[rustc_const_unstable(feature = "const_index_range_slice_index", issue = "none")] -unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange { +unsafe impl<T> SliceIndex<[T]> for ops::IndexRange { type Output = [T]; #[inline] @@ -346,7 +344,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange { #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> { +unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> { type Output = [T]; #[inline] @@ -371,25 +369,25 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> { #[inline] unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { - let this = ops::Range { start: self.start, end: self.end }; + let this = ops::Range { ..self }; // SAFETY: the caller guarantees that `slice` is not dangling, so it // cannot be longer than `isize::MAX`. They also guarantee that // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, - // so the call to `add` is safe. - + // so the call to `add` is safe and the length calculation cannot overflow. unsafe { assert_unsafe_precondition!( "slice::get_unchecked requires that the range is within the slice", [T](this: ops::Range<usize>, slice: *const [T]) => this.end >= this.start && this.end <= slice.len() ); - ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) + let new_len = unchecked_sub(self.end, self.start); + ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { - let this = ops::Range { start: self.start, end: self.end }; + let this = ops::Range { ..self }; // SAFETY: see comments for `get_unchecked` above. unsafe { assert_unsafe_precondition!( @@ -397,7 +395,8 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> { [T](this: ops::Range<usize>, slice: *mut [T]) => this.end >= this.start && this.end <= slice.len() ); - ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) + let new_len = unchecked_sub(self.end, self.start); + ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) } } @@ -426,7 +425,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> { #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl<T> const SliceIndex<[T]> for ops::RangeTo<usize> { +unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> { type Output = [T]; #[inline] @@ -464,7 +463,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeTo<usize> { #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> { +unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> { type Output = [T]; #[inline] @@ -510,7 +509,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> { #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl<T> const SliceIndex<[T]> for ops::RangeFull { +unsafe impl<T> SliceIndex<[T]> for ops::RangeFull { type Output = [T]; #[inline] @@ -546,7 +545,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFull { #[stable(feature = "inclusive_range", since = "1.26.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> { +unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> { type Output = [T]; #[inline] @@ -590,7 +589,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> { #[stable(feature = "inclusive_range", since = "1.26.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> { +unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { type Output = [T]; #[inline] diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index c4317799bcc..5369fe0a9a9 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -13,7 +13,7 @@ use crate::iter::{ use crate::marker::{PhantomData, Send, Sized, Sync}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZeroUsize; -use crate::ptr::NonNull; +use crate::ptr::{invalid, invalid_mut, NonNull}; use super::{from_raw_parts, from_raw_parts_mut}; @@ -60,10 +60,15 @@ impl<'a, T> IntoIterator for &'a mut [T] { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, T: 'a> { + /// The pointer to the next element to return, or the past-the-end location + /// if the iterator is empty. + /// + /// This address will be used for all ZST elements, never changed. ptr: NonNull<T>, - end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that - // ptr == end is a quick test for the Iterator being empty, that works - // for both ZST and non-ZST. + /// For non-ZSTs, the non-null pointer to the past-the-end element. + /// + /// For ZSTs, this is `ptr::invalid(len)`. + end: *const T, _marker: PhantomData<&'a T>, } @@ -85,10 +90,7 @@ impl<'a, T> Iter<'a, T> { let ptr = slice.as_ptr(); // SAFETY: Similar to `IterMut::new`. unsafe { - assume(!ptr.is_null()); - - let end = - if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) }; + let end = if T::IS_ZST { invalid(slice.len()) } else { ptr.add(slice.len()) }; Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData } } @@ -132,9 +134,7 @@ iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, { Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>, { - self.as_slice().windows(2).all(|w| { - compare(&&w[0], &&w[1]).map(|o| o != Ordering::Greater).unwrap_or(false) - }) + self.as_slice().is_sorted_by(|a, b| compare(&a, &b)) } }} @@ -181,10 +181,15 @@ impl<T> AsRef<[T]> for Iter<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct IterMut<'a, T: 'a> { + /// The pointer to the next element to return, or the past-the-end location + /// if the iterator is empty. + /// + /// This address will be used for all ZST elements, never changed. ptr: NonNull<T>, - end: *mut T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that - // ptr == end is a quick test for the Iterator being empty, that works - // for both ZST and non-ZST. + /// For non-ZSTs, the non-null pointer to the past-the-end element. + /// + /// For ZSTs, this is `ptr::invalid_mut(len)`. + end: *mut T, _marker: PhantomData<&'a mut T>, } @@ -221,10 +226,7 @@ impl<'a, T> IterMut<'a, T> { // See the `next_unchecked!` and `is_empty!` macros as well as the // `post_inc_start` method for more information. unsafe { - assume(!ptr.is_null()); - - let end = - if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) }; + let end = if T::IS_ZST { invalid_mut(slice.len()) } else { ptr.add(slice.len()) }; Self { ptr: NonNull::new_unchecked(ptr), end, _marker: PhantomData } } @@ -687,7 +689,7 @@ where None } else { self.finished = true; - Some(mem::replace(&mut self.v, &mut [])) + Some(mem::take(&mut self.v)) } } } @@ -751,7 +753,7 @@ where match idx_opt { None => self.finish(), Some(idx) => { - let tmp = mem::replace(&mut self.v, &mut []); + let tmp = mem::take(&mut self.v); let (head, tail) = tmp.split_at_mut(idx); self.v = head; Some(&mut tail[1..]) @@ -832,7 +834,7 @@ where if idx == self.v.len() { self.finished = true; } - let tmp = mem::replace(&mut self.v, &mut []); + let tmp = mem::take(&mut self.v); let (head, tail) = tmp.split_at_mut(idx); self.v = tail; Some(head) @@ -878,7 +880,7 @@ where if idx == 0 { self.finished = true; } - let tmp = mem::replace(&mut self.v, &mut []); + let tmp = mem::take(&mut self.v); let (head, tail) = tmp.split_at_mut(idx); self.v = head; Some(tail) diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs index 89b92a7d597..3462c0e020a 100644 --- a/library/core/src/slice/iter/macros.rs +++ b/library/core/src/slice/iter/macros.rs @@ -1,11 +1,30 @@ //! Macros used by iterators of slice. +// Shrinks the iterator when T is a ZST, setting the length to `new_len`. +// `new_len` must not exceed `self.len()`. +macro_rules! zst_set_len { + ($self: ident, $new_len: expr) => {{ + #![allow(unused_unsafe)] // we're sometimes used within an unsafe block + + // SAFETY: same as `invalid(_mut)`, but the macro doesn't know + // which versions of that function to call, so open-code it. + $self.end = unsafe { mem::transmute::<usize, _>($new_len) }; + }}; +} + +// Shrinks the iterator when T is a ZST, reducing the length by `n`. +// `n` must not exceed `self.len()`. +macro_rules! zst_shrink { + ($self: ident, $n: ident) => { + let new_len = $self.end.addr() - $n; + zst_set_len!($self, new_len); + }; +} + // Inlining is_empty and len makes a huge performance difference macro_rules! is_empty { - // The way we encode the length of a ZST iterator, this works both for ZST - // and non-ZST. ($self: ident) => { - $self.ptr.as_ptr() as *const T == $self.end + if T::IS_ZST { $self.end.addr() == 0 } else { $self.ptr.as_ptr() as *const _ == $self.end } }; } @@ -13,16 +32,13 @@ macro_rules! len { ($self: ident) => {{ #![allow(unused_unsafe)] // we're sometimes used within an unsafe block - let start = $self.ptr; if T::IS_ZST { - // This _cannot_ use `ptr_sub` because we depend on wrapping - // to represent the length of long ZST slice iterators. - $self.end.addr().wrapping_sub(start.as_ptr().addr()) + $self.end.addr() } else { // To get rid of some bounds checks (see `position`), we use ptr_sub instead of // offset_from (Tested by `codegen/slice-position-bounds-check`.) // SAFETY: by the type invariant pointers are aligned and `start <= end` - unsafe { $self.end.sub_ptr(start.as_ptr()) } + unsafe { $self.end.sub_ptr($self.ptr.as_ptr()) } } }}; } @@ -50,14 +66,6 @@ macro_rules! iterator { ($self: ident) => {& $( $mut_ )? *$self.pre_dec_end(1)} } - // Shrinks the iterator when T is a ZST, by moving the end of the iterator - // backwards by `n`. `n` must not exceed `self.len()`. - macro_rules! zst_shrink { - ($self: ident, $n: ident) => { - $self.end = $self.end.wrapping_byte_sub($n); - } - } - impl<'a, T> $name<'a, T> { // Helper function for creating a slice from the iterator. #[inline(always)] @@ -73,16 +81,15 @@ macro_rules! iterator { // Unsafe because the offset must not exceed `self.len()`. #[inline(always)] unsafe fn post_inc_start(&mut self, offset: usize) -> * $raw_mut T { - if mem::size_of::<T>() == 0 { + let old = self.ptr; + if T::IS_ZST { zst_shrink!(self, offset); - self.ptr.as_ptr() } else { - let old = self.ptr.as_ptr(); // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, // so this new pointer is inside `self` and thus guaranteed to be non-null. - self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().add(offset)) }; - old + self.ptr = unsafe { self.ptr.add(offset) }; } + old.as_ptr() } // Helper function for moving the end of the iterator backwards by `offset` elements, @@ -124,12 +131,10 @@ macro_rules! iterator { fn next(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks - // SAFETY: `assume` calls are safe since a slice's start pointer - // must be non-null, and slices over non-ZSTs must also have a - // non-null end pointer. The call to `next_unchecked!` is safe - // since we check if the iterator is empty first. + // SAFETY: `assume` call is safe because slices over non-ZSTs must + // have a non-null end pointer. The call to `next_unchecked!` is + // safe since we check if the iterator is empty first. unsafe { - assume(!self.ptr.as_ptr().is_null()); if !<T>::IS_ZST { assume(!self.end.is_null()); } @@ -157,9 +162,7 @@ macro_rules! iterator { if n >= len!(self) { // This iterator is now empty. if T::IS_ZST { - // We have to do it this way as `ptr` may never be 0, but `end` - // could be (due to wrapping). - self.end = self.ptr.as_ptr(); + zst_set_len!(self, 0); } else { // SAFETY: end can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr unsafe { @@ -176,11 +179,11 @@ macro_rules! iterator { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let advance = cmp::min(len!(self), n); // SAFETY: By construction, `advance` does not exceed `self.len()`. unsafe { self.post_inc_start(advance) }; - if advance == n { Ok(()) } else { Err(advance) } + NonZeroUsize::new(n - advance).map_or(Ok(()), Err) } #[inline] @@ -339,12 +342,10 @@ macro_rules! iterator { fn next_back(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks - // SAFETY: `assume` calls are safe since a slice's start pointer must be non-null, - // and slices over non-ZSTs must also have a non-null end pointer. - // The call to `next_back_unchecked!` is safe since we check if the iterator is - // empty first. + // SAFETY: `assume` call is safe because slices over non-ZSTs must + // have a non-null end pointer. The call to `next_back_unchecked!` + // is safe since we check if the iterator is empty first. unsafe { - assume(!self.ptr.as_ptr().is_null()); if !<T>::IS_ZST { assume(!self.end.is_null()); } @@ -360,7 +361,11 @@ macro_rules! iterator { fn nth_back(&mut self, n: usize) -> Option<$elem> { if n >= len!(self) { // This iterator is now empty. - self.end = self.ptr.as_ptr(); + if T::IS_ZST { + zst_set_len!(self, 0); + } else { + self.end = self.ptr.as_ptr(); + } return None; } // SAFETY: We are in bounds. `pre_dec_end` does the right thing even for ZSTs. @@ -371,11 +376,11 @@ macro_rules! iterator { } #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { let advance = cmp::min(len!(self), n); // SAFETY: By construction, `advance` does not exceed `self.len()`. unsafe { self.pre_dec_end(advance) }; - if advance == n { Ok(()) } else { Err(advance) } + NonZeroUsize::new(n - advance).map_or(Ok(()), Err) } } @@ -393,6 +398,20 @@ macro_rules! iterator { } } } + + #[stable(feature = "default_iters", since = "1.70.0")] + impl<T> Default for $name<'_, T> { + /// Creates an empty slice iterator. + /// + /// ``` + #[doc = concat!("# use core::slice::", stringify!($name), ";")] + #[doc = concat!("let iter: ", stringify!($name<'_, u8>), " = Default::default();")] + /// assert_eq!(iter.len(), 0); + /// ``` + fn default() -> Self { + (& $( $mut_ )? []).into_iter() + } + } } } diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 98c8349eb60..3a8b59d727b 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -1,7 +1,6 @@ // Original implementation taken from rust-memchr. // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch -use crate::cmp; use crate::mem; const LO_USIZE: usize = usize::repeat_u8(0x01); @@ -83,8 +82,12 @@ const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> { let mut offset = ptr.align_offset(USIZE_BYTES); if offset > 0 { - offset = cmp::min(offset, len); - if let Some(index) = memchr_naive(x, &text[..offset]) { + // FIXME(const-hack, fee1-dead): replace with min + offset = if offset < len { offset } else { len }; + // FIXME(const-hack, fee1-dead): replace with range slicing + // SAFETY: offset is within bounds + let slice = unsafe { super::from_raw_parts(text.as_ptr(), offset) }; + if let Some(index) = memchr_naive(x, slice) { return Some(index); } } @@ -110,7 +113,10 @@ const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> { // Find the byte after the point the body loop stopped. // FIXME(const-hack): Use `?` instead. - if let Some(i) = memchr_naive(x, &text[offset..]) { Some(offset + i) } else { None } + // FIXME(const-hack, fee1-dead): use range slicing + // SAFETY: offset is within bounds + let slice = unsafe { super::from_raw_parts(text.as_ptr().add(offset), text.len() - offset) }; + if let Some(i) = memchr_naive(x, slice) { Some(offset + i) } else { None } } /// Returns the last index matching the byte `x` in `text`. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index fae5ce4128a..6fd2b87d0e3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -44,6 +44,10 @@ mod raw; mod rotate; mod specialize; +#[unstable(feature = "str_internals", issue = "none")] +#[doc(hidden)] +pub use ascii::is_ascii_simple; + #[stable(feature = "rust1", since = "1.0.0")] pub use iter::{Chunks, ChunksMut, Windows}; #[stable(feature = "rust1", since = "1.0.0")] @@ -333,12 +337,11 @@ impl<T> [T] { /// assert_eq!(None, v.get(0..4)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] #[must_use] - pub const fn get<I>(&self, index: I) -> Option<&I::Output> + pub fn get<I>(&self, index: I) -> Option<&I::Output> where - I: ~const SliceIndex<Self>, + I: SliceIndex<Self>, { index.get(self) } @@ -359,12 +362,11 @@ impl<T> [T] { /// assert_eq!(x, &[0, 42, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] #[must_use] - pub const fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output> + pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output> where - I: ~const SliceIndex<Self>, + I: SliceIndex<Self>, { index.get_mut(self) } @@ -392,12 +394,11 @@ impl<T> [T] { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] #[must_use] - pub const unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output + pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output where - I: ~const SliceIndex<Self>, + I: SliceIndex<Self>, { // SAFETY: the caller must uphold most of the safety requirements for `get_unchecked`; // the slice is dereferenceable because `self` is a safe reference. @@ -430,12 +431,11 @@ impl<T> [T] { /// assert_eq!(x, &[1, 13, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] #[must_use] - pub const unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output + pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output where - I: ~const SliceIndex<Self>, + I: SliceIndex<Self>, { // SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`; // the slice is dereferenceable because `self` is a safe reference. @@ -678,9 +678,8 @@ impl<T> [T] { /// assert!(v == [3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_reverse", issue = "100784")] #[inline] - pub const fn reverse(&mut self) { + pub fn reverse(&mut self) { let half_len = self.len() / 2; let Range { start, end } = self.as_mut_ptr_range(); @@ -703,7 +702,7 @@ impl<T> [T] { revswap(front_half, back_half, half_len); #[inline] - const fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) { + fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) { debug_assert!(a.len() == n); debug_assert!(b.len() == n); @@ -1696,7 +1695,13 @@ impl<T> [T] { let ptr = self.as_ptr(); // SAFETY: Caller has to check that `0 <= mid <= self.len()` - unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) } + unsafe { + assert_unsafe_precondition!( + "slice::split_at_unchecked requires the index to be within the slice", + (mid: usize, len: usize) => mid <= len + ); + (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) + } } /// Divides one mutable slice into two at an index, without doing bounds checking. @@ -2382,7 +2387,8 @@ impl<T> [T] { } /// Binary searches this slice for a given element. - /// This behaves similarly to [`contains`] if this slice is sorted. + /// If the slice is not sorted, the returned result is unspecified and + /// meaningless. /// /// If the value is found then [`Result::Ok`] is returned, containing the /// index of the matching element. If there are multiple matches, then any @@ -2394,7 +2400,6 @@ impl<T> [T] { /// /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`]. /// - /// [`contains`]: slice::contains /// [`binary_search_by`]: slice::binary_search_by /// [`binary_search_by_key`]: slice::binary_search_by_key /// [`partition_point`]: slice::partition_point @@ -2457,12 +2462,13 @@ impl<T> [T] { } /// Binary searches this slice with a comparator function. - /// This behaves similarly to [`contains`] if this slice is sorted. /// - /// The comparator function should implement an order consistent - /// with the sort order of the underlying slice, returning an - /// order code that indicates whether its argument is `Less`, - /// `Equal` or `Greater` the desired target. + /// The comparator function should return an order code that indicates + /// whether its argument is `Less`, `Equal` or `Greater` the desired + /// target. + /// If the slice is not sorted or if the comparator function does not + /// implement an order consistent with the sort order of the underlying + /// slice, the returned result is unspecified and meaningless. /// /// If the value is found then [`Result::Ok`] is returned, containing the /// index of the matching element. If there are multiple matches, then any @@ -2474,7 +2480,6 @@ impl<T> [T] { /// /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`]. /// - /// [`contains`]: slice::contains /// [`binary_search`]: slice::binary_search /// [`binary_search_by_key`]: slice::binary_search_by_key /// [`partition_point`]: slice::partition_point @@ -2543,10 +2548,11 @@ impl<T> [T] { } /// Binary searches this slice with a key extraction function. - /// This behaves similarly to [`contains`] if this slice is sorted. /// /// Assumes that the slice is sorted by the key, for instance with /// [`sort_by_key`] using the same key extraction function. + /// If the slice is not sorted by the key, the returned result is + /// unspecified and meaningless. /// /// If the value is found then [`Result::Ok`] is returned, containing the /// index of the matching element. If there are multiple matches, then any @@ -2558,7 +2564,6 @@ impl<T> [T] { /// /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`]. /// - /// [`contains`]: slice::contains /// [`sort_by_key`]: slice::sort_by_key /// [`binary_search`]: slice::binary_search /// [`binary_search_by`]: slice::binary_search_by @@ -2956,7 +2961,7 @@ impl<T> [T] { // This operation is still `O(n)`. // // Example: We start in this state, where `r` represents "next - // read" and `w` represents "next_write`. + // read" and `w` represents "next_write". // // r // +---+---+---+---+---+---+ @@ -3474,44 +3479,13 @@ impl<T> [T] { // Ts = size_of::<U> / gcd(size_of::<T>, size_of::<U>) // // Luckily since all this is constant-evaluated... performance here matters not! - #[inline] - fn gcd(a: usize, b: usize) -> usize { - use crate::intrinsics; - // iterative stein’s algorithm - // We should still make this `const fn` (and revert to recursive algorithm if we do) - // because relying on llvm to consteval all this is… well, it makes me uncomfortable. - - // SAFETY: `a` and `b` are checked to be non-zero values. - let (ctz_a, mut ctz_b) = unsafe { - if a == 0 { - return b; - } - if b == 0 { - return a; - } - (intrinsics::cttz_nonzero(a), intrinsics::cttz_nonzero(b)) - }; - let k = ctz_a.min(ctz_b); - let mut a = a >> ctz_a; - let mut b = b; - loop { - // remove all factors of 2 from b - b >>= ctz_b; - if a > b { - mem::swap(&mut a, &mut b); - } - b = b - a; - // SAFETY: `b` is checked to be non-zero. - unsafe { - if b == 0 { - break; - } - ctz_b = intrinsics::cttz_nonzero(b); - } - } - a << k + const fn gcd(a: usize, b: usize) -> usize { + if b == 0 { a } else { gcd(b, a % b) } } - let gcd: usize = gcd(mem::size_of::<T>(), mem::size_of::<U>()); + + // Explicitly wrap the function call in a const block so it gets + // constant-evaluated even in debug mode. + let gcd: usize = const { gcd(mem::size_of::<T>(), mem::size_of::<U>()) }; let ts: usize = mem::size_of::<U>() / gcd; let us: usize = mem::size_of::<T>() / gcd; @@ -3817,7 +3791,7 @@ impl<T> [T] { where F: FnMut(&'a T, &'a T) -> Option<Ordering>, { - self.iter().is_sorted_by(|a, b| compare(*a, *b)) + self.array_windows().all(|[a, b]| compare(a, b).map_or(false, Ordering::is_le)) } /// Checks if the elements of this slice are sorted using the given key extraction function. @@ -4257,7 +4231,7 @@ impl<T, const N: usize> [[T; N]] { /// assert!(empty_slice_of_arrays.flatten().is_empty()); /// ``` #[unstable(feature = "slice_flatten", issue = "95629")] - pub fn flatten(&self) -> &[T] { + pub const fn flatten(&self) -> &[T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") } else { @@ -4399,8 +4373,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T> const Default for &[T] { +impl<T> Default for &[T] { /// Creates an empty slice. fn default() -> Self { &[] @@ -4408,8 +4381,7 @@ impl<T> const Default for &[T] { } #[stable(feature = "mut_slice_default", since = "1.5.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T> const Default for &mut [T] { +impl<T> Default for &mut [T] { /// Creates a mutable empty slice. fn default() -> Self { &mut [] @@ -4453,7 +4425,7 @@ impl<T, const N: usize> SlicePattern for [T; N] { /// This will do `binomial(N + 1, 2) = N * (N + 1) / 2 = 0, 1, 3, 6, 10, ..` /// comparison operations. fn get_many_check_valid<const N: usize>(indices: &[usize; N], len: usize) -> bool { - // NB: The optimzer should inline the loops into a sequence + // NB: The optimizer should inline the loops into a sequence // of instructions without additional branching. let mut valid = true; for (i, &idx) in indices.iter().enumerate() { diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 4ca4eb86bde..e6e3b55efa9 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -317,7 +317,7 @@ where // 1. `block` - Number of elements in the block. // 2. `start` - Start pointer into the `offsets` array. // 3. `end` - End pointer into the `offsets` array. - // 4. `offsets - Indices of out-of-order elements within the block. + // 4. `offsets` - Indices of out-of-order elements within the block. // The current block on the left side (from `l` to `l.add(block_l)`). let mut l = v.as_mut_ptr(); @@ -327,7 +327,7 @@ where let mut offsets_l = [MaybeUninit::<u8>::uninit(); BLOCK]; // The current block on the right side (from `r.sub(block_r)` to `r`). - // SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe` + // SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe let mut r = unsafe { l.add(v.len()) }; let mut block_r = BLOCK; let mut start_r = ptr::null_mut(); @@ -673,19 +673,23 @@ where fn break_patterns<T>(v: &mut [T]) { let len = v.len(); if len >= 8 { - // Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia. - let mut random = len as u32; - let mut gen_u32 = || { - random ^= random << 13; - random ^= random >> 17; - random ^= random << 5; - random - }; + let mut seed = len; let mut gen_usize = || { + // Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia. if usize::BITS <= 32 { - gen_u32() as usize + let mut r = seed as u32; + r ^= r << 13; + r ^= r >> 17; + r ^= r << 5; + seed = r as usize; + seed } else { - (((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize + let mut r = seed as u64; + r ^= r << 13; + r ^= r >> 7; + r ^= r << 17; + seed = r as usize; + seed } }; @@ -1452,7 +1456,6 @@ pub struct TimSortRun { /// Takes a range as denoted by start and end, that is already sorted and extends it to the right if /// necessary with sorts optimized for smaller ranges such as insertion sort. -#[cfg(not(no_global_oom_handling))] fn provide_sorted_batch<T, F>(v: &mut [T], start: usize, mut end: usize, is_less: &mut F) -> usize where F: FnMut(&T, &T) -> bool, @@ -1482,7 +1485,7 @@ where } /// Finds a streak of presorted elements starting at the beginning of the slice. Returns the first -/// value that is not part of said streak, and a bool denoting wether the streak was reversed. +/// value that is not part of said streak, and a bool denoting whether the streak was reversed. /// Streaks can be increasing or decreasing. fn find_streak<T, F>(v: &[T], is_less: &mut F) -> (usize, bool) where diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 95c682f42d0..772c3605562 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -13,7 +13,7 @@ use super::from_utf8_unchecked; use super::pattern::Pattern; use super::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher}; use super::validations::{next_code_point, next_code_point_reverse}; -use super::LinesAnyMap; +use super::LinesMap; use super::{BytesIsNotEmpty, UnsafeBytesToStr}; use super::{CharEscapeDebugContinue, CharEscapeDefault, CharEscapeUnicode}; use super::{IsAsciiWhitespace, IsNotEmpty, IsWhitespace}; @@ -1104,7 +1104,7 @@ generate_pattern_iterators! { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] #[derive(Clone, Debug)] -pub struct Lines<'a>(pub(super) Map<SplitTerminator<'a, char>, LinesAnyMap>); +pub struct Lines<'a>(pub(super) Map<SplitInclusive<'a, char>, LinesMap>); #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Iterator for Lines<'a> { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index ab2f8520ecb..ef05b25fdd0 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -16,6 +16,7 @@ mod validations; use self::pattern::Pattern; use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher}; +use crate::ascii; use crate::char::{self, EscapeDebugExtArgs}; use crate::mem; use crate::slice::{self, SliceIndex}; @@ -206,9 +207,8 @@ impl str { /// ``` #[must_use] #[stable(feature = "is_char_boundary", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_is_char_boundary", issue = "none")] #[inline] - pub const fn is_char_boundary(&self, index: usize) -> bool { + pub fn is_char_boundary(&self, index: usize) -> bool { // 0 is always ok. // Test for 0 explicitly so that it can optimize out the check // easily and skip reading string data for that case. @@ -436,9 +436,8 @@ impl str { /// assert!(v.get(..42).is_none()); /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub const fn get<I: ~const SliceIndex<str>>(&self, i: I) -> Option<&I::Output> { + pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> { i.get(self) } @@ -469,9 +468,8 @@ impl str { /// assert_eq!("HEllo", v); /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub const fn get_mut<I: ~const SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> { + pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> { i.get_mut(self) } @@ -502,9 +500,8 @@ impl str { /// } /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub const unsafe fn get_unchecked<I: ~const SliceIndex<str>>(&self, i: I) -> &I::Output { + pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked`; // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. @@ -538,12 +535,8 @@ impl str { /// } /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub const unsafe fn get_unchecked_mut<I: ~const SliceIndex<str>>( - &mut self, - i: I, - ) -> &mut I::Output { + pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`; // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. @@ -1011,7 +1004,7 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn lines(&self) -> Lines<'_> { - Lines(self.split_terminator('\n').map(LinesAnyMap)) + Lines(self.split_inclusive('\n').map(LinesMap)) } /// An iterator over the lines of a string. @@ -2365,15 +2358,26 @@ impl str { /// assert!(!non_ascii.is_ascii()); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_unstable(feature = "const_slice_is_ascii", issue = "111090")] #[must_use] #[inline] - pub fn is_ascii(&self) -> bool { + pub const fn is_ascii(&self) -> bool { // We can treat each byte as character here: all multibyte characters // start with a byte that is not in the ASCII range, so we will stop // there already. self.as_bytes().is_ascii() } + /// If this string slice [`is_ascii`](Self::is_ascii), returns it as a slice + /// of [ASCII characters](`ascii::Char`), otherwise returns `None`. + #[unstable(feature = "ascii_char", issue = "110998")] + #[must_use] + #[inline] + pub const fn as_ascii(&self) -> Option<&[ascii::Char]> { + // Like in `is_ascii`, we can work on the bytes directly. + self.as_bytes().as_ascii() + } + /// Checks that two strings are an ASCII case-insensitive match. /// /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, @@ -2582,8 +2586,7 @@ impl AsRef<[u8]> for str { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl const Default for &str { +impl Default for &str { /// Creates an empty str #[inline] fn default() -> Self { @@ -2604,10 +2607,10 @@ impl Default for &mut str { impl_fn_for_zst! { /// A nameable, cloneable fn type #[derive(Clone)] - struct LinesAnyMap impl<'a> Fn = |line: &'a str| -> &'a str { - let l = line.len(); - if l > 0 && line.as_bytes()[l - 1] == b'\r' { &line[0 .. l - 1] } - else { line } + struct LinesMap impl<'a> Fn = |line: &'a str| -> &'a str { + let Some(line) = line.strip_suffix('\n') else { return line }; + let Some(line) = line.strip_suffix('\r') else { return line }; + line }; #[derive(Clone)] @@ -2655,5 +2658,6 @@ impl_fn_for_zst! { }; } +// This is required to make `impl From<&str> for Box<dyn Error>` and `impl<E> From<E> for Box<dyn Error>` not overlap. #[stable(feature = "rust1", since = "1.0.0")] impl !crate::error::Error for &str {} diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 19da6d2fbec..e3a464a1c51 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -1891,7 +1891,7 @@ unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool { // SAFETY: Via the conditional above, we know that both `px` and `py` // have the same length, so `px < pxend` implies that `py < pyend`. - // Thus, derefencing both `px` and `py` in the loop below is safe. + // Thus, dereferencing both `px` and `py` in the loop below is safe. // // Moreover, we set `pxend` and `pyend` to be 4 bytes before the actual // end of `px` and `py`. Thus, the final dereference outside of the diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index d3ed811b157..1d52335f28e 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -1,6 +1,7 @@ //! Trait implementations for `str`. use crate::cmp::Ordering; +use crate::intrinsics::assert_unsafe_precondition; use crate::ops; use crate::ptr; use crate::slice::SliceIndex; @@ -28,10 +29,6 @@ impl PartialEq for str { fn eq(&self, other: &str) -> bool { self.as_bytes() == other.as_bytes() } - #[inline] - fn ne(&self, other: &str) -> bool { - !(*self).eq(other) - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -53,10 +50,9 @@ impl PartialOrd for str { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -impl<I> const ops::Index<I> for str +impl<I> ops::Index<I> for str where - I: ~const SliceIndex<str>, + I: SliceIndex<str>, { type Output = I::Output; @@ -67,10 +63,9 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -impl<I> const ops::IndexMut<I> for str +impl<I> ops::IndexMut<I> for str where - I: ~const SliceIndex<str>, + I: SliceIndex<str>, { #[inline] fn index_mut(&mut self, index: I) -> &mut I::Output { @@ -99,7 +94,7 @@ const fn str_index_overflow_fail() -> ! { /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl const SliceIndex<str> for ops::RangeFull { +unsafe impl SliceIndex<str> for ops::RangeFull { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -164,7 +159,7 @@ unsafe impl const SliceIndex<str> for ops::RangeFull { /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl const SliceIndex<str> for ops::Range<usize> { +unsafe impl SliceIndex<str> for ops::Range<usize> { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -198,7 +193,21 @@ unsafe impl const SliceIndex<str> for ops::Range<usize> { let slice = slice as *const [u8]; // SAFETY: the caller guarantees that `self` is in bounds of `slice` // which satisfies all the conditions for `add`. - let ptr = unsafe { slice.as_ptr().add(self.start) }; + let ptr = unsafe { + let this = ops::Range { ..self }; + assert_unsafe_precondition!( + "str::get_unchecked requires that the range is within the string slice", + (this: ops::Range<usize>, slice: *const [u8]) => + // We'd like to check that the bounds are on char boundaries, + // but there's not really a way to do so without reading + // behind the pointer, which has aliasing implications. + // It's also not possible to move this check up to + // `str::get_unchecked` without adding a special function + // to `SliceIndex` just for this. + this.end >= this.start && this.end <= slice.len() + ); + slice.as_ptr().add(self.start) + }; let len = self.end - self.start; ptr::slice_from_raw_parts(ptr, len) as *const str } @@ -206,7 +215,15 @@ unsafe impl const SliceIndex<str> for ops::Range<usize> { unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { let slice = slice as *mut [u8]; // SAFETY: see comments for `get_unchecked`. - let ptr = unsafe { slice.as_mut_ptr().add(self.start) }; + let ptr = unsafe { + let this = ops::Range { ..self }; + assert_unsafe_precondition!( + "str::get_unchecked_mut requires that the range is within the string slice", + (this: ops::Range<usize>, slice: *mut [u8]) => + this.end >= this.start && this.end <= slice.len() + ); + slice.as_mut_ptr().add(self.start) + }; let len = self.end - self.start; ptr::slice_from_raw_parts_mut(ptr, len) as *mut str } @@ -252,7 +269,7 @@ unsafe impl const SliceIndex<str> for ops::Range<usize> { /// character (as defined by `is_char_boundary`), or if `end > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl const SliceIndex<str> for ops::RangeTo<usize> { +unsafe impl SliceIndex<str> for ops::RangeTo<usize> { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -276,15 +293,13 @@ unsafe impl const SliceIndex<str> for ops::RangeTo<usize> { } #[inline] unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { - let slice = slice as *const [u8]; - let ptr = slice.as_ptr(); - ptr::slice_from_raw_parts(ptr, self.end) as *const str + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (0..self.end).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { - let slice = slice as *mut [u8]; - let ptr = slice.as_mut_ptr(); - ptr::slice_from_raw_parts_mut(ptr, self.end) as *mut str + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (0..self.end).get_unchecked_mut(slice) } } #[inline] fn index(self, slice: &str) -> &Self::Output { @@ -323,7 +338,7 @@ unsafe impl const SliceIndex<str> for ops::RangeTo<usize> { /// a character (as defined by `is_char_boundary`), or if `begin > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> { +unsafe impl SliceIndex<str> for ops::RangeFrom<usize> { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -347,20 +362,15 @@ unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> { } #[inline] unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { - let slice = slice as *const [u8]; - // SAFETY: the caller guarantees that `self` is in bounds of `slice` - // which satisfies all the conditions for `add`. - let ptr = unsafe { slice.as_ptr().add(self.start) }; - let len = slice.len() - self.start; - ptr::slice_from_raw_parts(ptr, len) as *const str + let len = (slice as *const [u8]).len(); + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. + unsafe { (self.start..len).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { - let slice = slice as *mut [u8]; - // SAFETY: identical to `get_unchecked`. - let ptr = unsafe { slice.as_mut_ptr().add(self.start) }; - let len = slice.len() - self.start; - ptr::slice_from_raw_parts_mut(ptr, len) as *mut str + let len = (slice as *mut [u8]).len(); + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. + unsafe { (self.start..len).get_unchecked_mut(slice) } } #[inline] fn index(self, slice: &str) -> &Self::Output { @@ -400,7 +410,7 @@ unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> { /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> { +unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -452,39 +462,33 @@ unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> { /// `is_char_boundary`, or equal to `len`), or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] -unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> { +unsafe impl SliceIndex<str> for ops::RangeToInclusive<usize> { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if self.end == usize::MAX { None } else { (..self.end + 1).get(slice) } + (0..=self.end).get(slice) } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if self.end == usize::MAX { None } else { (..self.end + 1).get_mut(slice) } + (0..=self.end).get_mut(slice) } #[inline] unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked`. - unsafe { (..self.end + 1).get_unchecked(slice) } + unsafe { (0..=self.end).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. - unsafe { (..self.end + 1).get_unchecked_mut(slice) } + unsafe { (0..=self.end).get_unchecked_mut(slice) } } #[inline] fn index(self, slice: &str) -> &Self::Output { - if self.end == usize::MAX { - str_index_overflow_fail(); - } - (..self.end + 1).index(slice) + (0..=self.end).index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { - if self.end == usize::MAX { - str_index_overflow_fail(); - } - (..self.end + 1).index_mut(slice) + (0..=self.end).index_mut(slice) } } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1d14efc7523..236b7f423d6 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -147,8 +147,7 @@ pub struct AtomicBool { #[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl const Default for AtomicBool { +impl Default for AtomicBool { /// Creates an `AtomicBool` initialized to `false`. #[inline] fn default() -> Self { @@ -179,8 +178,7 @@ pub struct AtomicPtr<T> { #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T> const Default for AtomicPtr<T> { +impl<T> Default for AtomicPtr<T> { /// Creates a null `AtomicPtr<T>`. fn default() -> AtomicPtr<T> { AtomicPtr::new(crate::ptr::null_mut()) @@ -305,6 +303,50 @@ impl AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } + /// Creates a new `AtomicBool` from a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_ptr, pointer_is_aligned)] + /// use std::sync::atomic::{self, AtomicBool}; + /// use std::mem::align_of; + /// + /// // Get a pointer to an allocated value + /// let ptr: *mut bool = Box::into_raw(Box::new(false)); + /// + /// assert!(ptr.is_aligned_to(align_of::<AtomicBool>())); + /// + /// { + /// // Create an atomic view of the allocated value + /// let atomic = unsafe { AtomicBool::from_ptr(ptr) }; + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(true, atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert_eq!(unsafe { *ptr }, true); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`). + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`. + /// + /// [valid]: crate::ptr#safety + #[unstable(feature = "atomic_from_ptr", issue = "108652")] + #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")] + pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + /// Returns a mutable reference to the underlying [`bool`]. /// /// This is safe because the mutable reference guarantees that no other threads are @@ -916,19 +958,21 @@ impl AtomicBool { /// ```ignore (extern-declaration) /// # fn main() { /// use std::sync::atomic::AtomicBool; + /// /// extern "C" { /// fn my_atomic_op(arg: *mut bool); /// } /// /// let mut atomic = AtomicBool::new(true); /// unsafe { - /// my_atomic_op(atomic.as_mut_ptr()); + /// my_atomic_op(atomic.as_ptr()); /// } /// # } /// ``` #[inline] - #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")] - pub const fn as_mut_ptr(&self) -> *mut bool { + #[stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + pub const fn as_ptr(&self) -> *mut bool { self.v.get().cast() } @@ -1017,6 +1061,50 @@ impl<T> AtomicPtr<T> { AtomicPtr { p: UnsafeCell::new(p) } } + /// Creates a new `AtomicPtr` from a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_ptr, pointer_is_aligned)] + /// use std::sync::atomic::{self, AtomicPtr}; + /// use std::mem::align_of; + /// + /// // Get a pointer to an allocated value + /// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut())); + /// + /// assert!(ptr.is_aligned_to(align_of::<AtomicPtr<u8>>())); + /// + /// { + /// // Create an atomic view of the allocated value + /// let atomic = unsafe { AtomicPtr::from_ptr(ptr) }; + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert!(!unsafe { *ptr }.is_null()); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this can be bigger than `align_of::<*mut T>()`). + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`. + /// + /// [valid]: crate::ptr#safety + #[unstable(feature = "atomic_from_ptr", issue = "108652")] + #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")] + pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + /// Returns a mutable reference to the underlying pointer. /// /// This is safe because the mutable reference guarantees that no other threads are @@ -1802,7 +1890,6 @@ impl<T> AtomicPtr<T> { /// # Examples /// /// ```ignore (extern-declaration) - /// #![feature(atomic_mut_ptr)] /// use std::sync::atomic::AtomicPtr; /// /// extern "C" { @@ -1814,20 +1901,20 @@ impl<T> AtomicPtr<T> { /// /// // SAFETY: Safe as long as `my_atomic_op` is atomic. /// unsafe { - /// my_atomic_op(atomic.as_mut_ptr()); + /// my_atomic_op(atomic.as_ptr()); /// } /// ``` #[inline] - #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")] - pub const fn as_mut_ptr(&self) -> *mut *mut T { + #[stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + pub const fn as_ptr(&self) -> *mut *mut T { self.p.get() } } #[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "atomic_bool_from", since = "1.24.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl const From<bool> for AtomicBool { +impl From<bool> for AtomicBool { /// Converts a `bool` into an `AtomicBool`. /// /// # Examples @@ -1845,8 +1932,7 @@ impl const From<bool> for AtomicBool { #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "atomic_from", since = "1.23.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<*mut T> for AtomicPtr<T> { +impl<T> From<*mut T> for AtomicPtr<T> { /// Converts a `*mut T` into an `AtomicPtr<T>`. #[inline] fn from(p: *mut T) -> Self { @@ -1861,8 +1947,7 @@ macro_rules! if_not_8_bit { ($_:ident, $($tt:tt)*) => { $($tt)* }; } -#[cfg_attr(not(bootstrap), cfg(target_has_atomic_load_store))] -#[cfg_attr(bootstrap, cfg(target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store)] macro_rules! atomic_int { ($cfg_cas:meta, $cfg_align:meta, @@ -1913,8 +1998,7 @@ macro_rules! atomic_int { pub const $atomic_init: $atomic_type = $atomic_type::new(0); #[$stable] - #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] - impl const Default for $atomic_type { + impl Default for $atomic_type { #[inline] fn default() -> Self { Self::new(Default::default()) @@ -1922,8 +2006,7 @@ macro_rules! atomic_int { } #[$stable_from] - #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] - impl const From<$int_type> for $atomic_type { + impl From<$int_type> for $atomic_type { #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")] #[inline] fn from(v: $int_type) -> Self { Self::new(v) } @@ -1958,6 +2041,53 @@ macro_rules! atomic_int { Self {v: UnsafeCell::new(v)} } + /// Creates a new reference to an atomic integer from a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_ptr, pointer_is_aligned)] + #[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")] + /// use std::mem::align_of; + /// + /// // Get a pointer to an allocated value + #[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")] + /// + #[doc = concat!("assert!(ptr.is_aligned_to(align_of::<", stringify!($atomic_type), ">()));")] + /// + /// { + /// // Create an atomic view of the allocated value + // SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above) + #[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")] + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(1, atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert_eq!(unsafe { *ptr }, 1); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`). + #[doc = concat!(" * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`).")] + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`. + /// + /// [valid]: crate::ptr#safety + #[unstable(feature = "atomic_from_ptr", issue = "108652")] + #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")] + pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + + /// Returns a mutable reference to the underlying integer. /// /// This is safe because the mutable reference guarantees that no other threads are @@ -2719,15 +2849,14 @@ macro_rules! atomic_int { /// /// // SAFETY: Safe as long as `my_atomic_op` is atomic. /// unsafe { - /// my_atomic_op(atomic.as_mut_ptr()); + /// my_atomic_op(atomic.as_ptr()); /// } /// # } /// ``` #[inline] - #[unstable(feature = "atomic_mut_ptr", - reason = "recently added", - issue = "66893")] - pub const fn as_mut_ptr(&self) -> *mut $int_type { + #[stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + pub const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } @@ -2989,8 +3118,7 @@ atomic_int_ptr_sized! { } #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release => Relaxed, @@ -3032,8 +3160,7 @@ unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T { } #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_swap`. @@ -3050,8 +3177,7 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the previous value (like __sync_fetch_and_add). #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_add`. @@ -3068,8 +3194,7 @@ unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the previous value (like __sync_fetch_and_sub). #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_sub`. @@ -3085,8 +3210,7 @@ unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_compare_exchange<T: Copy>( dst: *mut T, @@ -3121,8 +3245,7 @@ unsafe fn atomic_compare_exchange<T: Copy>( } #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_compare_exchange_weak<T: Copy>( dst: *mut T, @@ -3157,8 +3280,7 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>( } #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_and` @@ -3174,8 +3296,7 @@ unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_nand` @@ -3191,8 +3312,7 @@ unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_or` @@ -3208,8 +3328,7 @@ unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_xor` @@ -3226,8 +3345,7 @@ unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (signed comparison) #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_max` @@ -3244,8 +3362,7 @@ unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (signed comparison) #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_min` @@ -3262,8 +3379,7 @@ unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (unsigned comparison) #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_umax` @@ -3280,8 +3396,7 @@ unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (unsigned comparison) #[inline] -#[cfg_attr(not(bootstrap), cfg(target_has_atomic))] -#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))] +#[cfg(target_has_atomic)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T { // SAFETY: the caller must uphold the safety contract for `atomic_umin` diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs index 301ad41c966..3f3e19c55d4 100644 --- a/library/core/src/sync/exclusive.rs +++ b/library/core/src/sync/exclusive.rs @@ -69,9 +69,6 @@ use core::task::{Context, Poll}; /// for any value. This is a parallel with the fact that /// `&` and `&mut` references together can be thought of as a _compile-time_ /// version of a read-write lock. -/// -/// -/// [`Sync`]: core::marker::Sync #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[doc(alias = "SyncWrapper")] #[doc(alias = "SyncCell")] diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 25b61c0e666..5283a576d1b 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -45,6 +45,7 @@ impl<T> Poll<T> { /// assert_eq!(poll_some_len, Poll::Ready(13)); /// ``` #[stable(feature = "futures_api", since = "1.36.0")] + #[inline] pub fn map<U, F>(self, f: F) -> Poll<U> where F: FnOnce(T) -> U, @@ -115,7 +116,7 @@ impl<T> Poll<T> { /// let fut = Pin::new(&mut fut); /// /// let num = fut.poll(cx).ready()?; - /// # drop(num); + /// # let _ = num; // to silence unused warning /// // ... use num /// /// Poll::Ready(()) @@ -144,6 +145,7 @@ impl<T, E> Poll<Result<T, E>> { /// assert_eq!(squared, Poll::Ready(Ok(144))); /// ``` #[stable(feature = "futures_api", since = "1.36.0")] + #[inline] pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>> where F: FnOnce(T) -> U, @@ -171,6 +173,7 @@ impl<T, E> Poll<Result<T, E>> { /// assert_eq!(res, Poll::Ready(Err(0))); /// ``` #[stable(feature = "futures_api", since = "1.36.0")] + #[inline] pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>> where F: FnOnce(E) -> U, @@ -199,6 +202,7 @@ impl<T, E> Poll<Option<Result<T, E>>> { /// assert_eq!(squared, Poll::Ready(Some(Ok(144)))); /// ``` #[stable(feature = "poll_map", since = "1.51.0")] + #[inline] pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>> where F: FnOnce(T) -> U, @@ -228,6 +232,7 @@ impl<T, E> Poll<Option<Result<T, E>>> { /// assert_eq!(res, Poll::Ready(Some(Err(0)))); /// ``` #[stable(feature = "poll_map", since = "1.51.0")] + #[inline] pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>> where F: FnOnce(E) -> U, @@ -242,8 +247,7 @@ impl<T, E> Poll<Option<Result<T, E>>> { } #[stable(feature = "futures_api", since = "1.36.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "88674")] -impl<T> const From<T> for Poll<T> { +impl<T> From<T> for Poll<T> { /// Moves the value into a [`Poll::Ready`] to make a `Poll<T>`. /// /// # Example diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index b1daf545fbe..8d12625e88d 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -22,7 +22,7 @@ use core::task::Poll; /// let fut = Pin::new(&mut fut); /// /// let num = ready!(fut.poll(cx)); -/// # drop(num); +/// # let _ = num; /// // ... use num /// /// Poll::Ready(()) @@ -44,7 +44,7 @@ use core::task::Poll; /// Poll::Ready(t) => t, /// Poll::Pending => return Poll::Pending, /// }; -/// # drop(num); +/// # let _ = num; // to silence unused warning /// # // ... use num /// # /// # Poll::Ready(()) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index ba1cb6efa04..b08d5782ab6 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -735,8 +735,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] - pub const fn from_secs_f64(secs: f64) -> Duration { + pub fn from_secs_f64(secs: f64) -> Duration { match Duration::try_from_secs_f64(secs) { Ok(v) => v, Err(e) => panic!("{}", e.description()), @@ -773,8 +772,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] - pub const fn from_secs_f32(secs: f32) -> Duration { + pub fn from_secs_f32(secs: f32) -> Duration { match Duration::try_from_secs_f32(secs) { Ok(v) => v, Err(e) => panic!("{}", e.description()), @@ -798,8 +796,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] - pub const fn mul_f64(self, rhs: f64) -> Duration { + pub fn mul_f64(self, rhs: f64) -> Duration { Duration::from_secs_f64(rhs * self.as_secs_f64()) } @@ -820,8 +817,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] - pub const fn mul_f32(self, rhs: f32) -> Duration { + pub fn mul_f32(self, rhs: f32) -> Duration { Duration::from_secs_f32(rhs * self.as_secs_f32()) } @@ -842,8 +838,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] - pub const fn div_f64(self, rhs: f64) -> Duration { + pub fn div_f64(self, rhs: f64) -> Duration { Duration::from_secs_f64(self.as_secs_f64() / rhs) } @@ -866,8 +861,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] - pub const fn div_f32(self, rhs: f32) -> Duration { + pub fn div_f32(self, rhs: f32) -> Duration { Duration::from_secs_f32(self.as_secs_f32() / rhs) } @@ -1178,7 +1172,7 @@ impl fmt::Debug for Duration { emit_without_padding(f) } else { // We need to add padding. Use the `Formatter::padding` helper function. - let default_align = crate::fmt::rt::v1::Alignment::Left; + let default_align = fmt::Alignment::Left; let post_padding = f.padding(requested_w - actual_w, default_align)?; emit_without_padding(f)?; post_padding.write(f) @@ -1402,9 +1396,8 @@ impl Duration { /// assert_eq!(res, Ok(Duration::new(1, 2_929_688))); /// ``` #[stable(feature = "duration_checked_float", since = "1.66.0")] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] #[inline] - pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, TryFromFloatSecsError> { + pub fn try_from_secs_f32(secs: f32) -> Result<Duration, TryFromFloatSecsError> { try_from_secs!( secs = secs, mantissa_bits = 23, @@ -1479,9 +1472,8 @@ impl Duration { /// assert_eq!(res, Ok(Duration::new(1, 2_929_688))); /// ``` #[stable(feature = "duration_checked_float", since = "1.66.0")] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] #[inline] - pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, TryFromFloatSecsError> { + pub fn try_from_secs_f64(secs: f64) -> Result<Duration, TryFromFloatSecsError> { try_from_secs!( secs = secs, mantissa_bits = 52, diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 28275798f75..172e5fccb61 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -1,7 +1,6 @@ // See src/libstd/primitive_docs.rs for documentation. -use crate::cmp::Ordering::*; -use crate::cmp::*; +use crate::cmp::Ordering::{self, *}; // Recursive macro for implementing n-ary tuple functions and operations // @@ -22,8 +21,7 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl<$($T: ~const PartialEq),+> const PartialEq for ($($T,)+) + impl<$($T: PartialEq),+> PartialEq for ($($T,)+) where last_type!($($T,)+): ?Sized { @@ -50,8 +48,7 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl<$($T: ~const PartialOrd + ~const PartialEq),+> const PartialOrd for ($($T,)+) + impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+) where last_type!($($T,)+): ?Sized { @@ -61,19 +58,19 @@ macro_rules! tuple_impls { } #[inline] fn lt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(lt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + lexical_ord!(lt, Less, $( ${ignore(T)} self.${index()}, other.${index()} ),+) } #[inline] fn le(&self, other: &($($T,)+)) -> bool { - lexical_ord!(le, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + lexical_ord!(le, Less, $( ${ignore(T)} self.${index()}, other.${index()} ),+) } #[inline] fn ge(&self, other: &($($T,)+)) -> bool { - lexical_ord!(ge, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + lexical_ord!(ge, Greater, $( ${ignore(T)} self.${index()}, other.${index()} ),+) } #[inline] fn gt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(gt, $( ${ignore(T)} self.${index()}, other.${index()} ),+) + lexical_ord!(gt, Greater, $( ${ignore(T)} self.${index()}, other.${index()} ),+) } } } @@ -81,8 +78,7 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] - impl<$($T: ~const Ord),+> const Ord for ($($T,)+) + impl<$($T: Ord),+> Ord for ($($T,)+) where last_type!($($T,)+): ?Sized { @@ -96,14 +92,33 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] - impl<$($T: ~const Default),+> const Default for ($($T,)+) { + impl<$($T: Default),+> Default for ($($T,)+) { #[inline] fn default() -> ($($T,)+) { ($({ let x: $T = Default::default(); x},)+) } } } + + #[stable(feature = "array_tuple_conv", since = "CURRENT_RUSTC_VERSION")] + impl<T> From<[T; ${count(T)}]> for ($(${ignore(T)} T,)+) { + #[inline] + #[allow(non_snake_case)] + fn from(array: [T; ${count(T)}]) -> Self { + let [$($T,)+] = array; + ($($T,)+) + } + } + + #[stable(feature = "array_tuple_conv", since = "CURRENT_RUSTC_VERSION")] + impl<T> From<($(${ignore(T)} T,)+)> for [T; ${count(T)}] { + #[inline] + #[allow(non_snake_case)] + fn from(tuple: ($(${ignore(T)} T,)+)) -> Self { + let ($($T,)+) = tuple; + [$($T,)+] + } + } } } @@ -123,16 +138,35 @@ macro_rules! maybe_tuple_doc { }; } -// Constructs an expression that performs a lexical ordering using method $rel. +#[inline] +const fn ordering_is_some(c: Option<Ordering>, x: Ordering) -> bool { + // FIXME: Just use `==` once that's const-stable on `Option`s. + // This is mapping `None` to 2 and then doing the comparison afterwards + // because it optimizes better (`None::<Ordering>` is represented as 2). + x as i8 + == match c { + Some(c) => c as i8, + None => 2, + } +} + +// Constructs an expression that performs a lexical ordering using method `$rel`. // The values are interleaved, so the macro invocation for -// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2, -// a3, b3)` (and similarly for `lexical_cmp`) +// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1, +// a2, b2, a3, b3)` (and similarly for `lexical_cmp`) +// +// `$ne_rel` is only used to determine the result after checking that they're +// not equal, so `lt` and `le` can both just use `Less`. macro_rules! lexical_ord { - ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { - if $a != $b { lexical_ord!($rel, $a, $b) } - else { lexical_ord!($rel, $($rest_a, $rest_b),+) } + ($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{ + let c = PartialOrd::partial_cmp(&$a, &$b); + if !ordering_is_some(c, Equal) { ordering_is_some(c, $ne_rel) } + else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) } + }}; + ($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => { + // Use the specific method for the last element + PartialOrd::$rel(&$a, &$b) }; - ($rel: ident, $a:expr, $b:expr) => { ($a) . $rel (& $b) }; } macro_rules! lexical_partial_cmp { diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index bd69ca520c2..b25e9df2868 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -580,14 +580,22 @@ pub mod white_space { #[rustfmt::skip] pub mod conversions { + const INDEX_MASK: u32 = 0x400000; + pub fn to_lower(c: char) -> [char; 3] { if c.is_ascii() { [(c as u8).to_ascii_lowercase() as char, '\0', '\0'] } else { - match bsearch_case_table(c, LOWERCASE_TABLE) { - None => [c, '\0', '\0'], - Some(index) => LOWERCASE_TABLE[index].1, - } + LOWERCASE_TABLE + .binary_search_by(|&(key, _)| key.cmp(&c)) + .map(|i| { + let u = LOWERCASE_TABLE[i].1; + char::from_u32(u).map(|c| [c, '\0', '\0']).unwrap_or_else(|| { + // SAFETY: Index comes from statically generated table + unsafe { *LOWERCASE_TABLE_MULTI.get_unchecked((u & (INDEX_MASK - 1)) as usize) } + }) + }) + .unwrap_or([c, '\0', '\0']) } } @@ -595,1800 +603,781 @@ pub mod conversions { if c.is_ascii() { [(c as u8).to_ascii_uppercase() as char, '\0', '\0'] } else { - match bsearch_case_table(c, UPPERCASE_TABLE) { - None => [c, '\0', '\0'], - Some(index) => UPPERCASE_TABLE[index].1, - } + UPPERCASE_TABLE + .binary_search_by(|&(key, _)| key.cmp(&c)) + .map(|i| { + let u = UPPERCASE_TABLE[i].1; + char::from_u32(u).map(|c| [c, '\0', '\0']).unwrap_or_else(|| { + // SAFETY: Index comes from statically generated table + unsafe { *UPPERCASE_TABLE_MULTI.get_unchecked((u & (INDEX_MASK - 1)) as usize) } + }) + }) + .unwrap_or([c, '\0', '\0']) } } - fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> { - table.binary_search_by(|&(key, _)| key.cmp(&c)).ok() - } - static LOWERCASE_TABLE: &[(char, [char; 3])] = &[ - ('A', ['a', '\u{0}', '\u{0}']), ('B', ['b', '\u{0}', '\u{0}']), - ('C', ['c', '\u{0}', '\u{0}']), ('D', ['d', '\u{0}', '\u{0}']), - ('E', ['e', '\u{0}', '\u{0}']), ('F', ['f', '\u{0}', '\u{0}']), - ('G', ['g', '\u{0}', '\u{0}']), ('H', ['h', '\u{0}', '\u{0}']), - ('I', ['i', '\u{0}', '\u{0}']), ('J', ['j', '\u{0}', '\u{0}']), - ('K', ['k', '\u{0}', '\u{0}']), ('L', ['l', '\u{0}', '\u{0}']), - ('M', ['m', '\u{0}', '\u{0}']), ('N', ['n', '\u{0}', '\u{0}']), - ('O', ['o', '\u{0}', '\u{0}']), ('P', ['p', '\u{0}', '\u{0}']), - ('Q', ['q', '\u{0}', '\u{0}']), ('R', ['r', '\u{0}', '\u{0}']), - ('S', ['s', '\u{0}', '\u{0}']), ('T', ['t', '\u{0}', '\u{0}']), - ('U', ['u', '\u{0}', '\u{0}']), ('V', ['v', '\u{0}', '\u{0}']), - ('W', ['w', '\u{0}', '\u{0}']), ('X', ['x', '\u{0}', '\u{0}']), - ('Y', ['y', '\u{0}', '\u{0}']), ('Z', ['z', '\u{0}', '\u{0}']), - ('\u{c0}', ['\u{e0}', '\u{0}', '\u{0}']), ('\u{c1}', ['\u{e1}', '\u{0}', '\u{0}']), - ('\u{c2}', ['\u{e2}', '\u{0}', '\u{0}']), ('\u{c3}', ['\u{e3}', '\u{0}', '\u{0}']), - ('\u{c4}', ['\u{e4}', '\u{0}', '\u{0}']), ('\u{c5}', ['\u{e5}', '\u{0}', '\u{0}']), - ('\u{c6}', ['\u{e6}', '\u{0}', '\u{0}']), ('\u{c7}', ['\u{e7}', '\u{0}', '\u{0}']), - ('\u{c8}', ['\u{e8}', '\u{0}', '\u{0}']), ('\u{c9}', ['\u{e9}', '\u{0}', '\u{0}']), - ('\u{ca}', ['\u{ea}', '\u{0}', '\u{0}']), ('\u{cb}', ['\u{eb}', '\u{0}', '\u{0}']), - ('\u{cc}', ['\u{ec}', '\u{0}', '\u{0}']), ('\u{cd}', ['\u{ed}', '\u{0}', '\u{0}']), - ('\u{ce}', ['\u{ee}', '\u{0}', '\u{0}']), ('\u{cf}', ['\u{ef}', '\u{0}', '\u{0}']), - ('\u{d0}', ['\u{f0}', '\u{0}', '\u{0}']), ('\u{d1}', ['\u{f1}', '\u{0}', '\u{0}']), - ('\u{d2}', ['\u{f2}', '\u{0}', '\u{0}']), ('\u{d3}', ['\u{f3}', '\u{0}', '\u{0}']), - ('\u{d4}', ['\u{f4}', '\u{0}', '\u{0}']), ('\u{d5}', ['\u{f5}', '\u{0}', '\u{0}']), - ('\u{d6}', ['\u{f6}', '\u{0}', '\u{0}']), ('\u{d8}', ['\u{f8}', '\u{0}', '\u{0}']), - ('\u{d9}', ['\u{f9}', '\u{0}', '\u{0}']), ('\u{da}', ['\u{fa}', '\u{0}', '\u{0}']), - ('\u{db}', ['\u{fb}', '\u{0}', '\u{0}']), ('\u{dc}', ['\u{fc}', '\u{0}', '\u{0}']), - ('\u{dd}', ['\u{fd}', '\u{0}', '\u{0}']), ('\u{de}', ['\u{fe}', '\u{0}', '\u{0}']), - ('\u{100}', ['\u{101}', '\u{0}', '\u{0}']), ('\u{102}', ['\u{103}', '\u{0}', '\u{0}']), - ('\u{104}', ['\u{105}', '\u{0}', '\u{0}']), ('\u{106}', ['\u{107}', '\u{0}', '\u{0}']), - ('\u{108}', ['\u{109}', '\u{0}', '\u{0}']), ('\u{10a}', ['\u{10b}', '\u{0}', '\u{0}']), - ('\u{10c}', ['\u{10d}', '\u{0}', '\u{0}']), ('\u{10e}', ['\u{10f}', '\u{0}', '\u{0}']), - ('\u{110}', ['\u{111}', '\u{0}', '\u{0}']), ('\u{112}', ['\u{113}', '\u{0}', '\u{0}']), - ('\u{114}', ['\u{115}', '\u{0}', '\u{0}']), ('\u{116}', ['\u{117}', '\u{0}', '\u{0}']), - ('\u{118}', ['\u{119}', '\u{0}', '\u{0}']), ('\u{11a}', ['\u{11b}', '\u{0}', '\u{0}']), - ('\u{11c}', ['\u{11d}', '\u{0}', '\u{0}']), ('\u{11e}', ['\u{11f}', '\u{0}', '\u{0}']), - ('\u{120}', ['\u{121}', '\u{0}', '\u{0}']), ('\u{122}', ['\u{123}', '\u{0}', '\u{0}']), - ('\u{124}', ['\u{125}', '\u{0}', '\u{0}']), ('\u{126}', ['\u{127}', '\u{0}', '\u{0}']), - ('\u{128}', ['\u{129}', '\u{0}', '\u{0}']), ('\u{12a}', ['\u{12b}', '\u{0}', '\u{0}']), - ('\u{12c}', ['\u{12d}', '\u{0}', '\u{0}']), ('\u{12e}', ['\u{12f}', '\u{0}', '\u{0}']), - ('\u{130}', ['i', '\u{307}', '\u{0}']), ('\u{132}', ['\u{133}', '\u{0}', '\u{0}']), - ('\u{134}', ['\u{135}', '\u{0}', '\u{0}']), ('\u{136}', ['\u{137}', '\u{0}', '\u{0}']), - ('\u{139}', ['\u{13a}', '\u{0}', '\u{0}']), ('\u{13b}', ['\u{13c}', '\u{0}', '\u{0}']), - ('\u{13d}', ['\u{13e}', '\u{0}', '\u{0}']), ('\u{13f}', ['\u{140}', '\u{0}', '\u{0}']), - ('\u{141}', ['\u{142}', '\u{0}', '\u{0}']), ('\u{143}', ['\u{144}', '\u{0}', '\u{0}']), - ('\u{145}', ['\u{146}', '\u{0}', '\u{0}']), ('\u{147}', ['\u{148}', '\u{0}', '\u{0}']), - ('\u{14a}', ['\u{14b}', '\u{0}', '\u{0}']), ('\u{14c}', ['\u{14d}', '\u{0}', '\u{0}']), - ('\u{14e}', ['\u{14f}', '\u{0}', '\u{0}']), ('\u{150}', ['\u{151}', '\u{0}', '\u{0}']), - ('\u{152}', ['\u{153}', '\u{0}', '\u{0}']), ('\u{154}', ['\u{155}', '\u{0}', '\u{0}']), - ('\u{156}', ['\u{157}', '\u{0}', '\u{0}']), ('\u{158}', ['\u{159}', '\u{0}', '\u{0}']), - ('\u{15a}', ['\u{15b}', '\u{0}', '\u{0}']), ('\u{15c}', ['\u{15d}', '\u{0}', '\u{0}']), - ('\u{15e}', ['\u{15f}', '\u{0}', '\u{0}']), ('\u{160}', ['\u{161}', '\u{0}', '\u{0}']), - ('\u{162}', ['\u{163}', '\u{0}', '\u{0}']), ('\u{164}', ['\u{165}', '\u{0}', '\u{0}']), - ('\u{166}', ['\u{167}', '\u{0}', '\u{0}']), ('\u{168}', ['\u{169}', '\u{0}', '\u{0}']), - ('\u{16a}', ['\u{16b}', '\u{0}', '\u{0}']), ('\u{16c}', ['\u{16d}', '\u{0}', '\u{0}']), - ('\u{16e}', ['\u{16f}', '\u{0}', '\u{0}']), ('\u{170}', ['\u{171}', '\u{0}', '\u{0}']), - ('\u{172}', ['\u{173}', '\u{0}', '\u{0}']), ('\u{174}', ['\u{175}', '\u{0}', '\u{0}']), - ('\u{176}', ['\u{177}', '\u{0}', '\u{0}']), ('\u{178}', ['\u{ff}', '\u{0}', '\u{0}']), - ('\u{179}', ['\u{17a}', '\u{0}', '\u{0}']), ('\u{17b}', ['\u{17c}', '\u{0}', '\u{0}']), - ('\u{17d}', ['\u{17e}', '\u{0}', '\u{0}']), ('\u{181}', ['\u{253}', '\u{0}', '\u{0}']), - ('\u{182}', ['\u{183}', '\u{0}', '\u{0}']), ('\u{184}', ['\u{185}', '\u{0}', '\u{0}']), - ('\u{186}', ['\u{254}', '\u{0}', '\u{0}']), ('\u{187}', ['\u{188}', '\u{0}', '\u{0}']), - ('\u{189}', ['\u{256}', '\u{0}', '\u{0}']), ('\u{18a}', ['\u{257}', '\u{0}', '\u{0}']), - ('\u{18b}', ['\u{18c}', '\u{0}', '\u{0}']), ('\u{18e}', ['\u{1dd}', '\u{0}', '\u{0}']), - ('\u{18f}', ['\u{259}', '\u{0}', '\u{0}']), ('\u{190}', ['\u{25b}', '\u{0}', '\u{0}']), - ('\u{191}', ['\u{192}', '\u{0}', '\u{0}']), ('\u{193}', ['\u{260}', '\u{0}', '\u{0}']), - ('\u{194}', ['\u{263}', '\u{0}', '\u{0}']), ('\u{196}', ['\u{269}', '\u{0}', '\u{0}']), - ('\u{197}', ['\u{268}', '\u{0}', '\u{0}']), ('\u{198}', ['\u{199}', '\u{0}', '\u{0}']), - ('\u{19c}', ['\u{26f}', '\u{0}', '\u{0}']), ('\u{19d}', ['\u{272}', '\u{0}', '\u{0}']), - ('\u{19f}', ['\u{275}', '\u{0}', '\u{0}']), ('\u{1a0}', ['\u{1a1}', '\u{0}', '\u{0}']), - ('\u{1a2}', ['\u{1a3}', '\u{0}', '\u{0}']), ('\u{1a4}', ['\u{1a5}', '\u{0}', '\u{0}']), - ('\u{1a6}', ['\u{280}', '\u{0}', '\u{0}']), ('\u{1a7}', ['\u{1a8}', '\u{0}', '\u{0}']), - ('\u{1a9}', ['\u{283}', '\u{0}', '\u{0}']), ('\u{1ac}', ['\u{1ad}', '\u{0}', '\u{0}']), - ('\u{1ae}', ['\u{288}', '\u{0}', '\u{0}']), ('\u{1af}', ['\u{1b0}', '\u{0}', '\u{0}']), - ('\u{1b1}', ['\u{28a}', '\u{0}', '\u{0}']), ('\u{1b2}', ['\u{28b}', '\u{0}', '\u{0}']), - ('\u{1b3}', ['\u{1b4}', '\u{0}', '\u{0}']), ('\u{1b5}', ['\u{1b6}', '\u{0}', '\u{0}']), - ('\u{1b7}', ['\u{292}', '\u{0}', '\u{0}']), ('\u{1b8}', ['\u{1b9}', '\u{0}', '\u{0}']), - ('\u{1bc}', ['\u{1bd}', '\u{0}', '\u{0}']), ('\u{1c4}', ['\u{1c6}', '\u{0}', '\u{0}']), - ('\u{1c5}', ['\u{1c6}', '\u{0}', '\u{0}']), ('\u{1c7}', ['\u{1c9}', '\u{0}', '\u{0}']), - ('\u{1c8}', ['\u{1c9}', '\u{0}', '\u{0}']), ('\u{1ca}', ['\u{1cc}', '\u{0}', '\u{0}']), - ('\u{1cb}', ['\u{1cc}', '\u{0}', '\u{0}']), ('\u{1cd}', ['\u{1ce}', '\u{0}', '\u{0}']), - ('\u{1cf}', ['\u{1d0}', '\u{0}', '\u{0}']), ('\u{1d1}', ['\u{1d2}', '\u{0}', '\u{0}']), - ('\u{1d3}', ['\u{1d4}', '\u{0}', '\u{0}']), ('\u{1d5}', ['\u{1d6}', '\u{0}', '\u{0}']), - ('\u{1d7}', ['\u{1d8}', '\u{0}', '\u{0}']), ('\u{1d9}', ['\u{1da}', '\u{0}', '\u{0}']), - ('\u{1db}', ['\u{1dc}', '\u{0}', '\u{0}']), ('\u{1de}', ['\u{1df}', '\u{0}', '\u{0}']), - ('\u{1e0}', ['\u{1e1}', '\u{0}', '\u{0}']), ('\u{1e2}', ['\u{1e3}', '\u{0}', '\u{0}']), - ('\u{1e4}', ['\u{1e5}', '\u{0}', '\u{0}']), ('\u{1e6}', ['\u{1e7}', '\u{0}', '\u{0}']), - ('\u{1e8}', ['\u{1e9}', '\u{0}', '\u{0}']), ('\u{1ea}', ['\u{1eb}', '\u{0}', '\u{0}']), - ('\u{1ec}', ['\u{1ed}', '\u{0}', '\u{0}']), ('\u{1ee}', ['\u{1ef}', '\u{0}', '\u{0}']), - ('\u{1f1}', ['\u{1f3}', '\u{0}', '\u{0}']), ('\u{1f2}', ['\u{1f3}', '\u{0}', '\u{0}']), - ('\u{1f4}', ['\u{1f5}', '\u{0}', '\u{0}']), ('\u{1f6}', ['\u{195}', '\u{0}', '\u{0}']), - ('\u{1f7}', ['\u{1bf}', '\u{0}', '\u{0}']), ('\u{1f8}', ['\u{1f9}', '\u{0}', '\u{0}']), - ('\u{1fa}', ['\u{1fb}', '\u{0}', '\u{0}']), ('\u{1fc}', ['\u{1fd}', '\u{0}', '\u{0}']), - ('\u{1fe}', ['\u{1ff}', '\u{0}', '\u{0}']), ('\u{200}', ['\u{201}', '\u{0}', '\u{0}']), - ('\u{202}', ['\u{203}', '\u{0}', '\u{0}']), ('\u{204}', ['\u{205}', '\u{0}', '\u{0}']), - ('\u{206}', ['\u{207}', '\u{0}', '\u{0}']), ('\u{208}', ['\u{209}', '\u{0}', '\u{0}']), - ('\u{20a}', ['\u{20b}', '\u{0}', '\u{0}']), ('\u{20c}', ['\u{20d}', '\u{0}', '\u{0}']), - ('\u{20e}', ['\u{20f}', '\u{0}', '\u{0}']), ('\u{210}', ['\u{211}', '\u{0}', '\u{0}']), - ('\u{212}', ['\u{213}', '\u{0}', '\u{0}']), ('\u{214}', ['\u{215}', '\u{0}', '\u{0}']), - ('\u{216}', ['\u{217}', '\u{0}', '\u{0}']), ('\u{218}', ['\u{219}', '\u{0}', '\u{0}']), - ('\u{21a}', ['\u{21b}', '\u{0}', '\u{0}']), ('\u{21c}', ['\u{21d}', '\u{0}', '\u{0}']), - ('\u{21e}', ['\u{21f}', '\u{0}', '\u{0}']), ('\u{220}', ['\u{19e}', '\u{0}', '\u{0}']), - ('\u{222}', ['\u{223}', '\u{0}', '\u{0}']), ('\u{224}', ['\u{225}', '\u{0}', '\u{0}']), - ('\u{226}', ['\u{227}', '\u{0}', '\u{0}']), ('\u{228}', ['\u{229}', '\u{0}', '\u{0}']), - ('\u{22a}', ['\u{22b}', '\u{0}', '\u{0}']), ('\u{22c}', ['\u{22d}', '\u{0}', '\u{0}']), - ('\u{22e}', ['\u{22f}', '\u{0}', '\u{0}']), ('\u{230}', ['\u{231}', '\u{0}', '\u{0}']), - ('\u{232}', ['\u{233}', '\u{0}', '\u{0}']), ('\u{23a}', ['\u{2c65}', '\u{0}', '\u{0}']), - ('\u{23b}', ['\u{23c}', '\u{0}', '\u{0}']), ('\u{23d}', ['\u{19a}', '\u{0}', '\u{0}']), - ('\u{23e}', ['\u{2c66}', '\u{0}', '\u{0}']), ('\u{241}', ['\u{242}', '\u{0}', '\u{0}']), - ('\u{243}', ['\u{180}', '\u{0}', '\u{0}']), ('\u{244}', ['\u{289}', '\u{0}', '\u{0}']), - ('\u{245}', ['\u{28c}', '\u{0}', '\u{0}']), ('\u{246}', ['\u{247}', '\u{0}', '\u{0}']), - ('\u{248}', ['\u{249}', '\u{0}', '\u{0}']), ('\u{24a}', ['\u{24b}', '\u{0}', '\u{0}']), - ('\u{24c}', ['\u{24d}', '\u{0}', '\u{0}']), ('\u{24e}', ['\u{24f}', '\u{0}', '\u{0}']), - ('\u{370}', ['\u{371}', '\u{0}', '\u{0}']), ('\u{372}', ['\u{373}', '\u{0}', '\u{0}']), - ('\u{376}', ['\u{377}', '\u{0}', '\u{0}']), ('\u{37f}', ['\u{3f3}', '\u{0}', '\u{0}']), - ('\u{386}', ['\u{3ac}', '\u{0}', '\u{0}']), ('\u{388}', ['\u{3ad}', '\u{0}', '\u{0}']), - ('\u{389}', ['\u{3ae}', '\u{0}', '\u{0}']), ('\u{38a}', ['\u{3af}', '\u{0}', '\u{0}']), - ('\u{38c}', ['\u{3cc}', '\u{0}', '\u{0}']), ('\u{38e}', ['\u{3cd}', '\u{0}', '\u{0}']), - ('\u{38f}', ['\u{3ce}', '\u{0}', '\u{0}']), ('\u{391}', ['\u{3b1}', '\u{0}', '\u{0}']), - ('\u{392}', ['\u{3b2}', '\u{0}', '\u{0}']), ('\u{393}', ['\u{3b3}', '\u{0}', '\u{0}']), - ('\u{394}', ['\u{3b4}', '\u{0}', '\u{0}']), ('\u{395}', ['\u{3b5}', '\u{0}', '\u{0}']), - ('\u{396}', ['\u{3b6}', '\u{0}', '\u{0}']), ('\u{397}', ['\u{3b7}', '\u{0}', '\u{0}']), - ('\u{398}', ['\u{3b8}', '\u{0}', '\u{0}']), ('\u{399}', ['\u{3b9}', '\u{0}', '\u{0}']), - ('\u{39a}', ['\u{3ba}', '\u{0}', '\u{0}']), ('\u{39b}', ['\u{3bb}', '\u{0}', '\u{0}']), - ('\u{39c}', ['\u{3bc}', '\u{0}', '\u{0}']), ('\u{39d}', ['\u{3bd}', '\u{0}', '\u{0}']), - ('\u{39e}', ['\u{3be}', '\u{0}', '\u{0}']), ('\u{39f}', ['\u{3bf}', '\u{0}', '\u{0}']), - ('\u{3a0}', ['\u{3c0}', '\u{0}', '\u{0}']), ('\u{3a1}', ['\u{3c1}', '\u{0}', '\u{0}']), - ('\u{3a3}', ['\u{3c3}', '\u{0}', '\u{0}']), ('\u{3a4}', ['\u{3c4}', '\u{0}', '\u{0}']), - ('\u{3a5}', ['\u{3c5}', '\u{0}', '\u{0}']), ('\u{3a6}', ['\u{3c6}', '\u{0}', '\u{0}']), - ('\u{3a7}', ['\u{3c7}', '\u{0}', '\u{0}']), ('\u{3a8}', ['\u{3c8}', '\u{0}', '\u{0}']), - ('\u{3a9}', ['\u{3c9}', '\u{0}', '\u{0}']), ('\u{3aa}', ['\u{3ca}', '\u{0}', '\u{0}']), - ('\u{3ab}', ['\u{3cb}', '\u{0}', '\u{0}']), ('\u{3cf}', ['\u{3d7}', '\u{0}', '\u{0}']), - ('\u{3d8}', ['\u{3d9}', '\u{0}', '\u{0}']), ('\u{3da}', ['\u{3db}', '\u{0}', '\u{0}']), - ('\u{3dc}', ['\u{3dd}', '\u{0}', '\u{0}']), ('\u{3de}', ['\u{3df}', '\u{0}', '\u{0}']), - ('\u{3e0}', ['\u{3e1}', '\u{0}', '\u{0}']), ('\u{3e2}', ['\u{3e3}', '\u{0}', '\u{0}']), - ('\u{3e4}', ['\u{3e5}', '\u{0}', '\u{0}']), ('\u{3e6}', ['\u{3e7}', '\u{0}', '\u{0}']), - ('\u{3e8}', ['\u{3e9}', '\u{0}', '\u{0}']), ('\u{3ea}', ['\u{3eb}', '\u{0}', '\u{0}']), - ('\u{3ec}', ['\u{3ed}', '\u{0}', '\u{0}']), ('\u{3ee}', ['\u{3ef}', '\u{0}', '\u{0}']), - ('\u{3f4}', ['\u{3b8}', '\u{0}', '\u{0}']), ('\u{3f7}', ['\u{3f8}', '\u{0}', '\u{0}']), - ('\u{3f9}', ['\u{3f2}', '\u{0}', '\u{0}']), ('\u{3fa}', ['\u{3fb}', '\u{0}', '\u{0}']), - ('\u{3fd}', ['\u{37b}', '\u{0}', '\u{0}']), ('\u{3fe}', ['\u{37c}', '\u{0}', '\u{0}']), - ('\u{3ff}', ['\u{37d}', '\u{0}', '\u{0}']), ('\u{400}', ['\u{450}', '\u{0}', '\u{0}']), - ('\u{401}', ['\u{451}', '\u{0}', '\u{0}']), ('\u{402}', ['\u{452}', '\u{0}', '\u{0}']), - ('\u{403}', ['\u{453}', '\u{0}', '\u{0}']), ('\u{404}', ['\u{454}', '\u{0}', '\u{0}']), - ('\u{405}', ['\u{455}', '\u{0}', '\u{0}']), ('\u{406}', ['\u{456}', '\u{0}', '\u{0}']), - ('\u{407}', ['\u{457}', '\u{0}', '\u{0}']), ('\u{408}', ['\u{458}', '\u{0}', '\u{0}']), - ('\u{409}', ['\u{459}', '\u{0}', '\u{0}']), ('\u{40a}', ['\u{45a}', '\u{0}', '\u{0}']), - ('\u{40b}', ['\u{45b}', '\u{0}', '\u{0}']), ('\u{40c}', ['\u{45c}', '\u{0}', '\u{0}']), - ('\u{40d}', ['\u{45d}', '\u{0}', '\u{0}']), ('\u{40e}', ['\u{45e}', '\u{0}', '\u{0}']), - ('\u{40f}', ['\u{45f}', '\u{0}', '\u{0}']), ('\u{410}', ['\u{430}', '\u{0}', '\u{0}']), - ('\u{411}', ['\u{431}', '\u{0}', '\u{0}']), ('\u{412}', ['\u{432}', '\u{0}', '\u{0}']), - ('\u{413}', ['\u{433}', '\u{0}', '\u{0}']), ('\u{414}', ['\u{434}', '\u{0}', '\u{0}']), - ('\u{415}', ['\u{435}', '\u{0}', '\u{0}']), ('\u{416}', ['\u{436}', '\u{0}', '\u{0}']), - ('\u{417}', ['\u{437}', '\u{0}', '\u{0}']), ('\u{418}', ['\u{438}', '\u{0}', '\u{0}']), - ('\u{419}', ['\u{439}', '\u{0}', '\u{0}']), ('\u{41a}', ['\u{43a}', '\u{0}', '\u{0}']), - ('\u{41b}', ['\u{43b}', '\u{0}', '\u{0}']), ('\u{41c}', ['\u{43c}', '\u{0}', '\u{0}']), - ('\u{41d}', ['\u{43d}', '\u{0}', '\u{0}']), ('\u{41e}', ['\u{43e}', '\u{0}', '\u{0}']), - ('\u{41f}', ['\u{43f}', '\u{0}', '\u{0}']), ('\u{420}', ['\u{440}', '\u{0}', '\u{0}']), - ('\u{421}', ['\u{441}', '\u{0}', '\u{0}']), ('\u{422}', ['\u{442}', '\u{0}', '\u{0}']), - ('\u{423}', ['\u{443}', '\u{0}', '\u{0}']), ('\u{424}', ['\u{444}', '\u{0}', '\u{0}']), - ('\u{425}', ['\u{445}', '\u{0}', '\u{0}']), ('\u{426}', ['\u{446}', '\u{0}', '\u{0}']), - ('\u{427}', ['\u{447}', '\u{0}', '\u{0}']), ('\u{428}', ['\u{448}', '\u{0}', '\u{0}']), - ('\u{429}', ['\u{449}', '\u{0}', '\u{0}']), ('\u{42a}', ['\u{44a}', '\u{0}', '\u{0}']), - ('\u{42b}', ['\u{44b}', '\u{0}', '\u{0}']), ('\u{42c}', ['\u{44c}', '\u{0}', '\u{0}']), - ('\u{42d}', ['\u{44d}', '\u{0}', '\u{0}']), ('\u{42e}', ['\u{44e}', '\u{0}', '\u{0}']), - ('\u{42f}', ['\u{44f}', '\u{0}', '\u{0}']), ('\u{460}', ['\u{461}', '\u{0}', '\u{0}']), - ('\u{462}', ['\u{463}', '\u{0}', '\u{0}']), ('\u{464}', ['\u{465}', '\u{0}', '\u{0}']), - ('\u{466}', ['\u{467}', '\u{0}', '\u{0}']), ('\u{468}', ['\u{469}', '\u{0}', '\u{0}']), - ('\u{46a}', ['\u{46b}', '\u{0}', '\u{0}']), ('\u{46c}', ['\u{46d}', '\u{0}', '\u{0}']), - ('\u{46e}', ['\u{46f}', '\u{0}', '\u{0}']), ('\u{470}', ['\u{471}', '\u{0}', '\u{0}']), - ('\u{472}', ['\u{473}', '\u{0}', '\u{0}']), ('\u{474}', ['\u{475}', '\u{0}', '\u{0}']), - ('\u{476}', ['\u{477}', '\u{0}', '\u{0}']), ('\u{478}', ['\u{479}', '\u{0}', '\u{0}']), - ('\u{47a}', ['\u{47b}', '\u{0}', '\u{0}']), ('\u{47c}', ['\u{47d}', '\u{0}', '\u{0}']), - ('\u{47e}', ['\u{47f}', '\u{0}', '\u{0}']), ('\u{480}', ['\u{481}', '\u{0}', '\u{0}']), - ('\u{48a}', ['\u{48b}', '\u{0}', '\u{0}']), ('\u{48c}', ['\u{48d}', '\u{0}', '\u{0}']), - ('\u{48e}', ['\u{48f}', '\u{0}', '\u{0}']), ('\u{490}', ['\u{491}', '\u{0}', '\u{0}']), - ('\u{492}', ['\u{493}', '\u{0}', '\u{0}']), ('\u{494}', ['\u{495}', '\u{0}', '\u{0}']), - ('\u{496}', ['\u{497}', '\u{0}', '\u{0}']), ('\u{498}', ['\u{499}', '\u{0}', '\u{0}']), - ('\u{49a}', ['\u{49b}', '\u{0}', '\u{0}']), ('\u{49c}', ['\u{49d}', '\u{0}', '\u{0}']), - ('\u{49e}', ['\u{49f}', '\u{0}', '\u{0}']), ('\u{4a0}', ['\u{4a1}', '\u{0}', '\u{0}']), - ('\u{4a2}', ['\u{4a3}', '\u{0}', '\u{0}']), ('\u{4a4}', ['\u{4a5}', '\u{0}', '\u{0}']), - ('\u{4a6}', ['\u{4a7}', '\u{0}', '\u{0}']), ('\u{4a8}', ['\u{4a9}', '\u{0}', '\u{0}']), - ('\u{4aa}', ['\u{4ab}', '\u{0}', '\u{0}']), ('\u{4ac}', ['\u{4ad}', '\u{0}', '\u{0}']), - ('\u{4ae}', ['\u{4af}', '\u{0}', '\u{0}']), ('\u{4b0}', ['\u{4b1}', '\u{0}', '\u{0}']), - ('\u{4b2}', ['\u{4b3}', '\u{0}', '\u{0}']), ('\u{4b4}', ['\u{4b5}', '\u{0}', '\u{0}']), - ('\u{4b6}', ['\u{4b7}', '\u{0}', '\u{0}']), ('\u{4b8}', ['\u{4b9}', '\u{0}', '\u{0}']), - ('\u{4ba}', ['\u{4bb}', '\u{0}', '\u{0}']), ('\u{4bc}', ['\u{4bd}', '\u{0}', '\u{0}']), - ('\u{4be}', ['\u{4bf}', '\u{0}', '\u{0}']), ('\u{4c0}', ['\u{4cf}', '\u{0}', '\u{0}']), - ('\u{4c1}', ['\u{4c2}', '\u{0}', '\u{0}']), ('\u{4c3}', ['\u{4c4}', '\u{0}', '\u{0}']), - ('\u{4c5}', ['\u{4c6}', '\u{0}', '\u{0}']), ('\u{4c7}', ['\u{4c8}', '\u{0}', '\u{0}']), - ('\u{4c9}', ['\u{4ca}', '\u{0}', '\u{0}']), ('\u{4cb}', ['\u{4cc}', '\u{0}', '\u{0}']), - ('\u{4cd}', ['\u{4ce}', '\u{0}', '\u{0}']), ('\u{4d0}', ['\u{4d1}', '\u{0}', '\u{0}']), - ('\u{4d2}', ['\u{4d3}', '\u{0}', '\u{0}']), ('\u{4d4}', ['\u{4d5}', '\u{0}', '\u{0}']), - ('\u{4d6}', ['\u{4d7}', '\u{0}', '\u{0}']), ('\u{4d8}', ['\u{4d9}', '\u{0}', '\u{0}']), - ('\u{4da}', ['\u{4db}', '\u{0}', '\u{0}']), ('\u{4dc}', ['\u{4dd}', '\u{0}', '\u{0}']), - ('\u{4de}', ['\u{4df}', '\u{0}', '\u{0}']), ('\u{4e0}', ['\u{4e1}', '\u{0}', '\u{0}']), - ('\u{4e2}', ['\u{4e3}', '\u{0}', '\u{0}']), ('\u{4e4}', ['\u{4e5}', '\u{0}', '\u{0}']), - ('\u{4e6}', ['\u{4e7}', '\u{0}', '\u{0}']), ('\u{4e8}', ['\u{4e9}', '\u{0}', '\u{0}']), - ('\u{4ea}', ['\u{4eb}', '\u{0}', '\u{0}']), ('\u{4ec}', ['\u{4ed}', '\u{0}', '\u{0}']), - ('\u{4ee}', ['\u{4ef}', '\u{0}', '\u{0}']), ('\u{4f0}', ['\u{4f1}', '\u{0}', '\u{0}']), - ('\u{4f2}', ['\u{4f3}', '\u{0}', '\u{0}']), ('\u{4f4}', ['\u{4f5}', '\u{0}', '\u{0}']), - ('\u{4f6}', ['\u{4f7}', '\u{0}', '\u{0}']), ('\u{4f8}', ['\u{4f9}', '\u{0}', '\u{0}']), - ('\u{4fa}', ['\u{4fb}', '\u{0}', '\u{0}']), ('\u{4fc}', ['\u{4fd}', '\u{0}', '\u{0}']), - ('\u{4fe}', ['\u{4ff}', '\u{0}', '\u{0}']), ('\u{500}', ['\u{501}', '\u{0}', '\u{0}']), - ('\u{502}', ['\u{503}', '\u{0}', '\u{0}']), ('\u{504}', ['\u{505}', '\u{0}', '\u{0}']), - ('\u{506}', ['\u{507}', '\u{0}', '\u{0}']), ('\u{508}', ['\u{509}', '\u{0}', '\u{0}']), - ('\u{50a}', ['\u{50b}', '\u{0}', '\u{0}']), ('\u{50c}', ['\u{50d}', '\u{0}', '\u{0}']), - ('\u{50e}', ['\u{50f}', '\u{0}', '\u{0}']), ('\u{510}', ['\u{511}', '\u{0}', '\u{0}']), - ('\u{512}', ['\u{513}', '\u{0}', '\u{0}']), ('\u{514}', ['\u{515}', '\u{0}', '\u{0}']), - ('\u{516}', ['\u{517}', '\u{0}', '\u{0}']), ('\u{518}', ['\u{519}', '\u{0}', '\u{0}']), - ('\u{51a}', ['\u{51b}', '\u{0}', '\u{0}']), ('\u{51c}', ['\u{51d}', '\u{0}', '\u{0}']), - ('\u{51e}', ['\u{51f}', '\u{0}', '\u{0}']), ('\u{520}', ['\u{521}', '\u{0}', '\u{0}']), - ('\u{522}', ['\u{523}', '\u{0}', '\u{0}']), ('\u{524}', ['\u{525}', '\u{0}', '\u{0}']), - ('\u{526}', ['\u{527}', '\u{0}', '\u{0}']), ('\u{528}', ['\u{529}', '\u{0}', '\u{0}']), - ('\u{52a}', ['\u{52b}', '\u{0}', '\u{0}']), ('\u{52c}', ['\u{52d}', '\u{0}', '\u{0}']), - ('\u{52e}', ['\u{52f}', '\u{0}', '\u{0}']), ('\u{531}', ['\u{561}', '\u{0}', '\u{0}']), - ('\u{532}', ['\u{562}', '\u{0}', '\u{0}']), ('\u{533}', ['\u{563}', '\u{0}', '\u{0}']), - ('\u{534}', ['\u{564}', '\u{0}', '\u{0}']), ('\u{535}', ['\u{565}', '\u{0}', '\u{0}']), - ('\u{536}', ['\u{566}', '\u{0}', '\u{0}']), ('\u{537}', ['\u{567}', '\u{0}', '\u{0}']), - ('\u{538}', ['\u{568}', '\u{0}', '\u{0}']), ('\u{539}', ['\u{569}', '\u{0}', '\u{0}']), - ('\u{53a}', ['\u{56a}', '\u{0}', '\u{0}']), ('\u{53b}', ['\u{56b}', '\u{0}', '\u{0}']), - ('\u{53c}', ['\u{56c}', '\u{0}', '\u{0}']), ('\u{53d}', ['\u{56d}', '\u{0}', '\u{0}']), - ('\u{53e}', ['\u{56e}', '\u{0}', '\u{0}']), ('\u{53f}', ['\u{56f}', '\u{0}', '\u{0}']), - ('\u{540}', ['\u{570}', '\u{0}', '\u{0}']), ('\u{541}', ['\u{571}', '\u{0}', '\u{0}']), - ('\u{542}', ['\u{572}', '\u{0}', '\u{0}']), ('\u{543}', ['\u{573}', '\u{0}', '\u{0}']), - ('\u{544}', ['\u{574}', '\u{0}', '\u{0}']), ('\u{545}', ['\u{575}', '\u{0}', '\u{0}']), - ('\u{546}', ['\u{576}', '\u{0}', '\u{0}']), ('\u{547}', ['\u{577}', '\u{0}', '\u{0}']), - ('\u{548}', ['\u{578}', '\u{0}', '\u{0}']), ('\u{549}', ['\u{579}', '\u{0}', '\u{0}']), - ('\u{54a}', ['\u{57a}', '\u{0}', '\u{0}']), ('\u{54b}', ['\u{57b}', '\u{0}', '\u{0}']), - ('\u{54c}', ['\u{57c}', '\u{0}', '\u{0}']), ('\u{54d}', ['\u{57d}', '\u{0}', '\u{0}']), - ('\u{54e}', ['\u{57e}', '\u{0}', '\u{0}']), ('\u{54f}', ['\u{57f}', '\u{0}', '\u{0}']), - ('\u{550}', ['\u{580}', '\u{0}', '\u{0}']), ('\u{551}', ['\u{581}', '\u{0}', '\u{0}']), - ('\u{552}', ['\u{582}', '\u{0}', '\u{0}']), ('\u{553}', ['\u{583}', '\u{0}', '\u{0}']), - ('\u{554}', ['\u{584}', '\u{0}', '\u{0}']), ('\u{555}', ['\u{585}', '\u{0}', '\u{0}']), - ('\u{556}', ['\u{586}', '\u{0}', '\u{0}']), ('\u{10a0}', ['\u{2d00}', '\u{0}', '\u{0}']), - ('\u{10a1}', ['\u{2d01}', '\u{0}', '\u{0}']), ('\u{10a2}', ['\u{2d02}', '\u{0}', '\u{0}']), - ('\u{10a3}', ['\u{2d03}', '\u{0}', '\u{0}']), ('\u{10a4}', ['\u{2d04}', '\u{0}', '\u{0}']), - ('\u{10a5}', ['\u{2d05}', '\u{0}', '\u{0}']), ('\u{10a6}', ['\u{2d06}', '\u{0}', '\u{0}']), - ('\u{10a7}', ['\u{2d07}', '\u{0}', '\u{0}']), ('\u{10a8}', ['\u{2d08}', '\u{0}', '\u{0}']), - ('\u{10a9}', ['\u{2d09}', '\u{0}', '\u{0}']), ('\u{10aa}', ['\u{2d0a}', '\u{0}', '\u{0}']), - ('\u{10ab}', ['\u{2d0b}', '\u{0}', '\u{0}']), ('\u{10ac}', ['\u{2d0c}', '\u{0}', '\u{0}']), - ('\u{10ad}', ['\u{2d0d}', '\u{0}', '\u{0}']), ('\u{10ae}', ['\u{2d0e}', '\u{0}', '\u{0}']), - ('\u{10af}', ['\u{2d0f}', '\u{0}', '\u{0}']), ('\u{10b0}', ['\u{2d10}', '\u{0}', '\u{0}']), - ('\u{10b1}', ['\u{2d11}', '\u{0}', '\u{0}']), ('\u{10b2}', ['\u{2d12}', '\u{0}', '\u{0}']), - ('\u{10b3}', ['\u{2d13}', '\u{0}', '\u{0}']), ('\u{10b4}', ['\u{2d14}', '\u{0}', '\u{0}']), - ('\u{10b5}', ['\u{2d15}', '\u{0}', '\u{0}']), ('\u{10b6}', ['\u{2d16}', '\u{0}', '\u{0}']), - ('\u{10b7}', ['\u{2d17}', '\u{0}', '\u{0}']), ('\u{10b8}', ['\u{2d18}', '\u{0}', '\u{0}']), - ('\u{10b9}', ['\u{2d19}', '\u{0}', '\u{0}']), ('\u{10ba}', ['\u{2d1a}', '\u{0}', '\u{0}']), - ('\u{10bb}', ['\u{2d1b}', '\u{0}', '\u{0}']), ('\u{10bc}', ['\u{2d1c}', '\u{0}', '\u{0}']), - ('\u{10bd}', ['\u{2d1d}', '\u{0}', '\u{0}']), ('\u{10be}', ['\u{2d1e}', '\u{0}', '\u{0}']), - ('\u{10bf}', ['\u{2d1f}', '\u{0}', '\u{0}']), ('\u{10c0}', ['\u{2d20}', '\u{0}', '\u{0}']), - ('\u{10c1}', ['\u{2d21}', '\u{0}', '\u{0}']), ('\u{10c2}', ['\u{2d22}', '\u{0}', '\u{0}']), - ('\u{10c3}', ['\u{2d23}', '\u{0}', '\u{0}']), ('\u{10c4}', ['\u{2d24}', '\u{0}', '\u{0}']), - ('\u{10c5}', ['\u{2d25}', '\u{0}', '\u{0}']), ('\u{10c7}', ['\u{2d27}', '\u{0}', '\u{0}']), - ('\u{10cd}', ['\u{2d2d}', '\u{0}', '\u{0}']), ('\u{13a0}', ['\u{ab70}', '\u{0}', '\u{0}']), - ('\u{13a1}', ['\u{ab71}', '\u{0}', '\u{0}']), ('\u{13a2}', ['\u{ab72}', '\u{0}', '\u{0}']), - ('\u{13a3}', ['\u{ab73}', '\u{0}', '\u{0}']), ('\u{13a4}', ['\u{ab74}', '\u{0}', '\u{0}']), - ('\u{13a5}', ['\u{ab75}', '\u{0}', '\u{0}']), ('\u{13a6}', ['\u{ab76}', '\u{0}', '\u{0}']), - ('\u{13a7}', ['\u{ab77}', '\u{0}', '\u{0}']), ('\u{13a8}', ['\u{ab78}', '\u{0}', '\u{0}']), - ('\u{13a9}', ['\u{ab79}', '\u{0}', '\u{0}']), ('\u{13aa}', ['\u{ab7a}', '\u{0}', '\u{0}']), - ('\u{13ab}', ['\u{ab7b}', '\u{0}', '\u{0}']), ('\u{13ac}', ['\u{ab7c}', '\u{0}', '\u{0}']), - ('\u{13ad}', ['\u{ab7d}', '\u{0}', '\u{0}']), ('\u{13ae}', ['\u{ab7e}', '\u{0}', '\u{0}']), - ('\u{13af}', ['\u{ab7f}', '\u{0}', '\u{0}']), ('\u{13b0}', ['\u{ab80}', '\u{0}', '\u{0}']), - ('\u{13b1}', ['\u{ab81}', '\u{0}', '\u{0}']), ('\u{13b2}', ['\u{ab82}', '\u{0}', '\u{0}']), - ('\u{13b3}', ['\u{ab83}', '\u{0}', '\u{0}']), ('\u{13b4}', ['\u{ab84}', '\u{0}', '\u{0}']), - ('\u{13b5}', ['\u{ab85}', '\u{0}', '\u{0}']), ('\u{13b6}', ['\u{ab86}', '\u{0}', '\u{0}']), - ('\u{13b7}', ['\u{ab87}', '\u{0}', '\u{0}']), ('\u{13b8}', ['\u{ab88}', '\u{0}', '\u{0}']), - ('\u{13b9}', ['\u{ab89}', '\u{0}', '\u{0}']), ('\u{13ba}', ['\u{ab8a}', '\u{0}', '\u{0}']), - ('\u{13bb}', ['\u{ab8b}', '\u{0}', '\u{0}']), ('\u{13bc}', ['\u{ab8c}', '\u{0}', '\u{0}']), - ('\u{13bd}', ['\u{ab8d}', '\u{0}', '\u{0}']), ('\u{13be}', ['\u{ab8e}', '\u{0}', '\u{0}']), - ('\u{13bf}', ['\u{ab8f}', '\u{0}', '\u{0}']), ('\u{13c0}', ['\u{ab90}', '\u{0}', '\u{0}']), - ('\u{13c1}', ['\u{ab91}', '\u{0}', '\u{0}']), ('\u{13c2}', ['\u{ab92}', '\u{0}', '\u{0}']), - ('\u{13c3}', ['\u{ab93}', '\u{0}', '\u{0}']), ('\u{13c4}', ['\u{ab94}', '\u{0}', '\u{0}']), - ('\u{13c5}', ['\u{ab95}', '\u{0}', '\u{0}']), ('\u{13c6}', ['\u{ab96}', '\u{0}', '\u{0}']), - ('\u{13c7}', ['\u{ab97}', '\u{0}', '\u{0}']), ('\u{13c8}', ['\u{ab98}', '\u{0}', '\u{0}']), - ('\u{13c9}', ['\u{ab99}', '\u{0}', '\u{0}']), ('\u{13ca}', ['\u{ab9a}', '\u{0}', '\u{0}']), - ('\u{13cb}', ['\u{ab9b}', '\u{0}', '\u{0}']), ('\u{13cc}', ['\u{ab9c}', '\u{0}', '\u{0}']), - ('\u{13cd}', ['\u{ab9d}', '\u{0}', '\u{0}']), ('\u{13ce}', ['\u{ab9e}', '\u{0}', '\u{0}']), - ('\u{13cf}', ['\u{ab9f}', '\u{0}', '\u{0}']), ('\u{13d0}', ['\u{aba0}', '\u{0}', '\u{0}']), - ('\u{13d1}', ['\u{aba1}', '\u{0}', '\u{0}']), ('\u{13d2}', ['\u{aba2}', '\u{0}', '\u{0}']), - ('\u{13d3}', ['\u{aba3}', '\u{0}', '\u{0}']), ('\u{13d4}', ['\u{aba4}', '\u{0}', '\u{0}']), - ('\u{13d5}', ['\u{aba5}', '\u{0}', '\u{0}']), ('\u{13d6}', ['\u{aba6}', '\u{0}', '\u{0}']), - ('\u{13d7}', ['\u{aba7}', '\u{0}', '\u{0}']), ('\u{13d8}', ['\u{aba8}', '\u{0}', '\u{0}']), - ('\u{13d9}', ['\u{aba9}', '\u{0}', '\u{0}']), ('\u{13da}', ['\u{abaa}', '\u{0}', '\u{0}']), - ('\u{13db}', ['\u{abab}', '\u{0}', '\u{0}']), ('\u{13dc}', ['\u{abac}', '\u{0}', '\u{0}']), - ('\u{13dd}', ['\u{abad}', '\u{0}', '\u{0}']), ('\u{13de}', ['\u{abae}', '\u{0}', '\u{0}']), - ('\u{13df}', ['\u{abaf}', '\u{0}', '\u{0}']), ('\u{13e0}', ['\u{abb0}', '\u{0}', '\u{0}']), - ('\u{13e1}', ['\u{abb1}', '\u{0}', '\u{0}']), ('\u{13e2}', ['\u{abb2}', '\u{0}', '\u{0}']), - ('\u{13e3}', ['\u{abb3}', '\u{0}', '\u{0}']), ('\u{13e4}', ['\u{abb4}', '\u{0}', '\u{0}']), - ('\u{13e5}', ['\u{abb5}', '\u{0}', '\u{0}']), ('\u{13e6}', ['\u{abb6}', '\u{0}', '\u{0}']), - ('\u{13e7}', ['\u{abb7}', '\u{0}', '\u{0}']), ('\u{13e8}', ['\u{abb8}', '\u{0}', '\u{0}']), - ('\u{13e9}', ['\u{abb9}', '\u{0}', '\u{0}']), ('\u{13ea}', ['\u{abba}', '\u{0}', '\u{0}']), - ('\u{13eb}', ['\u{abbb}', '\u{0}', '\u{0}']), ('\u{13ec}', ['\u{abbc}', '\u{0}', '\u{0}']), - ('\u{13ed}', ['\u{abbd}', '\u{0}', '\u{0}']), ('\u{13ee}', ['\u{abbe}', '\u{0}', '\u{0}']), - ('\u{13ef}', ['\u{abbf}', '\u{0}', '\u{0}']), ('\u{13f0}', ['\u{13f8}', '\u{0}', '\u{0}']), - ('\u{13f1}', ['\u{13f9}', '\u{0}', '\u{0}']), ('\u{13f2}', ['\u{13fa}', '\u{0}', '\u{0}']), - ('\u{13f3}', ['\u{13fb}', '\u{0}', '\u{0}']), ('\u{13f4}', ['\u{13fc}', '\u{0}', '\u{0}']), - ('\u{13f5}', ['\u{13fd}', '\u{0}', '\u{0}']), ('\u{1c90}', ['\u{10d0}', '\u{0}', '\u{0}']), - ('\u{1c91}', ['\u{10d1}', '\u{0}', '\u{0}']), ('\u{1c92}', ['\u{10d2}', '\u{0}', '\u{0}']), - ('\u{1c93}', ['\u{10d3}', '\u{0}', '\u{0}']), ('\u{1c94}', ['\u{10d4}', '\u{0}', '\u{0}']), - ('\u{1c95}', ['\u{10d5}', '\u{0}', '\u{0}']), ('\u{1c96}', ['\u{10d6}', '\u{0}', '\u{0}']), - ('\u{1c97}', ['\u{10d7}', '\u{0}', '\u{0}']), ('\u{1c98}', ['\u{10d8}', '\u{0}', '\u{0}']), - ('\u{1c99}', ['\u{10d9}', '\u{0}', '\u{0}']), ('\u{1c9a}', ['\u{10da}', '\u{0}', '\u{0}']), - ('\u{1c9b}', ['\u{10db}', '\u{0}', '\u{0}']), ('\u{1c9c}', ['\u{10dc}', '\u{0}', '\u{0}']), - ('\u{1c9d}', ['\u{10dd}', '\u{0}', '\u{0}']), ('\u{1c9e}', ['\u{10de}', '\u{0}', '\u{0}']), - ('\u{1c9f}', ['\u{10df}', '\u{0}', '\u{0}']), ('\u{1ca0}', ['\u{10e0}', '\u{0}', '\u{0}']), - ('\u{1ca1}', ['\u{10e1}', '\u{0}', '\u{0}']), ('\u{1ca2}', ['\u{10e2}', '\u{0}', '\u{0}']), - ('\u{1ca3}', ['\u{10e3}', '\u{0}', '\u{0}']), ('\u{1ca4}', ['\u{10e4}', '\u{0}', '\u{0}']), - ('\u{1ca5}', ['\u{10e5}', '\u{0}', '\u{0}']), ('\u{1ca6}', ['\u{10e6}', '\u{0}', '\u{0}']), - ('\u{1ca7}', ['\u{10e7}', '\u{0}', '\u{0}']), ('\u{1ca8}', ['\u{10e8}', '\u{0}', '\u{0}']), - ('\u{1ca9}', ['\u{10e9}', '\u{0}', '\u{0}']), ('\u{1caa}', ['\u{10ea}', '\u{0}', '\u{0}']), - ('\u{1cab}', ['\u{10eb}', '\u{0}', '\u{0}']), ('\u{1cac}', ['\u{10ec}', '\u{0}', '\u{0}']), - ('\u{1cad}', ['\u{10ed}', '\u{0}', '\u{0}']), ('\u{1cae}', ['\u{10ee}', '\u{0}', '\u{0}']), - ('\u{1caf}', ['\u{10ef}', '\u{0}', '\u{0}']), ('\u{1cb0}', ['\u{10f0}', '\u{0}', '\u{0}']), - ('\u{1cb1}', ['\u{10f1}', '\u{0}', '\u{0}']), ('\u{1cb2}', ['\u{10f2}', '\u{0}', '\u{0}']), - ('\u{1cb3}', ['\u{10f3}', '\u{0}', '\u{0}']), ('\u{1cb4}', ['\u{10f4}', '\u{0}', '\u{0}']), - ('\u{1cb5}', ['\u{10f5}', '\u{0}', '\u{0}']), ('\u{1cb6}', ['\u{10f6}', '\u{0}', '\u{0}']), - ('\u{1cb7}', ['\u{10f7}', '\u{0}', '\u{0}']), ('\u{1cb8}', ['\u{10f8}', '\u{0}', '\u{0}']), - ('\u{1cb9}', ['\u{10f9}', '\u{0}', '\u{0}']), ('\u{1cba}', ['\u{10fa}', '\u{0}', '\u{0}']), - ('\u{1cbd}', ['\u{10fd}', '\u{0}', '\u{0}']), ('\u{1cbe}', ['\u{10fe}', '\u{0}', '\u{0}']), - ('\u{1cbf}', ['\u{10ff}', '\u{0}', '\u{0}']), ('\u{1e00}', ['\u{1e01}', '\u{0}', '\u{0}']), - ('\u{1e02}', ['\u{1e03}', '\u{0}', '\u{0}']), ('\u{1e04}', ['\u{1e05}', '\u{0}', '\u{0}']), - ('\u{1e06}', ['\u{1e07}', '\u{0}', '\u{0}']), ('\u{1e08}', ['\u{1e09}', '\u{0}', '\u{0}']), - ('\u{1e0a}', ['\u{1e0b}', '\u{0}', '\u{0}']), ('\u{1e0c}', ['\u{1e0d}', '\u{0}', '\u{0}']), - ('\u{1e0e}', ['\u{1e0f}', '\u{0}', '\u{0}']), ('\u{1e10}', ['\u{1e11}', '\u{0}', '\u{0}']), - ('\u{1e12}', ['\u{1e13}', '\u{0}', '\u{0}']), ('\u{1e14}', ['\u{1e15}', '\u{0}', '\u{0}']), - ('\u{1e16}', ['\u{1e17}', '\u{0}', '\u{0}']), ('\u{1e18}', ['\u{1e19}', '\u{0}', '\u{0}']), - ('\u{1e1a}', ['\u{1e1b}', '\u{0}', '\u{0}']), ('\u{1e1c}', ['\u{1e1d}', '\u{0}', '\u{0}']), - ('\u{1e1e}', ['\u{1e1f}', '\u{0}', '\u{0}']), ('\u{1e20}', ['\u{1e21}', '\u{0}', '\u{0}']), - ('\u{1e22}', ['\u{1e23}', '\u{0}', '\u{0}']), ('\u{1e24}', ['\u{1e25}', '\u{0}', '\u{0}']), - ('\u{1e26}', ['\u{1e27}', '\u{0}', '\u{0}']), ('\u{1e28}', ['\u{1e29}', '\u{0}', '\u{0}']), - ('\u{1e2a}', ['\u{1e2b}', '\u{0}', '\u{0}']), ('\u{1e2c}', ['\u{1e2d}', '\u{0}', '\u{0}']), - ('\u{1e2e}', ['\u{1e2f}', '\u{0}', '\u{0}']), ('\u{1e30}', ['\u{1e31}', '\u{0}', '\u{0}']), - ('\u{1e32}', ['\u{1e33}', '\u{0}', '\u{0}']), ('\u{1e34}', ['\u{1e35}', '\u{0}', '\u{0}']), - ('\u{1e36}', ['\u{1e37}', '\u{0}', '\u{0}']), ('\u{1e38}', ['\u{1e39}', '\u{0}', '\u{0}']), - ('\u{1e3a}', ['\u{1e3b}', '\u{0}', '\u{0}']), ('\u{1e3c}', ['\u{1e3d}', '\u{0}', '\u{0}']), - ('\u{1e3e}', ['\u{1e3f}', '\u{0}', '\u{0}']), ('\u{1e40}', ['\u{1e41}', '\u{0}', '\u{0}']), - ('\u{1e42}', ['\u{1e43}', '\u{0}', '\u{0}']), ('\u{1e44}', ['\u{1e45}', '\u{0}', '\u{0}']), - ('\u{1e46}', ['\u{1e47}', '\u{0}', '\u{0}']), ('\u{1e48}', ['\u{1e49}', '\u{0}', '\u{0}']), - ('\u{1e4a}', ['\u{1e4b}', '\u{0}', '\u{0}']), ('\u{1e4c}', ['\u{1e4d}', '\u{0}', '\u{0}']), - ('\u{1e4e}', ['\u{1e4f}', '\u{0}', '\u{0}']), ('\u{1e50}', ['\u{1e51}', '\u{0}', '\u{0}']), - ('\u{1e52}', ['\u{1e53}', '\u{0}', '\u{0}']), ('\u{1e54}', ['\u{1e55}', '\u{0}', '\u{0}']), - ('\u{1e56}', ['\u{1e57}', '\u{0}', '\u{0}']), ('\u{1e58}', ['\u{1e59}', '\u{0}', '\u{0}']), - ('\u{1e5a}', ['\u{1e5b}', '\u{0}', '\u{0}']), ('\u{1e5c}', ['\u{1e5d}', '\u{0}', '\u{0}']), - ('\u{1e5e}', ['\u{1e5f}', '\u{0}', '\u{0}']), ('\u{1e60}', ['\u{1e61}', '\u{0}', '\u{0}']), - ('\u{1e62}', ['\u{1e63}', '\u{0}', '\u{0}']), ('\u{1e64}', ['\u{1e65}', '\u{0}', '\u{0}']), - ('\u{1e66}', ['\u{1e67}', '\u{0}', '\u{0}']), ('\u{1e68}', ['\u{1e69}', '\u{0}', '\u{0}']), - ('\u{1e6a}', ['\u{1e6b}', '\u{0}', '\u{0}']), ('\u{1e6c}', ['\u{1e6d}', '\u{0}', '\u{0}']), - ('\u{1e6e}', ['\u{1e6f}', '\u{0}', '\u{0}']), ('\u{1e70}', ['\u{1e71}', '\u{0}', '\u{0}']), - ('\u{1e72}', ['\u{1e73}', '\u{0}', '\u{0}']), ('\u{1e74}', ['\u{1e75}', '\u{0}', '\u{0}']), - ('\u{1e76}', ['\u{1e77}', '\u{0}', '\u{0}']), ('\u{1e78}', ['\u{1e79}', '\u{0}', '\u{0}']), - ('\u{1e7a}', ['\u{1e7b}', '\u{0}', '\u{0}']), ('\u{1e7c}', ['\u{1e7d}', '\u{0}', '\u{0}']), - ('\u{1e7e}', ['\u{1e7f}', '\u{0}', '\u{0}']), ('\u{1e80}', ['\u{1e81}', '\u{0}', '\u{0}']), - ('\u{1e82}', ['\u{1e83}', '\u{0}', '\u{0}']), ('\u{1e84}', ['\u{1e85}', '\u{0}', '\u{0}']), - ('\u{1e86}', ['\u{1e87}', '\u{0}', '\u{0}']), ('\u{1e88}', ['\u{1e89}', '\u{0}', '\u{0}']), - ('\u{1e8a}', ['\u{1e8b}', '\u{0}', '\u{0}']), ('\u{1e8c}', ['\u{1e8d}', '\u{0}', '\u{0}']), - ('\u{1e8e}', ['\u{1e8f}', '\u{0}', '\u{0}']), ('\u{1e90}', ['\u{1e91}', '\u{0}', '\u{0}']), - ('\u{1e92}', ['\u{1e93}', '\u{0}', '\u{0}']), ('\u{1e94}', ['\u{1e95}', '\u{0}', '\u{0}']), - ('\u{1e9e}', ['\u{df}', '\u{0}', '\u{0}']), ('\u{1ea0}', ['\u{1ea1}', '\u{0}', '\u{0}']), - ('\u{1ea2}', ['\u{1ea3}', '\u{0}', '\u{0}']), ('\u{1ea4}', ['\u{1ea5}', '\u{0}', '\u{0}']), - ('\u{1ea6}', ['\u{1ea7}', '\u{0}', '\u{0}']), ('\u{1ea8}', ['\u{1ea9}', '\u{0}', '\u{0}']), - ('\u{1eaa}', ['\u{1eab}', '\u{0}', '\u{0}']), ('\u{1eac}', ['\u{1ead}', '\u{0}', '\u{0}']), - ('\u{1eae}', ['\u{1eaf}', '\u{0}', '\u{0}']), ('\u{1eb0}', ['\u{1eb1}', '\u{0}', '\u{0}']), - ('\u{1eb2}', ['\u{1eb3}', '\u{0}', '\u{0}']), ('\u{1eb4}', ['\u{1eb5}', '\u{0}', '\u{0}']), - ('\u{1eb6}', ['\u{1eb7}', '\u{0}', '\u{0}']), ('\u{1eb8}', ['\u{1eb9}', '\u{0}', '\u{0}']), - ('\u{1eba}', ['\u{1ebb}', '\u{0}', '\u{0}']), ('\u{1ebc}', ['\u{1ebd}', '\u{0}', '\u{0}']), - ('\u{1ebe}', ['\u{1ebf}', '\u{0}', '\u{0}']), ('\u{1ec0}', ['\u{1ec1}', '\u{0}', '\u{0}']), - ('\u{1ec2}', ['\u{1ec3}', '\u{0}', '\u{0}']), ('\u{1ec4}', ['\u{1ec5}', '\u{0}', '\u{0}']), - ('\u{1ec6}', ['\u{1ec7}', '\u{0}', '\u{0}']), ('\u{1ec8}', ['\u{1ec9}', '\u{0}', '\u{0}']), - ('\u{1eca}', ['\u{1ecb}', '\u{0}', '\u{0}']), ('\u{1ecc}', ['\u{1ecd}', '\u{0}', '\u{0}']), - ('\u{1ece}', ['\u{1ecf}', '\u{0}', '\u{0}']), ('\u{1ed0}', ['\u{1ed1}', '\u{0}', '\u{0}']), - ('\u{1ed2}', ['\u{1ed3}', '\u{0}', '\u{0}']), ('\u{1ed4}', ['\u{1ed5}', '\u{0}', '\u{0}']), - ('\u{1ed6}', ['\u{1ed7}', '\u{0}', '\u{0}']), ('\u{1ed8}', ['\u{1ed9}', '\u{0}', '\u{0}']), - ('\u{1eda}', ['\u{1edb}', '\u{0}', '\u{0}']), ('\u{1edc}', ['\u{1edd}', '\u{0}', '\u{0}']), - ('\u{1ede}', ['\u{1edf}', '\u{0}', '\u{0}']), ('\u{1ee0}', ['\u{1ee1}', '\u{0}', '\u{0}']), - ('\u{1ee2}', ['\u{1ee3}', '\u{0}', '\u{0}']), ('\u{1ee4}', ['\u{1ee5}', '\u{0}', '\u{0}']), - ('\u{1ee6}', ['\u{1ee7}', '\u{0}', '\u{0}']), ('\u{1ee8}', ['\u{1ee9}', '\u{0}', '\u{0}']), - ('\u{1eea}', ['\u{1eeb}', '\u{0}', '\u{0}']), ('\u{1eec}', ['\u{1eed}', '\u{0}', '\u{0}']), - ('\u{1eee}', ['\u{1eef}', '\u{0}', '\u{0}']), ('\u{1ef0}', ['\u{1ef1}', '\u{0}', '\u{0}']), - ('\u{1ef2}', ['\u{1ef3}', '\u{0}', '\u{0}']), ('\u{1ef4}', ['\u{1ef5}', '\u{0}', '\u{0}']), - ('\u{1ef6}', ['\u{1ef7}', '\u{0}', '\u{0}']), ('\u{1ef8}', ['\u{1ef9}', '\u{0}', '\u{0}']), - ('\u{1efa}', ['\u{1efb}', '\u{0}', '\u{0}']), ('\u{1efc}', ['\u{1efd}', '\u{0}', '\u{0}']), - ('\u{1efe}', ['\u{1eff}', '\u{0}', '\u{0}']), ('\u{1f08}', ['\u{1f00}', '\u{0}', '\u{0}']), - ('\u{1f09}', ['\u{1f01}', '\u{0}', '\u{0}']), ('\u{1f0a}', ['\u{1f02}', '\u{0}', '\u{0}']), - ('\u{1f0b}', ['\u{1f03}', '\u{0}', '\u{0}']), ('\u{1f0c}', ['\u{1f04}', '\u{0}', '\u{0}']), - ('\u{1f0d}', ['\u{1f05}', '\u{0}', '\u{0}']), ('\u{1f0e}', ['\u{1f06}', '\u{0}', '\u{0}']), - ('\u{1f0f}', ['\u{1f07}', '\u{0}', '\u{0}']), ('\u{1f18}', ['\u{1f10}', '\u{0}', '\u{0}']), - ('\u{1f19}', ['\u{1f11}', '\u{0}', '\u{0}']), ('\u{1f1a}', ['\u{1f12}', '\u{0}', '\u{0}']), - ('\u{1f1b}', ['\u{1f13}', '\u{0}', '\u{0}']), ('\u{1f1c}', ['\u{1f14}', '\u{0}', '\u{0}']), - ('\u{1f1d}', ['\u{1f15}', '\u{0}', '\u{0}']), ('\u{1f28}', ['\u{1f20}', '\u{0}', '\u{0}']), - ('\u{1f29}', ['\u{1f21}', '\u{0}', '\u{0}']), ('\u{1f2a}', ['\u{1f22}', '\u{0}', '\u{0}']), - ('\u{1f2b}', ['\u{1f23}', '\u{0}', '\u{0}']), ('\u{1f2c}', ['\u{1f24}', '\u{0}', '\u{0}']), - ('\u{1f2d}', ['\u{1f25}', '\u{0}', '\u{0}']), ('\u{1f2e}', ['\u{1f26}', '\u{0}', '\u{0}']), - ('\u{1f2f}', ['\u{1f27}', '\u{0}', '\u{0}']), ('\u{1f38}', ['\u{1f30}', '\u{0}', '\u{0}']), - ('\u{1f39}', ['\u{1f31}', '\u{0}', '\u{0}']), ('\u{1f3a}', ['\u{1f32}', '\u{0}', '\u{0}']), - ('\u{1f3b}', ['\u{1f33}', '\u{0}', '\u{0}']), ('\u{1f3c}', ['\u{1f34}', '\u{0}', '\u{0}']), - ('\u{1f3d}', ['\u{1f35}', '\u{0}', '\u{0}']), ('\u{1f3e}', ['\u{1f36}', '\u{0}', '\u{0}']), - ('\u{1f3f}', ['\u{1f37}', '\u{0}', '\u{0}']), ('\u{1f48}', ['\u{1f40}', '\u{0}', '\u{0}']), - ('\u{1f49}', ['\u{1f41}', '\u{0}', '\u{0}']), ('\u{1f4a}', ['\u{1f42}', '\u{0}', '\u{0}']), - ('\u{1f4b}', ['\u{1f43}', '\u{0}', '\u{0}']), ('\u{1f4c}', ['\u{1f44}', '\u{0}', '\u{0}']), - ('\u{1f4d}', ['\u{1f45}', '\u{0}', '\u{0}']), ('\u{1f59}', ['\u{1f51}', '\u{0}', '\u{0}']), - ('\u{1f5b}', ['\u{1f53}', '\u{0}', '\u{0}']), ('\u{1f5d}', ['\u{1f55}', '\u{0}', '\u{0}']), - ('\u{1f5f}', ['\u{1f57}', '\u{0}', '\u{0}']), ('\u{1f68}', ['\u{1f60}', '\u{0}', '\u{0}']), - ('\u{1f69}', ['\u{1f61}', '\u{0}', '\u{0}']), ('\u{1f6a}', ['\u{1f62}', '\u{0}', '\u{0}']), - ('\u{1f6b}', ['\u{1f63}', '\u{0}', '\u{0}']), ('\u{1f6c}', ['\u{1f64}', '\u{0}', '\u{0}']), - ('\u{1f6d}', ['\u{1f65}', '\u{0}', '\u{0}']), ('\u{1f6e}', ['\u{1f66}', '\u{0}', '\u{0}']), - ('\u{1f6f}', ['\u{1f67}', '\u{0}', '\u{0}']), ('\u{1f88}', ['\u{1f80}', '\u{0}', '\u{0}']), - ('\u{1f89}', ['\u{1f81}', '\u{0}', '\u{0}']), ('\u{1f8a}', ['\u{1f82}', '\u{0}', '\u{0}']), - ('\u{1f8b}', ['\u{1f83}', '\u{0}', '\u{0}']), ('\u{1f8c}', ['\u{1f84}', '\u{0}', '\u{0}']), - ('\u{1f8d}', ['\u{1f85}', '\u{0}', '\u{0}']), ('\u{1f8e}', ['\u{1f86}', '\u{0}', '\u{0}']), - ('\u{1f8f}', ['\u{1f87}', '\u{0}', '\u{0}']), ('\u{1f98}', ['\u{1f90}', '\u{0}', '\u{0}']), - ('\u{1f99}', ['\u{1f91}', '\u{0}', '\u{0}']), ('\u{1f9a}', ['\u{1f92}', '\u{0}', '\u{0}']), - ('\u{1f9b}', ['\u{1f93}', '\u{0}', '\u{0}']), ('\u{1f9c}', ['\u{1f94}', '\u{0}', '\u{0}']), - ('\u{1f9d}', ['\u{1f95}', '\u{0}', '\u{0}']), ('\u{1f9e}', ['\u{1f96}', '\u{0}', '\u{0}']), - ('\u{1f9f}', ['\u{1f97}', '\u{0}', '\u{0}']), ('\u{1fa8}', ['\u{1fa0}', '\u{0}', '\u{0}']), - ('\u{1fa9}', ['\u{1fa1}', '\u{0}', '\u{0}']), ('\u{1faa}', ['\u{1fa2}', '\u{0}', '\u{0}']), - ('\u{1fab}', ['\u{1fa3}', '\u{0}', '\u{0}']), ('\u{1fac}', ['\u{1fa4}', '\u{0}', '\u{0}']), - ('\u{1fad}', ['\u{1fa5}', '\u{0}', '\u{0}']), ('\u{1fae}', ['\u{1fa6}', '\u{0}', '\u{0}']), - ('\u{1faf}', ['\u{1fa7}', '\u{0}', '\u{0}']), ('\u{1fb8}', ['\u{1fb0}', '\u{0}', '\u{0}']), - ('\u{1fb9}', ['\u{1fb1}', '\u{0}', '\u{0}']), ('\u{1fba}', ['\u{1f70}', '\u{0}', '\u{0}']), - ('\u{1fbb}', ['\u{1f71}', '\u{0}', '\u{0}']), ('\u{1fbc}', ['\u{1fb3}', '\u{0}', '\u{0}']), - ('\u{1fc8}', ['\u{1f72}', '\u{0}', '\u{0}']), ('\u{1fc9}', ['\u{1f73}', '\u{0}', '\u{0}']), - ('\u{1fca}', ['\u{1f74}', '\u{0}', '\u{0}']), ('\u{1fcb}', ['\u{1f75}', '\u{0}', '\u{0}']), - ('\u{1fcc}', ['\u{1fc3}', '\u{0}', '\u{0}']), ('\u{1fd8}', ['\u{1fd0}', '\u{0}', '\u{0}']), - ('\u{1fd9}', ['\u{1fd1}', '\u{0}', '\u{0}']), ('\u{1fda}', ['\u{1f76}', '\u{0}', '\u{0}']), - ('\u{1fdb}', ['\u{1f77}', '\u{0}', '\u{0}']), ('\u{1fe8}', ['\u{1fe0}', '\u{0}', '\u{0}']), - ('\u{1fe9}', ['\u{1fe1}', '\u{0}', '\u{0}']), ('\u{1fea}', ['\u{1f7a}', '\u{0}', '\u{0}']), - ('\u{1feb}', ['\u{1f7b}', '\u{0}', '\u{0}']), ('\u{1fec}', ['\u{1fe5}', '\u{0}', '\u{0}']), - ('\u{1ff8}', ['\u{1f78}', '\u{0}', '\u{0}']), ('\u{1ff9}', ['\u{1f79}', '\u{0}', '\u{0}']), - ('\u{1ffa}', ['\u{1f7c}', '\u{0}', '\u{0}']), ('\u{1ffb}', ['\u{1f7d}', '\u{0}', '\u{0}']), - ('\u{1ffc}', ['\u{1ff3}', '\u{0}', '\u{0}']), ('\u{2126}', ['\u{3c9}', '\u{0}', '\u{0}']), - ('\u{212a}', ['k', '\u{0}', '\u{0}']), ('\u{212b}', ['\u{e5}', '\u{0}', '\u{0}']), - ('\u{2132}', ['\u{214e}', '\u{0}', '\u{0}']), ('\u{2160}', ['\u{2170}', '\u{0}', '\u{0}']), - ('\u{2161}', ['\u{2171}', '\u{0}', '\u{0}']), ('\u{2162}', ['\u{2172}', '\u{0}', '\u{0}']), - ('\u{2163}', ['\u{2173}', '\u{0}', '\u{0}']), ('\u{2164}', ['\u{2174}', '\u{0}', '\u{0}']), - ('\u{2165}', ['\u{2175}', '\u{0}', '\u{0}']), ('\u{2166}', ['\u{2176}', '\u{0}', '\u{0}']), - ('\u{2167}', ['\u{2177}', '\u{0}', '\u{0}']), ('\u{2168}', ['\u{2178}', '\u{0}', '\u{0}']), - ('\u{2169}', ['\u{2179}', '\u{0}', '\u{0}']), ('\u{216a}', ['\u{217a}', '\u{0}', '\u{0}']), - ('\u{216b}', ['\u{217b}', '\u{0}', '\u{0}']), ('\u{216c}', ['\u{217c}', '\u{0}', '\u{0}']), - ('\u{216d}', ['\u{217d}', '\u{0}', '\u{0}']), ('\u{216e}', ['\u{217e}', '\u{0}', '\u{0}']), - ('\u{216f}', ['\u{217f}', '\u{0}', '\u{0}']), ('\u{2183}', ['\u{2184}', '\u{0}', '\u{0}']), - ('\u{24b6}', ['\u{24d0}', '\u{0}', '\u{0}']), ('\u{24b7}', ['\u{24d1}', '\u{0}', '\u{0}']), - ('\u{24b8}', ['\u{24d2}', '\u{0}', '\u{0}']), ('\u{24b9}', ['\u{24d3}', '\u{0}', '\u{0}']), - ('\u{24ba}', ['\u{24d4}', '\u{0}', '\u{0}']), ('\u{24bb}', ['\u{24d5}', '\u{0}', '\u{0}']), - ('\u{24bc}', ['\u{24d6}', '\u{0}', '\u{0}']), ('\u{24bd}', ['\u{24d7}', '\u{0}', '\u{0}']), - ('\u{24be}', ['\u{24d8}', '\u{0}', '\u{0}']), ('\u{24bf}', ['\u{24d9}', '\u{0}', '\u{0}']), - ('\u{24c0}', ['\u{24da}', '\u{0}', '\u{0}']), ('\u{24c1}', ['\u{24db}', '\u{0}', '\u{0}']), - ('\u{24c2}', ['\u{24dc}', '\u{0}', '\u{0}']), ('\u{24c3}', ['\u{24dd}', '\u{0}', '\u{0}']), - ('\u{24c4}', ['\u{24de}', '\u{0}', '\u{0}']), ('\u{24c5}', ['\u{24df}', '\u{0}', '\u{0}']), - ('\u{24c6}', ['\u{24e0}', '\u{0}', '\u{0}']), ('\u{24c7}', ['\u{24e1}', '\u{0}', '\u{0}']), - ('\u{24c8}', ['\u{24e2}', '\u{0}', '\u{0}']), ('\u{24c9}', ['\u{24e3}', '\u{0}', '\u{0}']), - ('\u{24ca}', ['\u{24e4}', '\u{0}', '\u{0}']), ('\u{24cb}', ['\u{24e5}', '\u{0}', '\u{0}']), - ('\u{24cc}', ['\u{24e6}', '\u{0}', '\u{0}']), ('\u{24cd}', ['\u{24e7}', '\u{0}', '\u{0}']), - ('\u{24ce}', ['\u{24e8}', '\u{0}', '\u{0}']), ('\u{24cf}', ['\u{24e9}', '\u{0}', '\u{0}']), - ('\u{2c00}', ['\u{2c30}', '\u{0}', '\u{0}']), ('\u{2c01}', ['\u{2c31}', '\u{0}', '\u{0}']), - ('\u{2c02}', ['\u{2c32}', '\u{0}', '\u{0}']), ('\u{2c03}', ['\u{2c33}', '\u{0}', '\u{0}']), - ('\u{2c04}', ['\u{2c34}', '\u{0}', '\u{0}']), ('\u{2c05}', ['\u{2c35}', '\u{0}', '\u{0}']), - ('\u{2c06}', ['\u{2c36}', '\u{0}', '\u{0}']), ('\u{2c07}', ['\u{2c37}', '\u{0}', '\u{0}']), - ('\u{2c08}', ['\u{2c38}', '\u{0}', '\u{0}']), ('\u{2c09}', ['\u{2c39}', '\u{0}', '\u{0}']), - ('\u{2c0a}', ['\u{2c3a}', '\u{0}', '\u{0}']), ('\u{2c0b}', ['\u{2c3b}', '\u{0}', '\u{0}']), - ('\u{2c0c}', ['\u{2c3c}', '\u{0}', '\u{0}']), ('\u{2c0d}', ['\u{2c3d}', '\u{0}', '\u{0}']), - ('\u{2c0e}', ['\u{2c3e}', '\u{0}', '\u{0}']), ('\u{2c0f}', ['\u{2c3f}', '\u{0}', '\u{0}']), - ('\u{2c10}', ['\u{2c40}', '\u{0}', '\u{0}']), ('\u{2c11}', ['\u{2c41}', '\u{0}', '\u{0}']), - ('\u{2c12}', ['\u{2c42}', '\u{0}', '\u{0}']), ('\u{2c13}', ['\u{2c43}', '\u{0}', '\u{0}']), - ('\u{2c14}', ['\u{2c44}', '\u{0}', '\u{0}']), ('\u{2c15}', ['\u{2c45}', '\u{0}', '\u{0}']), - ('\u{2c16}', ['\u{2c46}', '\u{0}', '\u{0}']), ('\u{2c17}', ['\u{2c47}', '\u{0}', '\u{0}']), - ('\u{2c18}', ['\u{2c48}', '\u{0}', '\u{0}']), ('\u{2c19}', ['\u{2c49}', '\u{0}', '\u{0}']), - ('\u{2c1a}', ['\u{2c4a}', '\u{0}', '\u{0}']), ('\u{2c1b}', ['\u{2c4b}', '\u{0}', '\u{0}']), - ('\u{2c1c}', ['\u{2c4c}', '\u{0}', '\u{0}']), ('\u{2c1d}', ['\u{2c4d}', '\u{0}', '\u{0}']), - ('\u{2c1e}', ['\u{2c4e}', '\u{0}', '\u{0}']), ('\u{2c1f}', ['\u{2c4f}', '\u{0}', '\u{0}']), - ('\u{2c20}', ['\u{2c50}', '\u{0}', '\u{0}']), ('\u{2c21}', ['\u{2c51}', '\u{0}', '\u{0}']), - ('\u{2c22}', ['\u{2c52}', '\u{0}', '\u{0}']), ('\u{2c23}', ['\u{2c53}', '\u{0}', '\u{0}']), - ('\u{2c24}', ['\u{2c54}', '\u{0}', '\u{0}']), ('\u{2c25}', ['\u{2c55}', '\u{0}', '\u{0}']), - ('\u{2c26}', ['\u{2c56}', '\u{0}', '\u{0}']), ('\u{2c27}', ['\u{2c57}', '\u{0}', '\u{0}']), - ('\u{2c28}', ['\u{2c58}', '\u{0}', '\u{0}']), ('\u{2c29}', ['\u{2c59}', '\u{0}', '\u{0}']), - ('\u{2c2a}', ['\u{2c5a}', '\u{0}', '\u{0}']), ('\u{2c2b}', ['\u{2c5b}', '\u{0}', '\u{0}']), - ('\u{2c2c}', ['\u{2c5c}', '\u{0}', '\u{0}']), ('\u{2c2d}', ['\u{2c5d}', '\u{0}', '\u{0}']), - ('\u{2c2e}', ['\u{2c5e}', '\u{0}', '\u{0}']), ('\u{2c2f}', ['\u{2c5f}', '\u{0}', '\u{0}']), - ('\u{2c60}', ['\u{2c61}', '\u{0}', '\u{0}']), ('\u{2c62}', ['\u{26b}', '\u{0}', '\u{0}']), - ('\u{2c63}', ['\u{1d7d}', '\u{0}', '\u{0}']), ('\u{2c64}', ['\u{27d}', '\u{0}', '\u{0}']), - ('\u{2c67}', ['\u{2c68}', '\u{0}', '\u{0}']), ('\u{2c69}', ['\u{2c6a}', '\u{0}', '\u{0}']), - ('\u{2c6b}', ['\u{2c6c}', '\u{0}', '\u{0}']), ('\u{2c6d}', ['\u{251}', '\u{0}', '\u{0}']), - ('\u{2c6e}', ['\u{271}', '\u{0}', '\u{0}']), ('\u{2c6f}', ['\u{250}', '\u{0}', '\u{0}']), - ('\u{2c70}', ['\u{252}', '\u{0}', '\u{0}']), ('\u{2c72}', ['\u{2c73}', '\u{0}', '\u{0}']), - ('\u{2c75}', ['\u{2c76}', '\u{0}', '\u{0}']), ('\u{2c7e}', ['\u{23f}', '\u{0}', '\u{0}']), - ('\u{2c7f}', ['\u{240}', '\u{0}', '\u{0}']), ('\u{2c80}', ['\u{2c81}', '\u{0}', '\u{0}']), - ('\u{2c82}', ['\u{2c83}', '\u{0}', '\u{0}']), ('\u{2c84}', ['\u{2c85}', '\u{0}', '\u{0}']), - ('\u{2c86}', ['\u{2c87}', '\u{0}', '\u{0}']), ('\u{2c88}', ['\u{2c89}', '\u{0}', '\u{0}']), - ('\u{2c8a}', ['\u{2c8b}', '\u{0}', '\u{0}']), ('\u{2c8c}', ['\u{2c8d}', '\u{0}', '\u{0}']), - ('\u{2c8e}', ['\u{2c8f}', '\u{0}', '\u{0}']), ('\u{2c90}', ['\u{2c91}', '\u{0}', '\u{0}']), - ('\u{2c92}', ['\u{2c93}', '\u{0}', '\u{0}']), ('\u{2c94}', ['\u{2c95}', '\u{0}', '\u{0}']), - ('\u{2c96}', ['\u{2c97}', '\u{0}', '\u{0}']), ('\u{2c98}', ['\u{2c99}', '\u{0}', '\u{0}']), - ('\u{2c9a}', ['\u{2c9b}', '\u{0}', '\u{0}']), ('\u{2c9c}', ['\u{2c9d}', '\u{0}', '\u{0}']), - ('\u{2c9e}', ['\u{2c9f}', '\u{0}', '\u{0}']), ('\u{2ca0}', ['\u{2ca1}', '\u{0}', '\u{0}']), - ('\u{2ca2}', ['\u{2ca3}', '\u{0}', '\u{0}']), ('\u{2ca4}', ['\u{2ca5}', '\u{0}', '\u{0}']), - ('\u{2ca6}', ['\u{2ca7}', '\u{0}', '\u{0}']), ('\u{2ca8}', ['\u{2ca9}', '\u{0}', '\u{0}']), - ('\u{2caa}', ['\u{2cab}', '\u{0}', '\u{0}']), ('\u{2cac}', ['\u{2cad}', '\u{0}', '\u{0}']), - ('\u{2cae}', ['\u{2caf}', '\u{0}', '\u{0}']), ('\u{2cb0}', ['\u{2cb1}', '\u{0}', '\u{0}']), - ('\u{2cb2}', ['\u{2cb3}', '\u{0}', '\u{0}']), ('\u{2cb4}', ['\u{2cb5}', '\u{0}', '\u{0}']), - ('\u{2cb6}', ['\u{2cb7}', '\u{0}', '\u{0}']), ('\u{2cb8}', ['\u{2cb9}', '\u{0}', '\u{0}']), - ('\u{2cba}', ['\u{2cbb}', '\u{0}', '\u{0}']), ('\u{2cbc}', ['\u{2cbd}', '\u{0}', '\u{0}']), - ('\u{2cbe}', ['\u{2cbf}', '\u{0}', '\u{0}']), ('\u{2cc0}', ['\u{2cc1}', '\u{0}', '\u{0}']), - ('\u{2cc2}', ['\u{2cc3}', '\u{0}', '\u{0}']), ('\u{2cc4}', ['\u{2cc5}', '\u{0}', '\u{0}']), - ('\u{2cc6}', ['\u{2cc7}', '\u{0}', '\u{0}']), ('\u{2cc8}', ['\u{2cc9}', '\u{0}', '\u{0}']), - ('\u{2cca}', ['\u{2ccb}', '\u{0}', '\u{0}']), ('\u{2ccc}', ['\u{2ccd}', '\u{0}', '\u{0}']), - ('\u{2cce}', ['\u{2ccf}', '\u{0}', '\u{0}']), ('\u{2cd0}', ['\u{2cd1}', '\u{0}', '\u{0}']), - ('\u{2cd2}', ['\u{2cd3}', '\u{0}', '\u{0}']), ('\u{2cd4}', ['\u{2cd5}', '\u{0}', '\u{0}']), - ('\u{2cd6}', ['\u{2cd7}', '\u{0}', '\u{0}']), ('\u{2cd8}', ['\u{2cd9}', '\u{0}', '\u{0}']), - ('\u{2cda}', ['\u{2cdb}', '\u{0}', '\u{0}']), ('\u{2cdc}', ['\u{2cdd}', '\u{0}', '\u{0}']), - ('\u{2cde}', ['\u{2cdf}', '\u{0}', '\u{0}']), ('\u{2ce0}', ['\u{2ce1}', '\u{0}', '\u{0}']), - ('\u{2ce2}', ['\u{2ce3}', '\u{0}', '\u{0}']), ('\u{2ceb}', ['\u{2cec}', '\u{0}', '\u{0}']), - ('\u{2ced}', ['\u{2cee}', '\u{0}', '\u{0}']), ('\u{2cf2}', ['\u{2cf3}', '\u{0}', '\u{0}']), - ('\u{a640}', ['\u{a641}', '\u{0}', '\u{0}']), ('\u{a642}', ['\u{a643}', '\u{0}', '\u{0}']), - ('\u{a644}', ['\u{a645}', '\u{0}', '\u{0}']), ('\u{a646}', ['\u{a647}', '\u{0}', '\u{0}']), - ('\u{a648}', ['\u{a649}', '\u{0}', '\u{0}']), ('\u{a64a}', ['\u{a64b}', '\u{0}', '\u{0}']), - ('\u{a64c}', ['\u{a64d}', '\u{0}', '\u{0}']), ('\u{a64e}', ['\u{a64f}', '\u{0}', '\u{0}']), - ('\u{a650}', ['\u{a651}', '\u{0}', '\u{0}']), ('\u{a652}', ['\u{a653}', '\u{0}', '\u{0}']), - ('\u{a654}', ['\u{a655}', '\u{0}', '\u{0}']), ('\u{a656}', ['\u{a657}', '\u{0}', '\u{0}']), - ('\u{a658}', ['\u{a659}', '\u{0}', '\u{0}']), ('\u{a65a}', ['\u{a65b}', '\u{0}', '\u{0}']), - ('\u{a65c}', ['\u{a65d}', '\u{0}', '\u{0}']), ('\u{a65e}', ['\u{a65f}', '\u{0}', '\u{0}']), - ('\u{a660}', ['\u{a661}', '\u{0}', '\u{0}']), ('\u{a662}', ['\u{a663}', '\u{0}', '\u{0}']), - ('\u{a664}', ['\u{a665}', '\u{0}', '\u{0}']), ('\u{a666}', ['\u{a667}', '\u{0}', '\u{0}']), - ('\u{a668}', ['\u{a669}', '\u{0}', '\u{0}']), ('\u{a66a}', ['\u{a66b}', '\u{0}', '\u{0}']), - ('\u{a66c}', ['\u{a66d}', '\u{0}', '\u{0}']), ('\u{a680}', ['\u{a681}', '\u{0}', '\u{0}']), - ('\u{a682}', ['\u{a683}', '\u{0}', '\u{0}']), ('\u{a684}', ['\u{a685}', '\u{0}', '\u{0}']), - ('\u{a686}', ['\u{a687}', '\u{0}', '\u{0}']), ('\u{a688}', ['\u{a689}', '\u{0}', '\u{0}']), - ('\u{a68a}', ['\u{a68b}', '\u{0}', '\u{0}']), ('\u{a68c}', ['\u{a68d}', '\u{0}', '\u{0}']), - ('\u{a68e}', ['\u{a68f}', '\u{0}', '\u{0}']), ('\u{a690}', ['\u{a691}', '\u{0}', '\u{0}']), - ('\u{a692}', ['\u{a693}', '\u{0}', '\u{0}']), ('\u{a694}', ['\u{a695}', '\u{0}', '\u{0}']), - ('\u{a696}', ['\u{a697}', '\u{0}', '\u{0}']), ('\u{a698}', ['\u{a699}', '\u{0}', '\u{0}']), - ('\u{a69a}', ['\u{a69b}', '\u{0}', '\u{0}']), ('\u{a722}', ['\u{a723}', '\u{0}', '\u{0}']), - ('\u{a724}', ['\u{a725}', '\u{0}', '\u{0}']), ('\u{a726}', ['\u{a727}', '\u{0}', '\u{0}']), - ('\u{a728}', ['\u{a729}', '\u{0}', '\u{0}']), ('\u{a72a}', ['\u{a72b}', '\u{0}', '\u{0}']), - ('\u{a72c}', ['\u{a72d}', '\u{0}', '\u{0}']), ('\u{a72e}', ['\u{a72f}', '\u{0}', '\u{0}']), - ('\u{a732}', ['\u{a733}', '\u{0}', '\u{0}']), ('\u{a734}', ['\u{a735}', '\u{0}', '\u{0}']), - ('\u{a736}', ['\u{a737}', '\u{0}', '\u{0}']), ('\u{a738}', ['\u{a739}', '\u{0}', '\u{0}']), - ('\u{a73a}', ['\u{a73b}', '\u{0}', '\u{0}']), ('\u{a73c}', ['\u{a73d}', '\u{0}', '\u{0}']), - ('\u{a73e}', ['\u{a73f}', '\u{0}', '\u{0}']), ('\u{a740}', ['\u{a741}', '\u{0}', '\u{0}']), - ('\u{a742}', ['\u{a743}', '\u{0}', '\u{0}']), ('\u{a744}', ['\u{a745}', '\u{0}', '\u{0}']), - ('\u{a746}', ['\u{a747}', '\u{0}', '\u{0}']), ('\u{a748}', ['\u{a749}', '\u{0}', '\u{0}']), - ('\u{a74a}', ['\u{a74b}', '\u{0}', '\u{0}']), ('\u{a74c}', ['\u{a74d}', '\u{0}', '\u{0}']), - ('\u{a74e}', ['\u{a74f}', '\u{0}', '\u{0}']), ('\u{a750}', ['\u{a751}', '\u{0}', '\u{0}']), - ('\u{a752}', ['\u{a753}', '\u{0}', '\u{0}']), ('\u{a754}', ['\u{a755}', '\u{0}', '\u{0}']), - ('\u{a756}', ['\u{a757}', '\u{0}', '\u{0}']), ('\u{a758}', ['\u{a759}', '\u{0}', '\u{0}']), - ('\u{a75a}', ['\u{a75b}', '\u{0}', '\u{0}']), ('\u{a75c}', ['\u{a75d}', '\u{0}', '\u{0}']), - ('\u{a75e}', ['\u{a75f}', '\u{0}', '\u{0}']), ('\u{a760}', ['\u{a761}', '\u{0}', '\u{0}']), - ('\u{a762}', ['\u{a763}', '\u{0}', '\u{0}']), ('\u{a764}', ['\u{a765}', '\u{0}', '\u{0}']), - ('\u{a766}', ['\u{a767}', '\u{0}', '\u{0}']), ('\u{a768}', ['\u{a769}', '\u{0}', '\u{0}']), - ('\u{a76a}', ['\u{a76b}', '\u{0}', '\u{0}']), ('\u{a76c}', ['\u{a76d}', '\u{0}', '\u{0}']), - ('\u{a76e}', ['\u{a76f}', '\u{0}', '\u{0}']), ('\u{a779}', ['\u{a77a}', '\u{0}', '\u{0}']), - ('\u{a77b}', ['\u{a77c}', '\u{0}', '\u{0}']), ('\u{a77d}', ['\u{1d79}', '\u{0}', '\u{0}']), - ('\u{a77e}', ['\u{a77f}', '\u{0}', '\u{0}']), ('\u{a780}', ['\u{a781}', '\u{0}', '\u{0}']), - ('\u{a782}', ['\u{a783}', '\u{0}', '\u{0}']), ('\u{a784}', ['\u{a785}', '\u{0}', '\u{0}']), - ('\u{a786}', ['\u{a787}', '\u{0}', '\u{0}']), ('\u{a78b}', ['\u{a78c}', '\u{0}', '\u{0}']), - ('\u{a78d}', ['\u{265}', '\u{0}', '\u{0}']), ('\u{a790}', ['\u{a791}', '\u{0}', '\u{0}']), - ('\u{a792}', ['\u{a793}', '\u{0}', '\u{0}']), ('\u{a796}', ['\u{a797}', '\u{0}', '\u{0}']), - ('\u{a798}', ['\u{a799}', '\u{0}', '\u{0}']), ('\u{a79a}', ['\u{a79b}', '\u{0}', '\u{0}']), - ('\u{a79c}', ['\u{a79d}', '\u{0}', '\u{0}']), ('\u{a79e}', ['\u{a79f}', '\u{0}', '\u{0}']), - ('\u{a7a0}', ['\u{a7a1}', '\u{0}', '\u{0}']), ('\u{a7a2}', ['\u{a7a3}', '\u{0}', '\u{0}']), - ('\u{a7a4}', ['\u{a7a5}', '\u{0}', '\u{0}']), ('\u{a7a6}', ['\u{a7a7}', '\u{0}', '\u{0}']), - ('\u{a7a8}', ['\u{a7a9}', '\u{0}', '\u{0}']), ('\u{a7aa}', ['\u{266}', '\u{0}', '\u{0}']), - ('\u{a7ab}', ['\u{25c}', '\u{0}', '\u{0}']), ('\u{a7ac}', ['\u{261}', '\u{0}', '\u{0}']), - ('\u{a7ad}', ['\u{26c}', '\u{0}', '\u{0}']), ('\u{a7ae}', ['\u{26a}', '\u{0}', '\u{0}']), - ('\u{a7b0}', ['\u{29e}', '\u{0}', '\u{0}']), ('\u{a7b1}', ['\u{287}', '\u{0}', '\u{0}']), - ('\u{a7b2}', ['\u{29d}', '\u{0}', '\u{0}']), ('\u{a7b3}', ['\u{ab53}', '\u{0}', '\u{0}']), - ('\u{a7b4}', ['\u{a7b5}', '\u{0}', '\u{0}']), ('\u{a7b6}', ['\u{a7b7}', '\u{0}', '\u{0}']), - ('\u{a7b8}', ['\u{a7b9}', '\u{0}', '\u{0}']), ('\u{a7ba}', ['\u{a7bb}', '\u{0}', '\u{0}']), - ('\u{a7bc}', ['\u{a7bd}', '\u{0}', '\u{0}']), ('\u{a7be}', ['\u{a7bf}', '\u{0}', '\u{0}']), - ('\u{a7c0}', ['\u{a7c1}', '\u{0}', '\u{0}']), ('\u{a7c2}', ['\u{a7c3}', '\u{0}', '\u{0}']), - ('\u{a7c4}', ['\u{a794}', '\u{0}', '\u{0}']), ('\u{a7c5}', ['\u{282}', '\u{0}', '\u{0}']), - ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{a7c7}', ['\u{a7c8}', '\u{0}', '\u{0}']), - ('\u{a7c9}', ['\u{a7ca}', '\u{0}', '\u{0}']), ('\u{a7d0}', ['\u{a7d1}', '\u{0}', '\u{0}']), - ('\u{a7d6}', ['\u{a7d7}', '\u{0}', '\u{0}']), ('\u{a7d8}', ['\u{a7d9}', '\u{0}', '\u{0}']), - ('\u{a7f5}', ['\u{a7f6}', '\u{0}', '\u{0}']), ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']), - ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']), ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']), - ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']), ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']), - ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']), ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']), - ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']), ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']), - ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']), ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']), - ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']), ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']), - ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']), ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']), - ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']), ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']), - ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']), ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']), - ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']), ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']), - ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']), ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']), - ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']), ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']), - ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']), - ('\u{10400}', ['\u{10428}', '\u{0}', '\u{0}']), - ('\u{10401}', ['\u{10429}', '\u{0}', '\u{0}']), - ('\u{10402}', ['\u{1042a}', '\u{0}', '\u{0}']), - ('\u{10403}', ['\u{1042b}', '\u{0}', '\u{0}']), - ('\u{10404}', ['\u{1042c}', '\u{0}', '\u{0}']), - ('\u{10405}', ['\u{1042d}', '\u{0}', '\u{0}']), - ('\u{10406}', ['\u{1042e}', '\u{0}', '\u{0}']), - ('\u{10407}', ['\u{1042f}', '\u{0}', '\u{0}']), - ('\u{10408}', ['\u{10430}', '\u{0}', '\u{0}']), - ('\u{10409}', ['\u{10431}', '\u{0}', '\u{0}']), - ('\u{1040a}', ['\u{10432}', '\u{0}', '\u{0}']), - ('\u{1040b}', ['\u{10433}', '\u{0}', '\u{0}']), - ('\u{1040c}', ['\u{10434}', '\u{0}', '\u{0}']), - ('\u{1040d}', ['\u{10435}', '\u{0}', '\u{0}']), - ('\u{1040e}', ['\u{10436}', '\u{0}', '\u{0}']), - ('\u{1040f}', ['\u{10437}', '\u{0}', '\u{0}']), - ('\u{10410}', ['\u{10438}', '\u{0}', '\u{0}']), - ('\u{10411}', ['\u{10439}', '\u{0}', '\u{0}']), - ('\u{10412}', ['\u{1043a}', '\u{0}', '\u{0}']), - ('\u{10413}', ['\u{1043b}', '\u{0}', '\u{0}']), - ('\u{10414}', ['\u{1043c}', '\u{0}', '\u{0}']), - ('\u{10415}', ['\u{1043d}', '\u{0}', '\u{0}']), - ('\u{10416}', ['\u{1043e}', '\u{0}', '\u{0}']), - ('\u{10417}', ['\u{1043f}', '\u{0}', '\u{0}']), - ('\u{10418}', ['\u{10440}', '\u{0}', '\u{0}']), - ('\u{10419}', ['\u{10441}', '\u{0}', '\u{0}']), - ('\u{1041a}', ['\u{10442}', '\u{0}', '\u{0}']), - ('\u{1041b}', ['\u{10443}', '\u{0}', '\u{0}']), - ('\u{1041c}', ['\u{10444}', '\u{0}', '\u{0}']), - ('\u{1041d}', ['\u{10445}', '\u{0}', '\u{0}']), - ('\u{1041e}', ['\u{10446}', '\u{0}', '\u{0}']), - ('\u{1041f}', ['\u{10447}', '\u{0}', '\u{0}']), - ('\u{10420}', ['\u{10448}', '\u{0}', '\u{0}']), - ('\u{10421}', ['\u{10449}', '\u{0}', '\u{0}']), - ('\u{10422}', ['\u{1044a}', '\u{0}', '\u{0}']), - ('\u{10423}', ['\u{1044b}', '\u{0}', '\u{0}']), - ('\u{10424}', ['\u{1044c}', '\u{0}', '\u{0}']), - ('\u{10425}', ['\u{1044d}', '\u{0}', '\u{0}']), - ('\u{10426}', ['\u{1044e}', '\u{0}', '\u{0}']), - ('\u{10427}', ['\u{1044f}', '\u{0}', '\u{0}']), - ('\u{104b0}', ['\u{104d8}', '\u{0}', '\u{0}']), - ('\u{104b1}', ['\u{104d9}', '\u{0}', '\u{0}']), - ('\u{104b2}', ['\u{104da}', '\u{0}', '\u{0}']), - ('\u{104b3}', ['\u{104db}', '\u{0}', '\u{0}']), - ('\u{104b4}', ['\u{104dc}', '\u{0}', '\u{0}']), - ('\u{104b5}', ['\u{104dd}', '\u{0}', '\u{0}']), - ('\u{104b6}', ['\u{104de}', '\u{0}', '\u{0}']), - ('\u{104b7}', ['\u{104df}', '\u{0}', '\u{0}']), - ('\u{104b8}', ['\u{104e0}', '\u{0}', '\u{0}']), - ('\u{104b9}', ['\u{104e1}', '\u{0}', '\u{0}']), - ('\u{104ba}', ['\u{104e2}', '\u{0}', '\u{0}']), - ('\u{104bb}', ['\u{104e3}', '\u{0}', '\u{0}']), - ('\u{104bc}', ['\u{104e4}', '\u{0}', '\u{0}']), - ('\u{104bd}', ['\u{104e5}', '\u{0}', '\u{0}']), - ('\u{104be}', ['\u{104e6}', '\u{0}', '\u{0}']), - ('\u{104bf}', ['\u{104e7}', '\u{0}', '\u{0}']), - ('\u{104c0}', ['\u{104e8}', '\u{0}', '\u{0}']), - ('\u{104c1}', ['\u{104e9}', '\u{0}', '\u{0}']), - ('\u{104c2}', ['\u{104ea}', '\u{0}', '\u{0}']), - ('\u{104c3}', ['\u{104eb}', '\u{0}', '\u{0}']), - ('\u{104c4}', ['\u{104ec}', '\u{0}', '\u{0}']), - ('\u{104c5}', ['\u{104ed}', '\u{0}', '\u{0}']), - ('\u{104c6}', ['\u{104ee}', '\u{0}', '\u{0}']), - ('\u{104c7}', ['\u{104ef}', '\u{0}', '\u{0}']), - ('\u{104c8}', ['\u{104f0}', '\u{0}', '\u{0}']), - ('\u{104c9}', ['\u{104f1}', '\u{0}', '\u{0}']), - ('\u{104ca}', ['\u{104f2}', '\u{0}', '\u{0}']), - ('\u{104cb}', ['\u{104f3}', '\u{0}', '\u{0}']), - ('\u{104cc}', ['\u{104f4}', '\u{0}', '\u{0}']), - ('\u{104cd}', ['\u{104f5}', '\u{0}', '\u{0}']), - ('\u{104ce}', ['\u{104f6}', '\u{0}', '\u{0}']), - ('\u{104cf}', ['\u{104f7}', '\u{0}', '\u{0}']), - ('\u{104d0}', ['\u{104f8}', '\u{0}', '\u{0}']), - ('\u{104d1}', ['\u{104f9}', '\u{0}', '\u{0}']), - ('\u{104d2}', ['\u{104fa}', '\u{0}', '\u{0}']), - ('\u{104d3}', ['\u{104fb}', '\u{0}', '\u{0}']), - ('\u{10570}', ['\u{10597}', '\u{0}', '\u{0}']), - ('\u{10571}', ['\u{10598}', '\u{0}', '\u{0}']), - ('\u{10572}', ['\u{10599}', '\u{0}', '\u{0}']), - ('\u{10573}', ['\u{1059a}', '\u{0}', '\u{0}']), - ('\u{10574}', ['\u{1059b}', '\u{0}', '\u{0}']), - ('\u{10575}', ['\u{1059c}', '\u{0}', '\u{0}']), - ('\u{10576}', ['\u{1059d}', '\u{0}', '\u{0}']), - ('\u{10577}', ['\u{1059e}', '\u{0}', '\u{0}']), - ('\u{10578}', ['\u{1059f}', '\u{0}', '\u{0}']), - ('\u{10579}', ['\u{105a0}', '\u{0}', '\u{0}']), - ('\u{1057a}', ['\u{105a1}', '\u{0}', '\u{0}']), - ('\u{1057c}', ['\u{105a3}', '\u{0}', '\u{0}']), - ('\u{1057d}', ['\u{105a4}', '\u{0}', '\u{0}']), - ('\u{1057e}', ['\u{105a5}', '\u{0}', '\u{0}']), - ('\u{1057f}', ['\u{105a6}', '\u{0}', '\u{0}']), - ('\u{10580}', ['\u{105a7}', '\u{0}', '\u{0}']), - ('\u{10581}', ['\u{105a8}', '\u{0}', '\u{0}']), - ('\u{10582}', ['\u{105a9}', '\u{0}', '\u{0}']), - ('\u{10583}', ['\u{105aa}', '\u{0}', '\u{0}']), - ('\u{10584}', ['\u{105ab}', '\u{0}', '\u{0}']), - ('\u{10585}', ['\u{105ac}', '\u{0}', '\u{0}']), - ('\u{10586}', ['\u{105ad}', '\u{0}', '\u{0}']), - ('\u{10587}', ['\u{105ae}', '\u{0}', '\u{0}']), - ('\u{10588}', ['\u{105af}', '\u{0}', '\u{0}']), - ('\u{10589}', ['\u{105b0}', '\u{0}', '\u{0}']), - ('\u{1058a}', ['\u{105b1}', '\u{0}', '\u{0}']), - ('\u{1058c}', ['\u{105b3}', '\u{0}', '\u{0}']), - ('\u{1058d}', ['\u{105b4}', '\u{0}', '\u{0}']), - ('\u{1058e}', ['\u{105b5}', '\u{0}', '\u{0}']), - ('\u{1058f}', ['\u{105b6}', '\u{0}', '\u{0}']), - ('\u{10590}', ['\u{105b7}', '\u{0}', '\u{0}']), - ('\u{10591}', ['\u{105b8}', '\u{0}', '\u{0}']), - ('\u{10592}', ['\u{105b9}', '\u{0}', '\u{0}']), - ('\u{10594}', ['\u{105bb}', '\u{0}', '\u{0}']), - ('\u{10595}', ['\u{105bc}', '\u{0}', '\u{0}']), - ('\u{10c80}', ['\u{10cc0}', '\u{0}', '\u{0}']), - ('\u{10c81}', ['\u{10cc1}', '\u{0}', '\u{0}']), - ('\u{10c82}', ['\u{10cc2}', '\u{0}', '\u{0}']), - ('\u{10c83}', ['\u{10cc3}', '\u{0}', '\u{0}']), - ('\u{10c84}', ['\u{10cc4}', '\u{0}', '\u{0}']), - ('\u{10c85}', ['\u{10cc5}', '\u{0}', '\u{0}']), - ('\u{10c86}', ['\u{10cc6}', '\u{0}', '\u{0}']), - ('\u{10c87}', ['\u{10cc7}', '\u{0}', '\u{0}']), - ('\u{10c88}', ['\u{10cc8}', '\u{0}', '\u{0}']), - ('\u{10c89}', ['\u{10cc9}', '\u{0}', '\u{0}']), - ('\u{10c8a}', ['\u{10cca}', '\u{0}', '\u{0}']), - ('\u{10c8b}', ['\u{10ccb}', '\u{0}', '\u{0}']), - ('\u{10c8c}', ['\u{10ccc}', '\u{0}', '\u{0}']), - ('\u{10c8d}', ['\u{10ccd}', '\u{0}', '\u{0}']), - ('\u{10c8e}', ['\u{10cce}', '\u{0}', '\u{0}']), - ('\u{10c8f}', ['\u{10ccf}', '\u{0}', '\u{0}']), - ('\u{10c90}', ['\u{10cd0}', '\u{0}', '\u{0}']), - ('\u{10c91}', ['\u{10cd1}', '\u{0}', '\u{0}']), - ('\u{10c92}', ['\u{10cd2}', '\u{0}', '\u{0}']), - ('\u{10c93}', ['\u{10cd3}', '\u{0}', '\u{0}']), - ('\u{10c94}', ['\u{10cd4}', '\u{0}', '\u{0}']), - ('\u{10c95}', ['\u{10cd5}', '\u{0}', '\u{0}']), - ('\u{10c96}', ['\u{10cd6}', '\u{0}', '\u{0}']), - ('\u{10c97}', ['\u{10cd7}', '\u{0}', '\u{0}']), - ('\u{10c98}', ['\u{10cd8}', '\u{0}', '\u{0}']), - ('\u{10c99}', ['\u{10cd9}', '\u{0}', '\u{0}']), - ('\u{10c9a}', ['\u{10cda}', '\u{0}', '\u{0}']), - ('\u{10c9b}', ['\u{10cdb}', '\u{0}', '\u{0}']), - ('\u{10c9c}', ['\u{10cdc}', '\u{0}', '\u{0}']), - ('\u{10c9d}', ['\u{10cdd}', '\u{0}', '\u{0}']), - ('\u{10c9e}', ['\u{10cde}', '\u{0}', '\u{0}']), - ('\u{10c9f}', ['\u{10cdf}', '\u{0}', '\u{0}']), - ('\u{10ca0}', ['\u{10ce0}', '\u{0}', '\u{0}']), - ('\u{10ca1}', ['\u{10ce1}', '\u{0}', '\u{0}']), - ('\u{10ca2}', ['\u{10ce2}', '\u{0}', '\u{0}']), - ('\u{10ca3}', ['\u{10ce3}', '\u{0}', '\u{0}']), - ('\u{10ca4}', ['\u{10ce4}', '\u{0}', '\u{0}']), - ('\u{10ca5}', ['\u{10ce5}', '\u{0}', '\u{0}']), - ('\u{10ca6}', ['\u{10ce6}', '\u{0}', '\u{0}']), - ('\u{10ca7}', ['\u{10ce7}', '\u{0}', '\u{0}']), - ('\u{10ca8}', ['\u{10ce8}', '\u{0}', '\u{0}']), - ('\u{10ca9}', ['\u{10ce9}', '\u{0}', '\u{0}']), - ('\u{10caa}', ['\u{10cea}', '\u{0}', '\u{0}']), - ('\u{10cab}', ['\u{10ceb}', '\u{0}', '\u{0}']), - ('\u{10cac}', ['\u{10cec}', '\u{0}', '\u{0}']), - ('\u{10cad}', ['\u{10ced}', '\u{0}', '\u{0}']), - ('\u{10cae}', ['\u{10cee}', '\u{0}', '\u{0}']), - ('\u{10caf}', ['\u{10cef}', '\u{0}', '\u{0}']), - ('\u{10cb0}', ['\u{10cf0}', '\u{0}', '\u{0}']), - ('\u{10cb1}', ['\u{10cf1}', '\u{0}', '\u{0}']), - ('\u{10cb2}', ['\u{10cf2}', '\u{0}', '\u{0}']), - ('\u{118a0}', ['\u{118c0}', '\u{0}', '\u{0}']), - ('\u{118a1}', ['\u{118c1}', '\u{0}', '\u{0}']), - ('\u{118a2}', ['\u{118c2}', '\u{0}', '\u{0}']), - ('\u{118a3}', ['\u{118c3}', '\u{0}', '\u{0}']), - ('\u{118a4}', ['\u{118c4}', '\u{0}', '\u{0}']), - ('\u{118a5}', ['\u{118c5}', '\u{0}', '\u{0}']), - ('\u{118a6}', ['\u{118c6}', '\u{0}', '\u{0}']), - ('\u{118a7}', ['\u{118c7}', '\u{0}', '\u{0}']), - ('\u{118a8}', ['\u{118c8}', '\u{0}', '\u{0}']), - ('\u{118a9}', ['\u{118c9}', '\u{0}', '\u{0}']), - ('\u{118aa}', ['\u{118ca}', '\u{0}', '\u{0}']), - ('\u{118ab}', ['\u{118cb}', '\u{0}', '\u{0}']), - ('\u{118ac}', ['\u{118cc}', '\u{0}', '\u{0}']), - ('\u{118ad}', ['\u{118cd}', '\u{0}', '\u{0}']), - ('\u{118ae}', ['\u{118ce}', '\u{0}', '\u{0}']), - ('\u{118af}', ['\u{118cf}', '\u{0}', '\u{0}']), - ('\u{118b0}', ['\u{118d0}', '\u{0}', '\u{0}']), - ('\u{118b1}', ['\u{118d1}', '\u{0}', '\u{0}']), - ('\u{118b2}', ['\u{118d2}', '\u{0}', '\u{0}']), - ('\u{118b3}', ['\u{118d3}', '\u{0}', '\u{0}']), - ('\u{118b4}', ['\u{118d4}', '\u{0}', '\u{0}']), - ('\u{118b5}', ['\u{118d5}', '\u{0}', '\u{0}']), - ('\u{118b6}', ['\u{118d6}', '\u{0}', '\u{0}']), - ('\u{118b7}', ['\u{118d7}', '\u{0}', '\u{0}']), - ('\u{118b8}', ['\u{118d8}', '\u{0}', '\u{0}']), - ('\u{118b9}', ['\u{118d9}', '\u{0}', '\u{0}']), - ('\u{118ba}', ['\u{118da}', '\u{0}', '\u{0}']), - ('\u{118bb}', ['\u{118db}', '\u{0}', '\u{0}']), - ('\u{118bc}', ['\u{118dc}', '\u{0}', '\u{0}']), - ('\u{118bd}', ['\u{118dd}', '\u{0}', '\u{0}']), - ('\u{118be}', ['\u{118de}', '\u{0}', '\u{0}']), - ('\u{118bf}', ['\u{118df}', '\u{0}', '\u{0}']), - ('\u{16e40}', ['\u{16e60}', '\u{0}', '\u{0}']), - ('\u{16e41}', ['\u{16e61}', '\u{0}', '\u{0}']), - ('\u{16e42}', ['\u{16e62}', '\u{0}', '\u{0}']), - ('\u{16e43}', ['\u{16e63}', '\u{0}', '\u{0}']), - ('\u{16e44}', ['\u{16e64}', '\u{0}', '\u{0}']), - ('\u{16e45}', ['\u{16e65}', '\u{0}', '\u{0}']), - ('\u{16e46}', ['\u{16e66}', '\u{0}', '\u{0}']), - ('\u{16e47}', ['\u{16e67}', '\u{0}', '\u{0}']), - ('\u{16e48}', ['\u{16e68}', '\u{0}', '\u{0}']), - ('\u{16e49}', ['\u{16e69}', '\u{0}', '\u{0}']), - ('\u{16e4a}', ['\u{16e6a}', '\u{0}', '\u{0}']), - ('\u{16e4b}', ['\u{16e6b}', '\u{0}', '\u{0}']), - ('\u{16e4c}', ['\u{16e6c}', '\u{0}', '\u{0}']), - ('\u{16e4d}', ['\u{16e6d}', '\u{0}', '\u{0}']), - ('\u{16e4e}', ['\u{16e6e}', '\u{0}', '\u{0}']), - ('\u{16e4f}', ['\u{16e6f}', '\u{0}', '\u{0}']), - ('\u{16e50}', ['\u{16e70}', '\u{0}', '\u{0}']), - ('\u{16e51}', ['\u{16e71}', '\u{0}', '\u{0}']), - ('\u{16e52}', ['\u{16e72}', '\u{0}', '\u{0}']), - ('\u{16e53}', ['\u{16e73}', '\u{0}', '\u{0}']), - ('\u{16e54}', ['\u{16e74}', '\u{0}', '\u{0}']), - ('\u{16e55}', ['\u{16e75}', '\u{0}', '\u{0}']), - ('\u{16e56}', ['\u{16e76}', '\u{0}', '\u{0}']), - ('\u{16e57}', ['\u{16e77}', '\u{0}', '\u{0}']), - ('\u{16e58}', ['\u{16e78}', '\u{0}', '\u{0}']), - ('\u{16e59}', ['\u{16e79}', '\u{0}', '\u{0}']), - ('\u{16e5a}', ['\u{16e7a}', '\u{0}', '\u{0}']), - ('\u{16e5b}', ['\u{16e7b}', '\u{0}', '\u{0}']), - ('\u{16e5c}', ['\u{16e7c}', '\u{0}', '\u{0}']), - ('\u{16e5d}', ['\u{16e7d}', '\u{0}', '\u{0}']), - ('\u{16e5e}', ['\u{16e7e}', '\u{0}', '\u{0}']), - ('\u{16e5f}', ['\u{16e7f}', '\u{0}', '\u{0}']), - ('\u{1e900}', ['\u{1e922}', '\u{0}', '\u{0}']), - ('\u{1e901}', ['\u{1e923}', '\u{0}', '\u{0}']), - ('\u{1e902}', ['\u{1e924}', '\u{0}', '\u{0}']), - ('\u{1e903}', ['\u{1e925}', '\u{0}', '\u{0}']), - ('\u{1e904}', ['\u{1e926}', '\u{0}', '\u{0}']), - ('\u{1e905}', ['\u{1e927}', '\u{0}', '\u{0}']), - ('\u{1e906}', ['\u{1e928}', '\u{0}', '\u{0}']), - ('\u{1e907}', ['\u{1e929}', '\u{0}', '\u{0}']), - ('\u{1e908}', ['\u{1e92a}', '\u{0}', '\u{0}']), - ('\u{1e909}', ['\u{1e92b}', '\u{0}', '\u{0}']), - ('\u{1e90a}', ['\u{1e92c}', '\u{0}', '\u{0}']), - ('\u{1e90b}', ['\u{1e92d}', '\u{0}', '\u{0}']), - ('\u{1e90c}', ['\u{1e92e}', '\u{0}', '\u{0}']), - ('\u{1e90d}', ['\u{1e92f}', '\u{0}', '\u{0}']), - ('\u{1e90e}', ['\u{1e930}', '\u{0}', '\u{0}']), - ('\u{1e90f}', ['\u{1e931}', '\u{0}', '\u{0}']), - ('\u{1e910}', ['\u{1e932}', '\u{0}', '\u{0}']), - ('\u{1e911}', ['\u{1e933}', '\u{0}', '\u{0}']), - ('\u{1e912}', ['\u{1e934}', '\u{0}', '\u{0}']), - ('\u{1e913}', ['\u{1e935}', '\u{0}', '\u{0}']), - ('\u{1e914}', ['\u{1e936}', '\u{0}', '\u{0}']), - ('\u{1e915}', ['\u{1e937}', '\u{0}', '\u{0}']), - ('\u{1e916}', ['\u{1e938}', '\u{0}', '\u{0}']), - ('\u{1e917}', ['\u{1e939}', '\u{0}', '\u{0}']), - ('\u{1e918}', ['\u{1e93a}', '\u{0}', '\u{0}']), - ('\u{1e919}', ['\u{1e93b}', '\u{0}', '\u{0}']), - ('\u{1e91a}', ['\u{1e93c}', '\u{0}', '\u{0}']), - ('\u{1e91b}', ['\u{1e93d}', '\u{0}', '\u{0}']), - ('\u{1e91c}', ['\u{1e93e}', '\u{0}', '\u{0}']), - ('\u{1e91d}', ['\u{1e93f}', '\u{0}', '\u{0}']), - ('\u{1e91e}', ['\u{1e940}', '\u{0}', '\u{0}']), - ('\u{1e91f}', ['\u{1e941}', '\u{0}', '\u{0}']), - ('\u{1e920}', ['\u{1e942}', '\u{0}', '\u{0}']), - ('\u{1e921}', ['\u{1e943}', '\u{0}', '\u{0}']), + static LOWERCASE_TABLE: &[(char, u32)] = &[ + ('\u{c0}', 224), ('\u{c1}', 225), ('\u{c2}', 226), ('\u{c3}', 227), ('\u{c4}', 228), + ('\u{c5}', 229), ('\u{c6}', 230), ('\u{c7}', 231), ('\u{c8}', 232), ('\u{c9}', 233), + ('\u{ca}', 234), ('\u{cb}', 235), ('\u{cc}', 236), ('\u{cd}', 237), ('\u{ce}', 238), + ('\u{cf}', 239), ('\u{d0}', 240), ('\u{d1}', 241), ('\u{d2}', 242), ('\u{d3}', 243), + ('\u{d4}', 244), ('\u{d5}', 245), ('\u{d6}', 246), ('\u{d8}', 248), ('\u{d9}', 249), + ('\u{da}', 250), ('\u{db}', 251), ('\u{dc}', 252), ('\u{dd}', 253), ('\u{de}', 254), + ('\u{100}', 257), ('\u{102}', 259), ('\u{104}', 261), ('\u{106}', 263), ('\u{108}', 265), + ('\u{10a}', 267), ('\u{10c}', 269), ('\u{10e}', 271), ('\u{110}', 273), ('\u{112}', 275), + ('\u{114}', 277), ('\u{116}', 279), ('\u{118}', 281), ('\u{11a}', 283), ('\u{11c}', 285), + ('\u{11e}', 287), ('\u{120}', 289), ('\u{122}', 291), ('\u{124}', 293), ('\u{126}', 295), + ('\u{128}', 297), ('\u{12a}', 299), ('\u{12c}', 301), ('\u{12e}', 303), + ('\u{130}', 4194304), ('\u{132}', 307), ('\u{134}', 309), ('\u{136}', 311), + ('\u{139}', 314), ('\u{13b}', 316), ('\u{13d}', 318), ('\u{13f}', 320), ('\u{141}', 322), + ('\u{143}', 324), ('\u{145}', 326), ('\u{147}', 328), ('\u{14a}', 331), ('\u{14c}', 333), + ('\u{14e}', 335), ('\u{150}', 337), ('\u{152}', 339), ('\u{154}', 341), ('\u{156}', 343), + ('\u{158}', 345), ('\u{15a}', 347), ('\u{15c}', 349), ('\u{15e}', 351), ('\u{160}', 353), + ('\u{162}', 355), ('\u{164}', 357), ('\u{166}', 359), ('\u{168}', 361), ('\u{16a}', 363), + ('\u{16c}', 365), ('\u{16e}', 367), ('\u{170}', 369), ('\u{172}', 371), ('\u{174}', 373), + ('\u{176}', 375), ('\u{178}', 255), ('\u{179}', 378), ('\u{17b}', 380), ('\u{17d}', 382), + ('\u{181}', 595), ('\u{182}', 387), ('\u{184}', 389), ('\u{186}', 596), ('\u{187}', 392), + ('\u{189}', 598), ('\u{18a}', 599), ('\u{18b}', 396), ('\u{18e}', 477), ('\u{18f}', 601), + ('\u{190}', 603), ('\u{191}', 402), ('\u{193}', 608), ('\u{194}', 611), ('\u{196}', 617), + ('\u{197}', 616), ('\u{198}', 409), ('\u{19c}', 623), ('\u{19d}', 626), ('\u{19f}', 629), + ('\u{1a0}', 417), ('\u{1a2}', 419), ('\u{1a4}', 421), ('\u{1a6}', 640), ('\u{1a7}', 424), + ('\u{1a9}', 643), ('\u{1ac}', 429), ('\u{1ae}', 648), ('\u{1af}', 432), ('\u{1b1}', 650), + ('\u{1b2}', 651), ('\u{1b3}', 436), ('\u{1b5}', 438), ('\u{1b7}', 658), ('\u{1b8}', 441), + ('\u{1bc}', 445), ('\u{1c4}', 454), ('\u{1c5}', 454), ('\u{1c7}', 457), ('\u{1c8}', 457), + ('\u{1ca}', 460), ('\u{1cb}', 460), ('\u{1cd}', 462), ('\u{1cf}', 464), ('\u{1d1}', 466), + ('\u{1d3}', 468), ('\u{1d5}', 470), ('\u{1d7}', 472), ('\u{1d9}', 474), ('\u{1db}', 476), + ('\u{1de}', 479), ('\u{1e0}', 481), ('\u{1e2}', 483), ('\u{1e4}', 485), ('\u{1e6}', 487), + ('\u{1e8}', 489), ('\u{1ea}', 491), ('\u{1ec}', 493), ('\u{1ee}', 495), ('\u{1f1}', 499), + ('\u{1f2}', 499), ('\u{1f4}', 501), ('\u{1f6}', 405), ('\u{1f7}', 447), ('\u{1f8}', 505), + ('\u{1fa}', 507), ('\u{1fc}', 509), ('\u{1fe}', 511), ('\u{200}', 513), ('\u{202}', 515), + ('\u{204}', 517), ('\u{206}', 519), ('\u{208}', 521), ('\u{20a}', 523), ('\u{20c}', 525), + ('\u{20e}', 527), ('\u{210}', 529), ('\u{212}', 531), ('\u{214}', 533), ('\u{216}', 535), + ('\u{218}', 537), ('\u{21a}', 539), ('\u{21c}', 541), ('\u{21e}', 543), ('\u{220}', 414), + ('\u{222}', 547), ('\u{224}', 549), ('\u{226}', 551), ('\u{228}', 553), ('\u{22a}', 555), + ('\u{22c}', 557), ('\u{22e}', 559), ('\u{230}', 561), ('\u{232}', 563), ('\u{23a}', 11365), + ('\u{23b}', 572), ('\u{23d}', 410), ('\u{23e}', 11366), ('\u{241}', 578), ('\u{243}', 384), + ('\u{244}', 649), ('\u{245}', 652), ('\u{246}', 583), ('\u{248}', 585), ('\u{24a}', 587), + ('\u{24c}', 589), ('\u{24e}', 591), ('\u{370}', 881), ('\u{372}', 883), ('\u{376}', 887), + ('\u{37f}', 1011), ('\u{386}', 940), ('\u{388}', 941), ('\u{389}', 942), ('\u{38a}', 943), + ('\u{38c}', 972), ('\u{38e}', 973), ('\u{38f}', 974), ('\u{391}', 945), ('\u{392}', 946), + ('\u{393}', 947), ('\u{394}', 948), ('\u{395}', 949), ('\u{396}', 950), ('\u{397}', 951), + ('\u{398}', 952), ('\u{399}', 953), ('\u{39a}', 954), ('\u{39b}', 955), ('\u{39c}', 956), + ('\u{39d}', 957), ('\u{39e}', 958), ('\u{39f}', 959), ('\u{3a0}', 960), ('\u{3a1}', 961), + ('\u{3a3}', 963), ('\u{3a4}', 964), ('\u{3a5}', 965), ('\u{3a6}', 966), ('\u{3a7}', 967), + ('\u{3a8}', 968), ('\u{3a9}', 969), ('\u{3aa}', 970), ('\u{3ab}', 971), ('\u{3cf}', 983), + ('\u{3d8}', 985), ('\u{3da}', 987), ('\u{3dc}', 989), ('\u{3de}', 991), ('\u{3e0}', 993), + ('\u{3e2}', 995), ('\u{3e4}', 997), ('\u{3e6}', 999), ('\u{3e8}', 1001), ('\u{3ea}', 1003), + ('\u{3ec}', 1005), ('\u{3ee}', 1007), ('\u{3f4}', 952), ('\u{3f7}', 1016), + ('\u{3f9}', 1010), ('\u{3fa}', 1019), ('\u{3fd}', 891), ('\u{3fe}', 892), ('\u{3ff}', 893), + ('\u{400}', 1104), ('\u{401}', 1105), ('\u{402}', 1106), ('\u{403}', 1107), + ('\u{404}', 1108), ('\u{405}', 1109), ('\u{406}', 1110), ('\u{407}', 1111), + ('\u{408}', 1112), ('\u{409}', 1113), ('\u{40a}', 1114), ('\u{40b}', 1115), + ('\u{40c}', 1116), ('\u{40d}', 1117), ('\u{40e}', 1118), ('\u{40f}', 1119), + ('\u{410}', 1072), ('\u{411}', 1073), ('\u{412}', 1074), ('\u{413}', 1075), + ('\u{414}', 1076), ('\u{415}', 1077), ('\u{416}', 1078), ('\u{417}', 1079), + ('\u{418}', 1080), ('\u{419}', 1081), ('\u{41a}', 1082), ('\u{41b}', 1083), + ('\u{41c}', 1084), ('\u{41d}', 1085), ('\u{41e}', 1086), ('\u{41f}', 1087), + ('\u{420}', 1088), ('\u{421}', 1089), ('\u{422}', 1090), ('\u{423}', 1091), + ('\u{424}', 1092), ('\u{425}', 1093), ('\u{426}', 1094), ('\u{427}', 1095), + ('\u{428}', 1096), ('\u{429}', 1097), ('\u{42a}', 1098), ('\u{42b}', 1099), + ('\u{42c}', 1100), ('\u{42d}', 1101), ('\u{42e}', 1102), ('\u{42f}', 1103), + ('\u{460}', 1121), ('\u{462}', 1123), ('\u{464}', 1125), ('\u{466}', 1127), + ('\u{468}', 1129), ('\u{46a}', 1131), ('\u{46c}', 1133), ('\u{46e}', 1135), + ('\u{470}', 1137), ('\u{472}', 1139), ('\u{474}', 1141), ('\u{476}', 1143), + ('\u{478}', 1145), ('\u{47a}', 1147), ('\u{47c}', 1149), ('\u{47e}', 1151), + ('\u{480}', 1153), ('\u{48a}', 1163), ('\u{48c}', 1165), ('\u{48e}', 1167), + ('\u{490}', 1169), ('\u{492}', 1171), ('\u{494}', 1173), ('\u{496}', 1175), + ('\u{498}', 1177), ('\u{49a}', 1179), ('\u{49c}', 1181), ('\u{49e}', 1183), + ('\u{4a0}', 1185), ('\u{4a2}', 1187), ('\u{4a4}', 1189), ('\u{4a6}', 1191), + ('\u{4a8}', 1193), ('\u{4aa}', 1195), ('\u{4ac}', 1197), ('\u{4ae}', 1199), + ('\u{4b0}', 1201), ('\u{4b2}', 1203), ('\u{4b4}', 1205), ('\u{4b6}', 1207), + ('\u{4b8}', 1209), ('\u{4ba}', 1211), ('\u{4bc}', 1213), ('\u{4be}', 1215), + ('\u{4c0}', 1231), ('\u{4c1}', 1218), ('\u{4c3}', 1220), ('\u{4c5}', 1222), + ('\u{4c7}', 1224), ('\u{4c9}', 1226), ('\u{4cb}', 1228), ('\u{4cd}', 1230), + ('\u{4d0}', 1233), ('\u{4d2}', 1235), ('\u{4d4}', 1237), ('\u{4d6}', 1239), + ('\u{4d8}', 1241), ('\u{4da}', 1243), ('\u{4dc}', 1245), ('\u{4de}', 1247), + ('\u{4e0}', 1249), ('\u{4e2}', 1251), ('\u{4e4}', 1253), ('\u{4e6}', 1255), + ('\u{4e8}', 1257), ('\u{4ea}', 1259), ('\u{4ec}', 1261), ('\u{4ee}', 1263), + ('\u{4f0}', 1265), ('\u{4f2}', 1267), ('\u{4f4}', 1269), ('\u{4f6}', 1271), + ('\u{4f8}', 1273), ('\u{4fa}', 1275), ('\u{4fc}', 1277), ('\u{4fe}', 1279), + ('\u{500}', 1281), ('\u{502}', 1283), ('\u{504}', 1285), ('\u{506}', 1287), + ('\u{508}', 1289), ('\u{50a}', 1291), ('\u{50c}', 1293), ('\u{50e}', 1295), + ('\u{510}', 1297), ('\u{512}', 1299), ('\u{514}', 1301), ('\u{516}', 1303), + ('\u{518}', 1305), ('\u{51a}', 1307), ('\u{51c}', 1309), ('\u{51e}', 1311), + ('\u{520}', 1313), ('\u{522}', 1315), ('\u{524}', 1317), ('\u{526}', 1319), + ('\u{528}', 1321), ('\u{52a}', 1323), ('\u{52c}', 1325), ('\u{52e}', 1327), + ('\u{531}', 1377), ('\u{532}', 1378), ('\u{533}', 1379), ('\u{534}', 1380), + ('\u{535}', 1381), ('\u{536}', 1382), ('\u{537}', 1383), ('\u{538}', 1384), + ('\u{539}', 1385), ('\u{53a}', 1386), ('\u{53b}', 1387), ('\u{53c}', 1388), + ('\u{53d}', 1389), ('\u{53e}', 1390), ('\u{53f}', 1391), ('\u{540}', 1392), + ('\u{541}', 1393), ('\u{542}', 1394), ('\u{543}', 1395), ('\u{544}', 1396), + ('\u{545}', 1397), ('\u{546}', 1398), ('\u{547}', 1399), ('\u{548}', 1400), + ('\u{549}', 1401), ('\u{54a}', 1402), ('\u{54b}', 1403), ('\u{54c}', 1404), + ('\u{54d}', 1405), ('\u{54e}', 1406), ('\u{54f}', 1407), ('\u{550}', 1408), + ('\u{551}', 1409), ('\u{552}', 1410), ('\u{553}', 1411), ('\u{554}', 1412), + ('\u{555}', 1413), ('\u{556}', 1414), ('\u{10a0}', 11520), ('\u{10a1}', 11521), + ('\u{10a2}', 11522), ('\u{10a3}', 11523), ('\u{10a4}', 11524), ('\u{10a5}', 11525), + ('\u{10a6}', 11526), ('\u{10a7}', 11527), ('\u{10a8}', 11528), ('\u{10a9}', 11529), + ('\u{10aa}', 11530), ('\u{10ab}', 11531), ('\u{10ac}', 11532), ('\u{10ad}', 11533), + ('\u{10ae}', 11534), ('\u{10af}', 11535), ('\u{10b0}', 11536), ('\u{10b1}', 11537), + ('\u{10b2}', 11538), ('\u{10b3}', 11539), ('\u{10b4}', 11540), ('\u{10b5}', 11541), + ('\u{10b6}', 11542), ('\u{10b7}', 11543), ('\u{10b8}', 11544), ('\u{10b9}', 11545), + ('\u{10ba}', 11546), ('\u{10bb}', 11547), ('\u{10bc}', 11548), ('\u{10bd}', 11549), + ('\u{10be}', 11550), ('\u{10bf}', 11551), ('\u{10c0}', 11552), ('\u{10c1}', 11553), + ('\u{10c2}', 11554), ('\u{10c3}', 11555), ('\u{10c4}', 11556), ('\u{10c5}', 11557), + ('\u{10c7}', 11559), ('\u{10cd}', 11565), ('\u{13a0}', 43888), ('\u{13a1}', 43889), + ('\u{13a2}', 43890), ('\u{13a3}', 43891), ('\u{13a4}', 43892), ('\u{13a5}', 43893), + ('\u{13a6}', 43894), ('\u{13a7}', 43895), ('\u{13a8}', 43896), ('\u{13a9}', 43897), + ('\u{13aa}', 43898), ('\u{13ab}', 43899), ('\u{13ac}', 43900), ('\u{13ad}', 43901), + ('\u{13ae}', 43902), ('\u{13af}', 43903), ('\u{13b0}', 43904), ('\u{13b1}', 43905), + ('\u{13b2}', 43906), ('\u{13b3}', 43907), ('\u{13b4}', 43908), ('\u{13b5}', 43909), + ('\u{13b6}', 43910), ('\u{13b7}', 43911), ('\u{13b8}', 43912), ('\u{13b9}', 43913), + ('\u{13ba}', 43914), ('\u{13bb}', 43915), ('\u{13bc}', 43916), ('\u{13bd}', 43917), + ('\u{13be}', 43918), ('\u{13bf}', 43919), ('\u{13c0}', 43920), ('\u{13c1}', 43921), + ('\u{13c2}', 43922), ('\u{13c3}', 43923), ('\u{13c4}', 43924), ('\u{13c5}', 43925), + ('\u{13c6}', 43926), ('\u{13c7}', 43927), ('\u{13c8}', 43928), ('\u{13c9}', 43929), + ('\u{13ca}', 43930), ('\u{13cb}', 43931), ('\u{13cc}', 43932), ('\u{13cd}', 43933), + ('\u{13ce}', 43934), ('\u{13cf}', 43935), ('\u{13d0}', 43936), ('\u{13d1}', 43937), + ('\u{13d2}', 43938), ('\u{13d3}', 43939), ('\u{13d4}', 43940), ('\u{13d5}', 43941), + ('\u{13d6}', 43942), ('\u{13d7}', 43943), ('\u{13d8}', 43944), ('\u{13d9}', 43945), + ('\u{13da}', 43946), ('\u{13db}', 43947), ('\u{13dc}', 43948), ('\u{13dd}', 43949), + ('\u{13de}', 43950), ('\u{13df}', 43951), ('\u{13e0}', 43952), ('\u{13e1}', 43953), + ('\u{13e2}', 43954), ('\u{13e3}', 43955), ('\u{13e4}', 43956), ('\u{13e5}', 43957), + ('\u{13e6}', 43958), ('\u{13e7}', 43959), ('\u{13e8}', 43960), ('\u{13e9}', 43961), + ('\u{13ea}', 43962), ('\u{13eb}', 43963), ('\u{13ec}', 43964), ('\u{13ed}', 43965), + ('\u{13ee}', 43966), ('\u{13ef}', 43967), ('\u{13f0}', 5112), ('\u{13f1}', 5113), + ('\u{13f2}', 5114), ('\u{13f3}', 5115), ('\u{13f4}', 5116), ('\u{13f5}', 5117), + ('\u{1c90}', 4304), ('\u{1c91}', 4305), ('\u{1c92}', 4306), ('\u{1c93}', 4307), + ('\u{1c94}', 4308), ('\u{1c95}', 4309), ('\u{1c96}', 4310), ('\u{1c97}', 4311), + ('\u{1c98}', 4312), ('\u{1c99}', 4313), ('\u{1c9a}', 4314), ('\u{1c9b}', 4315), + ('\u{1c9c}', 4316), ('\u{1c9d}', 4317), ('\u{1c9e}', 4318), ('\u{1c9f}', 4319), + ('\u{1ca0}', 4320), ('\u{1ca1}', 4321), ('\u{1ca2}', 4322), ('\u{1ca3}', 4323), + ('\u{1ca4}', 4324), ('\u{1ca5}', 4325), ('\u{1ca6}', 4326), ('\u{1ca7}', 4327), + ('\u{1ca8}', 4328), ('\u{1ca9}', 4329), ('\u{1caa}', 4330), ('\u{1cab}', 4331), + ('\u{1cac}', 4332), ('\u{1cad}', 4333), ('\u{1cae}', 4334), ('\u{1caf}', 4335), + ('\u{1cb0}', 4336), ('\u{1cb1}', 4337), ('\u{1cb2}', 4338), ('\u{1cb3}', 4339), + ('\u{1cb4}', 4340), ('\u{1cb5}', 4341), ('\u{1cb6}', 4342), ('\u{1cb7}', 4343), + ('\u{1cb8}', 4344), ('\u{1cb9}', 4345), ('\u{1cba}', 4346), ('\u{1cbd}', 4349), + ('\u{1cbe}', 4350), ('\u{1cbf}', 4351), ('\u{1e00}', 7681), ('\u{1e02}', 7683), + ('\u{1e04}', 7685), ('\u{1e06}', 7687), ('\u{1e08}', 7689), ('\u{1e0a}', 7691), + ('\u{1e0c}', 7693), ('\u{1e0e}', 7695), ('\u{1e10}', 7697), ('\u{1e12}', 7699), + ('\u{1e14}', 7701), ('\u{1e16}', 7703), ('\u{1e18}', 7705), ('\u{1e1a}', 7707), + ('\u{1e1c}', 7709), ('\u{1e1e}', 7711), ('\u{1e20}', 7713), ('\u{1e22}', 7715), + ('\u{1e24}', 7717), ('\u{1e26}', 7719), ('\u{1e28}', 7721), ('\u{1e2a}', 7723), + ('\u{1e2c}', 7725), ('\u{1e2e}', 7727), ('\u{1e30}', 7729), ('\u{1e32}', 7731), + ('\u{1e34}', 7733), ('\u{1e36}', 7735), ('\u{1e38}', 7737), ('\u{1e3a}', 7739), + ('\u{1e3c}', 7741), ('\u{1e3e}', 7743), ('\u{1e40}', 7745), ('\u{1e42}', 7747), + ('\u{1e44}', 7749), ('\u{1e46}', 7751), ('\u{1e48}', 7753), ('\u{1e4a}', 7755), + ('\u{1e4c}', 7757), ('\u{1e4e}', 7759), ('\u{1e50}', 7761), ('\u{1e52}', 7763), + ('\u{1e54}', 7765), ('\u{1e56}', 7767), ('\u{1e58}', 7769), ('\u{1e5a}', 7771), + ('\u{1e5c}', 7773), ('\u{1e5e}', 7775), ('\u{1e60}', 7777), ('\u{1e62}', 7779), + ('\u{1e64}', 7781), ('\u{1e66}', 7783), ('\u{1e68}', 7785), ('\u{1e6a}', 7787), + ('\u{1e6c}', 7789), ('\u{1e6e}', 7791), ('\u{1e70}', 7793), ('\u{1e72}', 7795), + ('\u{1e74}', 7797), ('\u{1e76}', 7799), ('\u{1e78}', 7801), ('\u{1e7a}', 7803), + ('\u{1e7c}', 7805), ('\u{1e7e}', 7807), ('\u{1e80}', 7809), ('\u{1e82}', 7811), + ('\u{1e84}', 7813), ('\u{1e86}', 7815), ('\u{1e88}', 7817), ('\u{1e8a}', 7819), + ('\u{1e8c}', 7821), ('\u{1e8e}', 7823), ('\u{1e90}', 7825), ('\u{1e92}', 7827), + ('\u{1e94}', 7829), ('\u{1e9e}', 223), ('\u{1ea0}', 7841), ('\u{1ea2}', 7843), + ('\u{1ea4}', 7845), ('\u{1ea6}', 7847), ('\u{1ea8}', 7849), ('\u{1eaa}', 7851), + ('\u{1eac}', 7853), ('\u{1eae}', 7855), ('\u{1eb0}', 7857), ('\u{1eb2}', 7859), + ('\u{1eb4}', 7861), ('\u{1eb6}', 7863), ('\u{1eb8}', 7865), ('\u{1eba}', 7867), + ('\u{1ebc}', 7869), ('\u{1ebe}', 7871), ('\u{1ec0}', 7873), ('\u{1ec2}', 7875), + ('\u{1ec4}', 7877), ('\u{1ec6}', 7879), ('\u{1ec8}', 7881), ('\u{1eca}', 7883), + ('\u{1ecc}', 7885), ('\u{1ece}', 7887), ('\u{1ed0}', 7889), ('\u{1ed2}', 7891), + ('\u{1ed4}', 7893), ('\u{1ed6}', 7895), ('\u{1ed8}', 7897), ('\u{1eda}', 7899), + ('\u{1edc}', 7901), ('\u{1ede}', 7903), ('\u{1ee0}', 7905), ('\u{1ee2}', 7907), + ('\u{1ee4}', 7909), ('\u{1ee6}', 7911), ('\u{1ee8}', 7913), ('\u{1eea}', 7915), + ('\u{1eec}', 7917), ('\u{1eee}', 7919), ('\u{1ef0}', 7921), ('\u{1ef2}', 7923), + ('\u{1ef4}', 7925), ('\u{1ef6}', 7927), ('\u{1ef8}', 7929), ('\u{1efa}', 7931), + ('\u{1efc}', 7933), ('\u{1efe}', 7935), ('\u{1f08}', 7936), ('\u{1f09}', 7937), + ('\u{1f0a}', 7938), ('\u{1f0b}', 7939), ('\u{1f0c}', 7940), ('\u{1f0d}', 7941), + ('\u{1f0e}', 7942), ('\u{1f0f}', 7943), ('\u{1f18}', 7952), ('\u{1f19}', 7953), + ('\u{1f1a}', 7954), ('\u{1f1b}', 7955), ('\u{1f1c}', 7956), ('\u{1f1d}', 7957), + ('\u{1f28}', 7968), ('\u{1f29}', 7969), ('\u{1f2a}', 7970), ('\u{1f2b}', 7971), + ('\u{1f2c}', 7972), ('\u{1f2d}', 7973), ('\u{1f2e}', 7974), ('\u{1f2f}', 7975), + ('\u{1f38}', 7984), ('\u{1f39}', 7985), ('\u{1f3a}', 7986), ('\u{1f3b}', 7987), + ('\u{1f3c}', 7988), ('\u{1f3d}', 7989), ('\u{1f3e}', 7990), ('\u{1f3f}', 7991), + ('\u{1f48}', 8000), ('\u{1f49}', 8001), ('\u{1f4a}', 8002), ('\u{1f4b}', 8003), + ('\u{1f4c}', 8004), ('\u{1f4d}', 8005), ('\u{1f59}', 8017), ('\u{1f5b}', 8019), + ('\u{1f5d}', 8021), ('\u{1f5f}', 8023), ('\u{1f68}', 8032), ('\u{1f69}', 8033), + ('\u{1f6a}', 8034), ('\u{1f6b}', 8035), ('\u{1f6c}', 8036), ('\u{1f6d}', 8037), + ('\u{1f6e}', 8038), ('\u{1f6f}', 8039), ('\u{1f88}', 8064), ('\u{1f89}', 8065), + ('\u{1f8a}', 8066), ('\u{1f8b}', 8067), ('\u{1f8c}', 8068), ('\u{1f8d}', 8069), + ('\u{1f8e}', 8070), ('\u{1f8f}', 8071), ('\u{1f98}', 8080), ('\u{1f99}', 8081), + ('\u{1f9a}', 8082), ('\u{1f9b}', 8083), ('\u{1f9c}', 8084), ('\u{1f9d}', 8085), + ('\u{1f9e}', 8086), ('\u{1f9f}', 8087), ('\u{1fa8}', 8096), ('\u{1fa9}', 8097), + ('\u{1faa}', 8098), ('\u{1fab}', 8099), ('\u{1fac}', 8100), ('\u{1fad}', 8101), + ('\u{1fae}', 8102), ('\u{1faf}', 8103), ('\u{1fb8}', 8112), ('\u{1fb9}', 8113), + ('\u{1fba}', 8048), ('\u{1fbb}', 8049), ('\u{1fbc}', 8115), ('\u{1fc8}', 8050), + ('\u{1fc9}', 8051), ('\u{1fca}', 8052), ('\u{1fcb}', 8053), ('\u{1fcc}', 8131), + ('\u{1fd8}', 8144), ('\u{1fd9}', 8145), ('\u{1fda}', 8054), ('\u{1fdb}', 8055), + ('\u{1fe8}', 8160), ('\u{1fe9}', 8161), ('\u{1fea}', 8058), ('\u{1feb}', 8059), + ('\u{1fec}', 8165), ('\u{1ff8}', 8056), ('\u{1ff9}', 8057), ('\u{1ffa}', 8060), + ('\u{1ffb}', 8061), ('\u{1ffc}', 8179), ('\u{2126}', 969), ('\u{212a}', 107), + ('\u{212b}', 229), ('\u{2132}', 8526), ('\u{2160}', 8560), ('\u{2161}', 8561), + ('\u{2162}', 8562), ('\u{2163}', 8563), ('\u{2164}', 8564), ('\u{2165}', 8565), + ('\u{2166}', 8566), ('\u{2167}', 8567), ('\u{2168}', 8568), ('\u{2169}', 8569), + ('\u{216a}', 8570), ('\u{216b}', 8571), ('\u{216c}', 8572), ('\u{216d}', 8573), + ('\u{216e}', 8574), ('\u{216f}', 8575), ('\u{2183}', 8580), ('\u{24b6}', 9424), + ('\u{24b7}', 9425), ('\u{24b8}', 9426), ('\u{24b9}', 9427), ('\u{24ba}', 9428), + ('\u{24bb}', 9429), ('\u{24bc}', 9430), ('\u{24bd}', 9431), ('\u{24be}', 9432), + ('\u{24bf}', 9433), ('\u{24c0}', 9434), ('\u{24c1}', 9435), ('\u{24c2}', 9436), + ('\u{24c3}', 9437), ('\u{24c4}', 9438), ('\u{24c5}', 9439), ('\u{24c6}', 9440), + ('\u{24c7}', 9441), ('\u{24c8}', 9442), ('\u{24c9}', 9443), ('\u{24ca}', 9444), + ('\u{24cb}', 9445), ('\u{24cc}', 9446), ('\u{24cd}', 9447), ('\u{24ce}', 9448), + ('\u{24cf}', 9449), ('\u{2c00}', 11312), ('\u{2c01}', 11313), ('\u{2c02}', 11314), + ('\u{2c03}', 11315), ('\u{2c04}', 11316), ('\u{2c05}', 11317), ('\u{2c06}', 11318), + ('\u{2c07}', 11319), ('\u{2c08}', 11320), ('\u{2c09}', 11321), ('\u{2c0a}', 11322), + ('\u{2c0b}', 11323), ('\u{2c0c}', 11324), ('\u{2c0d}', 11325), ('\u{2c0e}', 11326), + ('\u{2c0f}', 11327), ('\u{2c10}', 11328), ('\u{2c11}', 11329), ('\u{2c12}', 11330), + ('\u{2c13}', 11331), ('\u{2c14}', 11332), ('\u{2c15}', 11333), ('\u{2c16}', 11334), + ('\u{2c17}', 11335), ('\u{2c18}', 11336), ('\u{2c19}', 11337), ('\u{2c1a}', 11338), + ('\u{2c1b}', 11339), ('\u{2c1c}', 11340), ('\u{2c1d}', 11341), ('\u{2c1e}', 11342), + ('\u{2c1f}', 11343), ('\u{2c20}', 11344), ('\u{2c21}', 11345), ('\u{2c22}', 11346), + ('\u{2c23}', 11347), ('\u{2c24}', 11348), ('\u{2c25}', 11349), ('\u{2c26}', 11350), + ('\u{2c27}', 11351), ('\u{2c28}', 11352), ('\u{2c29}', 11353), ('\u{2c2a}', 11354), + ('\u{2c2b}', 11355), ('\u{2c2c}', 11356), ('\u{2c2d}', 11357), ('\u{2c2e}', 11358), + ('\u{2c2f}', 11359), ('\u{2c60}', 11361), ('\u{2c62}', 619), ('\u{2c63}', 7549), + ('\u{2c64}', 637), ('\u{2c67}', 11368), ('\u{2c69}', 11370), ('\u{2c6b}', 11372), + ('\u{2c6d}', 593), ('\u{2c6e}', 625), ('\u{2c6f}', 592), ('\u{2c70}', 594), + ('\u{2c72}', 11379), ('\u{2c75}', 11382), ('\u{2c7e}', 575), ('\u{2c7f}', 576), + ('\u{2c80}', 11393), ('\u{2c82}', 11395), ('\u{2c84}', 11397), ('\u{2c86}', 11399), + ('\u{2c88}', 11401), ('\u{2c8a}', 11403), ('\u{2c8c}', 11405), ('\u{2c8e}', 11407), + ('\u{2c90}', 11409), ('\u{2c92}', 11411), ('\u{2c94}', 11413), ('\u{2c96}', 11415), + ('\u{2c98}', 11417), ('\u{2c9a}', 11419), ('\u{2c9c}', 11421), ('\u{2c9e}', 11423), + ('\u{2ca0}', 11425), ('\u{2ca2}', 11427), ('\u{2ca4}', 11429), ('\u{2ca6}', 11431), + ('\u{2ca8}', 11433), ('\u{2caa}', 11435), ('\u{2cac}', 11437), ('\u{2cae}', 11439), + ('\u{2cb0}', 11441), ('\u{2cb2}', 11443), ('\u{2cb4}', 11445), ('\u{2cb6}', 11447), + ('\u{2cb8}', 11449), ('\u{2cba}', 11451), ('\u{2cbc}', 11453), ('\u{2cbe}', 11455), + ('\u{2cc0}', 11457), ('\u{2cc2}', 11459), ('\u{2cc4}', 11461), ('\u{2cc6}', 11463), + ('\u{2cc8}', 11465), ('\u{2cca}', 11467), ('\u{2ccc}', 11469), ('\u{2cce}', 11471), + ('\u{2cd0}', 11473), ('\u{2cd2}', 11475), ('\u{2cd4}', 11477), ('\u{2cd6}', 11479), + ('\u{2cd8}', 11481), ('\u{2cda}', 11483), ('\u{2cdc}', 11485), ('\u{2cde}', 11487), + ('\u{2ce0}', 11489), ('\u{2ce2}', 11491), ('\u{2ceb}', 11500), ('\u{2ced}', 11502), + ('\u{2cf2}', 11507), ('\u{a640}', 42561), ('\u{a642}', 42563), ('\u{a644}', 42565), + ('\u{a646}', 42567), ('\u{a648}', 42569), ('\u{a64a}', 42571), ('\u{a64c}', 42573), + ('\u{a64e}', 42575), ('\u{a650}', 42577), ('\u{a652}', 42579), ('\u{a654}', 42581), + ('\u{a656}', 42583), ('\u{a658}', 42585), ('\u{a65a}', 42587), ('\u{a65c}', 42589), + ('\u{a65e}', 42591), ('\u{a660}', 42593), ('\u{a662}', 42595), ('\u{a664}', 42597), + ('\u{a666}', 42599), ('\u{a668}', 42601), ('\u{a66a}', 42603), ('\u{a66c}', 42605), + ('\u{a680}', 42625), ('\u{a682}', 42627), ('\u{a684}', 42629), ('\u{a686}', 42631), + ('\u{a688}', 42633), ('\u{a68a}', 42635), ('\u{a68c}', 42637), ('\u{a68e}', 42639), + ('\u{a690}', 42641), ('\u{a692}', 42643), ('\u{a694}', 42645), ('\u{a696}', 42647), + ('\u{a698}', 42649), ('\u{a69a}', 42651), ('\u{a722}', 42787), ('\u{a724}', 42789), + ('\u{a726}', 42791), ('\u{a728}', 42793), ('\u{a72a}', 42795), ('\u{a72c}', 42797), + ('\u{a72e}', 42799), ('\u{a732}', 42803), ('\u{a734}', 42805), ('\u{a736}', 42807), + ('\u{a738}', 42809), ('\u{a73a}', 42811), ('\u{a73c}', 42813), ('\u{a73e}', 42815), + ('\u{a740}', 42817), ('\u{a742}', 42819), ('\u{a744}', 42821), ('\u{a746}', 42823), + ('\u{a748}', 42825), ('\u{a74a}', 42827), ('\u{a74c}', 42829), ('\u{a74e}', 42831), + ('\u{a750}', 42833), ('\u{a752}', 42835), ('\u{a754}', 42837), ('\u{a756}', 42839), + ('\u{a758}', 42841), ('\u{a75a}', 42843), ('\u{a75c}', 42845), ('\u{a75e}', 42847), + ('\u{a760}', 42849), ('\u{a762}', 42851), ('\u{a764}', 42853), ('\u{a766}', 42855), + ('\u{a768}', 42857), ('\u{a76a}', 42859), ('\u{a76c}', 42861), ('\u{a76e}', 42863), + ('\u{a779}', 42874), ('\u{a77b}', 42876), ('\u{a77d}', 7545), ('\u{a77e}', 42879), + ('\u{a780}', 42881), ('\u{a782}', 42883), ('\u{a784}', 42885), ('\u{a786}', 42887), + ('\u{a78b}', 42892), ('\u{a78d}', 613), ('\u{a790}', 42897), ('\u{a792}', 42899), + ('\u{a796}', 42903), ('\u{a798}', 42905), ('\u{a79a}', 42907), ('\u{a79c}', 42909), + ('\u{a79e}', 42911), ('\u{a7a0}', 42913), ('\u{a7a2}', 42915), ('\u{a7a4}', 42917), + ('\u{a7a6}', 42919), ('\u{a7a8}', 42921), ('\u{a7aa}', 614), ('\u{a7ab}', 604), + ('\u{a7ac}', 609), ('\u{a7ad}', 620), ('\u{a7ae}', 618), ('\u{a7b0}', 670), + ('\u{a7b1}', 647), ('\u{a7b2}', 669), ('\u{a7b3}', 43859), ('\u{a7b4}', 42933), + ('\u{a7b6}', 42935), ('\u{a7b8}', 42937), ('\u{a7ba}', 42939), ('\u{a7bc}', 42941), + ('\u{a7be}', 42943), ('\u{a7c0}', 42945), ('\u{a7c2}', 42947), ('\u{a7c4}', 42900), + ('\u{a7c5}', 642), ('\u{a7c6}', 7566), ('\u{a7c7}', 42952), ('\u{a7c9}', 42954), + ('\u{a7d0}', 42961), ('\u{a7d6}', 42967), ('\u{a7d8}', 42969), ('\u{a7f5}', 42998), + ('\u{ff21}', 65345), ('\u{ff22}', 65346), ('\u{ff23}', 65347), ('\u{ff24}', 65348), + ('\u{ff25}', 65349), ('\u{ff26}', 65350), ('\u{ff27}', 65351), ('\u{ff28}', 65352), + ('\u{ff29}', 65353), ('\u{ff2a}', 65354), ('\u{ff2b}', 65355), ('\u{ff2c}', 65356), + ('\u{ff2d}', 65357), ('\u{ff2e}', 65358), ('\u{ff2f}', 65359), ('\u{ff30}', 65360), + ('\u{ff31}', 65361), ('\u{ff32}', 65362), ('\u{ff33}', 65363), ('\u{ff34}', 65364), + ('\u{ff35}', 65365), ('\u{ff36}', 65366), ('\u{ff37}', 65367), ('\u{ff38}', 65368), + ('\u{ff39}', 65369), ('\u{ff3a}', 65370), ('\u{10400}', 66600), ('\u{10401}', 66601), + ('\u{10402}', 66602), ('\u{10403}', 66603), ('\u{10404}', 66604), ('\u{10405}', 66605), + ('\u{10406}', 66606), ('\u{10407}', 66607), ('\u{10408}', 66608), ('\u{10409}', 66609), + ('\u{1040a}', 66610), ('\u{1040b}', 66611), ('\u{1040c}', 66612), ('\u{1040d}', 66613), + ('\u{1040e}', 66614), ('\u{1040f}', 66615), ('\u{10410}', 66616), ('\u{10411}', 66617), + ('\u{10412}', 66618), ('\u{10413}', 66619), ('\u{10414}', 66620), ('\u{10415}', 66621), + ('\u{10416}', 66622), ('\u{10417}', 66623), ('\u{10418}', 66624), ('\u{10419}', 66625), + ('\u{1041a}', 66626), ('\u{1041b}', 66627), ('\u{1041c}', 66628), ('\u{1041d}', 66629), + ('\u{1041e}', 66630), ('\u{1041f}', 66631), ('\u{10420}', 66632), ('\u{10421}', 66633), + ('\u{10422}', 66634), ('\u{10423}', 66635), ('\u{10424}', 66636), ('\u{10425}', 66637), + ('\u{10426}', 66638), ('\u{10427}', 66639), ('\u{104b0}', 66776), ('\u{104b1}', 66777), + ('\u{104b2}', 66778), ('\u{104b3}', 66779), ('\u{104b4}', 66780), ('\u{104b5}', 66781), + ('\u{104b6}', 66782), ('\u{104b7}', 66783), ('\u{104b8}', 66784), ('\u{104b9}', 66785), + ('\u{104ba}', 66786), ('\u{104bb}', 66787), ('\u{104bc}', 66788), ('\u{104bd}', 66789), + ('\u{104be}', 66790), ('\u{104bf}', 66791), ('\u{104c0}', 66792), ('\u{104c1}', 66793), + ('\u{104c2}', 66794), ('\u{104c3}', 66795), ('\u{104c4}', 66796), ('\u{104c5}', 66797), + ('\u{104c6}', 66798), ('\u{104c7}', 66799), ('\u{104c8}', 66800), ('\u{104c9}', 66801), + ('\u{104ca}', 66802), ('\u{104cb}', 66803), ('\u{104cc}', 66804), ('\u{104cd}', 66805), + ('\u{104ce}', 66806), ('\u{104cf}', 66807), ('\u{104d0}', 66808), ('\u{104d1}', 66809), + ('\u{104d2}', 66810), ('\u{104d3}', 66811), ('\u{10570}', 66967), ('\u{10571}', 66968), + ('\u{10572}', 66969), ('\u{10573}', 66970), ('\u{10574}', 66971), ('\u{10575}', 66972), + ('\u{10576}', 66973), ('\u{10577}', 66974), ('\u{10578}', 66975), ('\u{10579}', 66976), + ('\u{1057a}', 66977), ('\u{1057c}', 66979), ('\u{1057d}', 66980), ('\u{1057e}', 66981), + ('\u{1057f}', 66982), ('\u{10580}', 66983), ('\u{10581}', 66984), ('\u{10582}', 66985), + ('\u{10583}', 66986), ('\u{10584}', 66987), ('\u{10585}', 66988), ('\u{10586}', 66989), + ('\u{10587}', 66990), ('\u{10588}', 66991), ('\u{10589}', 66992), ('\u{1058a}', 66993), + ('\u{1058c}', 66995), ('\u{1058d}', 66996), ('\u{1058e}', 66997), ('\u{1058f}', 66998), + ('\u{10590}', 66999), ('\u{10591}', 67000), ('\u{10592}', 67001), ('\u{10594}', 67003), + ('\u{10595}', 67004), ('\u{10c80}', 68800), ('\u{10c81}', 68801), ('\u{10c82}', 68802), + ('\u{10c83}', 68803), ('\u{10c84}', 68804), ('\u{10c85}', 68805), ('\u{10c86}', 68806), + ('\u{10c87}', 68807), ('\u{10c88}', 68808), ('\u{10c89}', 68809), ('\u{10c8a}', 68810), + ('\u{10c8b}', 68811), ('\u{10c8c}', 68812), ('\u{10c8d}', 68813), ('\u{10c8e}', 68814), + ('\u{10c8f}', 68815), ('\u{10c90}', 68816), ('\u{10c91}', 68817), ('\u{10c92}', 68818), + ('\u{10c93}', 68819), ('\u{10c94}', 68820), ('\u{10c95}', 68821), ('\u{10c96}', 68822), + ('\u{10c97}', 68823), ('\u{10c98}', 68824), ('\u{10c99}', 68825), ('\u{10c9a}', 68826), + ('\u{10c9b}', 68827), ('\u{10c9c}', 68828), ('\u{10c9d}', 68829), ('\u{10c9e}', 68830), + ('\u{10c9f}', 68831), ('\u{10ca0}', 68832), ('\u{10ca1}', 68833), ('\u{10ca2}', 68834), + ('\u{10ca3}', 68835), ('\u{10ca4}', 68836), ('\u{10ca5}', 68837), ('\u{10ca6}', 68838), + ('\u{10ca7}', 68839), ('\u{10ca8}', 68840), ('\u{10ca9}', 68841), ('\u{10caa}', 68842), + ('\u{10cab}', 68843), ('\u{10cac}', 68844), ('\u{10cad}', 68845), ('\u{10cae}', 68846), + ('\u{10caf}', 68847), ('\u{10cb0}', 68848), ('\u{10cb1}', 68849), ('\u{10cb2}', 68850), + ('\u{118a0}', 71872), ('\u{118a1}', 71873), ('\u{118a2}', 71874), ('\u{118a3}', 71875), + ('\u{118a4}', 71876), ('\u{118a5}', 71877), ('\u{118a6}', 71878), ('\u{118a7}', 71879), + ('\u{118a8}', 71880), ('\u{118a9}', 71881), ('\u{118aa}', 71882), ('\u{118ab}', 71883), + ('\u{118ac}', 71884), ('\u{118ad}', 71885), ('\u{118ae}', 71886), ('\u{118af}', 71887), + ('\u{118b0}', 71888), ('\u{118b1}', 71889), ('\u{118b2}', 71890), ('\u{118b3}', 71891), + ('\u{118b4}', 71892), ('\u{118b5}', 71893), ('\u{118b6}', 71894), ('\u{118b7}', 71895), + ('\u{118b8}', 71896), ('\u{118b9}', 71897), ('\u{118ba}', 71898), ('\u{118bb}', 71899), + ('\u{118bc}', 71900), ('\u{118bd}', 71901), ('\u{118be}', 71902), ('\u{118bf}', 71903), + ('\u{16e40}', 93792), ('\u{16e41}', 93793), ('\u{16e42}', 93794), ('\u{16e43}', 93795), + ('\u{16e44}', 93796), ('\u{16e45}', 93797), ('\u{16e46}', 93798), ('\u{16e47}', 93799), + ('\u{16e48}', 93800), ('\u{16e49}', 93801), ('\u{16e4a}', 93802), ('\u{16e4b}', 93803), + ('\u{16e4c}', 93804), ('\u{16e4d}', 93805), ('\u{16e4e}', 93806), ('\u{16e4f}', 93807), + ('\u{16e50}', 93808), ('\u{16e51}', 93809), ('\u{16e52}', 93810), ('\u{16e53}', 93811), + ('\u{16e54}', 93812), ('\u{16e55}', 93813), ('\u{16e56}', 93814), ('\u{16e57}', 93815), + ('\u{16e58}', 93816), ('\u{16e59}', 93817), ('\u{16e5a}', 93818), ('\u{16e5b}', 93819), + ('\u{16e5c}', 93820), ('\u{16e5d}', 93821), ('\u{16e5e}', 93822), ('\u{16e5f}', 93823), + ('\u{1e900}', 125218), ('\u{1e901}', 125219), ('\u{1e902}', 125220), ('\u{1e903}', 125221), + ('\u{1e904}', 125222), ('\u{1e905}', 125223), ('\u{1e906}', 125224), ('\u{1e907}', 125225), + ('\u{1e908}', 125226), ('\u{1e909}', 125227), ('\u{1e90a}', 125228), ('\u{1e90b}', 125229), + ('\u{1e90c}', 125230), ('\u{1e90d}', 125231), ('\u{1e90e}', 125232), ('\u{1e90f}', 125233), + ('\u{1e910}', 125234), ('\u{1e911}', 125235), ('\u{1e912}', 125236), ('\u{1e913}', 125237), + ('\u{1e914}', 125238), ('\u{1e915}', 125239), ('\u{1e916}', 125240), ('\u{1e917}', 125241), + ('\u{1e918}', 125242), ('\u{1e919}', 125243), ('\u{1e91a}', 125244), ('\u{1e91b}', 125245), + ('\u{1e91c}', 125246), ('\u{1e91d}', 125247), ('\u{1e91e}', 125248), ('\u{1e91f}', 125249), + ('\u{1e920}', 125250), ('\u{1e921}', 125251), + ]; + + static LOWERCASE_TABLE_MULTI: &[[char; 3]] = &[ + ['i', '\u{307}', '\u{0}'], + ]; + + static UPPERCASE_TABLE: &[(char, u32)] = &[ + ('\u{b5}', 924), ('\u{df}', 4194304), ('\u{e0}', 192), ('\u{e1}', 193), ('\u{e2}', 194), + ('\u{e3}', 195), ('\u{e4}', 196), ('\u{e5}', 197), ('\u{e6}', 198), ('\u{e7}', 199), + ('\u{e8}', 200), ('\u{e9}', 201), ('\u{ea}', 202), ('\u{eb}', 203), ('\u{ec}', 204), + ('\u{ed}', 205), ('\u{ee}', 206), ('\u{ef}', 207), ('\u{f0}', 208), ('\u{f1}', 209), + ('\u{f2}', 210), ('\u{f3}', 211), ('\u{f4}', 212), ('\u{f5}', 213), ('\u{f6}', 214), + ('\u{f8}', 216), ('\u{f9}', 217), ('\u{fa}', 218), ('\u{fb}', 219), ('\u{fc}', 220), + ('\u{fd}', 221), ('\u{fe}', 222), ('\u{ff}', 376), ('\u{101}', 256), ('\u{103}', 258), + ('\u{105}', 260), ('\u{107}', 262), ('\u{109}', 264), ('\u{10b}', 266), ('\u{10d}', 268), + ('\u{10f}', 270), ('\u{111}', 272), ('\u{113}', 274), ('\u{115}', 276), ('\u{117}', 278), + ('\u{119}', 280), ('\u{11b}', 282), ('\u{11d}', 284), ('\u{11f}', 286), ('\u{121}', 288), + ('\u{123}', 290), ('\u{125}', 292), ('\u{127}', 294), ('\u{129}', 296), ('\u{12b}', 298), + ('\u{12d}', 300), ('\u{12f}', 302), ('\u{131}', 73), ('\u{133}', 306), ('\u{135}', 308), + ('\u{137}', 310), ('\u{13a}', 313), ('\u{13c}', 315), ('\u{13e}', 317), ('\u{140}', 319), + ('\u{142}', 321), ('\u{144}', 323), ('\u{146}', 325), ('\u{148}', 327), + ('\u{149}', 4194305), ('\u{14b}', 330), ('\u{14d}', 332), ('\u{14f}', 334), + ('\u{151}', 336), ('\u{153}', 338), ('\u{155}', 340), ('\u{157}', 342), ('\u{159}', 344), + ('\u{15b}', 346), ('\u{15d}', 348), ('\u{15f}', 350), ('\u{161}', 352), ('\u{163}', 354), + ('\u{165}', 356), ('\u{167}', 358), ('\u{169}', 360), ('\u{16b}', 362), ('\u{16d}', 364), + ('\u{16f}', 366), ('\u{171}', 368), ('\u{173}', 370), ('\u{175}', 372), ('\u{177}', 374), + ('\u{17a}', 377), ('\u{17c}', 379), ('\u{17e}', 381), ('\u{17f}', 83), ('\u{180}', 579), + ('\u{183}', 386), ('\u{185}', 388), ('\u{188}', 391), ('\u{18c}', 395), ('\u{192}', 401), + ('\u{195}', 502), ('\u{199}', 408), ('\u{19a}', 573), ('\u{19e}', 544), ('\u{1a1}', 416), + ('\u{1a3}', 418), ('\u{1a5}', 420), ('\u{1a8}', 423), ('\u{1ad}', 428), ('\u{1b0}', 431), + ('\u{1b4}', 435), ('\u{1b6}', 437), ('\u{1b9}', 440), ('\u{1bd}', 444), ('\u{1bf}', 503), + ('\u{1c5}', 452), ('\u{1c6}', 452), ('\u{1c8}', 455), ('\u{1c9}', 455), ('\u{1cb}', 458), + ('\u{1cc}', 458), ('\u{1ce}', 461), ('\u{1d0}', 463), ('\u{1d2}', 465), ('\u{1d4}', 467), + ('\u{1d6}', 469), ('\u{1d8}', 471), ('\u{1da}', 473), ('\u{1dc}', 475), ('\u{1dd}', 398), + ('\u{1df}', 478), ('\u{1e1}', 480), ('\u{1e3}', 482), ('\u{1e5}', 484), ('\u{1e7}', 486), + ('\u{1e9}', 488), ('\u{1eb}', 490), ('\u{1ed}', 492), ('\u{1ef}', 494), + ('\u{1f0}', 4194306), ('\u{1f2}', 497), ('\u{1f3}', 497), ('\u{1f5}', 500), + ('\u{1f9}', 504), ('\u{1fb}', 506), ('\u{1fd}', 508), ('\u{1ff}', 510), ('\u{201}', 512), + ('\u{203}', 514), ('\u{205}', 516), ('\u{207}', 518), ('\u{209}', 520), ('\u{20b}', 522), + ('\u{20d}', 524), ('\u{20f}', 526), ('\u{211}', 528), ('\u{213}', 530), ('\u{215}', 532), + ('\u{217}', 534), ('\u{219}', 536), ('\u{21b}', 538), ('\u{21d}', 540), ('\u{21f}', 542), + ('\u{223}', 546), ('\u{225}', 548), ('\u{227}', 550), ('\u{229}', 552), ('\u{22b}', 554), + ('\u{22d}', 556), ('\u{22f}', 558), ('\u{231}', 560), ('\u{233}', 562), ('\u{23c}', 571), + ('\u{23f}', 11390), ('\u{240}', 11391), ('\u{242}', 577), ('\u{247}', 582), + ('\u{249}', 584), ('\u{24b}', 586), ('\u{24d}', 588), ('\u{24f}', 590), ('\u{250}', 11375), + ('\u{251}', 11373), ('\u{252}', 11376), ('\u{253}', 385), ('\u{254}', 390), + ('\u{256}', 393), ('\u{257}', 394), ('\u{259}', 399), ('\u{25b}', 400), ('\u{25c}', 42923), + ('\u{260}', 403), ('\u{261}', 42924), ('\u{263}', 404), ('\u{265}', 42893), + ('\u{266}', 42922), ('\u{268}', 407), ('\u{269}', 406), ('\u{26a}', 42926), + ('\u{26b}', 11362), ('\u{26c}', 42925), ('\u{26f}', 412), ('\u{271}', 11374), + ('\u{272}', 413), ('\u{275}', 415), ('\u{27d}', 11364), ('\u{280}', 422), + ('\u{282}', 42949), ('\u{283}', 425), ('\u{287}', 42929), ('\u{288}', 430), + ('\u{289}', 580), ('\u{28a}', 433), ('\u{28b}', 434), ('\u{28c}', 581), ('\u{292}', 439), + ('\u{29d}', 42930), ('\u{29e}', 42928), ('\u{345}', 921), ('\u{371}', 880), + ('\u{373}', 882), ('\u{377}', 886), ('\u{37b}', 1021), ('\u{37c}', 1022), ('\u{37d}', 1023), + ('\u{390}', 4194307), ('\u{3ac}', 902), ('\u{3ad}', 904), ('\u{3ae}', 905), + ('\u{3af}', 906), ('\u{3b0}', 4194308), ('\u{3b1}', 913), ('\u{3b2}', 914), + ('\u{3b3}', 915), ('\u{3b4}', 916), ('\u{3b5}', 917), ('\u{3b6}', 918), ('\u{3b7}', 919), + ('\u{3b8}', 920), ('\u{3b9}', 921), ('\u{3ba}', 922), ('\u{3bb}', 923), ('\u{3bc}', 924), + ('\u{3bd}', 925), ('\u{3be}', 926), ('\u{3bf}', 927), ('\u{3c0}', 928), ('\u{3c1}', 929), + ('\u{3c2}', 931), ('\u{3c3}', 931), ('\u{3c4}', 932), ('\u{3c5}', 933), ('\u{3c6}', 934), + ('\u{3c7}', 935), ('\u{3c8}', 936), ('\u{3c9}', 937), ('\u{3ca}', 938), ('\u{3cb}', 939), + ('\u{3cc}', 908), ('\u{3cd}', 910), ('\u{3ce}', 911), ('\u{3d0}', 914), ('\u{3d1}', 920), + ('\u{3d5}', 934), ('\u{3d6}', 928), ('\u{3d7}', 975), ('\u{3d9}', 984), ('\u{3db}', 986), + ('\u{3dd}', 988), ('\u{3df}', 990), ('\u{3e1}', 992), ('\u{3e3}', 994), ('\u{3e5}', 996), + ('\u{3e7}', 998), ('\u{3e9}', 1000), ('\u{3eb}', 1002), ('\u{3ed}', 1004), + ('\u{3ef}', 1006), ('\u{3f0}', 922), ('\u{3f1}', 929), ('\u{3f2}', 1017), ('\u{3f3}', 895), + ('\u{3f5}', 917), ('\u{3f8}', 1015), ('\u{3fb}', 1018), ('\u{430}', 1040), + ('\u{431}', 1041), ('\u{432}', 1042), ('\u{433}', 1043), ('\u{434}', 1044), + ('\u{435}', 1045), ('\u{436}', 1046), ('\u{437}', 1047), ('\u{438}', 1048), + ('\u{439}', 1049), ('\u{43a}', 1050), ('\u{43b}', 1051), ('\u{43c}', 1052), + ('\u{43d}', 1053), ('\u{43e}', 1054), ('\u{43f}', 1055), ('\u{440}', 1056), + ('\u{441}', 1057), ('\u{442}', 1058), ('\u{443}', 1059), ('\u{444}', 1060), + ('\u{445}', 1061), ('\u{446}', 1062), ('\u{447}', 1063), ('\u{448}', 1064), + ('\u{449}', 1065), ('\u{44a}', 1066), ('\u{44b}', 1067), ('\u{44c}', 1068), + ('\u{44d}', 1069), ('\u{44e}', 1070), ('\u{44f}', 1071), ('\u{450}', 1024), + ('\u{451}', 1025), ('\u{452}', 1026), ('\u{453}', 1027), ('\u{454}', 1028), + ('\u{455}', 1029), ('\u{456}', 1030), ('\u{457}', 1031), ('\u{458}', 1032), + ('\u{459}', 1033), ('\u{45a}', 1034), ('\u{45b}', 1035), ('\u{45c}', 1036), + ('\u{45d}', 1037), ('\u{45e}', 1038), ('\u{45f}', 1039), ('\u{461}', 1120), + ('\u{463}', 1122), ('\u{465}', 1124), ('\u{467}', 1126), ('\u{469}', 1128), + ('\u{46b}', 1130), ('\u{46d}', 1132), ('\u{46f}', 1134), ('\u{471}', 1136), + ('\u{473}', 1138), ('\u{475}', 1140), ('\u{477}', 1142), ('\u{479}', 1144), + ('\u{47b}', 1146), ('\u{47d}', 1148), ('\u{47f}', 1150), ('\u{481}', 1152), + ('\u{48b}', 1162), ('\u{48d}', 1164), ('\u{48f}', 1166), ('\u{491}', 1168), + ('\u{493}', 1170), ('\u{495}', 1172), ('\u{497}', 1174), ('\u{499}', 1176), + ('\u{49b}', 1178), ('\u{49d}', 1180), ('\u{49f}', 1182), ('\u{4a1}', 1184), + ('\u{4a3}', 1186), ('\u{4a5}', 1188), ('\u{4a7}', 1190), ('\u{4a9}', 1192), + ('\u{4ab}', 1194), ('\u{4ad}', 1196), ('\u{4af}', 1198), ('\u{4b1}', 1200), + ('\u{4b3}', 1202), ('\u{4b5}', 1204), ('\u{4b7}', 1206), ('\u{4b9}', 1208), + ('\u{4bb}', 1210), ('\u{4bd}', 1212), ('\u{4bf}', 1214), ('\u{4c2}', 1217), + ('\u{4c4}', 1219), ('\u{4c6}', 1221), ('\u{4c8}', 1223), ('\u{4ca}', 1225), + ('\u{4cc}', 1227), ('\u{4ce}', 1229), ('\u{4cf}', 1216), ('\u{4d1}', 1232), + ('\u{4d3}', 1234), ('\u{4d5}', 1236), ('\u{4d7}', 1238), ('\u{4d9}', 1240), + ('\u{4db}', 1242), ('\u{4dd}', 1244), ('\u{4df}', 1246), ('\u{4e1}', 1248), + ('\u{4e3}', 1250), ('\u{4e5}', 1252), ('\u{4e7}', 1254), ('\u{4e9}', 1256), + ('\u{4eb}', 1258), ('\u{4ed}', 1260), ('\u{4ef}', 1262), ('\u{4f1}', 1264), + ('\u{4f3}', 1266), ('\u{4f5}', 1268), ('\u{4f7}', 1270), ('\u{4f9}', 1272), + ('\u{4fb}', 1274), ('\u{4fd}', 1276), ('\u{4ff}', 1278), ('\u{501}', 1280), + ('\u{503}', 1282), ('\u{505}', 1284), ('\u{507}', 1286), ('\u{509}', 1288), + ('\u{50b}', 1290), ('\u{50d}', 1292), ('\u{50f}', 1294), ('\u{511}', 1296), + ('\u{513}', 1298), ('\u{515}', 1300), ('\u{517}', 1302), ('\u{519}', 1304), + ('\u{51b}', 1306), ('\u{51d}', 1308), ('\u{51f}', 1310), ('\u{521}', 1312), + ('\u{523}', 1314), ('\u{525}', 1316), ('\u{527}', 1318), ('\u{529}', 1320), + ('\u{52b}', 1322), ('\u{52d}', 1324), ('\u{52f}', 1326), ('\u{561}', 1329), + ('\u{562}', 1330), ('\u{563}', 1331), ('\u{564}', 1332), ('\u{565}', 1333), + ('\u{566}', 1334), ('\u{567}', 1335), ('\u{568}', 1336), ('\u{569}', 1337), + ('\u{56a}', 1338), ('\u{56b}', 1339), ('\u{56c}', 1340), ('\u{56d}', 1341), + ('\u{56e}', 1342), ('\u{56f}', 1343), ('\u{570}', 1344), ('\u{571}', 1345), + ('\u{572}', 1346), ('\u{573}', 1347), ('\u{574}', 1348), ('\u{575}', 1349), + ('\u{576}', 1350), ('\u{577}', 1351), ('\u{578}', 1352), ('\u{579}', 1353), + ('\u{57a}', 1354), ('\u{57b}', 1355), ('\u{57c}', 1356), ('\u{57d}', 1357), + ('\u{57e}', 1358), ('\u{57f}', 1359), ('\u{580}', 1360), ('\u{581}', 1361), + ('\u{582}', 1362), ('\u{583}', 1363), ('\u{584}', 1364), ('\u{585}', 1365), + ('\u{586}', 1366), ('\u{587}', 4194309), ('\u{10d0}', 7312), ('\u{10d1}', 7313), + ('\u{10d2}', 7314), ('\u{10d3}', 7315), ('\u{10d4}', 7316), ('\u{10d5}', 7317), + ('\u{10d6}', 7318), ('\u{10d7}', 7319), ('\u{10d8}', 7320), ('\u{10d9}', 7321), + ('\u{10da}', 7322), ('\u{10db}', 7323), ('\u{10dc}', 7324), ('\u{10dd}', 7325), + ('\u{10de}', 7326), ('\u{10df}', 7327), ('\u{10e0}', 7328), ('\u{10e1}', 7329), + ('\u{10e2}', 7330), ('\u{10e3}', 7331), ('\u{10e4}', 7332), ('\u{10e5}', 7333), + ('\u{10e6}', 7334), ('\u{10e7}', 7335), ('\u{10e8}', 7336), ('\u{10e9}', 7337), + ('\u{10ea}', 7338), ('\u{10eb}', 7339), ('\u{10ec}', 7340), ('\u{10ed}', 7341), + ('\u{10ee}', 7342), ('\u{10ef}', 7343), ('\u{10f0}', 7344), ('\u{10f1}', 7345), + ('\u{10f2}', 7346), ('\u{10f3}', 7347), ('\u{10f4}', 7348), ('\u{10f5}', 7349), + ('\u{10f6}', 7350), ('\u{10f7}', 7351), ('\u{10f8}', 7352), ('\u{10f9}', 7353), + ('\u{10fa}', 7354), ('\u{10fd}', 7357), ('\u{10fe}', 7358), ('\u{10ff}', 7359), + ('\u{13f8}', 5104), ('\u{13f9}', 5105), ('\u{13fa}', 5106), ('\u{13fb}', 5107), + ('\u{13fc}', 5108), ('\u{13fd}', 5109), ('\u{1c80}', 1042), ('\u{1c81}', 1044), + ('\u{1c82}', 1054), ('\u{1c83}', 1057), ('\u{1c84}', 1058), ('\u{1c85}', 1058), + ('\u{1c86}', 1066), ('\u{1c87}', 1122), ('\u{1c88}', 42570), ('\u{1d79}', 42877), + ('\u{1d7d}', 11363), ('\u{1d8e}', 42950), ('\u{1e01}', 7680), ('\u{1e03}', 7682), + ('\u{1e05}', 7684), ('\u{1e07}', 7686), ('\u{1e09}', 7688), ('\u{1e0b}', 7690), + ('\u{1e0d}', 7692), ('\u{1e0f}', 7694), ('\u{1e11}', 7696), ('\u{1e13}', 7698), + ('\u{1e15}', 7700), ('\u{1e17}', 7702), ('\u{1e19}', 7704), ('\u{1e1b}', 7706), + ('\u{1e1d}', 7708), ('\u{1e1f}', 7710), ('\u{1e21}', 7712), ('\u{1e23}', 7714), + ('\u{1e25}', 7716), ('\u{1e27}', 7718), ('\u{1e29}', 7720), ('\u{1e2b}', 7722), + ('\u{1e2d}', 7724), ('\u{1e2f}', 7726), ('\u{1e31}', 7728), ('\u{1e33}', 7730), + ('\u{1e35}', 7732), ('\u{1e37}', 7734), ('\u{1e39}', 7736), ('\u{1e3b}', 7738), + ('\u{1e3d}', 7740), ('\u{1e3f}', 7742), ('\u{1e41}', 7744), ('\u{1e43}', 7746), + ('\u{1e45}', 7748), ('\u{1e47}', 7750), ('\u{1e49}', 7752), ('\u{1e4b}', 7754), + ('\u{1e4d}', 7756), ('\u{1e4f}', 7758), ('\u{1e51}', 7760), ('\u{1e53}', 7762), + ('\u{1e55}', 7764), ('\u{1e57}', 7766), ('\u{1e59}', 7768), ('\u{1e5b}', 7770), + ('\u{1e5d}', 7772), ('\u{1e5f}', 7774), ('\u{1e61}', 7776), ('\u{1e63}', 7778), + ('\u{1e65}', 7780), ('\u{1e67}', 7782), ('\u{1e69}', 7784), ('\u{1e6b}', 7786), + ('\u{1e6d}', 7788), ('\u{1e6f}', 7790), ('\u{1e71}', 7792), ('\u{1e73}', 7794), + ('\u{1e75}', 7796), ('\u{1e77}', 7798), ('\u{1e79}', 7800), ('\u{1e7b}', 7802), + ('\u{1e7d}', 7804), ('\u{1e7f}', 7806), ('\u{1e81}', 7808), ('\u{1e83}', 7810), + ('\u{1e85}', 7812), ('\u{1e87}', 7814), ('\u{1e89}', 7816), ('\u{1e8b}', 7818), + ('\u{1e8d}', 7820), ('\u{1e8f}', 7822), ('\u{1e91}', 7824), ('\u{1e93}', 7826), + ('\u{1e95}', 7828), ('\u{1e96}', 4194310), ('\u{1e97}', 4194311), ('\u{1e98}', 4194312), + ('\u{1e99}', 4194313), ('\u{1e9a}', 4194314), ('\u{1e9b}', 7776), ('\u{1ea1}', 7840), + ('\u{1ea3}', 7842), ('\u{1ea5}', 7844), ('\u{1ea7}', 7846), ('\u{1ea9}', 7848), + ('\u{1eab}', 7850), ('\u{1ead}', 7852), ('\u{1eaf}', 7854), ('\u{1eb1}', 7856), + ('\u{1eb3}', 7858), ('\u{1eb5}', 7860), ('\u{1eb7}', 7862), ('\u{1eb9}', 7864), + ('\u{1ebb}', 7866), ('\u{1ebd}', 7868), ('\u{1ebf}', 7870), ('\u{1ec1}', 7872), + ('\u{1ec3}', 7874), ('\u{1ec5}', 7876), ('\u{1ec7}', 7878), ('\u{1ec9}', 7880), + ('\u{1ecb}', 7882), ('\u{1ecd}', 7884), ('\u{1ecf}', 7886), ('\u{1ed1}', 7888), + ('\u{1ed3}', 7890), ('\u{1ed5}', 7892), ('\u{1ed7}', 7894), ('\u{1ed9}', 7896), + ('\u{1edb}', 7898), ('\u{1edd}', 7900), ('\u{1edf}', 7902), ('\u{1ee1}', 7904), + ('\u{1ee3}', 7906), ('\u{1ee5}', 7908), ('\u{1ee7}', 7910), ('\u{1ee9}', 7912), + ('\u{1eeb}', 7914), ('\u{1eed}', 7916), ('\u{1eef}', 7918), ('\u{1ef1}', 7920), + ('\u{1ef3}', 7922), ('\u{1ef5}', 7924), ('\u{1ef7}', 7926), ('\u{1ef9}', 7928), + ('\u{1efb}', 7930), ('\u{1efd}', 7932), ('\u{1eff}', 7934), ('\u{1f00}', 7944), + ('\u{1f01}', 7945), ('\u{1f02}', 7946), ('\u{1f03}', 7947), ('\u{1f04}', 7948), + ('\u{1f05}', 7949), ('\u{1f06}', 7950), ('\u{1f07}', 7951), ('\u{1f10}', 7960), + ('\u{1f11}', 7961), ('\u{1f12}', 7962), ('\u{1f13}', 7963), ('\u{1f14}', 7964), + ('\u{1f15}', 7965), ('\u{1f20}', 7976), ('\u{1f21}', 7977), ('\u{1f22}', 7978), + ('\u{1f23}', 7979), ('\u{1f24}', 7980), ('\u{1f25}', 7981), ('\u{1f26}', 7982), + ('\u{1f27}', 7983), ('\u{1f30}', 7992), ('\u{1f31}', 7993), ('\u{1f32}', 7994), + ('\u{1f33}', 7995), ('\u{1f34}', 7996), ('\u{1f35}', 7997), ('\u{1f36}', 7998), + ('\u{1f37}', 7999), ('\u{1f40}', 8008), ('\u{1f41}', 8009), ('\u{1f42}', 8010), + ('\u{1f43}', 8011), ('\u{1f44}', 8012), ('\u{1f45}', 8013), ('\u{1f50}', 4194315), + ('\u{1f51}', 8025), ('\u{1f52}', 4194316), ('\u{1f53}', 8027), ('\u{1f54}', 4194317), + ('\u{1f55}', 8029), ('\u{1f56}', 4194318), ('\u{1f57}', 8031), ('\u{1f60}', 8040), + ('\u{1f61}', 8041), ('\u{1f62}', 8042), ('\u{1f63}', 8043), ('\u{1f64}', 8044), + ('\u{1f65}', 8045), ('\u{1f66}', 8046), ('\u{1f67}', 8047), ('\u{1f70}', 8122), + ('\u{1f71}', 8123), ('\u{1f72}', 8136), ('\u{1f73}', 8137), ('\u{1f74}', 8138), + ('\u{1f75}', 8139), ('\u{1f76}', 8154), ('\u{1f77}', 8155), ('\u{1f78}', 8184), + ('\u{1f79}', 8185), ('\u{1f7a}', 8170), ('\u{1f7b}', 8171), ('\u{1f7c}', 8186), + ('\u{1f7d}', 8187), ('\u{1f80}', 4194319), ('\u{1f81}', 4194320), ('\u{1f82}', 4194321), + ('\u{1f83}', 4194322), ('\u{1f84}', 4194323), ('\u{1f85}', 4194324), ('\u{1f86}', 4194325), + ('\u{1f87}', 4194326), ('\u{1f88}', 4194327), ('\u{1f89}', 4194328), ('\u{1f8a}', 4194329), + ('\u{1f8b}', 4194330), ('\u{1f8c}', 4194331), ('\u{1f8d}', 4194332), ('\u{1f8e}', 4194333), + ('\u{1f8f}', 4194334), ('\u{1f90}', 4194335), ('\u{1f91}', 4194336), ('\u{1f92}', 4194337), + ('\u{1f93}', 4194338), ('\u{1f94}', 4194339), ('\u{1f95}', 4194340), ('\u{1f96}', 4194341), + ('\u{1f97}', 4194342), ('\u{1f98}', 4194343), ('\u{1f99}', 4194344), ('\u{1f9a}', 4194345), + ('\u{1f9b}', 4194346), ('\u{1f9c}', 4194347), ('\u{1f9d}', 4194348), ('\u{1f9e}', 4194349), + ('\u{1f9f}', 4194350), ('\u{1fa0}', 4194351), ('\u{1fa1}', 4194352), ('\u{1fa2}', 4194353), + ('\u{1fa3}', 4194354), ('\u{1fa4}', 4194355), ('\u{1fa5}', 4194356), ('\u{1fa6}', 4194357), + ('\u{1fa7}', 4194358), ('\u{1fa8}', 4194359), ('\u{1fa9}', 4194360), ('\u{1faa}', 4194361), + ('\u{1fab}', 4194362), ('\u{1fac}', 4194363), ('\u{1fad}', 4194364), ('\u{1fae}', 4194365), + ('\u{1faf}', 4194366), ('\u{1fb0}', 8120), ('\u{1fb1}', 8121), ('\u{1fb2}', 4194367), + ('\u{1fb3}', 4194368), ('\u{1fb4}', 4194369), ('\u{1fb6}', 4194370), ('\u{1fb7}', 4194371), + ('\u{1fbc}', 4194372), ('\u{1fbe}', 921), ('\u{1fc2}', 4194373), ('\u{1fc3}', 4194374), + ('\u{1fc4}', 4194375), ('\u{1fc6}', 4194376), ('\u{1fc7}', 4194377), ('\u{1fcc}', 4194378), + ('\u{1fd0}', 8152), ('\u{1fd1}', 8153), ('\u{1fd2}', 4194379), ('\u{1fd3}', 4194380), + ('\u{1fd6}', 4194381), ('\u{1fd7}', 4194382), ('\u{1fe0}', 8168), ('\u{1fe1}', 8169), + ('\u{1fe2}', 4194383), ('\u{1fe3}', 4194384), ('\u{1fe4}', 4194385), ('\u{1fe5}', 8172), + ('\u{1fe6}', 4194386), ('\u{1fe7}', 4194387), ('\u{1ff2}', 4194388), ('\u{1ff3}', 4194389), + ('\u{1ff4}', 4194390), ('\u{1ff6}', 4194391), ('\u{1ff7}', 4194392), ('\u{1ffc}', 4194393), + ('\u{214e}', 8498), ('\u{2170}', 8544), ('\u{2171}', 8545), ('\u{2172}', 8546), + ('\u{2173}', 8547), ('\u{2174}', 8548), ('\u{2175}', 8549), ('\u{2176}', 8550), + ('\u{2177}', 8551), ('\u{2178}', 8552), ('\u{2179}', 8553), ('\u{217a}', 8554), + ('\u{217b}', 8555), ('\u{217c}', 8556), ('\u{217d}', 8557), ('\u{217e}', 8558), + ('\u{217f}', 8559), ('\u{2184}', 8579), ('\u{24d0}', 9398), ('\u{24d1}', 9399), + ('\u{24d2}', 9400), ('\u{24d3}', 9401), ('\u{24d4}', 9402), ('\u{24d5}', 9403), + ('\u{24d6}', 9404), ('\u{24d7}', 9405), ('\u{24d8}', 9406), ('\u{24d9}', 9407), + ('\u{24da}', 9408), ('\u{24db}', 9409), ('\u{24dc}', 9410), ('\u{24dd}', 9411), + ('\u{24de}', 9412), ('\u{24df}', 9413), ('\u{24e0}', 9414), ('\u{24e1}', 9415), + ('\u{24e2}', 9416), ('\u{24e3}', 9417), ('\u{24e4}', 9418), ('\u{24e5}', 9419), + ('\u{24e6}', 9420), ('\u{24e7}', 9421), ('\u{24e8}', 9422), ('\u{24e9}', 9423), + ('\u{2c30}', 11264), ('\u{2c31}', 11265), ('\u{2c32}', 11266), ('\u{2c33}', 11267), + ('\u{2c34}', 11268), ('\u{2c35}', 11269), ('\u{2c36}', 11270), ('\u{2c37}', 11271), + ('\u{2c38}', 11272), ('\u{2c39}', 11273), ('\u{2c3a}', 11274), ('\u{2c3b}', 11275), + ('\u{2c3c}', 11276), ('\u{2c3d}', 11277), ('\u{2c3e}', 11278), ('\u{2c3f}', 11279), + ('\u{2c40}', 11280), ('\u{2c41}', 11281), ('\u{2c42}', 11282), ('\u{2c43}', 11283), + ('\u{2c44}', 11284), ('\u{2c45}', 11285), ('\u{2c46}', 11286), ('\u{2c47}', 11287), + ('\u{2c48}', 11288), ('\u{2c49}', 11289), ('\u{2c4a}', 11290), ('\u{2c4b}', 11291), + ('\u{2c4c}', 11292), ('\u{2c4d}', 11293), ('\u{2c4e}', 11294), ('\u{2c4f}', 11295), + ('\u{2c50}', 11296), ('\u{2c51}', 11297), ('\u{2c52}', 11298), ('\u{2c53}', 11299), + ('\u{2c54}', 11300), ('\u{2c55}', 11301), ('\u{2c56}', 11302), ('\u{2c57}', 11303), + ('\u{2c58}', 11304), ('\u{2c59}', 11305), ('\u{2c5a}', 11306), ('\u{2c5b}', 11307), + ('\u{2c5c}', 11308), ('\u{2c5d}', 11309), ('\u{2c5e}', 11310), ('\u{2c5f}', 11311), + ('\u{2c61}', 11360), ('\u{2c65}', 570), ('\u{2c66}', 574), ('\u{2c68}', 11367), + ('\u{2c6a}', 11369), ('\u{2c6c}', 11371), ('\u{2c73}', 11378), ('\u{2c76}', 11381), + ('\u{2c81}', 11392), ('\u{2c83}', 11394), ('\u{2c85}', 11396), ('\u{2c87}', 11398), + ('\u{2c89}', 11400), ('\u{2c8b}', 11402), ('\u{2c8d}', 11404), ('\u{2c8f}', 11406), + ('\u{2c91}', 11408), ('\u{2c93}', 11410), ('\u{2c95}', 11412), ('\u{2c97}', 11414), + ('\u{2c99}', 11416), ('\u{2c9b}', 11418), ('\u{2c9d}', 11420), ('\u{2c9f}', 11422), + ('\u{2ca1}', 11424), ('\u{2ca3}', 11426), ('\u{2ca5}', 11428), ('\u{2ca7}', 11430), + ('\u{2ca9}', 11432), ('\u{2cab}', 11434), ('\u{2cad}', 11436), ('\u{2caf}', 11438), + ('\u{2cb1}', 11440), ('\u{2cb3}', 11442), ('\u{2cb5}', 11444), ('\u{2cb7}', 11446), + ('\u{2cb9}', 11448), ('\u{2cbb}', 11450), ('\u{2cbd}', 11452), ('\u{2cbf}', 11454), + ('\u{2cc1}', 11456), ('\u{2cc3}', 11458), ('\u{2cc5}', 11460), ('\u{2cc7}', 11462), + ('\u{2cc9}', 11464), ('\u{2ccb}', 11466), ('\u{2ccd}', 11468), ('\u{2ccf}', 11470), + ('\u{2cd1}', 11472), ('\u{2cd3}', 11474), ('\u{2cd5}', 11476), ('\u{2cd7}', 11478), + ('\u{2cd9}', 11480), ('\u{2cdb}', 11482), ('\u{2cdd}', 11484), ('\u{2cdf}', 11486), + ('\u{2ce1}', 11488), ('\u{2ce3}', 11490), ('\u{2cec}', 11499), ('\u{2cee}', 11501), + ('\u{2cf3}', 11506), ('\u{2d00}', 4256), ('\u{2d01}', 4257), ('\u{2d02}', 4258), + ('\u{2d03}', 4259), ('\u{2d04}', 4260), ('\u{2d05}', 4261), ('\u{2d06}', 4262), + ('\u{2d07}', 4263), ('\u{2d08}', 4264), ('\u{2d09}', 4265), ('\u{2d0a}', 4266), + ('\u{2d0b}', 4267), ('\u{2d0c}', 4268), ('\u{2d0d}', 4269), ('\u{2d0e}', 4270), + ('\u{2d0f}', 4271), ('\u{2d10}', 4272), ('\u{2d11}', 4273), ('\u{2d12}', 4274), + ('\u{2d13}', 4275), ('\u{2d14}', 4276), ('\u{2d15}', 4277), ('\u{2d16}', 4278), + ('\u{2d17}', 4279), ('\u{2d18}', 4280), ('\u{2d19}', 4281), ('\u{2d1a}', 4282), + ('\u{2d1b}', 4283), ('\u{2d1c}', 4284), ('\u{2d1d}', 4285), ('\u{2d1e}', 4286), + ('\u{2d1f}', 4287), ('\u{2d20}', 4288), ('\u{2d21}', 4289), ('\u{2d22}', 4290), + ('\u{2d23}', 4291), ('\u{2d24}', 4292), ('\u{2d25}', 4293), ('\u{2d27}', 4295), + ('\u{2d2d}', 4301), ('\u{a641}', 42560), ('\u{a643}', 42562), ('\u{a645}', 42564), + ('\u{a647}', 42566), ('\u{a649}', 42568), ('\u{a64b}', 42570), ('\u{a64d}', 42572), + ('\u{a64f}', 42574), ('\u{a651}', 42576), ('\u{a653}', 42578), ('\u{a655}', 42580), + ('\u{a657}', 42582), ('\u{a659}', 42584), ('\u{a65b}', 42586), ('\u{a65d}', 42588), + ('\u{a65f}', 42590), ('\u{a661}', 42592), ('\u{a663}', 42594), ('\u{a665}', 42596), + ('\u{a667}', 42598), ('\u{a669}', 42600), ('\u{a66b}', 42602), ('\u{a66d}', 42604), + ('\u{a681}', 42624), ('\u{a683}', 42626), ('\u{a685}', 42628), ('\u{a687}', 42630), + ('\u{a689}', 42632), ('\u{a68b}', 42634), ('\u{a68d}', 42636), ('\u{a68f}', 42638), + ('\u{a691}', 42640), ('\u{a693}', 42642), ('\u{a695}', 42644), ('\u{a697}', 42646), + ('\u{a699}', 42648), ('\u{a69b}', 42650), ('\u{a723}', 42786), ('\u{a725}', 42788), + ('\u{a727}', 42790), ('\u{a729}', 42792), ('\u{a72b}', 42794), ('\u{a72d}', 42796), + ('\u{a72f}', 42798), ('\u{a733}', 42802), ('\u{a735}', 42804), ('\u{a737}', 42806), + ('\u{a739}', 42808), ('\u{a73b}', 42810), ('\u{a73d}', 42812), ('\u{a73f}', 42814), + ('\u{a741}', 42816), ('\u{a743}', 42818), ('\u{a745}', 42820), ('\u{a747}', 42822), + ('\u{a749}', 42824), ('\u{a74b}', 42826), ('\u{a74d}', 42828), ('\u{a74f}', 42830), + ('\u{a751}', 42832), ('\u{a753}', 42834), ('\u{a755}', 42836), ('\u{a757}', 42838), + ('\u{a759}', 42840), ('\u{a75b}', 42842), ('\u{a75d}', 42844), ('\u{a75f}', 42846), + ('\u{a761}', 42848), ('\u{a763}', 42850), ('\u{a765}', 42852), ('\u{a767}', 42854), + ('\u{a769}', 42856), ('\u{a76b}', 42858), ('\u{a76d}', 42860), ('\u{a76f}', 42862), + ('\u{a77a}', 42873), ('\u{a77c}', 42875), ('\u{a77f}', 42878), ('\u{a781}', 42880), + ('\u{a783}', 42882), ('\u{a785}', 42884), ('\u{a787}', 42886), ('\u{a78c}', 42891), + ('\u{a791}', 42896), ('\u{a793}', 42898), ('\u{a794}', 42948), ('\u{a797}', 42902), + ('\u{a799}', 42904), ('\u{a79b}', 42906), ('\u{a79d}', 42908), ('\u{a79f}', 42910), + ('\u{a7a1}', 42912), ('\u{a7a3}', 42914), ('\u{a7a5}', 42916), ('\u{a7a7}', 42918), + ('\u{a7a9}', 42920), ('\u{a7b5}', 42932), ('\u{a7b7}', 42934), ('\u{a7b9}', 42936), + ('\u{a7bb}', 42938), ('\u{a7bd}', 42940), ('\u{a7bf}', 42942), ('\u{a7c1}', 42944), + ('\u{a7c3}', 42946), ('\u{a7c8}', 42951), ('\u{a7ca}', 42953), ('\u{a7d1}', 42960), + ('\u{a7d7}', 42966), ('\u{a7d9}', 42968), ('\u{a7f6}', 42997), ('\u{ab53}', 42931), + ('\u{ab70}', 5024), ('\u{ab71}', 5025), ('\u{ab72}', 5026), ('\u{ab73}', 5027), + ('\u{ab74}', 5028), ('\u{ab75}', 5029), ('\u{ab76}', 5030), ('\u{ab77}', 5031), + ('\u{ab78}', 5032), ('\u{ab79}', 5033), ('\u{ab7a}', 5034), ('\u{ab7b}', 5035), + ('\u{ab7c}', 5036), ('\u{ab7d}', 5037), ('\u{ab7e}', 5038), ('\u{ab7f}', 5039), + ('\u{ab80}', 5040), ('\u{ab81}', 5041), ('\u{ab82}', 5042), ('\u{ab83}', 5043), + ('\u{ab84}', 5044), ('\u{ab85}', 5045), ('\u{ab86}', 5046), ('\u{ab87}', 5047), + ('\u{ab88}', 5048), ('\u{ab89}', 5049), ('\u{ab8a}', 5050), ('\u{ab8b}', 5051), + ('\u{ab8c}', 5052), ('\u{ab8d}', 5053), ('\u{ab8e}', 5054), ('\u{ab8f}', 5055), + ('\u{ab90}', 5056), ('\u{ab91}', 5057), ('\u{ab92}', 5058), ('\u{ab93}', 5059), + ('\u{ab94}', 5060), ('\u{ab95}', 5061), ('\u{ab96}', 5062), ('\u{ab97}', 5063), + ('\u{ab98}', 5064), ('\u{ab99}', 5065), ('\u{ab9a}', 5066), ('\u{ab9b}', 5067), + ('\u{ab9c}', 5068), ('\u{ab9d}', 5069), ('\u{ab9e}', 5070), ('\u{ab9f}', 5071), + ('\u{aba0}', 5072), ('\u{aba1}', 5073), ('\u{aba2}', 5074), ('\u{aba3}', 5075), + ('\u{aba4}', 5076), ('\u{aba5}', 5077), ('\u{aba6}', 5078), ('\u{aba7}', 5079), + ('\u{aba8}', 5080), ('\u{aba9}', 5081), ('\u{abaa}', 5082), ('\u{abab}', 5083), + ('\u{abac}', 5084), ('\u{abad}', 5085), ('\u{abae}', 5086), ('\u{abaf}', 5087), + ('\u{abb0}', 5088), ('\u{abb1}', 5089), ('\u{abb2}', 5090), ('\u{abb3}', 5091), + ('\u{abb4}', 5092), ('\u{abb5}', 5093), ('\u{abb6}', 5094), ('\u{abb7}', 5095), + ('\u{abb8}', 5096), ('\u{abb9}', 5097), ('\u{abba}', 5098), ('\u{abbb}', 5099), + ('\u{abbc}', 5100), ('\u{abbd}', 5101), ('\u{abbe}', 5102), ('\u{abbf}', 5103), + ('\u{fb00}', 4194394), ('\u{fb01}', 4194395), ('\u{fb02}', 4194396), ('\u{fb03}', 4194397), + ('\u{fb04}', 4194398), ('\u{fb05}', 4194399), ('\u{fb06}', 4194400), ('\u{fb13}', 4194401), + ('\u{fb14}', 4194402), ('\u{fb15}', 4194403), ('\u{fb16}', 4194404), ('\u{fb17}', 4194405), + ('\u{ff41}', 65313), ('\u{ff42}', 65314), ('\u{ff43}', 65315), ('\u{ff44}', 65316), + ('\u{ff45}', 65317), ('\u{ff46}', 65318), ('\u{ff47}', 65319), ('\u{ff48}', 65320), + ('\u{ff49}', 65321), ('\u{ff4a}', 65322), ('\u{ff4b}', 65323), ('\u{ff4c}', 65324), + ('\u{ff4d}', 65325), ('\u{ff4e}', 65326), ('\u{ff4f}', 65327), ('\u{ff50}', 65328), + ('\u{ff51}', 65329), ('\u{ff52}', 65330), ('\u{ff53}', 65331), ('\u{ff54}', 65332), + ('\u{ff55}', 65333), ('\u{ff56}', 65334), ('\u{ff57}', 65335), ('\u{ff58}', 65336), + ('\u{ff59}', 65337), ('\u{ff5a}', 65338), ('\u{10428}', 66560), ('\u{10429}', 66561), + ('\u{1042a}', 66562), ('\u{1042b}', 66563), ('\u{1042c}', 66564), ('\u{1042d}', 66565), + ('\u{1042e}', 66566), ('\u{1042f}', 66567), ('\u{10430}', 66568), ('\u{10431}', 66569), + ('\u{10432}', 66570), ('\u{10433}', 66571), ('\u{10434}', 66572), ('\u{10435}', 66573), + ('\u{10436}', 66574), ('\u{10437}', 66575), ('\u{10438}', 66576), ('\u{10439}', 66577), + ('\u{1043a}', 66578), ('\u{1043b}', 66579), ('\u{1043c}', 66580), ('\u{1043d}', 66581), + ('\u{1043e}', 66582), ('\u{1043f}', 66583), ('\u{10440}', 66584), ('\u{10441}', 66585), + ('\u{10442}', 66586), ('\u{10443}', 66587), ('\u{10444}', 66588), ('\u{10445}', 66589), + ('\u{10446}', 66590), ('\u{10447}', 66591), ('\u{10448}', 66592), ('\u{10449}', 66593), + ('\u{1044a}', 66594), ('\u{1044b}', 66595), ('\u{1044c}', 66596), ('\u{1044d}', 66597), + ('\u{1044e}', 66598), ('\u{1044f}', 66599), ('\u{104d8}', 66736), ('\u{104d9}', 66737), + ('\u{104da}', 66738), ('\u{104db}', 66739), ('\u{104dc}', 66740), ('\u{104dd}', 66741), + ('\u{104de}', 66742), ('\u{104df}', 66743), ('\u{104e0}', 66744), ('\u{104e1}', 66745), + ('\u{104e2}', 66746), ('\u{104e3}', 66747), ('\u{104e4}', 66748), ('\u{104e5}', 66749), + ('\u{104e6}', 66750), ('\u{104e7}', 66751), ('\u{104e8}', 66752), ('\u{104e9}', 66753), + ('\u{104ea}', 66754), ('\u{104eb}', 66755), ('\u{104ec}', 66756), ('\u{104ed}', 66757), + ('\u{104ee}', 66758), ('\u{104ef}', 66759), ('\u{104f0}', 66760), ('\u{104f1}', 66761), + ('\u{104f2}', 66762), ('\u{104f3}', 66763), ('\u{104f4}', 66764), ('\u{104f5}', 66765), + ('\u{104f6}', 66766), ('\u{104f7}', 66767), ('\u{104f8}', 66768), ('\u{104f9}', 66769), + ('\u{104fa}', 66770), ('\u{104fb}', 66771), ('\u{10597}', 66928), ('\u{10598}', 66929), + ('\u{10599}', 66930), ('\u{1059a}', 66931), ('\u{1059b}', 66932), ('\u{1059c}', 66933), + ('\u{1059d}', 66934), ('\u{1059e}', 66935), ('\u{1059f}', 66936), ('\u{105a0}', 66937), + ('\u{105a1}', 66938), ('\u{105a3}', 66940), ('\u{105a4}', 66941), ('\u{105a5}', 66942), + ('\u{105a6}', 66943), ('\u{105a7}', 66944), ('\u{105a8}', 66945), ('\u{105a9}', 66946), + ('\u{105aa}', 66947), ('\u{105ab}', 66948), ('\u{105ac}', 66949), ('\u{105ad}', 66950), + ('\u{105ae}', 66951), ('\u{105af}', 66952), ('\u{105b0}', 66953), ('\u{105b1}', 66954), + ('\u{105b3}', 66956), ('\u{105b4}', 66957), ('\u{105b5}', 66958), ('\u{105b6}', 66959), + ('\u{105b7}', 66960), ('\u{105b8}', 66961), ('\u{105b9}', 66962), ('\u{105bb}', 66964), + ('\u{105bc}', 66965), ('\u{10cc0}', 68736), ('\u{10cc1}', 68737), ('\u{10cc2}', 68738), + ('\u{10cc3}', 68739), ('\u{10cc4}', 68740), ('\u{10cc5}', 68741), ('\u{10cc6}', 68742), + ('\u{10cc7}', 68743), ('\u{10cc8}', 68744), ('\u{10cc9}', 68745), ('\u{10cca}', 68746), + ('\u{10ccb}', 68747), ('\u{10ccc}', 68748), ('\u{10ccd}', 68749), ('\u{10cce}', 68750), + ('\u{10ccf}', 68751), ('\u{10cd0}', 68752), ('\u{10cd1}', 68753), ('\u{10cd2}', 68754), + ('\u{10cd3}', 68755), ('\u{10cd4}', 68756), ('\u{10cd5}', 68757), ('\u{10cd6}', 68758), + ('\u{10cd7}', 68759), ('\u{10cd8}', 68760), ('\u{10cd9}', 68761), ('\u{10cda}', 68762), + ('\u{10cdb}', 68763), ('\u{10cdc}', 68764), ('\u{10cdd}', 68765), ('\u{10cde}', 68766), + ('\u{10cdf}', 68767), ('\u{10ce0}', 68768), ('\u{10ce1}', 68769), ('\u{10ce2}', 68770), + ('\u{10ce3}', 68771), ('\u{10ce4}', 68772), ('\u{10ce5}', 68773), ('\u{10ce6}', 68774), + ('\u{10ce7}', 68775), ('\u{10ce8}', 68776), ('\u{10ce9}', 68777), ('\u{10cea}', 68778), + ('\u{10ceb}', 68779), ('\u{10cec}', 68780), ('\u{10ced}', 68781), ('\u{10cee}', 68782), + ('\u{10cef}', 68783), ('\u{10cf0}', 68784), ('\u{10cf1}', 68785), ('\u{10cf2}', 68786), + ('\u{118c0}', 71840), ('\u{118c1}', 71841), ('\u{118c2}', 71842), ('\u{118c3}', 71843), + ('\u{118c4}', 71844), ('\u{118c5}', 71845), ('\u{118c6}', 71846), ('\u{118c7}', 71847), + ('\u{118c8}', 71848), ('\u{118c9}', 71849), ('\u{118ca}', 71850), ('\u{118cb}', 71851), + ('\u{118cc}', 71852), ('\u{118cd}', 71853), ('\u{118ce}', 71854), ('\u{118cf}', 71855), + ('\u{118d0}', 71856), ('\u{118d1}', 71857), ('\u{118d2}', 71858), ('\u{118d3}', 71859), + ('\u{118d4}', 71860), ('\u{118d5}', 71861), ('\u{118d6}', 71862), ('\u{118d7}', 71863), + ('\u{118d8}', 71864), ('\u{118d9}', 71865), ('\u{118da}', 71866), ('\u{118db}', 71867), + ('\u{118dc}', 71868), ('\u{118dd}', 71869), ('\u{118de}', 71870), ('\u{118df}', 71871), + ('\u{16e60}', 93760), ('\u{16e61}', 93761), ('\u{16e62}', 93762), ('\u{16e63}', 93763), + ('\u{16e64}', 93764), ('\u{16e65}', 93765), ('\u{16e66}', 93766), ('\u{16e67}', 93767), + ('\u{16e68}', 93768), ('\u{16e69}', 93769), ('\u{16e6a}', 93770), ('\u{16e6b}', 93771), + ('\u{16e6c}', 93772), ('\u{16e6d}', 93773), ('\u{16e6e}', 93774), ('\u{16e6f}', 93775), + ('\u{16e70}', 93776), ('\u{16e71}', 93777), ('\u{16e72}', 93778), ('\u{16e73}', 93779), + ('\u{16e74}', 93780), ('\u{16e75}', 93781), ('\u{16e76}', 93782), ('\u{16e77}', 93783), + ('\u{16e78}', 93784), ('\u{16e79}', 93785), ('\u{16e7a}', 93786), ('\u{16e7b}', 93787), + ('\u{16e7c}', 93788), ('\u{16e7d}', 93789), ('\u{16e7e}', 93790), ('\u{16e7f}', 93791), + ('\u{1e922}', 125184), ('\u{1e923}', 125185), ('\u{1e924}', 125186), ('\u{1e925}', 125187), + ('\u{1e926}', 125188), ('\u{1e927}', 125189), ('\u{1e928}', 125190), ('\u{1e929}', 125191), + ('\u{1e92a}', 125192), ('\u{1e92b}', 125193), ('\u{1e92c}', 125194), ('\u{1e92d}', 125195), + ('\u{1e92e}', 125196), ('\u{1e92f}', 125197), ('\u{1e930}', 125198), ('\u{1e931}', 125199), + ('\u{1e932}', 125200), ('\u{1e933}', 125201), ('\u{1e934}', 125202), ('\u{1e935}', 125203), + ('\u{1e936}', 125204), ('\u{1e937}', 125205), ('\u{1e938}', 125206), ('\u{1e939}', 125207), + ('\u{1e93a}', 125208), ('\u{1e93b}', 125209), ('\u{1e93c}', 125210), ('\u{1e93d}', 125211), + ('\u{1e93e}', 125212), ('\u{1e93f}', 125213), ('\u{1e940}', 125214), ('\u{1e941}', 125215), + ('\u{1e942}', 125216), ('\u{1e943}', 125217), ]; - static UPPERCASE_TABLE: &[(char, [char; 3])] = &[ - ('a', ['A', '\u{0}', '\u{0}']), ('b', ['B', '\u{0}', '\u{0}']), - ('c', ['C', '\u{0}', '\u{0}']), ('d', ['D', '\u{0}', '\u{0}']), - ('e', ['E', '\u{0}', '\u{0}']), ('f', ['F', '\u{0}', '\u{0}']), - ('g', ['G', '\u{0}', '\u{0}']), ('h', ['H', '\u{0}', '\u{0}']), - ('i', ['I', '\u{0}', '\u{0}']), ('j', ['J', '\u{0}', '\u{0}']), - ('k', ['K', '\u{0}', '\u{0}']), ('l', ['L', '\u{0}', '\u{0}']), - ('m', ['M', '\u{0}', '\u{0}']), ('n', ['N', '\u{0}', '\u{0}']), - ('o', ['O', '\u{0}', '\u{0}']), ('p', ['P', '\u{0}', '\u{0}']), - ('q', ['Q', '\u{0}', '\u{0}']), ('r', ['R', '\u{0}', '\u{0}']), - ('s', ['S', '\u{0}', '\u{0}']), ('t', ['T', '\u{0}', '\u{0}']), - ('u', ['U', '\u{0}', '\u{0}']), ('v', ['V', '\u{0}', '\u{0}']), - ('w', ['W', '\u{0}', '\u{0}']), ('x', ['X', '\u{0}', '\u{0}']), - ('y', ['Y', '\u{0}', '\u{0}']), ('z', ['Z', '\u{0}', '\u{0}']), - ('\u{b5}', ['\u{39c}', '\u{0}', '\u{0}']), ('\u{df}', ['S', 'S', '\u{0}']), - ('\u{e0}', ['\u{c0}', '\u{0}', '\u{0}']), ('\u{e1}', ['\u{c1}', '\u{0}', '\u{0}']), - ('\u{e2}', ['\u{c2}', '\u{0}', '\u{0}']), ('\u{e3}', ['\u{c3}', '\u{0}', '\u{0}']), - ('\u{e4}', ['\u{c4}', '\u{0}', '\u{0}']), ('\u{e5}', ['\u{c5}', '\u{0}', '\u{0}']), - ('\u{e6}', ['\u{c6}', '\u{0}', '\u{0}']), ('\u{e7}', ['\u{c7}', '\u{0}', '\u{0}']), - ('\u{e8}', ['\u{c8}', '\u{0}', '\u{0}']), ('\u{e9}', ['\u{c9}', '\u{0}', '\u{0}']), - ('\u{ea}', ['\u{ca}', '\u{0}', '\u{0}']), ('\u{eb}', ['\u{cb}', '\u{0}', '\u{0}']), - ('\u{ec}', ['\u{cc}', '\u{0}', '\u{0}']), ('\u{ed}', ['\u{cd}', '\u{0}', '\u{0}']), - ('\u{ee}', ['\u{ce}', '\u{0}', '\u{0}']), ('\u{ef}', ['\u{cf}', '\u{0}', '\u{0}']), - ('\u{f0}', ['\u{d0}', '\u{0}', '\u{0}']), ('\u{f1}', ['\u{d1}', '\u{0}', '\u{0}']), - ('\u{f2}', ['\u{d2}', '\u{0}', '\u{0}']), ('\u{f3}', ['\u{d3}', '\u{0}', '\u{0}']), - ('\u{f4}', ['\u{d4}', '\u{0}', '\u{0}']), ('\u{f5}', ['\u{d5}', '\u{0}', '\u{0}']), - ('\u{f6}', ['\u{d6}', '\u{0}', '\u{0}']), ('\u{f8}', ['\u{d8}', '\u{0}', '\u{0}']), - ('\u{f9}', ['\u{d9}', '\u{0}', '\u{0}']), ('\u{fa}', ['\u{da}', '\u{0}', '\u{0}']), - ('\u{fb}', ['\u{db}', '\u{0}', '\u{0}']), ('\u{fc}', ['\u{dc}', '\u{0}', '\u{0}']), - ('\u{fd}', ['\u{dd}', '\u{0}', '\u{0}']), ('\u{fe}', ['\u{de}', '\u{0}', '\u{0}']), - ('\u{ff}', ['\u{178}', '\u{0}', '\u{0}']), ('\u{101}', ['\u{100}', '\u{0}', '\u{0}']), - ('\u{103}', ['\u{102}', '\u{0}', '\u{0}']), ('\u{105}', ['\u{104}', '\u{0}', '\u{0}']), - ('\u{107}', ['\u{106}', '\u{0}', '\u{0}']), ('\u{109}', ['\u{108}', '\u{0}', '\u{0}']), - ('\u{10b}', ['\u{10a}', '\u{0}', '\u{0}']), ('\u{10d}', ['\u{10c}', '\u{0}', '\u{0}']), - ('\u{10f}', ['\u{10e}', '\u{0}', '\u{0}']), ('\u{111}', ['\u{110}', '\u{0}', '\u{0}']), - ('\u{113}', ['\u{112}', '\u{0}', '\u{0}']), ('\u{115}', ['\u{114}', '\u{0}', '\u{0}']), - ('\u{117}', ['\u{116}', '\u{0}', '\u{0}']), ('\u{119}', ['\u{118}', '\u{0}', '\u{0}']), - ('\u{11b}', ['\u{11a}', '\u{0}', '\u{0}']), ('\u{11d}', ['\u{11c}', '\u{0}', '\u{0}']), - ('\u{11f}', ['\u{11e}', '\u{0}', '\u{0}']), ('\u{121}', ['\u{120}', '\u{0}', '\u{0}']), - ('\u{123}', ['\u{122}', '\u{0}', '\u{0}']), ('\u{125}', ['\u{124}', '\u{0}', '\u{0}']), - ('\u{127}', ['\u{126}', '\u{0}', '\u{0}']), ('\u{129}', ['\u{128}', '\u{0}', '\u{0}']), - ('\u{12b}', ['\u{12a}', '\u{0}', '\u{0}']), ('\u{12d}', ['\u{12c}', '\u{0}', '\u{0}']), - ('\u{12f}', ['\u{12e}', '\u{0}', '\u{0}']), ('\u{131}', ['I', '\u{0}', '\u{0}']), - ('\u{133}', ['\u{132}', '\u{0}', '\u{0}']), ('\u{135}', ['\u{134}', '\u{0}', '\u{0}']), - ('\u{137}', ['\u{136}', '\u{0}', '\u{0}']), ('\u{13a}', ['\u{139}', '\u{0}', '\u{0}']), - ('\u{13c}', ['\u{13b}', '\u{0}', '\u{0}']), ('\u{13e}', ['\u{13d}', '\u{0}', '\u{0}']), - ('\u{140}', ['\u{13f}', '\u{0}', '\u{0}']), ('\u{142}', ['\u{141}', '\u{0}', '\u{0}']), - ('\u{144}', ['\u{143}', '\u{0}', '\u{0}']), ('\u{146}', ['\u{145}', '\u{0}', '\u{0}']), - ('\u{148}', ['\u{147}', '\u{0}', '\u{0}']), ('\u{149}', ['\u{2bc}', 'N', '\u{0}']), - ('\u{14b}', ['\u{14a}', '\u{0}', '\u{0}']), ('\u{14d}', ['\u{14c}', '\u{0}', '\u{0}']), - ('\u{14f}', ['\u{14e}', '\u{0}', '\u{0}']), ('\u{151}', ['\u{150}', '\u{0}', '\u{0}']), - ('\u{153}', ['\u{152}', '\u{0}', '\u{0}']), ('\u{155}', ['\u{154}', '\u{0}', '\u{0}']), - ('\u{157}', ['\u{156}', '\u{0}', '\u{0}']), ('\u{159}', ['\u{158}', '\u{0}', '\u{0}']), - ('\u{15b}', ['\u{15a}', '\u{0}', '\u{0}']), ('\u{15d}', ['\u{15c}', '\u{0}', '\u{0}']), - ('\u{15f}', ['\u{15e}', '\u{0}', '\u{0}']), ('\u{161}', ['\u{160}', '\u{0}', '\u{0}']), - ('\u{163}', ['\u{162}', '\u{0}', '\u{0}']), ('\u{165}', ['\u{164}', '\u{0}', '\u{0}']), - ('\u{167}', ['\u{166}', '\u{0}', '\u{0}']), ('\u{169}', ['\u{168}', '\u{0}', '\u{0}']), - ('\u{16b}', ['\u{16a}', '\u{0}', '\u{0}']), ('\u{16d}', ['\u{16c}', '\u{0}', '\u{0}']), - ('\u{16f}', ['\u{16e}', '\u{0}', '\u{0}']), ('\u{171}', ['\u{170}', '\u{0}', '\u{0}']), - ('\u{173}', ['\u{172}', '\u{0}', '\u{0}']), ('\u{175}', ['\u{174}', '\u{0}', '\u{0}']), - ('\u{177}', ['\u{176}', '\u{0}', '\u{0}']), ('\u{17a}', ['\u{179}', '\u{0}', '\u{0}']), - ('\u{17c}', ['\u{17b}', '\u{0}', '\u{0}']), ('\u{17e}', ['\u{17d}', '\u{0}', '\u{0}']), - ('\u{17f}', ['S', '\u{0}', '\u{0}']), ('\u{180}', ['\u{243}', '\u{0}', '\u{0}']), - ('\u{183}', ['\u{182}', '\u{0}', '\u{0}']), ('\u{185}', ['\u{184}', '\u{0}', '\u{0}']), - ('\u{188}', ['\u{187}', '\u{0}', '\u{0}']), ('\u{18c}', ['\u{18b}', '\u{0}', '\u{0}']), - ('\u{192}', ['\u{191}', '\u{0}', '\u{0}']), ('\u{195}', ['\u{1f6}', '\u{0}', '\u{0}']), - ('\u{199}', ['\u{198}', '\u{0}', '\u{0}']), ('\u{19a}', ['\u{23d}', '\u{0}', '\u{0}']), - ('\u{19e}', ['\u{220}', '\u{0}', '\u{0}']), ('\u{1a1}', ['\u{1a0}', '\u{0}', '\u{0}']), - ('\u{1a3}', ['\u{1a2}', '\u{0}', '\u{0}']), ('\u{1a5}', ['\u{1a4}', '\u{0}', '\u{0}']), - ('\u{1a8}', ['\u{1a7}', '\u{0}', '\u{0}']), ('\u{1ad}', ['\u{1ac}', '\u{0}', '\u{0}']), - ('\u{1b0}', ['\u{1af}', '\u{0}', '\u{0}']), ('\u{1b4}', ['\u{1b3}', '\u{0}', '\u{0}']), - ('\u{1b6}', ['\u{1b5}', '\u{0}', '\u{0}']), ('\u{1b9}', ['\u{1b8}', '\u{0}', '\u{0}']), - ('\u{1bd}', ['\u{1bc}', '\u{0}', '\u{0}']), ('\u{1bf}', ['\u{1f7}', '\u{0}', '\u{0}']), - ('\u{1c5}', ['\u{1c4}', '\u{0}', '\u{0}']), ('\u{1c6}', ['\u{1c4}', '\u{0}', '\u{0}']), - ('\u{1c8}', ['\u{1c7}', '\u{0}', '\u{0}']), ('\u{1c9}', ['\u{1c7}', '\u{0}', '\u{0}']), - ('\u{1cb}', ['\u{1ca}', '\u{0}', '\u{0}']), ('\u{1cc}', ['\u{1ca}', '\u{0}', '\u{0}']), - ('\u{1ce}', ['\u{1cd}', '\u{0}', '\u{0}']), ('\u{1d0}', ['\u{1cf}', '\u{0}', '\u{0}']), - ('\u{1d2}', ['\u{1d1}', '\u{0}', '\u{0}']), ('\u{1d4}', ['\u{1d3}', '\u{0}', '\u{0}']), - ('\u{1d6}', ['\u{1d5}', '\u{0}', '\u{0}']), ('\u{1d8}', ['\u{1d7}', '\u{0}', '\u{0}']), - ('\u{1da}', ['\u{1d9}', '\u{0}', '\u{0}']), ('\u{1dc}', ['\u{1db}', '\u{0}', '\u{0}']), - ('\u{1dd}', ['\u{18e}', '\u{0}', '\u{0}']), ('\u{1df}', ['\u{1de}', '\u{0}', '\u{0}']), - ('\u{1e1}', ['\u{1e0}', '\u{0}', '\u{0}']), ('\u{1e3}', ['\u{1e2}', '\u{0}', '\u{0}']), - ('\u{1e5}', ['\u{1e4}', '\u{0}', '\u{0}']), ('\u{1e7}', ['\u{1e6}', '\u{0}', '\u{0}']), - ('\u{1e9}', ['\u{1e8}', '\u{0}', '\u{0}']), ('\u{1eb}', ['\u{1ea}', '\u{0}', '\u{0}']), - ('\u{1ed}', ['\u{1ec}', '\u{0}', '\u{0}']), ('\u{1ef}', ['\u{1ee}', '\u{0}', '\u{0}']), - ('\u{1f0}', ['J', '\u{30c}', '\u{0}']), ('\u{1f2}', ['\u{1f1}', '\u{0}', '\u{0}']), - ('\u{1f3}', ['\u{1f1}', '\u{0}', '\u{0}']), ('\u{1f5}', ['\u{1f4}', '\u{0}', '\u{0}']), - ('\u{1f9}', ['\u{1f8}', '\u{0}', '\u{0}']), ('\u{1fb}', ['\u{1fa}', '\u{0}', '\u{0}']), - ('\u{1fd}', ['\u{1fc}', '\u{0}', '\u{0}']), ('\u{1ff}', ['\u{1fe}', '\u{0}', '\u{0}']), - ('\u{201}', ['\u{200}', '\u{0}', '\u{0}']), ('\u{203}', ['\u{202}', '\u{0}', '\u{0}']), - ('\u{205}', ['\u{204}', '\u{0}', '\u{0}']), ('\u{207}', ['\u{206}', '\u{0}', '\u{0}']), - ('\u{209}', ['\u{208}', '\u{0}', '\u{0}']), ('\u{20b}', ['\u{20a}', '\u{0}', '\u{0}']), - ('\u{20d}', ['\u{20c}', '\u{0}', '\u{0}']), ('\u{20f}', ['\u{20e}', '\u{0}', '\u{0}']), - ('\u{211}', ['\u{210}', '\u{0}', '\u{0}']), ('\u{213}', ['\u{212}', '\u{0}', '\u{0}']), - ('\u{215}', ['\u{214}', '\u{0}', '\u{0}']), ('\u{217}', ['\u{216}', '\u{0}', '\u{0}']), - ('\u{219}', ['\u{218}', '\u{0}', '\u{0}']), ('\u{21b}', ['\u{21a}', '\u{0}', '\u{0}']), - ('\u{21d}', ['\u{21c}', '\u{0}', '\u{0}']), ('\u{21f}', ['\u{21e}', '\u{0}', '\u{0}']), - ('\u{223}', ['\u{222}', '\u{0}', '\u{0}']), ('\u{225}', ['\u{224}', '\u{0}', '\u{0}']), - ('\u{227}', ['\u{226}', '\u{0}', '\u{0}']), ('\u{229}', ['\u{228}', '\u{0}', '\u{0}']), - ('\u{22b}', ['\u{22a}', '\u{0}', '\u{0}']), ('\u{22d}', ['\u{22c}', '\u{0}', '\u{0}']), - ('\u{22f}', ['\u{22e}', '\u{0}', '\u{0}']), ('\u{231}', ['\u{230}', '\u{0}', '\u{0}']), - ('\u{233}', ['\u{232}', '\u{0}', '\u{0}']), ('\u{23c}', ['\u{23b}', '\u{0}', '\u{0}']), - ('\u{23f}', ['\u{2c7e}', '\u{0}', '\u{0}']), ('\u{240}', ['\u{2c7f}', '\u{0}', '\u{0}']), - ('\u{242}', ['\u{241}', '\u{0}', '\u{0}']), ('\u{247}', ['\u{246}', '\u{0}', '\u{0}']), - ('\u{249}', ['\u{248}', '\u{0}', '\u{0}']), ('\u{24b}', ['\u{24a}', '\u{0}', '\u{0}']), - ('\u{24d}', ['\u{24c}', '\u{0}', '\u{0}']), ('\u{24f}', ['\u{24e}', '\u{0}', '\u{0}']), - ('\u{250}', ['\u{2c6f}', '\u{0}', '\u{0}']), ('\u{251}', ['\u{2c6d}', '\u{0}', '\u{0}']), - ('\u{252}', ['\u{2c70}', '\u{0}', '\u{0}']), ('\u{253}', ['\u{181}', '\u{0}', '\u{0}']), - ('\u{254}', ['\u{186}', '\u{0}', '\u{0}']), ('\u{256}', ['\u{189}', '\u{0}', '\u{0}']), - ('\u{257}', ['\u{18a}', '\u{0}', '\u{0}']), ('\u{259}', ['\u{18f}', '\u{0}', '\u{0}']), - ('\u{25b}', ['\u{190}', '\u{0}', '\u{0}']), ('\u{25c}', ['\u{a7ab}', '\u{0}', '\u{0}']), - ('\u{260}', ['\u{193}', '\u{0}', '\u{0}']), ('\u{261}', ['\u{a7ac}', '\u{0}', '\u{0}']), - ('\u{263}', ['\u{194}', '\u{0}', '\u{0}']), ('\u{265}', ['\u{a78d}', '\u{0}', '\u{0}']), - ('\u{266}', ['\u{a7aa}', '\u{0}', '\u{0}']), ('\u{268}', ['\u{197}', '\u{0}', '\u{0}']), - ('\u{269}', ['\u{196}', '\u{0}', '\u{0}']), ('\u{26a}', ['\u{a7ae}', '\u{0}', '\u{0}']), - ('\u{26b}', ['\u{2c62}', '\u{0}', '\u{0}']), ('\u{26c}', ['\u{a7ad}', '\u{0}', '\u{0}']), - ('\u{26f}', ['\u{19c}', '\u{0}', '\u{0}']), ('\u{271}', ['\u{2c6e}', '\u{0}', '\u{0}']), - ('\u{272}', ['\u{19d}', '\u{0}', '\u{0}']), ('\u{275}', ['\u{19f}', '\u{0}', '\u{0}']), - ('\u{27d}', ['\u{2c64}', '\u{0}', '\u{0}']), ('\u{280}', ['\u{1a6}', '\u{0}', '\u{0}']), - ('\u{282}', ['\u{a7c5}', '\u{0}', '\u{0}']), ('\u{283}', ['\u{1a9}', '\u{0}', '\u{0}']), - ('\u{287}', ['\u{a7b1}', '\u{0}', '\u{0}']), ('\u{288}', ['\u{1ae}', '\u{0}', '\u{0}']), - ('\u{289}', ['\u{244}', '\u{0}', '\u{0}']), ('\u{28a}', ['\u{1b1}', '\u{0}', '\u{0}']), - ('\u{28b}', ['\u{1b2}', '\u{0}', '\u{0}']), ('\u{28c}', ['\u{245}', '\u{0}', '\u{0}']), - ('\u{292}', ['\u{1b7}', '\u{0}', '\u{0}']), ('\u{29d}', ['\u{a7b2}', '\u{0}', '\u{0}']), - ('\u{29e}', ['\u{a7b0}', '\u{0}', '\u{0}']), ('\u{345}', ['\u{399}', '\u{0}', '\u{0}']), - ('\u{371}', ['\u{370}', '\u{0}', '\u{0}']), ('\u{373}', ['\u{372}', '\u{0}', '\u{0}']), - ('\u{377}', ['\u{376}', '\u{0}', '\u{0}']), ('\u{37b}', ['\u{3fd}', '\u{0}', '\u{0}']), - ('\u{37c}', ['\u{3fe}', '\u{0}', '\u{0}']), ('\u{37d}', ['\u{3ff}', '\u{0}', '\u{0}']), - ('\u{390}', ['\u{399}', '\u{308}', '\u{301}']), ('\u{3ac}', ['\u{386}', '\u{0}', '\u{0}']), - ('\u{3ad}', ['\u{388}', '\u{0}', '\u{0}']), ('\u{3ae}', ['\u{389}', '\u{0}', '\u{0}']), - ('\u{3af}', ['\u{38a}', '\u{0}', '\u{0}']), ('\u{3b0}', ['\u{3a5}', '\u{308}', '\u{301}']), - ('\u{3b1}', ['\u{391}', '\u{0}', '\u{0}']), ('\u{3b2}', ['\u{392}', '\u{0}', '\u{0}']), - ('\u{3b3}', ['\u{393}', '\u{0}', '\u{0}']), ('\u{3b4}', ['\u{394}', '\u{0}', '\u{0}']), - ('\u{3b5}', ['\u{395}', '\u{0}', '\u{0}']), ('\u{3b6}', ['\u{396}', '\u{0}', '\u{0}']), - ('\u{3b7}', ['\u{397}', '\u{0}', '\u{0}']), ('\u{3b8}', ['\u{398}', '\u{0}', '\u{0}']), - ('\u{3b9}', ['\u{399}', '\u{0}', '\u{0}']), ('\u{3ba}', ['\u{39a}', '\u{0}', '\u{0}']), - ('\u{3bb}', ['\u{39b}', '\u{0}', '\u{0}']), ('\u{3bc}', ['\u{39c}', '\u{0}', '\u{0}']), - ('\u{3bd}', ['\u{39d}', '\u{0}', '\u{0}']), ('\u{3be}', ['\u{39e}', '\u{0}', '\u{0}']), - ('\u{3bf}', ['\u{39f}', '\u{0}', '\u{0}']), ('\u{3c0}', ['\u{3a0}', '\u{0}', '\u{0}']), - ('\u{3c1}', ['\u{3a1}', '\u{0}', '\u{0}']), ('\u{3c2}', ['\u{3a3}', '\u{0}', '\u{0}']), - ('\u{3c3}', ['\u{3a3}', '\u{0}', '\u{0}']), ('\u{3c4}', ['\u{3a4}', '\u{0}', '\u{0}']), - ('\u{3c5}', ['\u{3a5}', '\u{0}', '\u{0}']), ('\u{3c6}', ['\u{3a6}', '\u{0}', '\u{0}']), - ('\u{3c7}', ['\u{3a7}', '\u{0}', '\u{0}']), ('\u{3c8}', ['\u{3a8}', '\u{0}', '\u{0}']), - ('\u{3c9}', ['\u{3a9}', '\u{0}', '\u{0}']), ('\u{3ca}', ['\u{3aa}', '\u{0}', '\u{0}']), - ('\u{3cb}', ['\u{3ab}', '\u{0}', '\u{0}']), ('\u{3cc}', ['\u{38c}', '\u{0}', '\u{0}']), - ('\u{3cd}', ['\u{38e}', '\u{0}', '\u{0}']), ('\u{3ce}', ['\u{38f}', '\u{0}', '\u{0}']), - ('\u{3d0}', ['\u{392}', '\u{0}', '\u{0}']), ('\u{3d1}', ['\u{398}', '\u{0}', '\u{0}']), - ('\u{3d5}', ['\u{3a6}', '\u{0}', '\u{0}']), ('\u{3d6}', ['\u{3a0}', '\u{0}', '\u{0}']), - ('\u{3d7}', ['\u{3cf}', '\u{0}', '\u{0}']), ('\u{3d9}', ['\u{3d8}', '\u{0}', '\u{0}']), - ('\u{3db}', ['\u{3da}', '\u{0}', '\u{0}']), ('\u{3dd}', ['\u{3dc}', '\u{0}', '\u{0}']), - ('\u{3df}', ['\u{3de}', '\u{0}', '\u{0}']), ('\u{3e1}', ['\u{3e0}', '\u{0}', '\u{0}']), - ('\u{3e3}', ['\u{3e2}', '\u{0}', '\u{0}']), ('\u{3e5}', ['\u{3e4}', '\u{0}', '\u{0}']), - ('\u{3e7}', ['\u{3e6}', '\u{0}', '\u{0}']), ('\u{3e9}', ['\u{3e8}', '\u{0}', '\u{0}']), - ('\u{3eb}', ['\u{3ea}', '\u{0}', '\u{0}']), ('\u{3ed}', ['\u{3ec}', '\u{0}', '\u{0}']), - ('\u{3ef}', ['\u{3ee}', '\u{0}', '\u{0}']), ('\u{3f0}', ['\u{39a}', '\u{0}', '\u{0}']), - ('\u{3f1}', ['\u{3a1}', '\u{0}', '\u{0}']), ('\u{3f2}', ['\u{3f9}', '\u{0}', '\u{0}']), - ('\u{3f3}', ['\u{37f}', '\u{0}', '\u{0}']), ('\u{3f5}', ['\u{395}', '\u{0}', '\u{0}']), - ('\u{3f8}', ['\u{3f7}', '\u{0}', '\u{0}']), ('\u{3fb}', ['\u{3fa}', '\u{0}', '\u{0}']), - ('\u{430}', ['\u{410}', '\u{0}', '\u{0}']), ('\u{431}', ['\u{411}', '\u{0}', '\u{0}']), - ('\u{432}', ['\u{412}', '\u{0}', '\u{0}']), ('\u{433}', ['\u{413}', '\u{0}', '\u{0}']), - ('\u{434}', ['\u{414}', '\u{0}', '\u{0}']), ('\u{435}', ['\u{415}', '\u{0}', '\u{0}']), - ('\u{436}', ['\u{416}', '\u{0}', '\u{0}']), ('\u{437}', ['\u{417}', '\u{0}', '\u{0}']), - ('\u{438}', ['\u{418}', '\u{0}', '\u{0}']), ('\u{439}', ['\u{419}', '\u{0}', '\u{0}']), - ('\u{43a}', ['\u{41a}', '\u{0}', '\u{0}']), ('\u{43b}', ['\u{41b}', '\u{0}', '\u{0}']), - ('\u{43c}', ['\u{41c}', '\u{0}', '\u{0}']), ('\u{43d}', ['\u{41d}', '\u{0}', '\u{0}']), - ('\u{43e}', ['\u{41e}', '\u{0}', '\u{0}']), ('\u{43f}', ['\u{41f}', '\u{0}', '\u{0}']), - ('\u{440}', ['\u{420}', '\u{0}', '\u{0}']), ('\u{441}', ['\u{421}', '\u{0}', '\u{0}']), - ('\u{442}', ['\u{422}', '\u{0}', '\u{0}']), ('\u{443}', ['\u{423}', '\u{0}', '\u{0}']), - ('\u{444}', ['\u{424}', '\u{0}', '\u{0}']), ('\u{445}', ['\u{425}', '\u{0}', '\u{0}']), - ('\u{446}', ['\u{426}', '\u{0}', '\u{0}']), ('\u{447}', ['\u{427}', '\u{0}', '\u{0}']), - ('\u{448}', ['\u{428}', '\u{0}', '\u{0}']), ('\u{449}', ['\u{429}', '\u{0}', '\u{0}']), - ('\u{44a}', ['\u{42a}', '\u{0}', '\u{0}']), ('\u{44b}', ['\u{42b}', '\u{0}', '\u{0}']), - ('\u{44c}', ['\u{42c}', '\u{0}', '\u{0}']), ('\u{44d}', ['\u{42d}', '\u{0}', '\u{0}']), - ('\u{44e}', ['\u{42e}', '\u{0}', '\u{0}']), ('\u{44f}', ['\u{42f}', '\u{0}', '\u{0}']), - ('\u{450}', ['\u{400}', '\u{0}', '\u{0}']), ('\u{451}', ['\u{401}', '\u{0}', '\u{0}']), - ('\u{452}', ['\u{402}', '\u{0}', '\u{0}']), ('\u{453}', ['\u{403}', '\u{0}', '\u{0}']), - ('\u{454}', ['\u{404}', '\u{0}', '\u{0}']), ('\u{455}', ['\u{405}', '\u{0}', '\u{0}']), - ('\u{456}', ['\u{406}', '\u{0}', '\u{0}']), ('\u{457}', ['\u{407}', '\u{0}', '\u{0}']), - ('\u{458}', ['\u{408}', '\u{0}', '\u{0}']), ('\u{459}', ['\u{409}', '\u{0}', '\u{0}']), - ('\u{45a}', ['\u{40a}', '\u{0}', '\u{0}']), ('\u{45b}', ['\u{40b}', '\u{0}', '\u{0}']), - ('\u{45c}', ['\u{40c}', '\u{0}', '\u{0}']), ('\u{45d}', ['\u{40d}', '\u{0}', '\u{0}']), - ('\u{45e}', ['\u{40e}', '\u{0}', '\u{0}']), ('\u{45f}', ['\u{40f}', '\u{0}', '\u{0}']), - ('\u{461}', ['\u{460}', '\u{0}', '\u{0}']), ('\u{463}', ['\u{462}', '\u{0}', '\u{0}']), - ('\u{465}', ['\u{464}', '\u{0}', '\u{0}']), ('\u{467}', ['\u{466}', '\u{0}', '\u{0}']), - ('\u{469}', ['\u{468}', '\u{0}', '\u{0}']), ('\u{46b}', ['\u{46a}', '\u{0}', '\u{0}']), - ('\u{46d}', ['\u{46c}', '\u{0}', '\u{0}']), ('\u{46f}', ['\u{46e}', '\u{0}', '\u{0}']), - ('\u{471}', ['\u{470}', '\u{0}', '\u{0}']), ('\u{473}', ['\u{472}', '\u{0}', '\u{0}']), - ('\u{475}', ['\u{474}', '\u{0}', '\u{0}']), ('\u{477}', ['\u{476}', '\u{0}', '\u{0}']), - ('\u{479}', ['\u{478}', '\u{0}', '\u{0}']), ('\u{47b}', ['\u{47a}', '\u{0}', '\u{0}']), - ('\u{47d}', ['\u{47c}', '\u{0}', '\u{0}']), ('\u{47f}', ['\u{47e}', '\u{0}', '\u{0}']), - ('\u{481}', ['\u{480}', '\u{0}', '\u{0}']), ('\u{48b}', ['\u{48a}', '\u{0}', '\u{0}']), - ('\u{48d}', ['\u{48c}', '\u{0}', '\u{0}']), ('\u{48f}', ['\u{48e}', '\u{0}', '\u{0}']), - ('\u{491}', ['\u{490}', '\u{0}', '\u{0}']), ('\u{493}', ['\u{492}', '\u{0}', '\u{0}']), - ('\u{495}', ['\u{494}', '\u{0}', '\u{0}']), ('\u{497}', ['\u{496}', '\u{0}', '\u{0}']), - ('\u{499}', ['\u{498}', '\u{0}', '\u{0}']), ('\u{49b}', ['\u{49a}', '\u{0}', '\u{0}']), - ('\u{49d}', ['\u{49c}', '\u{0}', '\u{0}']), ('\u{49f}', ['\u{49e}', '\u{0}', '\u{0}']), - ('\u{4a1}', ['\u{4a0}', '\u{0}', '\u{0}']), ('\u{4a3}', ['\u{4a2}', '\u{0}', '\u{0}']), - ('\u{4a5}', ['\u{4a4}', '\u{0}', '\u{0}']), ('\u{4a7}', ['\u{4a6}', '\u{0}', '\u{0}']), - ('\u{4a9}', ['\u{4a8}', '\u{0}', '\u{0}']), ('\u{4ab}', ['\u{4aa}', '\u{0}', '\u{0}']), - ('\u{4ad}', ['\u{4ac}', '\u{0}', '\u{0}']), ('\u{4af}', ['\u{4ae}', '\u{0}', '\u{0}']), - ('\u{4b1}', ['\u{4b0}', '\u{0}', '\u{0}']), ('\u{4b3}', ['\u{4b2}', '\u{0}', '\u{0}']), - ('\u{4b5}', ['\u{4b4}', '\u{0}', '\u{0}']), ('\u{4b7}', ['\u{4b6}', '\u{0}', '\u{0}']), - ('\u{4b9}', ['\u{4b8}', '\u{0}', '\u{0}']), ('\u{4bb}', ['\u{4ba}', '\u{0}', '\u{0}']), - ('\u{4bd}', ['\u{4bc}', '\u{0}', '\u{0}']), ('\u{4bf}', ['\u{4be}', '\u{0}', '\u{0}']), - ('\u{4c2}', ['\u{4c1}', '\u{0}', '\u{0}']), ('\u{4c4}', ['\u{4c3}', '\u{0}', '\u{0}']), - ('\u{4c6}', ['\u{4c5}', '\u{0}', '\u{0}']), ('\u{4c8}', ['\u{4c7}', '\u{0}', '\u{0}']), - ('\u{4ca}', ['\u{4c9}', '\u{0}', '\u{0}']), ('\u{4cc}', ['\u{4cb}', '\u{0}', '\u{0}']), - ('\u{4ce}', ['\u{4cd}', '\u{0}', '\u{0}']), ('\u{4cf}', ['\u{4c0}', '\u{0}', '\u{0}']), - ('\u{4d1}', ['\u{4d0}', '\u{0}', '\u{0}']), ('\u{4d3}', ['\u{4d2}', '\u{0}', '\u{0}']), - ('\u{4d5}', ['\u{4d4}', '\u{0}', '\u{0}']), ('\u{4d7}', ['\u{4d6}', '\u{0}', '\u{0}']), - ('\u{4d9}', ['\u{4d8}', '\u{0}', '\u{0}']), ('\u{4db}', ['\u{4da}', '\u{0}', '\u{0}']), - ('\u{4dd}', ['\u{4dc}', '\u{0}', '\u{0}']), ('\u{4df}', ['\u{4de}', '\u{0}', '\u{0}']), - ('\u{4e1}', ['\u{4e0}', '\u{0}', '\u{0}']), ('\u{4e3}', ['\u{4e2}', '\u{0}', '\u{0}']), - ('\u{4e5}', ['\u{4e4}', '\u{0}', '\u{0}']), ('\u{4e7}', ['\u{4e6}', '\u{0}', '\u{0}']), - ('\u{4e9}', ['\u{4e8}', '\u{0}', '\u{0}']), ('\u{4eb}', ['\u{4ea}', '\u{0}', '\u{0}']), - ('\u{4ed}', ['\u{4ec}', '\u{0}', '\u{0}']), ('\u{4ef}', ['\u{4ee}', '\u{0}', '\u{0}']), - ('\u{4f1}', ['\u{4f0}', '\u{0}', '\u{0}']), ('\u{4f3}', ['\u{4f2}', '\u{0}', '\u{0}']), - ('\u{4f5}', ['\u{4f4}', '\u{0}', '\u{0}']), ('\u{4f7}', ['\u{4f6}', '\u{0}', '\u{0}']), - ('\u{4f9}', ['\u{4f8}', '\u{0}', '\u{0}']), ('\u{4fb}', ['\u{4fa}', '\u{0}', '\u{0}']), - ('\u{4fd}', ['\u{4fc}', '\u{0}', '\u{0}']), ('\u{4ff}', ['\u{4fe}', '\u{0}', '\u{0}']), - ('\u{501}', ['\u{500}', '\u{0}', '\u{0}']), ('\u{503}', ['\u{502}', '\u{0}', '\u{0}']), - ('\u{505}', ['\u{504}', '\u{0}', '\u{0}']), ('\u{507}', ['\u{506}', '\u{0}', '\u{0}']), - ('\u{509}', ['\u{508}', '\u{0}', '\u{0}']), ('\u{50b}', ['\u{50a}', '\u{0}', '\u{0}']), - ('\u{50d}', ['\u{50c}', '\u{0}', '\u{0}']), ('\u{50f}', ['\u{50e}', '\u{0}', '\u{0}']), - ('\u{511}', ['\u{510}', '\u{0}', '\u{0}']), ('\u{513}', ['\u{512}', '\u{0}', '\u{0}']), - ('\u{515}', ['\u{514}', '\u{0}', '\u{0}']), ('\u{517}', ['\u{516}', '\u{0}', '\u{0}']), - ('\u{519}', ['\u{518}', '\u{0}', '\u{0}']), ('\u{51b}', ['\u{51a}', '\u{0}', '\u{0}']), - ('\u{51d}', ['\u{51c}', '\u{0}', '\u{0}']), ('\u{51f}', ['\u{51e}', '\u{0}', '\u{0}']), - ('\u{521}', ['\u{520}', '\u{0}', '\u{0}']), ('\u{523}', ['\u{522}', '\u{0}', '\u{0}']), - ('\u{525}', ['\u{524}', '\u{0}', '\u{0}']), ('\u{527}', ['\u{526}', '\u{0}', '\u{0}']), - ('\u{529}', ['\u{528}', '\u{0}', '\u{0}']), ('\u{52b}', ['\u{52a}', '\u{0}', '\u{0}']), - ('\u{52d}', ['\u{52c}', '\u{0}', '\u{0}']), ('\u{52f}', ['\u{52e}', '\u{0}', '\u{0}']), - ('\u{561}', ['\u{531}', '\u{0}', '\u{0}']), ('\u{562}', ['\u{532}', '\u{0}', '\u{0}']), - ('\u{563}', ['\u{533}', '\u{0}', '\u{0}']), ('\u{564}', ['\u{534}', '\u{0}', '\u{0}']), - ('\u{565}', ['\u{535}', '\u{0}', '\u{0}']), ('\u{566}', ['\u{536}', '\u{0}', '\u{0}']), - ('\u{567}', ['\u{537}', '\u{0}', '\u{0}']), ('\u{568}', ['\u{538}', '\u{0}', '\u{0}']), - ('\u{569}', ['\u{539}', '\u{0}', '\u{0}']), ('\u{56a}', ['\u{53a}', '\u{0}', '\u{0}']), - ('\u{56b}', ['\u{53b}', '\u{0}', '\u{0}']), ('\u{56c}', ['\u{53c}', '\u{0}', '\u{0}']), - ('\u{56d}', ['\u{53d}', '\u{0}', '\u{0}']), ('\u{56e}', ['\u{53e}', '\u{0}', '\u{0}']), - ('\u{56f}', ['\u{53f}', '\u{0}', '\u{0}']), ('\u{570}', ['\u{540}', '\u{0}', '\u{0}']), - ('\u{571}', ['\u{541}', '\u{0}', '\u{0}']), ('\u{572}', ['\u{542}', '\u{0}', '\u{0}']), - ('\u{573}', ['\u{543}', '\u{0}', '\u{0}']), ('\u{574}', ['\u{544}', '\u{0}', '\u{0}']), - ('\u{575}', ['\u{545}', '\u{0}', '\u{0}']), ('\u{576}', ['\u{546}', '\u{0}', '\u{0}']), - ('\u{577}', ['\u{547}', '\u{0}', '\u{0}']), ('\u{578}', ['\u{548}', '\u{0}', '\u{0}']), - ('\u{579}', ['\u{549}', '\u{0}', '\u{0}']), ('\u{57a}', ['\u{54a}', '\u{0}', '\u{0}']), - ('\u{57b}', ['\u{54b}', '\u{0}', '\u{0}']), ('\u{57c}', ['\u{54c}', '\u{0}', '\u{0}']), - ('\u{57d}', ['\u{54d}', '\u{0}', '\u{0}']), ('\u{57e}', ['\u{54e}', '\u{0}', '\u{0}']), - ('\u{57f}', ['\u{54f}', '\u{0}', '\u{0}']), ('\u{580}', ['\u{550}', '\u{0}', '\u{0}']), - ('\u{581}', ['\u{551}', '\u{0}', '\u{0}']), ('\u{582}', ['\u{552}', '\u{0}', '\u{0}']), - ('\u{583}', ['\u{553}', '\u{0}', '\u{0}']), ('\u{584}', ['\u{554}', '\u{0}', '\u{0}']), - ('\u{585}', ['\u{555}', '\u{0}', '\u{0}']), ('\u{586}', ['\u{556}', '\u{0}', '\u{0}']), - ('\u{587}', ['\u{535}', '\u{552}', '\u{0}']), ('\u{10d0}', ['\u{1c90}', '\u{0}', '\u{0}']), - ('\u{10d1}', ['\u{1c91}', '\u{0}', '\u{0}']), ('\u{10d2}', ['\u{1c92}', '\u{0}', '\u{0}']), - ('\u{10d3}', ['\u{1c93}', '\u{0}', '\u{0}']), ('\u{10d4}', ['\u{1c94}', '\u{0}', '\u{0}']), - ('\u{10d5}', ['\u{1c95}', '\u{0}', '\u{0}']), ('\u{10d6}', ['\u{1c96}', '\u{0}', '\u{0}']), - ('\u{10d7}', ['\u{1c97}', '\u{0}', '\u{0}']), ('\u{10d8}', ['\u{1c98}', '\u{0}', '\u{0}']), - ('\u{10d9}', ['\u{1c99}', '\u{0}', '\u{0}']), ('\u{10da}', ['\u{1c9a}', '\u{0}', '\u{0}']), - ('\u{10db}', ['\u{1c9b}', '\u{0}', '\u{0}']), ('\u{10dc}', ['\u{1c9c}', '\u{0}', '\u{0}']), - ('\u{10dd}', ['\u{1c9d}', '\u{0}', '\u{0}']), ('\u{10de}', ['\u{1c9e}', '\u{0}', '\u{0}']), - ('\u{10df}', ['\u{1c9f}', '\u{0}', '\u{0}']), ('\u{10e0}', ['\u{1ca0}', '\u{0}', '\u{0}']), - ('\u{10e1}', ['\u{1ca1}', '\u{0}', '\u{0}']), ('\u{10e2}', ['\u{1ca2}', '\u{0}', '\u{0}']), - ('\u{10e3}', ['\u{1ca3}', '\u{0}', '\u{0}']), ('\u{10e4}', ['\u{1ca4}', '\u{0}', '\u{0}']), - ('\u{10e5}', ['\u{1ca5}', '\u{0}', '\u{0}']), ('\u{10e6}', ['\u{1ca6}', '\u{0}', '\u{0}']), - ('\u{10e7}', ['\u{1ca7}', '\u{0}', '\u{0}']), ('\u{10e8}', ['\u{1ca8}', '\u{0}', '\u{0}']), - ('\u{10e9}', ['\u{1ca9}', '\u{0}', '\u{0}']), ('\u{10ea}', ['\u{1caa}', '\u{0}', '\u{0}']), - ('\u{10eb}', ['\u{1cab}', '\u{0}', '\u{0}']), ('\u{10ec}', ['\u{1cac}', '\u{0}', '\u{0}']), - ('\u{10ed}', ['\u{1cad}', '\u{0}', '\u{0}']), ('\u{10ee}', ['\u{1cae}', '\u{0}', '\u{0}']), - ('\u{10ef}', ['\u{1caf}', '\u{0}', '\u{0}']), ('\u{10f0}', ['\u{1cb0}', '\u{0}', '\u{0}']), - ('\u{10f1}', ['\u{1cb1}', '\u{0}', '\u{0}']), ('\u{10f2}', ['\u{1cb2}', '\u{0}', '\u{0}']), - ('\u{10f3}', ['\u{1cb3}', '\u{0}', '\u{0}']), ('\u{10f4}', ['\u{1cb4}', '\u{0}', '\u{0}']), - ('\u{10f5}', ['\u{1cb5}', '\u{0}', '\u{0}']), ('\u{10f6}', ['\u{1cb6}', '\u{0}', '\u{0}']), - ('\u{10f7}', ['\u{1cb7}', '\u{0}', '\u{0}']), ('\u{10f8}', ['\u{1cb8}', '\u{0}', '\u{0}']), - ('\u{10f9}', ['\u{1cb9}', '\u{0}', '\u{0}']), ('\u{10fa}', ['\u{1cba}', '\u{0}', '\u{0}']), - ('\u{10fd}', ['\u{1cbd}', '\u{0}', '\u{0}']), ('\u{10fe}', ['\u{1cbe}', '\u{0}', '\u{0}']), - ('\u{10ff}', ['\u{1cbf}', '\u{0}', '\u{0}']), ('\u{13f8}', ['\u{13f0}', '\u{0}', '\u{0}']), - ('\u{13f9}', ['\u{13f1}', '\u{0}', '\u{0}']), ('\u{13fa}', ['\u{13f2}', '\u{0}', '\u{0}']), - ('\u{13fb}', ['\u{13f3}', '\u{0}', '\u{0}']), ('\u{13fc}', ['\u{13f4}', '\u{0}', '\u{0}']), - ('\u{13fd}', ['\u{13f5}', '\u{0}', '\u{0}']), ('\u{1c80}', ['\u{412}', '\u{0}', '\u{0}']), - ('\u{1c81}', ['\u{414}', '\u{0}', '\u{0}']), ('\u{1c82}', ['\u{41e}', '\u{0}', '\u{0}']), - ('\u{1c83}', ['\u{421}', '\u{0}', '\u{0}']), ('\u{1c84}', ['\u{422}', '\u{0}', '\u{0}']), - ('\u{1c85}', ['\u{422}', '\u{0}', '\u{0}']), ('\u{1c86}', ['\u{42a}', '\u{0}', '\u{0}']), - ('\u{1c87}', ['\u{462}', '\u{0}', '\u{0}']), ('\u{1c88}', ['\u{a64a}', '\u{0}', '\u{0}']), - ('\u{1d79}', ['\u{a77d}', '\u{0}', '\u{0}']), ('\u{1d7d}', ['\u{2c63}', '\u{0}', '\u{0}']), - ('\u{1d8e}', ['\u{a7c6}', '\u{0}', '\u{0}']), ('\u{1e01}', ['\u{1e00}', '\u{0}', '\u{0}']), - ('\u{1e03}', ['\u{1e02}', '\u{0}', '\u{0}']), ('\u{1e05}', ['\u{1e04}', '\u{0}', '\u{0}']), - ('\u{1e07}', ['\u{1e06}', '\u{0}', '\u{0}']), ('\u{1e09}', ['\u{1e08}', '\u{0}', '\u{0}']), - ('\u{1e0b}', ['\u{1e0a}', '\u{0}', '\u{0}']), ('\u{1e0d}', ['\u{1e0c}', '\u{0}', '\u{0}']), - ('\u{1e0f}', ['\u{1e0e}', '\u{0}', '\u{0}']), ('\u{1e11}', ['\u{1e10}', '\u{0}', '\u{0}']), - ('\u{1e13}', ['\u{1e12}', '\u{0}', '\u{0}']), ('\u{1e15}', ['\u{1e14}', '\u{0}', '\u{0}']), - ('\u{1e17}', ['\u{1e16}', '\u{0}', '\u{0}']), ('\u{1e19}', ['\u{1e18}', '\u{0}', '\u{0}']), - ('\u{1e1b}', ['\u{1e1a}', '\u{0}', '\u{0}']), ('\u{1e1d}', ['\u{1e1c}', '\u{0}', '\u{0}']), - ('\u{1e1f}', ['\u{1e1e}', '\u{0}', '\u{0}']), ('\u{1e21}', ['\u{1e20}', '\u{0}', '\u{0}']), - ('\u{1e23}', ['\u{1e22}', '\u{0}', '\u{0}']), ('\u{1e25}', ['\u{1e24}', '\u{0}', '\u{0}']), - ('\u{1e27}', ['\u{1e26}', '\u{0}', '\u{0}']), ('\u{1e29}', ['\u{1e28}', '\u{0}', '\u{0}']), - ('\u{1e2b}', ['\u{1e2a}', '\u{0}', '\u{0}']), ('\u{1e2d}', ['\u{1e2c}', '\u{0}', '\u{0}']), - ('\u{1e2f}', ['\u{1e2e}', '\u{0}', '\u{0}']), ('\u{1e31}', ['\u{1e30}', '\u{0}', '\u{0}']), - ('\u{1e33}', ['\u{1e32}', '\u{0}', '\u{0}']), ('\u{1e35}', ['\u{1e34}', '\u{0}', '\u{0}']), - ('\u{1e37}', ['\u{1e36}', '\u{0}', '\u{0}']), ('\u{1e39}', ['\u{1e38}', '\u{0}', '\u{0}']), - ('\u{1e3b}', ['\u{1e3a}', '\u{0}', '\u{0}']), ('\u{1e3d}', ['\u{1e3c}', '\u{0}', '\u{0}']), - ('\u{1e3f}', ['\u{1e3e}', '\u{0}', '\u{0}']), ('\u{1e41}', ['\u{1e40}', '\u{0}', '\u{0}']), - ('\u{1e43}', ['\u{1e42}', '\u{0}', '\u{0}']), ('\u{1e45}', ['\u{1e44}', '\u{0}', '\u{0}']), - ('\u{1e47}', ['\u{1e46}', '\u{0}', '\u{0}']), ('\u{1e49}', ['\u{1e48}', '\u{0}', '\u{0}']), - ('\u{1e4b}', ['\u{1e4a}', '\u{0}', '\u{0}']), ('\u{1e4d}', ['\u{1e4c}', '\u{0}', '\u{0}']), - ('\u{1e4f}', ['\u{1e4e}', '\u{0}', '\u{0}']), ('\u{1e51}', ['\u{1e50}', '\u{0}', '\u{0}']), - ('\u{1e53}', ['\u{1e52}', '\u{0}', '\u{0}']), ('\u{1e55}', ['\u{1e54}', '\u{0}', '\u{0}']), - ('\u{1e57}', ['\u{1e56}', '\u{0}', '\u{0}']), ('\u{1e59}', ['\u{1e58}', '\u{0}', '\u{0}']), - ('\u{1e5b}', ['\u{1e5a}', '\u{0}', '\u{0}']), ('\u{1e5d}', ['\u{1e5c}', '\u{0}', '\u{0}']), - ('\u{1e5f}', ['\u{1e5e}', '\u{0}', '\u{0}']), ('\u{1e61}', ['\u{1e60}', '\u{0}', '\u{0}']), - ('\u{1e63}', ['\u{1e62}', '\u{0}', '\u{0}']), ('\u{1e65}', ['\u{1e64}', '\u{0}', '\u{0}']), - ('\u{1e67}', ['\u{1e66}', '\u{0}', '\u{0}']), ('\u{1e69}', ['\u{1e68}', '\u{0}', '\u{0}']), - ('\u{1e6b}', ['\u{1e6a}', '\u{0}', '\u{0}']), ('\u{1e6d}', ['\u{1e6c}', '\u{0}', '\u{0}']), - ('\u{1e6f}', ['\u{1e6e}', '\u{0}', '\u{0}']), ('\u{1e71}', ['\u{1e70}', '\u{0}', '\u{0}']), - ('\u{1e73}', ['\u{1e72}', '\u{0}', '\u{0}']), ('\u{1e75}', ['\u{1e74}', '\u{0}', '\u{0}']), - ('\u{1e77}', ['\u{1e76}', '\u{0}', '\u{0}']), ('\u{1e79}', ['\u{1e78}', '\u{0}', '\u{0}']), - ('\u{1e7b}', ['\u{1e7a}', '\u{0}', '\u{0}']), ('\u{1e7d}', ['\u{1e7c}', '\u{0}', '\u{0}']), - ('\u{1e7f}', ['\u{1e7e}', '\u{0}', '\u{0}']), ('\u{1e81}', ['\u{1e80}', '\u{0}', '\u{0}']), - ('\u{1e83}', ['\u{1e82}', '\u{0}', '\u{0}']), ('\u{1e85}', ['\u{1e84}', '\u{0}', '\u{0}']), - ('\u{1e87}', ['\u{1e86}', '\u{0}', '\u{0}']), ('\u{1e89}', ['\u{1e88}', '\u{0}', '\u{0}']), - ('\u{1e8b}', ['\u{1e8a}', '\u{0}', '\u{0}']), ('\u{1e8d}', ['\u{1e8c}', '\u{0}', '\u{0}']), - ('\u{1e8f}', ['\u{1e8e}', '\u{0}', '\u{0}']), ('\u{1e91}', ['\u{1e90}', '\u{0}', '\u{0}']), - ('\u{1e93}', ['\u{1e92}', '\u{0}', '\u{0}']), ('\u{1e95}', ['\u{1e94}', '\u{0}', '\u{0}']), - ('\u{1e96}', ['H', '\u{331}', '\u{0}']), ('\u{1e97}', ['T', '\u{308}', '\u{0}']), - ('\u{1e98}', ['W', '\u{30a}', '\u{0}']), ('\u{1e99}', ['Y', '\u{30a}', '\u{0}']), - ('\u{1e9a}', ['A', '\u{2be}', '\u{0}']), ('\u{1e9b}', ['\u{1e60}', '\u{0}', '\u{0}']), - ('\u{1ea1}', ['\u{1ea0}', '\u{0}', '\u{0}']), ('\u{1ea3}', ['\u{1ea2}', '\u{0}', '\u{0}']), - ('\u{1ea5}', ['\u{1ea4}', '\u{0}', '\u{0}']), ('\u{1ea7}', ['\u{1ea6}', '\u{0}', '\u{0}']), - ('\u{1ea9}', ['\u{1ea8}', '\u{0}', '\u{0}']), ('\u{1eab}', ['\u{1eaa}', '\u{0}', '\u{0}']), - ('\u{1ead}', ['\u{1eac}', '\u{0}', '\u{0}']), ('\u{1eaf}', ['\u{1eae}', '\u{0}', '\u{0}']), - ('\u{1eb1}', ['\u{1eb0}', '\u{0}', '\u{0}']), ('\u{1eb3}', ['\u{1eb2}', '\u{0}', '\u{0}']), - ('\u{1eb5}', ['\u{1eb4}', '\u{0}', '\u{0}']), ('\u{1eb7}', ['\u{1eb6}', '\u{0}', '\u{0}']), - ('\u{1eb9}', ['\u{1eb8}', '\u{0}', '\u{0}']), ('\u{1ebb}', ['\u{1eba}', '\u{0}', '\u{0}']), - ('\u{1ebd}', ['\u{1ebc}', '\u{0}', '\u{0}']), ('\u{1ebf}', ['\u{1ebe}', '\u{0}', '\u{0}']), - ('\u{1ec1}', ['\u{1ec0}', '\u{0}', '\u{0}']), ('\u{1ec3}', ['\u{1ec2}', '\u{0}', '\u{0}']), - ('\u{1ec5}', ['\u{1ec4}', '\u{0}', '\u{0}']), ('\u{1ec7}', ['\u{1ec6}', '\u{0}', '\u{0}']), - ('\u{1ec9}', ['\u{1ec8}', '\u{0}', '\u{0}']), ('\u{1ecb}', ['\u{1eca}', '\u{0}', '\u{0}']), - ('\u{1ecd}', ['\u{1ecc}', '\u{0}', '\u{0}']), ('\u{1ecf}', ['\u{1ece}', '\u{0}', '\u{0}']), - ('\u{1ed1}', ['\u{1ed0}', '\u{0}', '\u{0}']), ('\u{1ed3}', ['\u{1ed2}', '\u{0}', '\u{0}']), - ('\u{1ed5}', ['\u{1ed4}', '\u{0}', '\u{0}']), ('\u{1ed7}', ['\u{1ed6}', '\u{0}', '\u{0}']), - ('\u{1ed9}', ['\u{1ed8}', '\u{0}', '\u{0}']), ('\u{1edb}', ['\u{1eda}', '\u{0}', '\u{0}']), - ('\u{1edd}', ['\u{1edc}', '\u{0}', '\u{0}']), ('\u{1edf}', ['\u{1ede}', '\u{0}', '\u{0}']), - ('\u{1ee1}', ['\u{1ee0}', '\u{0}', '\u{0}']), ('\u{1ee3}', ['\u{1ee2}', '\u{0}', '\u{0}']), - ('\u{1ee5}', ['\u{1ee4}', '\u{0}', '\u{0}']), ('\u{1ee7}', ['\u{1ee6}', '\u{0}', '\u{0}']), - ('\u{1ee9}', ['\u{1ee8}', '\u{0}', '\u{0}']), ('\u{1eeb}', ['\u{1eea}', '\u{0}', '\u{0}']), - ('\u{1eed}', ['\u{1eec}', '\u{0}', '\u{0}']), ('\u{1eef}', ['\u{1eee}', '\u{0}', '\u{0}']), - ('\u{1ef1}', ['\u{1ef0}', '\u{0}', '\u{0}']), ('\u{1ef3}', ['\u{1ef2}', '\u{0}', '\u{0}']), - ('\u{1ef5}', ['\u{1ef4}', '\u{0}', '\u{0}']), ('\u{1ef7}', ['\u{1ef6}', '\u{0}', '\u{0}']), - ('\u{1ef9}', ['\u{1ef8}', '\u{0}', '\u{0}']), ('\u{1efb}', ['\u{1efa}', '\u{0}', '\u{0}']), - ('\u{1efd}', ['\u{1efc}', '\u{0}', '\u{0}']), ('\u{1eff}', ['\u{1efe}', '\u{0}', '\u{0}']), - ('\u{1f00}', ['\u{1f08}', '\u{0}', '\u{0}']), ('\u{1f01}', ['\u{1f09}', '\u{0}', '\u{0}']), - ('\u{1f02}', ['\u{1f0a}', '\u{0}', '\u{0}']), ('\u{1f03}', ['\u{1f0b}', '\u{0}', '\u{0}']), - ('\u{1f04}', ['\u{1f0c}', '\u{0}', '\u{0}']), ('\u{1f05}', ['\u{1f0d}', '\u{0}', '\u{0}']), - ('\u{1f06}', ['\u{1f0e}', '\u{0}', '\u{0}']), ('\u{1f07}', ['\u{1f0f}', '\u{0}', '\u{0}']), - ('\u{1f10}', ['\u{1f18}', '\u{0}', '\u{0}']), ('\u{1f11}', ['\u{1f19}', '\u{0}', '\u{0}']), - ('\u{1f12}', ['\u{1f1a}', '\u{0}', '\u{0}']), ('\u{1f13}', ['\u{1f1b}', '\u{0}', '\u{0}']), - ('\u{1f14}', ['\u{1f1c}', '\u{0}', '\u{0}']), ('\u{1f15}', ['\u{1f1d}', '\u{0}', '\u{0}']), - ('\u{1f20}', ['\u{1f28}', '\u{0}', '\u{0}']), ('\u{1f21}', ['\u{1f29}', '\u{0}', '\u{0}']), - ('\u{1f22}', ['\u{1f2a}', '\u{0}', '\u{0}']), ('\u{1f23}', ['\u{1f2b}', '\u{0}', '\u{0}']), - ('\u{1f24}', ['\u{1f2c}', '\u{0}', '\u{0}']), ('\u{1f25}', ['\u{1f2d}', '\u{0}', '\u{0}']), - ('\u{1f26}', ['\u{1f2e}', '\u{0}', '\u{0}']), ('\u{1f27}', ['\u{1f2f}', '\u{0}', '\u{0}']), - ('\u{1f30}', ['\u{1f38}', '\u{0}', '\u{0}']), ('\u{1f31}', ['\u{1f39}', '\u{0}', '\u{0}']), - ('\u{1f32}', ['\u{1f3a}', '\u{0}', '\u{0}']), ('\u{1f33}', ['\u{1f3b}', '\u{0}', '\u{0}']), - ('\u{1f34}', ['\u{1f3c}', '\u{0}', '\u{0}']), ('\u{1f35}', ['\u{1f3d}', '\u{0}', '\u{0}']), - ('\u{1f36}', ['\u{1f3e}', '\u{0}', '\u{0}']), ('\u{1f37}', ['\u{1f3f}', '\u{0}', '\u{0}']), - ('\u{1f40}', ['\u{1f48}', '\u{0}', '\u{0}']), ('\u{1f41}', ['\u{1f49}', '\u{0}', '\u{0}']), - ('\u{1f42}', ['\u{1f4a}', '\u{0}', '\u{0}']), ('\u{1f43}', ['\u{1f4b}', '\u{0}', '\u{0}']), - ('\u{1f44}', ['\u{1f4c}', '\u{0}', '\u{0}']), ('\u{1f45}', ['\u{1f4d}', '\u{0}', '\u{0}']), - ('\u{1f50}', ['\u{3a5}', '\u{313}', '\u{0}']), ('\u{1f51}', ['\u{1f59}', '\u{0}', '\u{0}']), - ('\u{1f52}', ['\u{3a5}', '\u{313}', '\u{300}']), - ('\u{1f53}', ['\u{1f5b}', '\u{0}', '\u{0}']), - ('\u{1f54}', ['\u{3a5}', '\u{313}', '\u{301}']), - ('\u{1f55}', ['\u{1f5d}', '\u{0}', '\u{0}']), - ('\u{1f56}', ['\u{3a5}', '\u{313}', '\u{342}']), - ('\u{1f57}', ['\u{1f5f}', '\u{0}', '\u{0}']), ('\u{1f60}', ['\u{1f68}', '\u{0}', '\u{0}']), - ('\u{1f61}', ['\u{1f69}', '\u{0}', '\u{0}']), ('\u{1f62}', ['\u{1f6a}', '\u{0}', '\u{0}']), - ('\u{1f63}', ['\u{1f6b}', '\u{0}', '\u{0}']), ('\u{1f64}', ['\u{1f6c}', '\u{0}', '\u{0}']), - ('\u{1f65}', ['\u{1f6d}', '\u{0}', '\u{0}']), ('\u{1f66}', ['\u{1f6e}', '\u{0}', '\u{0}']), - ('\u{1f67}', ['\u{1f6f}', '\u{0}', '\u{0}']), ('\u{1f70}', ['\u{1fba}', '\u{0}', '\u{0}']), - ('\u{1f71}', ['\u{1fbb}', '\u{0}', '\u{0}']), ('\u{1f72}', ['\u{1fc8}', '\u{0}', '\u{0}']), - ('\u{1f73}', ['\u{1fc9}', '\u{0}', '\u{0}']), ('\u{1f74}', ['\u{1fca}', '\u{0}', '\u{0}']), - ('\u{1f75}', ['\u{1fcb}', '\u{0}', '\u{0}']), ('\u{1f76}', ['\u{1fda}', '\u{0}', '\u{0}']), - ('\u{1f77}', ['\u{1fdb}', '\u{0}', '\u{0}']), ('\u{1f78}', ['\u{1ff8}', '\u{0}', '\u{0}']), - ('\u{1f79}', ['\u{1ff9}', '\u{0}', '\u{0}']), ('\u{1f7a}', ['\u{1fea}', '\u{0}', '\u{0}']), - ('\u{1f7b}', ['\u{1feb}', '\u{0}', '\u{0}']), ('\u{1f7c}', ['\u{1ffa}', '\u{0}', '\u{0}']), - ('\u{1f7d}', ['\u{1ffb}', '\u{0}', '\u{0}']), - ('\u{1f80}', ['\u{1f08}', '\u{399}', '\u{0}']), - ('\u{1f81}', ['\u{1f09}', '\u{399}', '\u{0}']), - ('\u{1f82}', ['\u{1f0a}', '\u{399}', '\u{0}']), - ('\u{1f83}', ['\u{1f0b}', '\u{399}', '\u{0}']), - ('\u{1f84}', ['\u{1f0c}', '\u{399}', '\u{0}']), - ('\u{1f85}', ['\u{1f0d}', '\u{399}', '\u{0}']), - ('\u{1f86}', ['\u{1f0e}', '\u{399}', '\u{0}']), - ('\u{1f87}', ['\u{1f0f}', '\u{399}', '\u{0}']), - ('\u{1f88}', ['\u{1f08}', '\u{399}', '\u{0}']), - ('\u{1f89}', ['\u{1f09}', '\u{399}', '\u{0}']), - ('\u{1f8a}', ['\u{1f0a}', '\u{399}', '\u{0}']), - ('\u{1f8b}', ['\u{1f0b}', '\u{399}', '\u{0}']), - ('\u{1f8c}', ['\u{1f0c}', '\u{399}', '\u{0}']), - ('\u{1f8d}', ['\u{1f0d}', '\u{399}', '\u{0}']), - ('\u{1f8e}', ['\u{1f0e}', '\u{399}', '\u{0}']), - ('\u{1f8f}', ['\u{1f0f}', '\u{399}', '\u{0}']), - ('\u{1f90}', ['\u{1f28}', '\u{399}', '\u{0}']), - ('\u{1f91}', ['\u{1f29}', '\u{399}', '\u{0}']), - ('\u{1f92}', ['\u{1f2a}', '\u{399}', '\u{0}']), - ('\u{1f93}', ['\u{1f2b}', '\u{399}', '\u{0}']), - ('\u{1f94}', ['\u{1f2c}', '\u{399}', '\u{0}']), - ('\u{1f95}', ['\u{1f2d}', '\u{399}', '\u{0}']), - ('\u{1f96}', ['\u{1f2e}', '\u{399}', '\u{0}']), - ('\u{1f97}', ['\u{1f2f}', '\u{399}', '\u{0}']), - ('\u{1f98}', ['\u{1f28}', '\u{399}', '\u{0}']), - ('\u{1f99}', ['\u{1f29}', '\u{399}', '\u{0}']), - ('\u{1f9a}', ['\u{1f2a}', '\u{399}', '\u{0}']), - ('\u{1f9b}', ['\u{1f2b}', '\u{399}', '\u{0}']), - ('\u{1f9c}', ['\u{1f2c}', '\u{399}', '\u{0}']), - ('\u{1f9d}', ['\u{1f2d}', '\u{399}', '\u{0}']), - ('\u{1f9e}', ['\u{1f2e}', '\u{399}', '\u{0}']), - ('\u{1f9f}', ['\u{1f2f}', '\u{399}', '\u{0}']), - ('\u{1fa0}', ['\u{1f68}', '\u{399}', '\u{0}']), - ('\u{1fa1}', ['\u{1f69}', '\u{399}', '\u{0}']), - ('\u{1fa2}', ['\u{1f6a}', '\u{399}', '\u{0}']), - ('\u{1fa3}', ['\u{1f6b}', '\u{399}', '\u{0}']), - ('\u{1fa4}', ['\u{1f6c}', '\u{399}', '\u{0}']), - ('\u{1fa5}', ['\u{1f6d}', '\u{399}', '\u{0}']), - ('\u{1fa6}', ['\u{1f6e}', '\u{399}', '\u{0}']), - ('\u{1fa7}', ['\u{1f6f}', '\u{399}', '\u{0}']), - ('\u{1fa8}', ['\u{1f68}', '\u{399}', '\u{0}']), - ('\u{1fa9}', ['\u{1f69}', '\u{399}', '\u{0}']), - ('\u{1faa}', ['\u{1f6a}', '\u{399}', '\u{0}']), - ('\u{1fab}', ['\u{1f6b}', '\u{399}', '\u{0}']), - ('\u{1fac}', ['\u{1f6c}', '\u{399}', '\u{0}']), - ('\u{1fad}', ['\u{1f6d}', '\u{399}', '\u{0}']), - ('\u{1fae}', ['\u{1f6e}', '\u{399}', '\u{0}']), - ('\u{1faf}', ['\u{1f6f}', '\u{399}', '\u{0}']), - ('\u{1fb0}', ['\u{1fb8}', '\u{0}', '\u{0}']), ('\u{1fb1}', ['\u{1fb9}', '\u{0}', '\u{0}']), - ('\u{1fb2}', ['\u{1fba}', '\u{399}', '\u{0}']), - ('\u{1fb3}', ['\u{391}', '\u{399}', '\u{0}']), - ('\u{1fb4}', ['\u{386}', '\u{399}', '\u{0}']), - ('\u{1fb6}', ['\u{391}', '\u{342}', '\u{0}']), - ('\u{1fb7}', ['\u{391}', '\u{342}', '\u{399}']), - ('\u{1fbc}', ['\u{391}', '\u{399}', '\u{0}']), ('\u{1fbe}', ['\u{399}', '\u{0}', '\u{0}']), - ('\u{1fc2}', ['\u{1fca}', '\u{399}', '\u{0}']), - ('\u{1fc3}', ['\u{397}', '\u{399}', '\u{0}']), - ('\u{1fc4}', ['\u{389}', '\u{399}', '\u{0}']), - ('\u{1fc6}', ['\u{397}', '\u{342}', '\u{0}']), - ('\u{1fc7}', ['\u{397}', '\u{342}', '\u{399}']), - ('\u{1fcc}', ['\u{397}', '\u{399}', '\u{0}']), ('\u{1fd0}', ['\u{1fd8}', '\u{0}', '\u{0}']), - ('\u{1fd1}', ['\u{1fd9}', '\u{0}', '\u{0}']), - ('\u{1fd2}', ['\u{399}', '\u{308}', '\u{300}']), - ('\u{1fd3}', ['\u{399}', '\u{308}', '\u{301}']), - ('\u{1fd6}', ['\u{399}', '\u{342}', '\u{0}']), - ('\u{1fd7}', ['\u{399}', '\u{308}', '\u{342}']), - ('\u{1fe0}', ['\u{1fe8}', '\u{0}', '\u{0}']), ('\u{1fe1}', ['\u{1fe9}', '\u{0}', '\u{0}']), - ('\u{1fe2}', ['\u{3a5}', '\u{308}', '\u{300}']), - ('\u{1fe3}', ['\u{3a5}', '\u{308}', '\u{301}']), - ('\u{1fe4}', ['\u{3a1}', '\u{313}', '\u{0}']), ('\u{1fe5}', ['\u{1fec}', '\u{0}', '\u{0}']), - ('\u{1fe6}', ['\u{3a5}', '\u{342}', '\u{0}']), - ('\u{1fe7}', ['\u{3a5}', '\u{308}', '\u{342}']), - ('\u{1ff2}', ['\u{1ffa}', '\u{399}', '\u{0}']), - ('\u{1ff3}', ['\u{3a9}', '\u{399}', '\u{0}']), - ('\u{1ff4}', ['\u{38f}', '\u{399}', '\u{0}']), - ('\u{1ff6}', ['\u{3a9}', '\u{342}', '\u{0}']), - ('\u{1ff7}', ['\u{3a9}', '\u{342}', '\u{399}']), - ('\u{1ffc}', ['\u{3a9}', '\u{399}', '\u{0}']), ('\u{214e}', ['\u{2132}', '\u{0}', '\u{0}']), - ('\u{2170}', ['\u{2160}', '\u{0}', '\u{0}']), ('\u{2171}', ['\u{2161}', '\u{0}', '\u{0}']), - ('\u{2172}', ['\u{2162}', '\u{0}', '\u{0}']), ('\u{2173}', ['\u{2163}', '\u{0}', '\u{0}']), - ('\u{2174}', ['\u{2164}', '\u{0}', '\u{0}']), ('\u{2175}', ['\u{2165}', '\u{0}', '\u{0}']), - ('\u{2176}', ['\u{2166}', '\u{0}', '\u{0}']), ('\u{2177}', ['\u{2167}', '\u{0}', '\u{0}']), - ('\u{2178}', ['\u{2168}', '\u{0}', '\u{0}']), ('\u{2179}', ['\u{2169}', '\u{0}', '\u{0}']), - ('\u{217a}', ['\u{216a}', '\u{0}', '\u{0}']), ('\u{217b}', ['\u{216b}', '\u{0}', '\u{0}']), - ('\u{217c}', ['\u{216c}', '\u{0}', '\u{0}']), ('\u{217d}', ['\u{216d}', '\u{0}', '\u{0}']), - ('\u{217e}', ['\u{216e}', '\u{0}', '\u{0}']), ('\u{217f}', ['\u{216f}', '\u{0}', '\u{0}']), - ('\u{2184}', ['\u{2183}', '\u{0}', '\u{0}']), ('\u{24d0}', ['\u{24b6}', '\u{0}', '\u{0}']), - ('\u{24d1}', ['\u{24b7}', '\u{0}', '\u{0}']), ('\u{24d2}', ['\u{24b8}', '\u{0}', '\u{0}']), - ('\u{24d3}', ['\u{24b9}', '\u{0}', '\u{0}']), ('\u{24d4}', ['\u{24ba}', '\u{0}', '\u{0}']), - ('\u{24d5}', ['\u{24bb}', '\u{0}', '\u{0}']), ('\u{24d6}', ['\u{24bc}', '\u{0}', '\u{0}']), - ('\u{24d7}', ['\u{24bd}', '\u{0}', '\u{0}']), ('\u{24d8}', ['\u{24be}', '\u{0}', '\u{0}']), - ('\u{24d9}', ['\u{24bf}', '\u{0}', '\u{0}']), ('\u{24da}', ['\u{24c0}', '\u{0}', '\u{0}']), - ('\u{24db}', ['\u{24c1}', '\u{0}', '\u{0}']), ('\u{24dc}', ['\u{24c2}', '\u{0}', '\u{0}']), - ('\u{24dd}', ['\u{24c3}', '\u{0}', '\u{0}']), ('\u{24de}', ['\u{24c4}', '\u{0}', '\u{0}']), - ('\u{24df}', ['\u{24c5}', '\u{0}', '\u{0}']), ('\u{24e0}', ['\u{24c6}', '\u{0}', '\u{0}']), - ('\u{24e1}', ['\u{24c7}', '\u{0}', '\u{0}']), ('\u{24e2}', ['\u{24c8}', '\u{0}', '\u{0}']), - ('\u{24e3}', ['\u{24c9}', '\u{0}', '\u{0}']), ('\u{24e4}', ['\u{24ca}', '\u{0}', '\u{0}']), - ('\u{24e5}', ['\u{24cb}', '\u{0}', '\u{0}']), ('\u{24e6}', ['\u{24cc}', '\u{0}', '\u{0}']), - ('\u{24e7}', ['\u{24cd}', '\u{0}', '\u{0}']), ('\u{24e8}', ['\u{24ce}', '\u{0}', '\u{0}']), - ('\u{24e9}', ['\u{24cf}', '\u{0}', '\u{0}']), ('\u{2c30}', ['\u{2c00}', '\u{0}', '\u{0}']), - ('\u{2c31}', ['\u{2c01}', '\u{0}', '\u{0}']), ('\u{2c32}', ['\u{2c02}', '\u{0}', '\u{0}']), - ('\u{2c33}', ['\u{2c03}', '\u{0}', '\u{0}']), ('\u{2c34}', ['\u{2c04}', '\u{0}', '\u{0}']), - ('\u{2c35}', ['\u{2c05}', '\u{0}', '\u{0}']), ('\u{2c36}', ['\u{2c06}', '\u{0}', '\u{0}']), - ('\u{2c37}', ['\u{2c07}', '\u{0}', '\u{0}']), ('\u{2c38}', ['\u{2c08}', '\u{0}', '\u{0}']), - ('\u{2c39}', ['\u{2c09}', '\u{0}', '\u{0}']), ('\u{2c3a}', ['\u{2c0a}', '\u{0}', '\u{0}']), - ('\u{2c3b}', ['\u{2c0b}', '\u{0}', '\u{0}']), ('\u{2c3c}', ['\u{2c0c}', '\u{0}', '\u{0}']), - ('\u{2c3d}', ['\u{2c0d}', '\u{0}', '\u{0}']), ('\u{2c3e}', ['\u{2c0e}', '\u{0}', '\u{0}']), - ('\u{2c3f}', ['\u{2c0f}', '\u{0}', '\u{0}']), ('\u{2c40}', ['\u{2c10}', '\u{0}', '\u{0}']), - ('\u{2c41}', ['\u{2c11}', '\u{0}', '\u{0}']), ('\u{2c42}', ['\u{2c12}', '\u{0}', '\u{0}']), - ('\u{2c43}', ['\u{2c13}', '\u{0}', '\u{0}']), ('\u{2c44}', ['\u{2c14}', '\u{0}', '\u{0}']), - ('\u{2c45}', ['\u{2c15}', '\u{0}', '\u{0}']), ('\u{2c46}', ['\u{2c16}', '\u{0}', '\u{0}']), - ('\u{2c47}', ['\u{2c17}', '\u{0}', '\u{0}']), ('\u{2c48}', ['\u{2c18}', '\u{0}', '\u{0}']), - ('\u{2c49}', ['\u{2c19}', '\u{0}', '\u{0}']), ('\u{2c4a}', ['\u{2c1a}', '\u{0}', '\u{0}']), - ('\u{2c4b}', ['\u{2c1b}', '\u{0}', '\u{0}']), ('\u{2c4c}', ['\u{2c1c}', '\u{0}', '\u{0}']), - ('\u{2c4d}', ['\u{2c1d}', '\u{0}', '\u{0}']), ('\u{2c4e}', ['\u{2c1e}', '\u{0}', '\u{0}']), - ('\u{2c4f}', ['\u{2c1f}', '\u{0}', '\u{0}']), ('\u{2c50}', ['\u{2c20}', '\u{0}', '\u{0}']), - ('\u{2c51}', ['\u{2c21}', '\u{0}', '\u{0}']), ('\u{2c52}', ['\u{2c22}', '\u{0}', '\u{0}']), - ('\u{2c53}', ['\u{2c23}', '\u{0}', '\u{0}']), ('\u{2c54}', ['\u{2c24}', '\u{0}', '\u{0}']), - ('\u{2c55}', ['\u{2c25}', '\u{0}', '\u{0}']), ('\u{2c56}', ['\u{2c26}', '\u{0}', '\u{0}']), - ('\u{2c57}', ['\u{2c27}', '\u{0}', '\u{0}']), ('\u{2c58}', ['\u{2c28}', '\u{0}', '\u{0}']), - ('\u{2c59}', ['\u{2c29}', '\u{0}', '\u{0}']), ('\u{2c5a}', ['\u{2c2a}', '\u{0}', '\u{0}']), - ('\u{2c5b}', ['\u{2c2b}', '\u{0}', '\u{0}']), ('\u{2c5c}', ['\u{2c2c}', '\u{0}', '\u{0}']), - ('\u{2c5d}', ['\u{2c2d}', '\u{0}', '\u{0}']), ('\u{2c5e}', ['\u{2c2e}', '\u{0}', '\u{0}']), - ('\u{2c5f}', ['\u{2c2f}', '\u{0}', '\u{0}']), ('\u{2c61}', ['\u{2c60}', '\u{0}', '\u{0}']), - ('\u{2c65}', ['\u{23a}', '\u{0}', '\u{0}']), ('\u{2c66}', ['\u{23e}', '\u{0}', '\u{0}']), - ('\u{2c68}', ['\u{2c67}', '\u{0}', '\u{0}']), ('\u{2c6a}', ['\u{2c69}', '\u{0}', '\u{0}']), - ('\u{2c6c}', ['\u{2c6b}', '\u{0}', '\u{0}']), ('\u{2c73}', ['\u{2c72}', '\u{0}', '\u{0}']), - ('\u{2c76}', ['\u{2c75}', '\u{0}', '\u{0}']), ('\u{2c81}', ['\u{2c80}', '\u{0}', '\u{0}']), - ('\u{2c83}', ['\u{2c82}', '\u{0}', '\u{0}']), ('\u{2c85}', ['\u{2c84}', '\u{0}', '\u{0}']), - ('\u{2c87}', ['\u{2c86}', '\u{0}', '\u{0}']), ('\u{2c89}', ['\u{2c88}', '\u{0}', '\u{0}']), - ('\u{2c8b}', ['\u{2c8a}', '\u{0}', '\u{0}']), ('\u{2c8d}', ['\u{2c8c}', '\u{0}', '\u{0}']), - ('\u{2c8f}', ['\u{2c8e}', '\u{0}', '\u{0}']), ('\u{2c91}', ['\u{2c90}', '\u{0}', '\u{0}']), - ('\u{2c93}', ['\u{2c92}', '\u{0}', '\u{0}']), ('\u{2c95}', ['\u{2c94}', '\u{0}', '\u{0}']), - ('\u{2c97}', ['\u{2c96}', '\u{0}', '\u{0}']), ('\u{2c99}', ['\u{2c98}', '\u{0}', '\u{0}']), - ('\u{2c9b}', ['\u{2c9a}', '\u{0}', '\u{0}']), ('\u{2c9d}', ['\u{2c9c}', '\u{0}', '\u{0}']), - ('\u{2c9f}', ['\u{2c9e}', '\u{0}', '\u{0}']), ('\u{2ca1}', ['\u{2ca0}', '\u{0}', '\u{0}']), - ('\u{2ca3}', ['\u{2ca2}', '\u{0}', '\u{0}']), ('\u{2ca5}', ['\u{2ca4}', '\u{0}', '\u{0}']), - ('\u{2ca7}', ['\u{2ca6}', '\u{0}', '\u{0}']), ('\u{2ca9}', ['\u{2ca8}', '\u{0}', '\u{0}']), - ('\u{2cab}', ['\u{2caa}', '\u{0}', '\u{0}']), ('\u{2cad}', ['\u{2cac}', '\u{0}', '\u{0}']), - ('\u{2caf}', ['\u{2cae}', '\u{0}', '\u{0}']), ('\u{2cb1}', ['\u{2cb0}', '\u{0}', '\u{0}']), - ('\u{2cb3}', ['\u{2cb2}', '\u{0}', '\u{0}']), ('\u{2cb5}', ['\u{2cb4}', '\u{0}', '\u{0}']), - ('\u{2cb7}', ['\u{2cb6}', '\u{0}', '\u{0}']), ('\u{2cb9}', ['\u{2cb8}', '\u{0}', '\u{0}']), - ('\u{2cbb}', ['\u{2cba}', '\u{0}', '\u{0}']), ('\u{2cbd}', ['\u{2cbc}', '\u{0}', '\u{0}']), - ('\u{2cbf}', ['\u{2cbe}', '\u{0}', '\u{0}']), ('\u{2cc1}', ['\u{2cc0}', '\u{0}', '\u{0}']), - ('\u{2cc3}', ['\u{2cc2}', '\u{0}', '\u{0}']), ('\u{2cc5}', ['\u{2cc4}', '\u{0}', '\u{0}']), - ('\u{2cc7}', ['\u{2cc6}', '\u{0}', '\u{0}']), ('\u{2cc9}', ['\u{2cc8}', '\u{0}', '\u{0}']), - ('\u{2ccb}', ['\u{2cca}', '\u{0}', '\u{0}']), ('\u{2ccd}', ['\u{2ccc}', '\u{0}', '\u{0}']), - ('\u{2ccf}', ['\u{2cce}', '\u{0}', '\u{0}']), ('\u{2cd1}', ['\u{2cd0}', '\u{0}', '\u{0}']), - ('\u{2cd3}', ['\u{2cd2}', '\u{0}', '\u{0}']), ('\u{2cd5}', ['\u{2cd4}', '\u{0}', '\u{0}']), - ('\u{2cd7}', ['\u{2cd6}', '\u{0}', '\u{0}']), ('\u{2cd9}', ['\u{2cd8}', '\u{0}', '\u{0}']), - ('\u{2cdb}', ['\u{2cda}', '\u{0}', '\u{0}']), ('\u{2cdd}', ['\u{2cdc}', '\u{0}', '\u{0}']), - ('\u{2cdf}', ['\u{2cde}', '\u{0}', '\u{0}']), ('\u{2ce1}', ['\u{2ce0}', '\u{0}', '\u{0}']), - ('\u{2ce3}', ['\u{2ce2}', '\u{0}', '\u{0}']), ('\u{2cec}', ['\u{2ceb}', '\u{0}', '\u{0}']), - ('\u{2cee}', ['\u{2ced}', '\u{0}', '\u{0}']), ('\u{2cf3}', ['\u{2cf2}', '\u{0}', '\u{0}']), - ('\u{2d00}', ['\u{10a0}', '\u{0}', '\u{0}']), ('\u{2d01}', ['\u{10a1}', '\u{0}', '\u{0}']), - ('\u{2d02}', ['\u{10a2}', '\u{0}', '\u{0}']), ('\u{2d03}', ['\u{10a3}', '\u{0}', '\u{0}']), - ('\u{2d04}', ['\u{10a4}', '\u{0}', '\u{0}']), ('\u{2d05}', ['\u{10a5}', '\u{0}', '\u{0}']), - ('\u{2d06}', ['\u{10a6}', '\u{0}', '\u{0}']), ('\u{2d07}', ['\u{10a7}', '\u{0}', '\u{0}']), - ('\u{2d08}', ['\u{10a8}', '\u{0}', '\u{0}']), ('\u{2d09}', ['\u{10a9}', '\u{0}', '\u{0}']), - ('\u{2d0a}', ['\u{10aa}', '\u{0}', '\u{0}']), ('\u{2d0b}', ['\u{10ab}', '\u{0}', '\u{0}']), - ('\u{2d0c}', ['\u{10ac}', '\u{0}', '\u{0}']), ('\u{2d0d}', ['\u{10ad}', '\u{0}', '\u{0}']), - ('\u{2d0e}', ['\u{10ae}', '\u{0}', '\u{0}']), ('\u{2d0f}', ['\u{10af}', '\u{0}', '\u{0}']), - ('\u{2d10}', ['\u{10b0}', '\u{0}', '\u{0}']), ('\u{2d11}', ['\u{10b1}', '\u{0}', '\u{0}']), - ('\u{2d12}', ['\u{10b2}', '\u{0}', '\u{0}']), ('\u{2d13}', ['\u{10b3}', '\u{0}', '\u{0}']), - ('\u{2d14}', ['\u{10b4}', '\u{0}', '\u{0}']), ('\u{2d15}', ['\u{10b5}', '\u{0}', '\u{0}']), - ('\u{2d16}', ['\u{10b6}', '\u{0}', '\u{0}']), ('\u{2d17}', ['\u{10b7}', '\u{0}', '\u{0}']), - ('\u{2d18}', ['\u{10b8}', '\u{0}', '\u{0}']), ('\u{2d19}', ['\u{10b9}', '\u{0}', '\u{0}']), - ('\u{2d1a}', ['\u{10ba}', '\u{0}', '\u{0}']), ('\u{2d1b}', ['\u{10bb}', '\u{0}', '\u{0}']), - ('\u{2d1c}', ['\u{10bc}', '\u{0}', '\u{0}']), ('\u{2d1d}', ['\u{10bd}', '\u{0}', '\u{0}']), - ('\u{2d1e}', ['\u{10be}', '\u{0}', '\u{0}']), ('\u{2d1f}', ['\u{10bf}', '\u{0}', '\u{0}']), - ('\u{2d20}', ['\u{10c0}', '\u{0}', '\u{0}']), ('\u{2d21}', ['\u{10c1}', '\u{0}', '\u{0}']), - ('\u{2d22}', ['\u{10c2}', '\u{0}', '\u{0}']), ('\u{2d23}', ['\u{10c3}', '\u{0}', '\u{0}']), - ('\u{2d24}', ['\u{10c4}', '\u{0}', '\u{0}']), ('\u{2d25}', ['\u{10c5}', '\u{0}', '\u{0}']), - ('\u{2d27}', ['\u{10c7}', '\u{0}', '\u{0}']), ('\u{2d2d}', ['\u{10cd}', '\u{0}', '\u{0}']), - ('\u{a641}', ['\u{a640}', '\u{0}', '\u{0}']), ('\u{a643}', ['\u{a642}', '\u{0}', '\u{0}']), - ('\u{a645}', ['\u{a644}', '\u{0}', '\u{0}']), ('\u{a647}', ['\u{a646}', '\u{0}', '\u{0}']), - ('\u{a649}', ['\u{a648}', '\u{0}', '\u{0}']), ('\u{a64b}', ['\u{a64a}', '\u{0}', '\u{0}']), - ('\u{a64d}', ['\u{a64c}', '\u{0}', '\u{0}']), ('\u{a64f}', ['\u{a64e}', '\u{0}', '\u{0}']), - ('\u{a651}', ['\u{a650}', '\u{0}', '\u{0}']), ('\u{a653}', ['\u{a652}', '\u{0}', '\u{0}']), - ('\u{a655}', ['\u{a654}', '\u{0}', '\u{0}']), ('\u{a657}', ['\u{a656}', '\u{0}', '\u{0}']), - ('\u{a659}', ['\u{a658}', '\u{0}', '\u{0}']), ('\u{a65b}', ['\u{a65a}', '\u{0}', '\u{0}']), - ('\u{a65d}', ['\u{a65c}', '\u{0}', '\u{0}']), ('\u{a65f}', ['\u{a65e}', '\u{0}', '\u{0}']), - ('\u{a661}', ['\u{a660}', '\u{0}', '\u{0}']), ('\u{a663}', ['\u{a662}', '\u{0}', '\u{0}']), - ('\u{a665}', ['\u{a664}', '\u{0}', '\u{0}']), ('\u{a667}', ['\u{a666}', '\u{0}', '\u{0}']), - ('\u{a669}', ['\u{a668}', '\u{0}', '\u{0}']), ('\u{a66b}', ['\u{a66a}', '\u{0}', '\u{0}']), - ('\u{a66d}', ['\u{a66c}', '\u{0}', '\u{0}']), ('\u{a681}', ['\u{a680}', '\u{0}', '\u{0}']), - ('\u{a683}', ['\u{a682}', '\u{0}', '\u{0}']), ('\u{a685}', ['\u{a684}', '\u{0}', '\u{0}']), - ('\u{a687}', ['\u{a686}', '\u{0}', '\u{0}']), ('\u{a689}', ['\u{a688}', '\u{0}', '\u{0}']), - ('\u{a68b}', ['\u{a68a}', '\u{0}', '\u{0}']), ('\u{a68d}', ['\u{a68c}', '\u{0}', '\u{0}']), - ('\u{a68f}', ['\u{a68e}', '\u{0}', '\u{0}']), ('\u{a691}', ['\u{a690}', '\u{0}', '\u{0}']), - ('\u{a693}', ['\u{a692}', '\u{0}', '\u{0}']), ('\u{a695}', ['\u{a694}', '\u{0}', '\u{0}']), - ('\u{a697}', ['\u{a696}', '\u{0}', '\u{0}']), ('\u{a699}', ['\u{a698}', '\u{0}', '\u{0}']), - ('\u{a69b}', ['\u{a69a}', '\u{0}', '\u{0}']), ('\u{a723}', ['\u{a722}', '\u{0}', '\u{0}']), - ('\u{a725}', ['\u{a724}', '\u{0}', '\u{0}']), ('\u{a727}', ['\u{a726}', '\u{0}', '\u{0}']), - ('\u{a729}', ['\u{a728}', '\u{0}', '\u{0}']), ('\u{a72b}', ['\u{a72a}', '\u{0}', '\u{0}']), - ('\u{a72d}', ['\u{a72c}', '\u{0}', '\u{0}']), ('\u{a72f}', ['\u{a72e}', '\u{0}', '\u{0}']), - ('\u{a733}', ['\u{a732}', '\u{0}', '\u{0}']), ('\u{a735}', ['\u{a734}', '\u{0}', '\u{0}']), - ('\u{a737}', ['\u{a736}', '\u{0}', '\u{0}']), ('\u{a739}', ['\u{a738}', '\u{0}', '\u{0}']), - ('\u{a73b}', ['\u{a73a}', '\u{0}', '\u{0}']), ('\u{a73d}', ['\u{a73c}', '\u{0}', '\u{0}']), - ('\u{a73f}', ['\u{a73e}', '\u{0}', '\u{0}']), ('\u{a741}', ['\u{a740}', '\u{0}', '\u{0}']), - ('\u{a743}', ['\u{a742}', '\u{0}', '\u{0}']), ('\u{a745}', ['\u{a744}', '\u{0}', '\u{0}']), - ('\u{a747}', ['\u{a746}', '\u{0}', '\u{0}']), ('\u{a749}', ['\u{a748}', '\u{0}', '\u{0}']), - ('\u{a74b}', ['\u{a74a}', '\u{0}', '\u{0}']), ('\u{a74d}', ['\u{a74c}', '\u{0}', '\u{0}']), - ('\u{a74f}', ['\u{a74e}', '\u{0}', '\u{0}']), ('\u{a751}', ['\u{a750}', '\u{0}', '\u{0}']), - ('\u{a753}', ['\u{a752}', '\u{0}', '\u{0}']), ('\u{a755}', ['\u{a754}', '\u{0}', '\u{0}']), - ('\u{a757}', ['\u{a756}', '\u{0}', '\u{0}']), ('\u{a759}', ['\u{a758}', '\u{0}', '\u{0}']), - ('\u{a75b}', ['\u{a75a}', '\u{0}', '\u{0}']), ('\u{a75d}', ['\u{a75c}', '\u{0}', '\u{0}']), - ('\u{a75f}', ['\u{a75e}', '\u{0}', '\u{0}']), ('\u{a761}', ['\u{a760}', '\u{0}', '\u{0}']), - ('\u{a763}', ['\u{a762}', '\u{0}', '\u{0}']), ('\u{a765}', ['\u{a764}', '\u{0}', '\u{0}']), - ('\u{a767}', ['\u{a766}', '\u{0}', '\u{0}']), ('\u{a769}', ['\u{a768}', '\u{0}', '\u{0}']), - ('\u{a76b}', ['\u{a76a}', '\u{0}', '\u{0}']), ('\u{a76d}', ['\u{a76c}', '\u{0}', '\u{0}']), - ('\u{a76f}', ['\u{a76e}', '\u{0}', '\u{0}']), ('\u{a77a}', ['\u{a779}', '\u{0}', '\u{0}']), - ('\u{a77c}', ['\u{a77b}', '\u{0}', '\u{0}']), ('\u{a77f}', ['\u{a77e}', '\u{0}', '\u{0}']), - ('\u{a781}', ['\u{a780}', '\u{0}', '\u{0}']), ('\u{a783}', ['\u{a782}', '\u{0}', '\u{0}']), - ('\u{a785}', ['\u{a784}', '\u{0}', '\u{0}']), ('\u{a787}', ['\u{a786}', '\u{0}', '\u{0}']), - ('\u{a78c}', ['\u{a78b}', '\u{0}', '\u{0}']), ('\u{a791}', ['\u{a790}', '\u{0}', '\u{0}']), - ('\u{a793}', ['\u{a792}', '\u{0}', '\u{0}']), ('\u{a794}', ['\u{a7c4}', '\u{0}', '\u{0}']), - ('\u{a797}', ['\u{a796}', '\u{0}', '\u{0}']), ('\u{a799}', ['\u{a798}', '\u{0}', '\u{0}']), - ('\u{a79b}', ['\u{a79a}', '\u{0}', '\u{0}']), ('\u{a79d}', ['\u{a79c}', '\u{0}', '\u{0}']), - ('\u{a79f}', ['\u{a79e}', '\u{0}', '\u{0}']), ('\u{a7a1}', ['\u{a7a0}', '\u{0}', '\u{0}']), - ('\u{a7a3}', ['\u{a7a2}', '\u{0}', '\u{0}']), ('\u{a7a5}', ['\u{a7a4}', '\u{0}', '\u{0}']), - ('\u{a7a7}', ['\u{a7a6}', '\u{0}', '\u{0}']), ('\u{a7a9}', ['\u{a7a8}', '\u{0}', '\u{0}']), - ('\u{a7b5}', ['\u{a7b4}', '\u{0}', '\u{0}']), ('\u{a7b7}', ['\u{a7b6}', '\u{0}', '\u{0}']), - ('\u{a7b9}', ['\u{a7b8}', '\u{0}', '\u{0}']), ('\u{a7bb}', ['\u{a7ba}', '\u{0}', '\u{0}']), - ('\u{a7bd}', ['\u{a7bc}', '\u{0}', '\u{0}']), ('\u{a7bf}', ['\u{a7be}', '\u{0}', '\u{0}']), - ('\u{a7c1}', ['\u{a7c0}', '\u{0}', '\u{0}']), ('\u{a7c3}', ['\u{a7c2}', '\u{0}', '\u{0}']), - ('\u{a7c8}', ['\u{a7c7}', '\u{0}', '\u{0}']), ('\u{a7ca}', ['\u{a7c9}', '\u{0}', '\u{0}']), - ('\u{a7d1}', ['\u{a7d0}', '\u{0}', '\u{0}']), ('\u{a7d7}', ['\u{a7d6}', '\u{0}', '\u{0}']), - ('\u{a7d9}', ['\u{a7d8}', '\u{0}', '\u{0}']), ('\u{a7f6}', ['\u{a7f5}', '\u{0}', '\u{0}']), - ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']), ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']), - ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']), ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']), - ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']), ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']), - ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']), ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']), - ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']), ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']), - ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']), ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']), - ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']), ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']), - ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']), ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']), - ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']), ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']), - ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']), ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']), - ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']), ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']), - ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']), ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']), - ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']), ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']), - ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']), ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']), - ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']), ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']), - ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']), ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']), - ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']), ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']), - ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']), ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']), - ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']), ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']), - ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']), ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']), - ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']), ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']), - ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']), ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']), - ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']), ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']), - ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']), ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']), - ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']), ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']), - ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']), ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']), - ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']), ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']), - ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']), ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']), - ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']), ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']), - ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']), ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']), - ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']), ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']), - ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']), ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']), - ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']), ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']), - ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']), ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']), - ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']), ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']), - ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']), ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']), - ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']), ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']), - ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']), ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']), - ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']), ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']), - ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']), ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']), - ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']), ('\u{fb00}', ['F', 'F', '\u{0}']), - ('\u{fb01}', ['F', 'I', '\u{0}']), ('\u{fb02}', ['F', 'L', '\u{0}']), - ('\u{fb03}', ['F', 'F', 'I']), ('\u{fb04}', ['F', 'F', 'L']), - ('\u{fb05}', ['S', 'T', '\u{0}']), ('\u{fb06}', ['S', 'T', '\u{0}']), - ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']), - ('\u{fb14}', ['\u{544}', '\u{535}', '\u{0}']), - ('\u{fb15}', ['\u{544}', '\u{53b}', '\u{0}']), - ('\u{fb16}', ['\u{54e}', '\u{546}', '\u{0}']), - ('\u{fb17}', ['\u{544}', '\u{53d}', '\u{0}']), ('\u{ff41}', ['\u{ff21}', '\u{0}', '\u{0}']), - ('\u{ff42}', ['\u{ff22}', '\u{0}', '\u{0}']), ('\u{ff43}', ['\u{ff23}', '\u{0}', '\u{0}']), - ('\u{ff44}', ['\u{ff24}', '\u{0}', '\u{0}']), ('\u{ff45}', ['\u{ff25}', '\u{0}', '\u{0}']), - ('\u{ff46}', ['\u{ff26}', '\u{0}', '\u{0}']), ('\u{ff47}', ['\u{ff27}', '\u{0}', '\u{0}']), - ('\u{ff48}', ['\u{ff28}', '\u{0}', '\u{0}']), ('\u{ff49}', ['\u{ff29}', '\u{0}', '\u{0}']), - ('\u{ff4a}', ['\u{ff2a}', '\u{0}', '\u{0}']), ('\u{ff4b}', ['\u{ff2b}', '\u{0}', '\u{0}']), - ('\u{ff4c}', ['\u{ff2c}', '\u{0}', '\u{0}']), ('\u{ff4d}', ['\u{ff2d}', '\u{0}', '\u{0}']), - ('\u{ff4e}', ['\u{ff2e}', '\u{0}', '\u{0}']), ('\u{ff4f}', ['\u{ff2f}', '\u{0}', '\u{0}']), - ('\u{ff50}', ['\u{ff30}', '\u{0}', '\u{0}']), ('\u{ff51}', ['\u{ff31}', '\u{0}', '\u{0}']), - ('\u{ff52}', ['\u{ff32}', '\u{0}', '\u{0}']), ('\u{ff53}', ['\u{ff33}', '\u{0}', '\u{0}']), - ('\u{ff54}', ['\u{ff34}', '\u{0}', '\u{0}']), ('\u{ff55}', ['\u{ff35}', '\u{0}', '\u{0}']), - ('\u{ff56}', ['\u{ff36}', '\u{0}', '\u{0}']), ('\u{ff57}', ['\u{ff37}', '\u{0}', '\u{0}']), - ('\u{ff58}', ['\u{ff38}', '\u{0}', '\u{0}']), ('\u{ff59}', ['\u{ff39}', '\u{0}', '\u{0}']), - ('\u{ff5a}', ['\u{ff3a}', '\u{0}', '\u{0}']), - ('\u{10428}', ['\u{10400}', '\u{0}', '\u{0}']), - ('\u{10429}', ['\u{10401}', '\u{0}', '\u{0}']), - ('\u{1042a}', ['\u{10402}', '\u{0}', '\u{0}']), - ('\u{1042b}', ['\u{10403}', '\u{0}', '\u{0}']), - ('\u{1042c}', ['\u{10404}', '\u{0}', '\u{0}']), - ('\u{1042d}', ['\u{10405}', '\u{0}', '\u{0}']), - ('\u{1042e}', ['\u{10406}', '\u{0}', '\u{0}']), - ('\u{1042f}', ['\u{10407}', '\u{0}', '\u{0}']), - ('\u{10430}', ['\u{10408}', '\u{0}', '\u{0}']), - ('\u{10431}', ['\u{10409}', '\u{0}', '\u{0}']), - ('\u{10432}', ['\u{1040a}', '\u{0}', '\u{0}']), - ('\u{10433}', ['\u{1040b}', '\u{0}', '\u{0}']), - ('\u{10434}', ['\u{1040c}', '\u{0}', '\u{0}']), - ('\u{10435}', ['\u{1040d}', '\u{0}', '\u{0}']), - ('\u{10436}', ['\u{1040e}', '\u{0}', '\u{0}']), - ('\u{10437}', ['\u{1040f}', '\u{0}', '\u{0}']), - ('\u{10438}', ['\u{10410}', '\u{0}', '\u{0}']), - ('\u{10439}', ['\u{10411}', '\u{0}', '\u{0}']), - ('\u{1043a}', ['\u{10412}', '\u{0}', '\u{0}']), - ('\u{1043b}', ['\u{10413}', '\u{0}', '\u{0}']), - ('\u{1043c}', ['\u{10414}', '\u{0}', '\u{0}']), - ('\u{1043d}', ['\u{10415}', '\u{0}', '\u{0}']), - ('\u{1043e}', ['\u{10416}', '\u{0}', '\u{0}']), - ('\u{1043f}', ['\u{10417}', '\u{0}', '\u{0}']), - ('\u{10440}', ['\u{10418}', '\u{0}', '\u{0}']), - ('\u{10441}', ['\u{10419}', '\u{0}', '\u{0}']), - ('\u{10442}', ['\u{1041a}', '\u{0}', '\u{0}']), - ('\u{10443}', ['\u{1041b}', '\u{0}', '\u{0}']), - ('\u{10444}', ['\u{1041c}', '\u{0}', '\u{0}']), - ('\u{10445}', ['\u{1041d}', '\u{0}', '\u{0}']), - ('\u{10446}', ['\u{1041e}', '\u{0}', '\u{0}']), - ('\u{10447}', ['\u{1041f}', '\u{0}', '\u{0}']), - ('\u{10448}', ['\u{10420}', '\u{0}', '\u{0}']), - ('\u{10449}', ['\u{10421}', '\u{0}', '\u{0}']), - ('\u{1044a}', ['\u{10422}', '\u{0}', '\u{0}']), - ('\u{1044b}', ['\u{10423}', '\u{0}', '\u{0}']), - ('\u{1044c}', ['\u{10424}', '\u{0}', '\u{0}']), - ('\u{1044d}', ['\u{10425}', '\u{0}', '\u{0}']), - ('\u{1044e}', ['\u{10426}', '\u{0}', '\u{0}']), - ('\u{1044f}', ['\u{10427}', '\u{0}', '\u{0}']), - ('\u{104d8}', ['\u{104b0}', '\u{0}', '\u{0}']), - ('\u{104d9}', ['\u{104b1}', '\u{0}', '\u{0}']), - ('\u{104da}', ['\u{104b2}', '\u{0}', '\u{0}']), - ('\u{104db}', ['\u{104b3}', '\u{0}', '\u{0}']), - ('\u{104dc}', ['\u{104b4}', '\u{0}', '\u{0}']), - ('\u{104dd}', ['\u{104b5}', '\u{0}', '\u{0}']), - ('\u{104de}', ['\u{104b6}', '\u{0}', '\u{0}']), - ('\u{104df}', ['\u{104b7}', '\u{0}', '\u{0}']), - ('\u{104e0}', ['\u{104b8}', '\u{0}', '\u{0}']), - ('\u{104e1}', ['\u{104b9}', '\u{0}', '\u{0}']), - ('\u{104e2}', ['\u{104ba}', '\u{0}', '\u{0}']), - ('\u{104e3}', ['\u{104bb}', '\u{0}', '\u{0}']), - ('\u{104e4}', ['\u{104bc}', '\u{0}', '\u{0}']), - ('\u{104e5}', ['\u{104bd}', '\u{0}', '\u{0}']), - ('\u{104e6}', ['\u{104be}', '\u{0}', '\u{0}']), - ('\u{104e7}', ['\u{104bf}', '\u{0}', '\u{0}']), - ('\u{104e8}', ['\u{104c0}', '\u{0}', '\u{0}']), - ('\u{104e9}', ['\u{104c1}', '\u{0}', '\u{0}']), - ('\u{104ea}', ['\u{104c2}', '\u{0}', '\u{0}']), - ('\u{104eb}', ['\u{104c3}', '\u{0}', '\u{0}']), - ('\u{104ec}', ['\u{104c4}', '\u{0}', '\u{0}']), - ('\u{104ed}', ['\u{104c5}', '\u{0}', '\u{0}']), - ('\u{104ee}', ['\u{104c6}', '\u{0}', '\u{0}']), - ('\u{104ef}', ['\u{104c7}', '\u{0}', '\u{0}']), - ('\u{104f0}', ['\u{104c8}', '\u{0}', '\u{0}']), - ('\u{104f1}', ['\u{104c9}', '\u{0}', '\u{0}']), - ('\u{104f2}', ['\u{104ca}', '\u{0}', '\u{0}']), - ('\u{104f3}', ['\u{104cb}', '\u{0}', '\u{0}']), - ('\u{104f4}', ['\u{104cc}', '\u{0}', '\u{0}']), - ('\u{104f5}', ['\u{104cd}', '\u{0}', '\u{0}']), - ('\u{104f6}', ['\u{104ce}', '\u{0}', '\u{0}']), - ('\u{104f7}', ['\u{104cf}', '\u{0}', '\u{0}']), - ('\u{104f8}', ['\u{104d0}', '\u{0}', '\u{0}']), - ('\u{104f9}', ['\u{104d1}', '\u{0}', '\u{0}']), - ('\u{104fa}', ['\u{104d2}', '\u{0}', '\u{0}']), - ('\u{104fb}', ['\u{104d3}', '\u{0}', '\u{0}']), - ('\u{10597}', ['\u{10570}', '\u{0}', '\u{0}']), - ('\u{10598}', ['\u{10571}', '\u{0}', '\u{0}']), - ('\u{10599}', ['\u{10572}', '\u{0}', '\u{0}']), - ('\u{1059a}', ['\u{10573}', '\u{0}', '\u{0}']), - ('\u{1059b}', ['\u{10574}', '\u{0}', '\u{0}']), - ('\u{1059c}', ['\u{10575}', '\u{0}', '\u{0}']), - ('\u{1059d}', ['\u{10576}', '\u{0}', '\u{0}']), - ('\u{1059e}', ['\u{10577}', '\u{0}', '\u{0}']), - ('\u{1059f}', ['\u{10578}', '\u{0}', '\u{0}']), - ('\u{105a0}', ['\u{10579}', '\u{0}', '\u{0}']), - ('\u{105a1}', ['\u{1057a}', '\u{0}', '\u{0}']), - ('\u{105a3}', ['\u{1057c}', '\u{0}', '\u{0}']), - ('\u{105a4}', ['\u{1057d}', '\u{0}', '\u{0}']), - ('\u{105a5}', ['\u{1057e}', '\u{0}', '\u{0}']), - ('\u{105a6}', ['\u{1057f}', '\u{0}', '\u{0}']), - ('\u{105a7}', ['\u{10580}', '\u{0}', '\u{0}']), - ('\u{105a8}', ['\u{10581}', '\u{0}', '\u{0}']), - ('\u{105a9}', ['\u{10582}', '\u{0}', '\u{0}']), - ('\u{105aa}', ['\u{10583}', '\u{0}', '\u{0}']), - ('\u{105ab}', ['\u{10584}', '\u{0}', '\u{0}']), - ('\u{105ac}', ['\u{10585}', '\u{0}', '\u{0}']), - ('\u{105ad}', ['\u{10586}', '\u{0}', '\u{0}']), - ('\u{105ae}', ['\u{10587}', '\u{0}', '\u{0}']), - ('\u{105af}', ['\u{10588}', '\u{0}', '\u{0}']), - ('\u{105b0}', ['\u{10589}', '\u{0}', '\u{0}']), - ('\u{105b1}', ['\u{1058a}', '\u{0}', '\u{0}']), - ('\u{105b3}', ['\u{1058c}', '\u{0}', '\u{0}']), - ('\u{105b4}', ['\u{1058d}', '\u{0}', '\u{0}']), - ('\u{105b5}', ['\u{1058e}', '\u{0}', '\u{0}']), - ('\u{105b6}', ['\u{1058f}', '\u{0}', '\u{0}']), - ('\u{105b7}', ['\u{10590}', '\u{0}', '\u{0}']), - ('\u{105b8}', ['\u{10591}', '\u{0}', '\u{0}']), - ('\u{105b9}', ['\u{10592}', '\u{0}', '\u{0}']), - ('\u{105bb}', ['\u{10594}', '\u{0}', '\u{0}']), - ('\u{105bc}', ['\u{10595}', '\u{0}', '\u{0}']), - ('\u{10cc0}', ['\u{10c80}', '\u{0}', '\u{0}']), - ('\u{10cc1}', ['\u{10c81}', '\u{0}', '\u{0}']), - ('\u{10cc2}', ['\u{10c82}', '\u{0}', '\u{0}']), - ('\u{10cc3}', ['\u{10c83}', '\u{0}', '\u{0}']), - ('\u{10cc4}', ['\u{10c84}', '\u{0}', '\u{0}']), - ('\u{10cc5}', ['\u{10c85}', '\u{0}', '\u{0}']), - ('\u{10cc6}', ['\u{10c86}', '\u{0}', '\u{0}']), - ('\u{10cc7}', ['\u{10c87}', '\u{0}', '\u{0}']), - ('\u{10cc8}', ['\u{10c88}', '\u{0}', '\u{0}']), - ('\u{10cc9}', ['\u{10c89}', '\u{0}', '\u{0}']), - ('\u{10cca}', ['\u{10c8a}', '\u{0}', '\u{0}']), - ('\u{10ccb}', ['\u{10c8b}', '\u{0}', '\u{0}']), - ('\u{10ccc}', ['\u{10c8c}', '\u{0}', '\u{0}']), - ('\u{10ccd}', ['\u{10c8d}', '\u{0}', '\u{0}']), - ('\u{10cce}', ['\u{10c8e}', '\u{0}', '\u{0}']), - ('\u{10ccf}', ['\u{10c8f}', '\u{0}', '\u{0}']), - ('\u{10cd0}', ['\u{10c90}', '\u{0}', '\u{0}']), - ('\u{10cd1}', ['\u{10c91}', '\u{0}', '\u{0}']), - ('\u{10cd2}', ['\u{10c92}', '\u{0}', '\u{0}']), - ('\u{10cd3}', ['\u{10c93}', '\u{0}', '\u{0}']), - ('\u{10cd4}', ['\u{10c94}', '\u{0}', '\u{0}']), - ('\u{10cd5}', ['\u{10c95}', '\u{0}', '\u{0}']), - ('\u{10cd6}', ['\u{10c96}', '\u{0}', '\u{0}']), - ('\u{10cd7}', ['\u{10c97}', '\u{0}', '\u{0}']), - ('\u{10cd8}', ['\u{10c98}', '\u{0}', '\u{0}']), - ('\u{10cd9}', ['\u{10c99}', '\u{0}', '\u{0}']), - ('\u{10cda}', ['\u{10c9a}', '\u{0}', '\u{0}']), - ('\u{10cdb}', ['\u{10c9b}', '\u{0}', '\u{0}']), - ('\u{10cdc}', ['\u{10c9c}', '\u{0}', '\u{0}']), - ('\u{10cdd}', ['\u{10c9d}', '\u{0}', '\u{0}']), - ('\u{10cde}', ['\u{10c9e}', '\u{0}', '\u{0}']), - ('\u{10cdf}', ['\u{10c9f}', '\u{0}', '\u{0}']), - ('\u{10ce0}', ['\u{10ca0}', '\u{0}', '\u{0}']), - ('\u{10ce1}', ['\u{10ca1}', '\u{0}', '\u{0}']), - ('\u{10ce2}', ['\u{10ca2}', '\u{0}', '\u{0}']), - ('\u{10ce3}', ['\u{10ca3}', '\u{0}', '\u{0}']), - ('\u{10ce4}', ['\u{10ca4}', '\u{0}', '\u{0}']), - ('\u{10ce5}', ['\u{10ca5}', '\u{0}', '\u{0}']), - ('\u{10ce6}', ['\u{10ca6}', '\u{0}', '\u{0}']), - ('\u{10ce7}', ['\u{10ca7}', '\u{0}', '\u{0}']), - ('\u{10ce8}', ['\u{10ca8}', '\u{0}', '\u{0}']), - ('\u{10ce9}', ['\u{10ca9}', '\u{0}', '\u{0}']), - ('\u{10cea}', ['\u{10caa}', '\u{0}', '\u{0}']), - ('\u{10ceb}', ['\u{10cab}', '\u{0}', '\u{0}']), - ('\u{10cec}', ['\u{10cac}', '\u{0}', '\u{0}']), - ('\u{10ced}', ['\u{10cad}', '\u{0}', '\u{0}']), - ('\u{10cee}', ['\u{10cae}', '\u{0}', '\u{0}']), - ('\u{10cef}', ['\u{10caf}', '\u{0}', '\u{0}']), - ('\u{10cf0}', ['\u{10cb0}', '\u{0}', '\u{0}']), - ('\u{10cf1}', ['\u{10cb1}', '\u{0}', '\u{0}']), - ('\u{10cf2}', ['\u{10cb2}', '\u{0}', '\u{0}']), - ('\u{118c0}', ['\u{118a0}', '\u{0}', '\u{0}']), - ('\u{118c1}', ['\u{118a1}', '\u{0}', '\u{0}']), - ('\u{118c2}', ['\u{118a2}', '\u{0}', '\u{0}']), - ('\u{118c3}', ['\u{118a3}', '\u{0}', '\u{0}']), - ('\u{118c4}', ['\u{118a4}', '\u{0}', '\u{0}']), - ('\u{118c5}', ['\u{118a5}', '\u{0}', '\u{0}']), - ('\u{118c6}', ['\u{118a6}', '\u{0}', '\u{0}']), - ('\u{118c7}', ['\u{118a7}', '\u{0}', '\u{0}']), - ('\u{118c8}', ['\u{118a8}', '\u{0}', '\u{0}']), - ('\u{118c9}', ['\u{118a9}', '\u{0}', '\u{0}']), - ('\u{118ca}', ['\u{118aa}', '\u{0}', '\u{0}']), - ('\u{118cb}', ['\u{118ab}', '\u{0}', '\u{0}']), - ('\u{118cc}', ['\u{118ac}', '\u{0}', '\u{0}']), - ('\u{118cd}', ['\u{118ad}', '\u{0}', '\u{0}']), - ('\u{118ce}', ['\u{118ae}', '\u{0}', '\u{0}']), - ('\u{118cf}', ['\u{118af}', '\u{0}', '\u{0}']), - ('\u{118d0}', ['\u{118b0}', '\u{0}', '\u{0}']), - ('\u{118d1}', ['\u{118b1}', '\u{0}', '\u{0}']), - ('\u{118d2}', ['\u{118b2}', '\u{0}', '\u{0}']), - ('\u{118d3}', ['\u{118b3}', '\u{0}', '\u{0}']), - ('\u{118d4}', ['\u{118b4}', '\u{0}', '\u{0}']), - ('\u{118d5}', ['\u{118b5}', '\u{0}', '\u{0}']), - ('\u{118d6}', ['\u{118b6}', '\u{0}', '\u{0}']), - ('\u{118d7}', ['\u{118b7}', '\u{0}', '\u{0}']), - ('\u{118d8}', ['\u{118b8}', '\u{0}', '\u{0}']), - ('\u{118d9}', ['\u{118b9}', '\u{0}', '\u{0}']), - ('\u{118da}', ['\u{118ba}', '\u{0}', '\u{0}']), - ('\u{118db}', ['\u{118bb}', '\u{0}', '\u{0}']), - ('\u{118dc}', ['\u{118bc}', '\u{0}', '\u{0}']), - ('\u{118dd}', ['\u{118bd}', '\u{0}', '\u{0}']), - ('\u{118de}', ['\u{118be}', '\u{0}', '\u{0}']), - ('\u{118df}', ['\u{118bf}', '\u{0}', '\u{0}']), - ('\u{16e60}', ['\u{16e40}', '\u{0}', '\u{0}']), - ('\u{16e61}', ['\u{16e41}', '\u{0}', '\u{0}']), - ('\u{16e62}', ['\u{16e42}', '\u{0}', '\u{0}']), - ('\u{16e63}', ['\u{16e43}', '\u{0}', '\u{0}']), - ('\u{16e64}', ['\u{16e44}', '\u{0}', '\u{0}']), - ('\u{16e65}', ['\u{16e45}', '\u{0}', '\u{0}']), - ('\u{16e66}', ['\u{16e46}', '\u{0}', '\u{0}']), - ('\u{16e67}', ['\u{16e47}', '\u{0}', '\u{0}']), - ('\u{16e68}', ['\u{16e48}', '\u{0}', '\u{0}']), - ('\u{16e69}', ['\u{16e49}', '\u{0}', '\u{0}']), - ('\u{16e6a}', ['\u{16e4a}', '\u{0}', '\u{0}']), - ('\u{16e6b}', ['\u{16e4b}', '\u{0}', '\u{0}']), - ('\u{16e6c}', ['\u{16e4c}', '\u{0}', '\u{0}']), - ('\u{16e6d}', ['\u{16e4d}', '\u{0}', '\u{0}']), - ('\u{16e6e}', ['\u{16e4e}', '\u{0}', '\u{0}']), - ('\u{16e6f}', ['\u{16e4f}', '\u{0}', '\u{0}']), - ('\u{16e70}', ['\u{16e50}', '\u{0}', '\u{0}']), - ('\u{16e71}', ['\u{16e51}', '\u{0}', '\u{0}']), - ('\u{16e72}', ['\u{16e52}', '\u{0}', '\u{0}']), - ('\u{16e73}', ['\u{16e53}', '\u{0}', '\u{0}']), - ('\u{16e74}', ['\u{16e54}', '\u{0}', '\u{0}']), - ('\u{16e75}', ['\u{16e55}', '\u{0}', '\u{0}']), - ('\u{16e76}', ['\u{16e56}', '\u{0}', '\u{0}']), - ('\u{16e77}', ['\u{16e57}', '\u{0}', '\u{0}']), - ('\u{16e78}', ['\u{16e58}', '\u{0}', '\u{0}']), - ('\u{16e79}', ['\u{16e59}', '\u{0}', '\u{0}']), - ('\u{16e7a}', ['\u{16e5a}', '\u{0}', '\u{0}']), - ('\u{16e7b}', ['\u{16e5b}', '\u{0}', '\u{0}']), - ('\u{16e7c}', ['\u{16e5c}', '\u{0}', '\u{0}']), - ('\u{16e7d}', ['\u{16e5d}', '\u{0}', '\u{0}']), - ('\u{16e7e}', ['\u{16e5e}', '\u{0}', '\u{0}']), - ('\u{16e7f}', ['\u{16e5f}', '\u{0}', '\u{0}']), - ('\u{1e922}', ['\u{1e900}', '\u{0}', '\u{0}']), - ('\u{1e923}', ['\u{1e901}', '\u{0}', '\u{0}']), - ('\u{1e924}', ['\u{1e902}', '\u{0}', '\u{0}']), - ('\u{1e925}', ['\u{1e903}', '\u{0}', '\u{0}']), - ('\u{1e926}', ['\u{1e904}', '\u{0}', '\u{0}']), - ('\u{1e927}', ['\u{1e905}', '\u{0}', '\u{0}']), - ('\u{1e928}', ['\u{1e906}', '\u{0}', '\u{0}']), - ('\u{1e929}', ['\u{1e907}', '\u{0}', '\u{0}']), - ('\u{1e92a}', ['\u{1e908}', '\u{0}', '\u{0}']), - ('\u{1e92b}', ['\u{1e909}', '\u{0}', '\u{0}']), - ('\u{1e92c}', ['\u{1e90a}', '\u{0}', '\u{0}']), - ('\u{1e92d}', ['\u{1e90b}', '\u{0}', '\u{0}']), - ('\u{1e92e}', ['\u{1e90c}', '\u{0}', '\u{0}']), - ('\u{1e92f}', ['\u{1e90d}', '\u{0}', '\u{0}']), - ('\u{1e930}', ['\u{1e90e}', '\u{0}', '\u{0}']), - ('\u{1e931}', ['\u{1e90f}', '\u{0}', '\u{0}']), - ('\u{1e932}', ['\u{1e910}', '\u{0}', '\u{0}']), - ('\u{1e933}', ['\u{1e911}', '\u{0}', '\u{0}']), - ('\u{1e934}', ['\u{1e912}', '\u{0}', '\u{0}']), - ('\u{1e935}', ['\u{1e913}', '\u{0}', '\u{0}']), - ('\u{1e936}', ['\u{1e914}', '\u{0}', '\u{0}']), - ('\u{1e937}', ['\u{1e915}', '\u{0}', '\u{0}']), - ('\u{1e938}', ['\u{1e916}', '\u{0}', '\u{0}']), - ('\u{1e939}', ['\u{1e917}', '\u{0}', '\u{0}']), - ('\u{1e93a}', ['\u{1e918}', '\u{0}', '\u{0}']), - ('\u{1e93b}', ['\u{1e919}', '\u{0}', '\u{0}']), - ('\u{1e93c}', ['\u{1e91a}', '\u{0}', '\u{0}']), - ('\u{1e93d}', ['\u{1e91b}', '\u{0}', '\u{0}']), - ('\u{1e93e}', ['\u{1e91c}', '\u{0}', '\u{0}']), - ('\u{1e93f}', ['\u{1e91d}', '\u{0}', '\u{0}']), - ('\u{1e940}', ['\u{1e91e}', '\u{0}', '\u{0}']), - ('\u{1e941}', ['\u{1e91f}', '\u{0}', '\u{0}']), - ('\u{1e942}', ['\u{1e920}', '\u{0}', '\u{0}']), - ('\u{1e943}', ['\u{1e921}', '\u{0}', '\u{0}']), + static UPPERCASE_TABLE_MULTI: &[[char; 3]] = &[ + ['S', 'S', '\u{0}'], ['\u{2bc}', 'N', '\u{0}'], ['J', '\u{30c}', '\u{0}'], + ['\u{399}', '\u{308}', '\u{301}'], ['\u{3a5}', '\u{308}', '\u{301}'], + ['\u{535}', '\u{552}', '\u{0}'], ['H', '\u{331}', '\u{0}'], ['T', '\u{308}', '\u{0}'], + ['W', '\u{30a}', '\u{0}'], ['Y', '\u{30a}', '\u{0}'], ['A', '\u{2be}', '\u{0}'], + ['\u{3a5}', '\u{313}', '\u{0}'], ['\u{3a5}', '\u{313}', '\u{300}'], + ['\u{3a5}', '\u{313}', '\u{301}'], ['\u{3a5}', '\u{313}', '\u{342}'], + ['\u{1f08}', '\u{399}', '\u{0}'], ['\u{1f09}', '\u{399}', '\u{0}'], + ['\u{1f0a}', '\u{399}', '\u{0}'], ['\u{1f0b}', '\u{399}', '\u{0}'], + ['\u{1f0c}', '\u{399}', '\u{0}'], ['\u{1f0d}', '\u{399}', '\u{0}'], + ['\u{1f0e}', '\u{399}', '\u{0}'], ['\u{1f0f}', '\u{399}', '\u{0}'], + ['\u{1f08}', '\u{399}', '\u{0}'], ['\u{1f09}', '\u{399}', '\u{0}'], + ['\u{1f0a}', '\u{399}', '\u{0}'], ['\u{1f0b}', '\u{399}', '\u{0}'], + ['\u{1f0c}', '\u{399}', '\u{0}'], ['\u{1f0d}', '\u{399}', '\u{0}'], + ['\u{1f0e}', '\u{399}', '\u{0}'], ['\u{1f0f}', '\u{399}', '\u{0}'], + ['\u{1f28}', '\u{399}', '\u{0}'], ['\u{1f29}', '\u{399}', '\u{0}'], + ['\u{1f2a}', '\u{399}', '\u{0}'], ['\u{1f2b}', '\u{399}', '\u{0}'], + ['\u{1f2c}', '\u{399}', '\u{0}'], ['\u{1f2d}', '\u{399}', '\u{0}'], + ['\u{1f2e}', '\u{399}', '\u{0}'], ['\u{1f2f}', '\u{399}', '\u{0}'], + ['\u{1f28}', '\u{399}', '\u{0}'], ['\u{1f29}', '\u{399}', '\u{0}'], + ['\u{1f2a}', '\u{399}', '\u{0}'], ['\u{1f2b}', '\u{399}', '\u{0}'], + ['\u{1f2c}', '\u{399}', '\u{0}'], ['\u{1f2d}', '\u{399}', '\u{0}'], + ['\u{1f2e}', '\u{399}', '\u{0}'], ['\u{1f2f}', '\u{399}', '\u{0}'], + ['\u{1f68}', '\u{399}', '\u{0}'], ['\u{1f69}', '\u{399}', '\u{0}'], + ['\u{1f6a}', '\u{399}', '\u{0}'], ['\u{1f6b}', '\u{399}', '\u{0}'], + ['\u{1f6c}', '\u{399}', '\u{0}'], ['\u{1f6d}', '\u{399}', '\u{0}'], + ['\u{1f6e}', '\u{399}', '\u{0}'], ['\u{1f6f}', '\u{399}', '\u{0}'], + ['\u{1f68}', '\u{399}', '\u{0}'], ['\u{1f69}', '\u{399}', '\u{0}'], + ['\u{1f6a}', '\u{399}', '\u{0}'], ['\u{1f6b}', '\u{399}', '\u{0}'], + ['\u{1f6c}', '\u{399}', '\u{0}'], ['\u{1f6d}', '\u{399}', '\u{0}'], + ['\u{1f6e}', '\u{399}', '\u{0}'], ['\u{1f6f}', '\u{399}', '\u{0}'], + ['\u{1fba}', '\u{399}', '\u{0}'], ['\u{391}', '\u{399}', '\u{0}'], + ['\u{386}', '\u{399}', '\u{0}'], ['\u{391}', '\u{342}', '\u{0}'], + ['\u{391}', '\u{342}', '\u{399}'], ['\u{391}', '\u{399}', '\u{0}'], + ['\u{1fca}', '\u{399}', '\u{0}'], ['\u{397}', '\u{399}', '\u{0}'], + ['\u{389}', '\u{399}', '\u{0}'], ['\u{397}', '\u{342}', '\u{0}'], + ['\u{397}', '\u{342}', '\u{399}'], ['\u{397}', '\u{399}', '\u{0}'], + ['\u{399}', '\u{308}', '\u{300}'], ['\u{399}', '\u{308}', '\u{301}'], + ['\u{399}', '\u{342}', '\u{0}'], ['\u{399}', '\u{308}', '\u{342}'], + ['\u{3a5}', '\u{308}', '\u{300}'], ['\u{3a5}', '\u{308}', '\u{301}'], + ['\u{3a1}', '\u{313}', '\u{0}'], ['\u{3a5}', '\u{342}', '\u{0}'], + ['\u{3a5}', '\u{308}', '\u{342}'], ['\u{1ffa}', '\u{399}', '\u{0}'], + ['\u{3a9}', '\u{399}', '\u{0}'], ['\u{38f}', '\u{399}', '\u{0}'], + ['\u{3a9}', '\u{342}', '\u{0}'], ['\u{3a9}', '\u{342}', '\u{399}'], + ['\u{3a9}', '\u{399}', '\u{0}'], ['F', 'F', '\u{0}'], ['F', 'I', '\u{0}'], + ['F', 'L', '\u{0}'], ['F', 'F', 'I'], ['F', 'F', 'L'], ['S', 'T', '\u{0}'], + ['S', 'T', '\u{0}'], ['\u{544}', '\u{546}', '\u{0}'], ['\u{544}', '\u{535}', '\u{0}'], + ['\u{544}', '\u{53b}', '\u{0}'], ['\u{54e}', '\u{546}', '\u{0}'], + ['\u{544}', '\u{53d}', '\u{0}'], ]; } diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 5327e4f8139..0869644c040 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -1,5 +1,6 @@ -use core::array; +use core::{array, assert_eq}; use core::convert::TryFrom; +use core::num::NonZeroUsize; use core::sync::atomic::{AtomicUsize, Ordering}; #[test] @@ -557,7 +558,7 @@ fn array_intoiter_advance_by() { assert_eq!(counter.get(), 13); let r = it.advance_by(123456); - assert_eq!(r, Err(87)); + assert_eq!(r, Err(NonZeroUsize::new(123456 - 87).unwrap())); assert_eq!(it.len(), 0); assert_eq!(counter.get(), 100); @@ -567,7 +568,7 @@ fn array_intoiter_advance_by() { assert_eq!(counter.get(), 100); let r = it.advance_by(10); - assert_eq!(r, Err(0)); + assert_eq!(r, Err(NonZeroUsize::new(10).unwrap())); assert_eq!(it.len(), 0); assert_eq!(counter.get(), 100); } @@ -610,7 +611,7 @@ fn array_intoiter_advance_back_by() { assert_eq!(counter.get(), 13); let r = it.advance_back_by(123456); - assert_eq!(r, Err(87)); + assert_eq!(r, Err(NonZeroUsize::new(123456 - 87).unwrap())); assert_eq!(it.len(), 0); assert_eq!(counter.get(), 100); @@ -620,7 +621,7 @@ fn array_intoiter_advance_back_by() { assert_eq!(counter.get(), 100); let r = it.advance_back_by(10); - assert_eq!(r, Err(0)); + assert_eq!(r, Err(NonZeroUsize::new(10).unwrap())); assert_eq!(it.len(), 0); assert_eq!(counter.get(), 100); } @@ -679,8 +680,8 @@ fn array_into_iter_fold() { let a = [1, 2, 3, 4, 5, 6]; let mut it = a.into_iter(); - it.advance_by(1).unwrap(); - it.advance_back_by(2).unwrap(); + assert_eq!(it.advance_by(1), Ok(())); + assert_eq!(it.advance_back_by(2), Ok(())); let s = it.fold(10, |a, b| 10 * a + b); assert_eq!(s, 10234); } @@ -695,8 +696,8 @@ fn array_into_iter_rfold() { let a = [1, 2, 3, 4, 5, 6]; let mut it = a.into_iter(); - it.advance_by(1).unwrap(); - it.advance_back_by(2).unwrap(); + assert_eq!(it.advance_by(1), Ok(())); + assert_eq!(it.advance_back_by(2), Ok(())); let s = it.rfold(10, |a, b| 10 * a + b); assert_eq!(s, 10432); } diff --git a/library/core/tests/asserting.rs b/library/core/tests/asserting.rs index 4b626ba6f2d..1d9670886eb 100644 --- a/library/core/tests/asserting.rs +++ b/library/core/tests/asserting.rs @@ -24,7 +24,7 @@ struct NoCopyNoDebug; struct NoDebug; test!( - capture_with_non_copyable_and_non_debugabble_elem_has_correct_params, + capture_with_non_copyable_and_non_debuggable_elem_has_correct_params, NoCopyNoDebug, None, "N/A" @@ -32,6 +32,6 @@ test!( test!(capture_with_non_copyable_elem_has_correct_params, NoCopy, None, "N/A"); -test!(capture_with_non_debugabble_elem_has_correct_params, NoDebug, None, "N/A"); +test!(capture_with_non_debuggable_elem_has_correct_params, NoDebug, None, "N/A"); -test!(capture_with_copyable_and_debugabble_elem_has_correct_params, 1i32, Some(1i32), "1"); +test!(capture_with_copyable_and_debuggable_elem_has_correct_params, 1i32, Some(1i32), "1"); diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index 94b0310603b..a67a842d340 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -306,9 +306,11 @@ fn atomic_compare_exchange() { ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok(); } +/* FIXME(#110395) #[test] fn atomic_const_from() { const _ATOMIC_U8: AtomicU8 = AtomicU8::from(1); const _ATOMIC_BOOL: AtomicBool = AtomicBool::from(true); const _ATOMIC_PTR: AtomicPtr<u32> = AtomicPtr::from(core::ptr::null_mut()); } +*/ diff --git a/library/core/tests/bool.rs b/library/core/tests/bool.rs index 4819ce911d6..47f6459915b 100644 --- a/library/core/tests/bool.rs +++ b/library/core/tests/bool.rs @@ -89,6 +89,7 @@ fn test_bool_to_option() { assert_eq!(false.then(|| 0), None); assert_eq!(true.then(|| 0), Some(0)); + /* FIXME(#110395) const fn zero() -> i32 { 0 } @@ -102,4 +103,5 @@ fn test_bool_to_option() { assert_eq!(B, Some(0)); assert_eq!(C, None); assert_eq!(D, Some(0)); + */ } diff --git a/library/core/tests/cell.rs b/library/core/tests/cell.rs index 7b77b2134cc..e084f867943 100644 --- a/library/core/tests/cell.rs +++ b/library/core/tests/cell.rs @@ -468,6 +468,7 @@ fn const_cells() { const CELL: Cell<i32> = Cell::new(3); const _: i32 = CELL.into_inner(); +/* FIXME(#110395) const UNSAFE_CELL_FROM: UnsafeCell<i32> = UnsafeCell::from(3); const _: i32 = UNSAFE_CELL.into_inner(); @@ -476,4 +477,5 @@ fn const_cells() { const CELL_FROM: Cell<i32> = Cell::from(3); const _: i32 = CELL.into_inner(); +*/ } diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs index ac0b2ca168b..85ba51c9228 100644 --- a/library/core/tests/char.rs +++ b/library/core/tests/char.rs @@ -21,6 +21,7 @@ fn test_convert() { assert!(char::try_from(0xFFFF_FFFF_u32).is_err()); } +/* FIXME(#110395) #[test] const fn test_convert_const() { assert!(u32::from('a') == 0x61); @@ -30,6 +31,7 @@ const fn test_convert_const() { assert!(char::from(b'a') == 'a'); assert!(char::from(b'\xFF') == '\u{FF}'); } +*/ #[test] fn test_from_str() { diff --git a/library/core/tests/clone.rs b/library/core/tests/clone.rs index 33ca9f2c6a3..aafe5ced2e9 100644 --- a/library/core/tests/clone.rs +++ b/library/core/tests/clone.rs @@ -1,4 +1,5 @@ #[test] +#[cfg_attr(not(bootstrap), allow(suspicious_double_ref_op))] fn test_borrowed_clone() { let x = 5; let y: &i32 = &x; diff --git a/library/core/tests/cmp.rs b/library/core/tests/cmp.rs index 8d0e59d5a49..72fdd490da1 100644 --- a/library/core/tests/cmp.rs +++ b/library/core/tests/cmp.rs @@ -217,18 +217,19 @@ fn cmp_default() { assert_eq!(Fool(false), Fool(true)); } +/* FIXME(#110395) mod const_cmp { use super::*; struct S(i32); - impl const PartialEq for S { + impl PartialEq for S { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } - impl const PartialOrd for S { + impl PartialOrd for S { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { let ret = match (self.0, other.0) { (a, b) if a > b => Ordering::Greater, @@ -248,3 +249,4 @@ mod const_cmp { const _: () = assert!(S(0) < S(1)); const _: () = assert!(S(1) > S(0)); } +*/ diff --git a/library/core/tests/convert.rs b/library/core/tests/convert.rs index f1048f4cf09..f76dd277884 100644 --- a/library/core/tests/convert.rs +++ b/library/core/tests/convert.rs @@ -1,3 +1,4 @@ +/* FIXME(#110395) #[test] fn convert() { const fn from(x: i32) -> i32 { @@ -14,3 +15,4 @@ fn convert() { const BAR: Vec<String> = into(Vec::new()); assert_eq!(BAR, Vec::<String>::new()); } +*/ diff --git a/library/core/tests/fmt/mod.rs b/library/core/tests/fmt/mod.rs index 61807635813..c1c80c46c78 100644 --- a/library/core/tests/fmt/mod.rs +++ b/library/core/tests/fmt/mod.rs @@ -22,11 +22,11 @@ fn test_pointer_formats_data_pointer() { #[test] fn test_estimated_capacity() { assert_eq!(format_args!("").estimated_capacity(), 0); - assert_eq!(format_args!("{}", "").estimated_capacity(), 0); + assert_eq!(format_args!("{}", {""}).estimated_capacity(), 0); assert_eq!(format_args!("Hello").estimated_capacity(), 5); - assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16); - assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0); - assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32); + assert_eq!(format_args!("Hello, {}!", {""}).estimated_capacity(), 16); + assert_eq!(format_args!("{}, hello!", {"World"}).estimated_capacity(), 0); + assert_eq!(format_args!("{}. 16-bytes piece", {"World"}).estimated_capacity(), 32); } #[test] diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 267245f05dc..033bd1ed6ed 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -9,13 +9,13 @@ struct MyHasher { hash: u64, } -impl const Default for MyHasher { +impl Default for MyHasher { fn default() -> MyHasher { MyHasher { hash: 0 } } } -impl const Hasher for MyHasher { +impl Hasher for MyHasher { fn write(&mut self, buf: &[u8]) { // FIXME(const_trait_impl): change to for loop let mut i = 0; @@ -35,13 +35,14 @@ impl const Hasher for MyHasher { #[test] fn test_writer_hasher() { - const fn hash<T: ~const Hash>(t: &T) -> u64 { + // FIXME(#110395) + /* const */ fn hash<T: Hash>(t: &T) -> u64 { let mut s = MyHasher { hash: 0 }; t.hash(&mut s); s.finish() } - const { + /* const { // FIXME(fee1-dead): assert_eq assert!(hash(&()) == 0); assert!(hash(&5_u8) == 5); @@ -52,7 +53,7 @@ fn test_writer_hasher() { let s: &str = "a"; assert!(hash(&s) == 97 + 0xFF); - }; + }; */ assert_eq!(hash(&()), 0); @@ -113,7 +114,7 @@ struct CustomHasher { output: u64, } -impl const Hasher for CustomHasher { +impl Hasher for CustomHasher { fn finish(&self) -> u64 { self.output } @@ -125,21 +126,22 @@ impl const Hasher for CustomHasher { } } -impl const Default for CustomHasher { +impl Default for CustomHasher { fn default() -> CustomHasher { CustomHasher { output: 0 } } } -impl const Hash for Custom { - fn hash<H: ~const Hasher>(&self, state: &mut H) { +impl Hash for Custom { + fn hash<H: Hasher>(&self, state: &mut H) { state.write_u64(self.hash); } } #[test] fn test_custom_state() { - const fn hash<T: ~const Hash>(t: &T) -> u64 { + // FIXME(#110395) + /* const */ fn hash<T: Hash>(t: &T) -> u64 { let mut c = CustomHasher { output: 0 }; t.hash(&mut c); c.finish() @@ -147,7 +149,7 @@ fn test_custom_state() { assert_eq!(hash(&Custom { hash: 5 }), 5); - const { assert!(hash(&Custom { hash: 6 }) == 6) }; + // const { assert!(hash(&Custom { hash: 6 }) == 6) }; } // FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten. diff --git a/library/core/tests/hash/sip.rs b/library/core/tests/hash/sip.rs index 3abf6efcfa9..0a67c485c98 100644 --- a/library/core/tests/hash/sip.rs +++ b/library/core/tests/hash/sip.rs @@ -23,12 +23,13 @@ fn hash<T: Hash>(x: &T) -> u64 { hash_with(SipHasher::new(), x) } +/* FIXME(#110395) #[test] const fn test_const_sip() { let val1 = 0x45; let val2 = 0xfeed; - const fn const_hash<T: ~const Hash>(x: &T) -> u64 { + const fn const_hash<T: Hash>(x: &T) -> u64 { let mut st = SipHasher::new(); x.hash(&mut st); st.finish() @@ -36,6 +37,7 @@ const fn test_const_sip() { assert!(const_hash(&(val1)) != const_hash(&(val2))); } +*/ #[test] #[allow(unused_must_use)] diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs index f419f9cec12..175a1b638e1 100644 --- a/library/core/tests/iter/adapters/chain.rs +++ b/library/core/tests/iter/adapters/chain.rs @@ -1,5 +1,6 @@ use super::*; use core::iter::*; +use core::num::NonZeroUsize; #[test] fn test_iterator_chain() { @@ -31,28 +32,28 @@ fn test_iterator_chain_advance_by() { for i in 0..xs.len() { let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys)); - iter.advance_by(i).unwrap(); + assert_eq!(iter.advance_by(i), Ok(())); assert_eq!(iter.next(), Some(&xs[i])); - assert_eq!(iter.advance_by(100), Err(len - i - 1)); - iter.advance_by(0).unwrap(); + assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (len - i - 1)).unwrap())); + assert_eq!(iter.advance_by(0), Ok(())); } for i in 0..ys.len() { let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys)); - iter.advance_by(xs.len() + i).unwrap(); + assert_eq!(iter.advance_by(xs.len() + i), Ok(())); assert_eq!(iter.next(), Some(&ys[i])); - assert_eq!(iter.advance_by(100), Err(ys.len() - i - 1)); - iter.advance_by(0).unwrap(); + assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (ys.len() - i - 1)).unwrap())); + assert_eq!(iter.advance_by(0), Ok(())); } let mut iter = xs.iter().chain(ys); - iter.advance_by(len).unwrap(); + assert_eq!(iter.advance_by(len), Ok(())); assert_eq!(iter.next(), None); - iter.advance_by(0).unwrap(); + assert_eq!(iter.advance_by(0), Ok(())); let mut iter = xs.iter().chain(ys); - assert_eq!(iter.advance_by(len + 1), Err(len)); - iter.advance_by(0).unwrap(); + assert_eq!(iter.advance_by(len + 1), Err(NonZeroUsize::new(1).unwrap())); + assert_eq!(iter.advance_by(0), Ok(())); } test_chain(&[], &[]); @@ -68,28 +69,28 @@ fn test_iterator_chain_advance_back_by() { for i in 0..ys.len() { let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys)); - iter.advance_back_by(i).unwrap(); + assert_eq!(iter.advance_back_by(i), Ok(())); assert_eq!(iter.next_back(), Some(&ys[ys.len() - i - 1])); - assert_eq!(iter.advance_back_by(100), Err(len - i - 1)); - iter.advance_back_by(0).unwrap(); + assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (len - i - 1)).unwrap())); + assert_eq!(iter.advance_back_by(0), Ok(())); } for i in 0..xs.len() { let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys)); - iter.advance_back_by(ys.len() + i).unwrap(); + assert_eq!(iter.advance_back_by(ys.len() + i), Ok(())); assert_eq!(iter.next_back(), Some(&xs[xs.len() - i - 1])); - assert_eq!(iter.advance_back_by(100), Err(xs.len() - i - 1)); - iter.advance_back_by(0).unwrap(); + assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (xs.len() - i - 1)).unwrap())); + assert_eq!(iter.advance_back_by(0), Ok(())); } let mut iter = xs.iter().chain(ys); - iter.advance_back_by(len).unwrap(); + assert_eq!(iter.advance_back_by(len), Ok(())); assert_eq!(iter.next_back(), None); - iter.advance_back_by(0).unwrap(); + assert_eq!(iter.advance_back_by(0), Ok(())); let mut iter = xs.iter().chain(ys); - assert_eq!(iter.advance_back_by(len + 1), Err(len)); - iter.advance_back_by(0).unwrap(); + assert_eq!(iter.advance_back_by(len + 1), Err(NonZeroUsize::new(1).unwrap())); + assert_eq!(iter.advance_back_by(0), Ok(())); } test_chain(&[], &[]); diff --git a/library/core/tests/iter/adapters/enumerate.rs b/library/core/tests/iter/adapters/enumerate.rs index 0e603387847..ff57973a62a 100644 --- a/library/core/tests/iter/adapters/enumerate.rs +++ b/library/core/tests/iter/adapters/enumerate.rs @@ -1,4 +1,5 @@ use core::iter::*; +use core::num::NonZeroUsize; #[test] fn test_iterator_enumerate() { @@ -56,6 +57,20 @@ fn test_iterator_enumerate_count() { } #[test] +fn test_iterator_enumerate_advance_by() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().enumerate(); + assert_eq!(it.advance_by(0), Ok(())); + assert_eq!(it.next(), Some((0, &0))); + assert_eq!(it.advance_by(1), Ok(())); + assert_eq!(it.next(), Some((2, &2))); + assert_eq!(it.advance_by(2), Ok(())); + assert_eq!(it.next(), Some((5, &5))); + assert_eq!(it.advance_by(1), Err(NonZeroUsize::new(1).unwrap())); + assert_eq!(it.next(), None); +} + +#[test] fn test_iterator_enumerate_fold() { let xs = [0, 1, 2, 3, 4, 5]; let mut it = xs.iter().enumerate(); diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index 690fd0c2197..91809c9e5fd 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -1,5 +1,7 @@ +use core::assert_eq; use super::*; use core::iter::*; +use core::num::NonZeroUsize; #[test] fn test_iterator_flatten() { @@ -61,19 +63,19 @@ fn test_flatten_try_folds() { fn test_flatten_advance_by() { let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten(); - it.advance_by(5).unwrap(); + assert_eq!(it.advance_by(5), Ok(())); assert_eq!(it.next(), Some(5)); - it.advance_by(9).unwrap(); + assert_eq!(it.advance_by(9), Ok(())); assert_eq!(it.next(), Some(15)); - it.advance_back_by(4).unwrap(); + assert_eq!(it.advance_back_by(4), Ok(())); assert_eq!(it.next_back(), Some(35)); - it.advance_back_by(9).unwrap(); + assert_eq!(it.advance_back_by(9), Ok(())); assert_eq!(it.next_back(), Some(25)); - assert_eq!(it.advance_by(usize::MAX), Err(9)); - assert_eq!(it.advance_back_by(usize::MAX), Err(0)); - it.advance_by(0).unwrap(); - it.advance_back_by(0).unwrap(); + assert_eq!(it.advance_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 9).unwrap())); + assert_eq!(it.advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX).unwrap())); + assert_eq!(it.advance_by(0), Ok(())); + assert_eq!(it.advance_back_by(0), Ok(())); assert_eq!(it.size_hint(), (0, Some(0))); } @@ -174,19 +176,19 @@ fn test_flatten_count() { let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten(); assert_eq!(it.clone().count(), 40); - it.advance_by(5).unwrap(); + assert_eq!(it.advance_by(5), Ok(())); assert_eq!(it.clone().count(), 35); - it.advance_back_by(5).unwrap(); + assert_eq!(it.advance_back_by(5), Ok(())); assert_eq!(it.clone().count(), 30); - it.advance_by(10).unwrap(); + assert_eq!(it.advance_by(10), Ok(())); assert_eq!(it.clone().count(), 20); - it.advance_back_by(8).unwrap(); + assert_eq!(it.advance_back_by(8), Ok(())); assert_eq!(it.clone().count(), 12); - it.advance_by(4).unwrap(); + assert_eq!(it.advance_by(4), Ok(())); assert_eq!(it.clone().count(), 8); - it.advance_back_by(5).unwrap(); + assert_eq!(it.advance_back_by(5), Ok(())); assert_eq!(it.clone().count(), 3); - it.advance_by(3).unwrap(); + assert_eq!(it.advance_by(3), Ok(())); assert_eq!(it.clone().count(), 0); } @@ -195,18 +197,18 @@ fn test_flatten_last() { let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten(); assert_eq!(it.clone().last(), Some(39)); - it.advance_by(5).unwrap(); // 5..40 + assert_eq!(it.advance_by(5), Ok(())); // 5..40 assert_eq!(it.clone().last(), Some(39)); - it.advance_back_by(5).unwrap(); // 5..35 + assert_eq!(it.advance_back_by(5), Ok(())); // 5..35 assert_eq!(it.clone().last(), Some(34)); - it.advance_by(10).unwrap(); // 15..35 + assert_eq!(it.advance_by(10), Ok(())); // 15..35 assert_eq!(it.clone().last(), Some(34)); - it.advance_back_by(8).unwrap(); // 15..27 + assert_eq!(it.advance_back_by(8), Ok(())); // 15..27 assert_eq!(it.clone().last(), Some(26)); - it.advance_by(4).unwrap(); // 19..27 + assert_eq!(it.advance_by(4), Ok(())); // 19..27 assert_eq!(it.clone().last(), Some(26)); - it.advance_back_by(5).unwrap(); // 19..22 + assert_eq!(it.advance_back_by(5), Ok(())); // 19..22 assert_eq!(it.clone().last(), Some(21)); - it.advance_by(3).unwrap(); // 22..22 + assert_eq!(it.advance_by(3), Ok(())); // 22..22 assert_eq!(it.clone().last(), None); } diff --git a/library/core/tests/iter/adapters/mod.rs b/library/core/tests/iter/adapters/mod.rs index ffd5f3857ae..ca3463aa7f7 100644 --- a/library/core/tests/iter/adapters/mod.rs +++ b/library/core/tests/iter/adapters/mod.rs @@ -24,7 +24,7 @@ mod zip; use core::cell::Cell; -/// An iterator that panics whenever `next` or next_back` is called +/// An iterator that panics whenever `next` or `next_back` is called /// after `None` has already been returned. This does not violate /// `Iterator`'s contract. Used to test that iterator adapters don't /// poll their inner iterators after exhausting them. diff --git a/library/core/tests/iter/adapters/skip.rs b/library/core/tests/iter/adapters/skip.rs index 754641834e8..e3e88a84fad 100644 --- a/library/core/tests/iter/adapters/skip.rs +++ b/library/core/tests/iter/adapters/skip.rs @@ -1,4 +1,5 @@ use core::iter::*; +use core::num::NonZeroUsize; use super::Unfuse; @@ -74,11 +75,14 @@ fn test_iterator_skip_nth() { #[test] fn test_skip_advance_by() { assert_eq!((0..0).skip(10).advance_by(0), Ok(())); - assert_eq!((0..0).skip(10).advance_by(1), Err(0)); - assert_eq!((0u128..(usize::MAX as u128) + 1).skip(usize::MAX).advance_by(usize::MAX), Err(1)); - assert_eq!((0u128..u128::MAX).skip(usize::MAX).advance_by(1), Ok(())); - - assert_eq!((0..2).skip(1).advance_back_by(10), Err(1)); + assert_eq!((0..0).skip(10).advance_by(1), Err(NonZeroUsize::new(1).unwrap())); + assert_eq!( + (0u128..(usize::MAX as u128) + 1).skip(usize::MAX - 10).advance_by(usize::MAX - 5), + Err(NonZeroUsize::new(usize::MAX - 16).unwrap()) + ); + assert_eq!((0u128..u128::MAX).skip(usize::MAX - 10).advance_by(20), Ok(())); + + assert_eq!((0..2).skip(1).advance_back_by(10), Err(NonZeroUsize::new(9).unwrap())); assert_eq!((0..0).skip(1).advance_back_by(0), Ok(())); } diff --git a/library/core/tests/iter/adapters/take.rs b/library/core/tests/iter/adapters/take.rs index 3e26b43a2ed..3cad47c06de 100644 --- a/library/core/tests/iter/adapters/take.rs +++ b/library/core/tests/iter/adapters/take.rs @@ -1,4 +1,5 @@ use core::iter::*; +use core::num::NonZeroUsize; #[test] fn test_iterator_take() { @@ -78,21 +79,21 @@ fn test_take_advance_by() { let mut take = (0..10).take(3); assert_eq!(take.advance_by(2), Ok(())); assert_eq!(take.next(), Some(2)); - assert_eq!(take.advance_by(1), Err(0)); + assert_eq!(take.advance_by(1), Err(NonZeroUsize::new(1).unwrap())); assert_eq!((0..0).take(10).advance_by(0), Ok(())); - assert_eq!((0..0).take(10).advance_by(1), Err(0)); - assert_eq!((0..10).take(4).advance_by(5), Err(4)); + assert_eq!((0..0).take(10).advance_by(1), Err(NonZeroUsize::new(1).unwrap())); + assert_eq!((0..10).take(4).advance_by(5), Err(NonZeroUsize::new(1).unwrap())); let mut take = (0..10).take(3); assert_eq!(take.advance_back_by(2), Ok(())); assert_eq!(take.next(), Some(0)); - assert_eq!(take.advance_back_by(1), Err(0)); + assert_eq!(take.advance_back_by(1), Err(NonZeroUsize::new(1).unwrap())); - assert_eq!((0..2).take(1).advance_back_by(10), Err(1)); - assert_eq!((0..0).take(1).advance_back_by(1), Err(0)); + assert_eq!((0..2).take(1).advance_back_by(10), Err(NonZeroUsize::new(9).unwrap())); + assert_eq!((0..0).take(1).advance_back_by(1), Err(NonZeroUsize::new(1).unwrap())); assert_eq!((0..0).take(1).advance_back_by(0), Ok(())); - assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(100)); + assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 100).unwrap())); } #[test] diff --git a/library/core/tests/iter/range.rs b/library/core/tests/iter/range.rs index 0f91ffe2dfc..0a77ecddb84 100644 --- a/library/core/tests/iter/range.rs +++ b/library/core/tests/iter/range.rs @@ -1,3 +1,4 @@ +use core::num::NonZeroUsize; use super::*; #[test] @@ -287,25 +288,25 @@ fn test_range_step() { #[test] fn test_range_advance_by() { let mut r = 0..usize::MAX; - r.advance_by(0).unwrap(); - r.advance_back_by(0).unwrap(); + assert_eq!(Ok(()), r.advance_by(0)); + assert_eq!(Ok(()), r.advance_back_by(0)); assert_eq!(r.len(), usize::MAX); - r.advance_by(1).unwrap(); - r.advance_back_by(1).unwrap(); + assert_eq!(Ok(()), r.advance_by(1)); + assert_eq!(Ok(()), r.advance_back_by(1)); assert_eq!((r.start, r.end), (1, usize::MAX - 1)); - assert_eq!(r.advance_by(usize::MAX), Err(usize::MAX - 2)); + assert_eq!(Err(NonZeroUsize::new(2).unwrap()), r.advance_by(usize::MAX)); - r.advance_by(0).unwrap(); - r.advance_back_by(0).unwrap(); + assert_eq!(Ok(()), r.advance_by(0)); + assert_eq!(Ok(()), r.advance_back_by(0)); let mut r = 0u128..u128::MAX; - r.advance_by(usize::MAX).unwrap(); - r.advance_back_by(usize::MAX).unwrap(); + assert_eq!(Ok(()), r.advance_by(usize::MAX)); + assert_eq!(Ok(()), r.advance_back_by(usize::MAX)); assert_eq!((r.start, r.end), (0u128 + usize::MAX as u128, u128::MAX - usize::MAX as u128)); } diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 62566a9502d..9eebfb1f1f3 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -1,3 +1,5 @@ +use core::num::NonZeroUsize; + /// A wrapper struct that implements `Eq` and `Ord` based on the wrapped /// integer modulo 3. Used to test that `Iterator::max` and `Iterator::min` /// return the correct element if some of them are equal. @@ -150,11 +152,11 @@ fn test_iterator_advance_by() { let mut iter = v.iter(); assert_eq!(iter.advance_by(i), Ok(())); assert_eq!(iter.next().unwrap(), &v[i]); - assert_eq!(iter.advance_by(100), Err(v.len() - 1 - i)); + assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap())); } assert_eq!(v.iter().advance_by(v.len()), Ok(())); - assert_eq!(v.iter().advance_by(100), Err(v.len())); + assert_eq!(v.iter().advance_by(100), Err(NonZeroUsize::new(100 - v.len()).unwrap())); } #[test] @@ -165,11 +167,11 @@ fn test_iterator_advance_back_by() { let mut iter = v.iter(); assert_eq!(iter.advance_back_by(i), Ok(())); assert_eq!(iter.next_back().unwrap(), &v[v.len() - 1 - i]); - assert_eq!(iter.advance_back_by(100), Err(v.len() - 1 - i)); + assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap())); } assert_eq!(v.iter().advance_back_by(v.len()), Ok(())); - assert_eq!(v.iter().advance_back_by(100), Err(v.len())); + assert_eq!(v.iter().advance_back_by(100), Err(NonZeroUsize::new(100 - v.len()).unwrap())); } #[test] @@ -180,11 +182,11 @@ fn test_iterator_rev_advance_back_by() { let mut iter = v.iter().rev(); assert_eq!(iter.advance_back_by(i), Ok(())); assert_eq!(iter.next_back().unwrap(), &v[i]); - assert_eq!(iter.advance_back_by(100), Err(v.len() - 1 - i)); + assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap())); } assert_eq!(v.iter().rev().advance_back_by(v.len()), Ok(())); - assert_eq!(v.iter().rev().advance_back_by(100), Err(v.len())); + assert_eq!(v.iter().rev().advance_back_by(100), Err(NonZeroUsize::new(100 - v.len()).unwrap())); } #[test] @@ -424,11 +426,11 @@ fn test_iterator_rev_advance_by() { let mut iter = v.iter().rev(); assert_eq!(iter.advance_by(i), Ok(())); assert_eq!(iter.next().unwrap(), &v[v.len() - 1 - i]); - assert_eq!(iter.advance_by(100), Err(v.len() - 1 - i)); + assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap())); } assert_eq!(v.iter().rev().advance_by(v.len()), Ok(())); - assert_eq!(v.iter().rev().advance_by(100), Err(v.len())); + assert_eq!(v.iter().rev().advance_by(100), Err(NonZeroUsize::new(100 - v.len()).unwrap())); } #[test] diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs index c7c3c479b71..7f7f1f00588 100644 --- a/library/core/tests/lazy.rs +++ b/library/core/tests/lazy.rs @@ -10,7 +10,7 @@ fn once_cell() { c.get_or_init(|| 92); assert_eq!(c.get(), Some(&92)); - c.get_or_init(|| panic!("Kabom!")); + c.get_or_init(|| panic!("Kaboom!")); assert_eq!(c.get(), Some(&92)); } @@ -46,11 +46,13 @@ fn unsync_once_cell_drop_empty() { drop(x); } +/* FIXME(#110395) #[test] const fn once_cell_const() { let _once_cell: OnceCell<u32> = OnceCell::new(); let _once_cell: OnceCell<u32> = OnceCell::from(32); } +*/ #[test] fn clone() { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 42a26ae1675..3933e328951 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -8,20 +8,16 @@ #![feature(const_assume)] #![feature(const_align_of_val_raw)] #![feature(const_black_box)] -#![feature(const_bool_to_option)] #![feature(const_caller_location)] #![feature(const_cell_into_inner)] -#![feature(const_convert)] #![feature(const_hash)] #![feature(const_heap)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init_read)] #![feature(const_nonnull_new)] -#![feature(const_num_from_num)] #![feature(const_pointer_byte_offsets)] #![feature(const_pointer_is_aligned)] #![feature(const_ptr_as_ref)] -#![feature(const_ptr_read)] #![feature(const_ptr_write)] #![feature(const_trait_impl)] #![feature(const_likely)] @@ -57,6 +53,7 @@ #![feature(maybe_uninit_uninit_array_transpose)] #![feature(min_specialization)] #![feature(numfmt)] +#![feature(num_midpoint)] #![feature(step_trait)] #![feature(str_internals)] #![feature(std_internals)] @@ -66,6 +63,8 @@ #![feature(try_trait_v2)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] +#![feature(ip)] +#![feature(ip_in_core)] #![feature(iter_advance_by)] #![feature(iter_array_chunks)] #![feature(iter_collect_into)] @@ -77,6 +76,9 @@ #![feature(iter_repeat_n)] #![feature(iterator_try_collect)] #![feature(iterator_try_reduce)] +#![feature(const_ip)] +#![feature(const_ipv4)] +#![feature(const_ipv6)] #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_waker)] @@ -86,8 +88,7 @@ #![feature(pointer_is_aligned)] #![feature(portable_simd)] #![feature(ptr_metadata)] -#![feature(once_cell)] -#![feature(option_result_contains)] +#![feature(lazy_cell)] #![feature(unsized_tuple_coercion)] #![feature(const_option)] #![feature(const_option_ext)] @@ -108,6 +109,7 @@ #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] +#![cfg_attr(not(bootstrap), feature(offset_of))] #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] @@ -135,6 +137,7 @@ mod lazy; mod macros; mod manually_drop; mod mem; +mod net; mod nonzero; mod num; mod ops; diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index f7740a114e7..7f033816901 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -364,3 +364,193 @@ fn const_maybe_uninit() { assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 }); } + +#[test] +#[cfg(not(bootstrap))] +fn offset_of() { + #[repr(C)] + struct Foo { + x: u8, + y: u16, + z: Bar, + } + + #[repr(C)] + struct Bar(u8, u8); + + assert_eq!(offset_of!(Foo, x), 0); + assert_eq!(offset_of!(Foo, y), 2); + assert_eq!(offset_of!(Foo, z.0), 4); + assert_eq!(offset_of!(Foo, z.1), 5); + + // Layout of tuples is unstable + assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1); + assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_union() { + #[repr(C)] + union Foo { + x: u8, + y: u16, + z: Bar, + } + + #[repr(C)] + #[derive(Copy, Clone)] + struct Bar(u8, u8); + + assert_eq!(offset_of!(Foo, x), 0); + assert_eq!(offset_of!(Foo, y), 0); + assert_eq!(offset_of!(Foo, z.0), 0); + assert_eq!(offset_of!(Foo, z.1), 1); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_dst() { + #[repr(C)] + struct Alpha { + x: u8, + y: u16, + z: [u8], + } + + trait Trait {} + + #[repr(C)] + struct Beta { + x: u8, + y: u16, + z: dyn Trait, + } + + extern "C" { + type Extern; + } + + #[repr(C)] + struct Gamma { + x: u8, + y: u16, + z: Extern, + } + + assert_eq!(offset_of!(Alpha, x), 0); + assert_eq!(offset_of!(Alpha, y), 2); + + assert_eq!(offset_of!(Beta, x), 0); + assert_eq!(offset_of!(Beta, y), 2); + + assert_eq!(offset_of!(Gamma, x), 0); + assert_eq!(offset_of!(Gamma, y), 2); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_packed() { + #[repr(C, packed)] + struct Foo { + x: u8, + y: u16, + } + + assert_eq!(offset_of!(Foo, x), 0); + assert_eq!(offset_of!(Foo, y), 1); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_projection() { + #[repr(C)] + struct Foo { + x: u8, + y: u16, + } + + trait Projector { + type Type; + } + + impl Projector for () { + type Type = Foo; + } + + assert_eq!(offset_of!(<() as Projector>::Type, x), 0); + assert_eq!(offset_of!(<() as Projector>::Type, y), 2); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_alias() { + #[repr(C)] + struct Foo { + x: u8, + y: u16, + } + + type Bar = Foo; + + assert_eq!(offset_of!(Bar, x), 0); + assert_eq!(offset_of!(Bar, y), 2); +} + +#[test] +#[cfg(not(bootstrap))] +fn const_offset_of() { + #[repr(C)] + struct Foo { + x: u8, + y: u16, + } + + const X_OFFSET: usize = offset_of!(Foo, x); + const Y_OFFSET: usize = offset_of!(Foo, y); + + assert_eq!(X_OFFSET, 0); + assert_eq!(Y_OFFSET, 2); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_without_const_promotion() { + #[repr(C)] + struct Foo<SuppressConstPromotion> { + x: u8, + y: u16, + _scp: SuppressConstPromotion, + } + + // Normally, offset_of is always const promoted. + // The generic parameter prevents this from happening. + // This is needed to test the codegen impl of offset_of + fn inner<SuppressConstPromotion>() { + assert_eq!(offset_of!(Foo<SuppressConstPromotion>, x), 0); + assert_eq!(offset_of!(Foo<SuppressConstPromotion>, y), 2); + } + + inner::<()>(); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_addr() { + #[repr(C)] + struct Foo { + x: u8, + y: u16, + z: Bar, + } + + #[repr(C)] + struct Bar(u8, u8); + + let base = Foo { x: 0, y: 0, z: Bar(0, 0) }; + + assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, x), ptr::addr_of!(base.x).addr()); + assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, y), ptr::addr_of!(base.y).addr()); + assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr()); + assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr()); +} diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs new file mode 100644 index 00000000000..5a6ac08c088 --- /dev/null +++ b/library/core/tests/net/ip_addr.rs @@ -0,0 +1,1035 @@ +use super::{sa4, sa6}; +use core::net::{ + IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope, SocketAddr, SocketAddrV4, SocketAddrV6, +}; +use core::str::FromStr; + +#[test] +fn test_from_str_ipv4() { + assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse()); + assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse()); + assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse()); + + // out of range + let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok(); + assert_eq!(None, none); + // too short + let none: Option<Ipv4Addr> = "255.0.0".parse().ok(); + assert_eq!(None, none); + // too long + let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok(); + assert_eq!(None, none); + // no number between dots + let none: Option<Ipv4Addr> = "255.0..1".parse().ok(); + assert_eq!(None, none); + // octal + let none: Option<Ipv4Addr> = "255.0.0.01".parse().ok(); + assert_eq!(None, none); + // octal zero + let none: Option<Ipv4Addr> = "255.0.0.00".parse().ok(); + assert_eq!(None, none); + let none: Option<Ipv4Addr> = "255.0.00.0".parse().ok(); + assert_eq!(None, none); +} + +#[test] +fn test_from_str_ipv6() { + assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse()); + assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse()); + + assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse()); + assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse()); + + assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), "2a02:6b8::11:11".parse()); + + // too long group + let none: Option<Ipv6Addr> = "::00000".parse().ok(); + assert_eq!(None, none); + // too short + let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok(); + assert_eq!(None, none); + // too long + let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok(); + assert_eq!(None, none); + // triple colon + let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok(); + assert_eq!(None, none); + // two double colons + let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok(); + assert_eq!(None, none); + // `::` indicating zero groups of zeros + let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok(); + assert_eq!(None, none); +} + +#[test] +fn test_from_str_ipv4_in_ipv6() { + assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse()); + assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), "::FFFF:192.0.2.33".parse()); + assert_eq!( + Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)), + "64:ff9b::192.0.2.33".parse() + ); + assert_eq!( + Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)), + "2001:db8:122:c000:2:2100:192.0.2.33".parse() + ); + + // colon after v4 + let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok(); + assert_eq!(None, none); + // not enough groups + let none: Option<Ipv6Addr> = "1:2:3:4:5:127.0.0.1".parse().ok(); + assert_eq!(None, none); + // too many groups + let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:127.0.0.1".parse().ok(); + assert_eq!(None, none); +} + +#[test] +fn test_from_str_socket_addr() { + assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse()); + assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse()); + assert_eq!( + Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), + "[2a02:6b8:0:1::1]:53".parse() + ); + assert_eq!( + Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)), + "[2a02:6b8:0:1::1]:53".parse() + ); + assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), "[::127.0.0.1]:22".parse()); + assert_eq!( + Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)), + "[::127.0.0.1]:22".parse() + ); + + // without port + let none: Option<SocketAddr> = "127.0.0.1".parse().ok(); + assert_eq!(None, none); + // without port + let none: Option<SocketAddr> = "127.0.0.1:".parse().ok(); + assert_eq!(None, none); + // wrong brackets around v4 + let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok(); + assert_eq!(None, none); + // port out of range + let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok(); + assert_eq!(None, none); +} + +#[test] +fn ipv4_addr_to_string() { + assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1"); + // Short address + assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1"); + // Long address + assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127"); + + // Test padding + assert_eq!(format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 "); + assert_eq!(format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1"); +} + +#[test] +fn ipv6_addr_to_string() { + // ipv4-mapped address + let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280); + assert_eq!(a1.to_string(), "::ffff:192.0.2.128"); + + // ipv4-compatible address + let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280); + assert_eq!(a1.to_string(), "::192.0.2.128"); + + // v6 address with no zero segments + assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f"); + + // longest possible IPv6 length + assert_eq!( + Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888).to_string(), + "1111:2222:3333:4444:5555:6666:7777:8888" + ); + // padding + assert_eq!(format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8 "); + assert_eq!(format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), " 1:2:3:4:5:6:7:8"); + + // reduce a single run of zeros + assert_eq!( + "ae::ffff:102:304", + Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string() + ); + + // don't reduce just a single zero segment + assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string()); + + // 'any' address + assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string()); + + // loopback address + assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string()); + + // ends in zeros + assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string()); + + // two runs of zeros, second one is longer + assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string()); + + // two runs of zeros, equal length + assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string()); + + // don't prefix `0x` to each segment in `dbg!`. + assert_eq!("1::4:5:0:0:8", &format!("{:#?}", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8))); +} + +#[test] +fn ipv4_to_ipv6() { + assert_eq!( + Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678), + Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped() + ); + assert_eq!( + Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678), + Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible() + ); +} + +#[test] +fn ipv6_to_ipv4_mapped() { + assert_eq!( + Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(), + Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)) + ); + assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None); +} + +#[test] +fn ipv6_to_ipv4() { + assert_eq!( + Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(), + Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)) + ); + assert_eq!( + Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), + Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)) + ); + assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None); +} + +#[test] +fn ip_properties() { + macro_rules! ip { + ($s:expr) => { + IpAddr::from_str($s).unwrap() + }; + } + + macro_rules! check { + ($s:expr) => { + check!($s, 0); + }; + + ($s:expr, $mask:expr) => {{ + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let global: u8 = 1 << 2; + let multicast: u8 = 1 << 3; + let doc: u8 = 1 << 4; + let benchmarking: u8 = 1 << 5; + + if ($mask & unspec) == unspec { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + + if ($mask & multicast) == multicast { + assert!(ip!($s).is_multicast()); + } else { + assert!(!ip!($s).is_multicast()); + } + + if ($mask & doc) == doc { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + + if ($mask & benchmarking) == benchmarking { + assert!(ip!($s).is_benchmarking()); + } else { + assert!(!ip!($s).is_benchmarking()); + } + }}; + } + + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let global: u8 = 1 << 2; + let multicast: u8 = 1 << 3; + let doc: u8 = 1 << 4; + let benchmarking: u8 = 1 << 5; + + check!("0.0.0.0", unspec); + check!("0.0.0.1"); + check!("0.1.0.0"); + check!("10.9.8.7"); + check!("127.1.2.3", loopback); + check!("172.31.254.253"); + check!("169.254.253.242"); + check!("192.0.2.183", doc); + check!("192.1.2.183", global); + check!("192.168.254.253"); + check!("198.51.100.0", doc); + check!("203.0.113.0", doc); + check!("203.2.113.0", global); + check!("224.0.0.0", global | multicast); + check!("239.255.255.255", global | multicast); + check!("255.255.255.255"); + // make sure benchmarking addresses are not global + check!("198.18.0.0", benchmarking); + check!("198.18.54.2", benchmarking); + check!("198.19.255.255", benchmarking); + // make sure addresses reserved for protocol assignment are not global + check!("192.0.0.0"); + check!("192.0.0.255"); + check!("192.0.0.100"); + // make sure reserved addresses are not global + check!("240.0.0.0"); + check!("251.54.1.76"); + check!("254.255.255.255"); + // make sure shared addresses are not global + check!("100.64.0.0"); + check!("100.127.255.255"); + check!("100.100.100.0"); + + check!("::", unspec); + check!("::1", loopback); + check!("::0.0.0.2", global); + check!("1::", global); + check!("fc00::"); + check!("fdff:ffff::"); + check!("fe80:ffff::"); + check!("febf:ffff::"); + check!("fec0::", global); + check!("ff01::", global | multicast); + check!("ff02::", global | multicast); + check!("ff03::", global | multicast); + check!("ff04::", global | multicast); + check!("ff05::", global | multicast); + check!("ff08::", global | multicast); + check!("ff0e::", global | multicast); + check!("2001:db8:85a3::8a2e:370:7334", doc); + check!("2001:2::ac32:23ff:21", benchmarking); + check!("102:304:506:708:90a:b0c:d0e:f10", global); +} + +#[test] +fn ipv4_properties() { + macro_rules! ip { + ($s:expr) => { + Ipv4Addr::from_str($s).unwrap() + }; + } + + macro_rules! check { + ($s:expr) => { + check!($s, 0); + }; + + ($s:expr, $mask:expr) => {{ + let unspec: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let private: u16 = 1 << 2; + let link_local: u16 = 1 << 3; + let global: u16 = 1 << 4; + let multicast: u16 = 1 << 5; + let broadcast: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let benchmarking: u16 = 1 << 8; + let reserved: u16 = 1 << 10; + let shared: u16 = 1 << 11; + + if ($mask & unspec) == unspec { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + + if ($mask & private) == private { + assert!(ip!($s).is_private()); + } else { + assert!(!ip!($s).is_private()); + } + + if ($mask & link_local) == link_local { + assert!(ip!($s).is_link_local()); + } else { + assert!(!ip!($s).is_link_local()); + } + + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + + if ($mask & multicast) == multicast { + assert!(ip!($s).is_multicast()); + } else { + assert!(!ip!($s).is_multicast()); + } + + if ($mask & broadcast) == broadcast { + assert!(ip!($s).is_broadcast()); + } else { + assert!(!ip!($s).is_broadcast()); + } + + if ($mask & documentation) == documentation { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + + if ($mask & benchmarking) == benchmarking { + assert!(ip!($s).is_benchmarking()); + } else { + assert!(!ip!($s).is_benchmarking()); + } + + if ($mask & reserved) == reserved { + assert!(ip!($s).is_reserved()); + } else { + assert!(!ip!($s).is_reserved()); + } + + if ($mask & shared) == shared { + assert!(ip!($s).is_shared()); + } else { + assert!(!ip!($s).is_shared()); + } + }}; + } + + let unspec: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let private: u16 = 1 << 2; + let link_local: u16 = 1 << 3; + let global: u16 = 1 << 4; + let multicast: u16 = 1 << 5; + let broadcast: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let benchmarking: u16 = 1 << 8; + let reserved: u16 = 1 << 10; + let shared: u16 = 1 << 11; + + check!("0.0.0.0", unspec); + check!("0.0.0.1"); + check!("0.1.0.0"); + check!("10.9.8.7", private); + check!("127.1.2.3", loopback); + check!("172.31.254.253", private); + check!("169.254.253.242", link_local); + check!("192.0.2.183", documentation); + check!("192.1.2.183", global); + check!("192.168.254.253", private); + check!("198.51.100.0", documentation); + check!("203.0.113.0", documentation); + check!("203.2.113.0", global); + check!("224.0.0.0", global | multicast); + check!("239.255.255.255", global | multicast); + check!("255.255.255.255", broadcast); + check!("198.18.0.0", benchmarking); + check!("198.18.54.2", benchmarking); + check!("198.19.255.255", benchmarking); + check!("192.0.0.0"); + check!("192.0.0.255"); + check!("192.0.0.100"); + check!("240.0.0.0", reserved); + check!("251.54.1.76", reserved); + check!("254.255.255.255", reserved); + check!("100.64.0.0", shared); + check!("100.127.255.255", shared); + check!("100.100.100.0", shared); +} + +#[test] +fn ipv6_properties() { + macro_rules! ip { + ($s:expr) => { + Ipv6Addr::from_str($s).unwrap() + }; + } + + macro_rules! check { + ($s:expr, &[$($octet:expr),*], $mask:expr) => { + assert_eq!($s, ip!($s).to_string()); + let octets = &[$($octet),*]; + assert_eq!(&ip!($s).octets(), octets); + assert_eq!(Ipv6Addr::from(*octets), ip!($s)); + + let unspecified: u32 = 1 << 0; + let loopback: u32 = 1 << 1; + let unique_local: u32 = 1 << 2; + let global: u32 = 1 << 3; + let unicast_link_local: u32 = 1 << 4; + let unicast_global: u32 = 1 << 7; + let documentation: u32 = 1 << 8; + let benchmarking: u32 = 1 << 16; + let multicast_interface_local: u32 = 1 << 9; + let multicast_link_local: u32 = 1 << 10; + let multicast_realm_local: u32 = 1 << 11; + let multicast_admin_local: u32 = 1 << 12; + let multicast_site_local: u32 = 1 << 13; + let multicast_organization_local: u32 = 1 << 14; + let multicast_global: u32 = 1 << 15; + let multicast: u32 = multicast_interface_local + | multicast_admin_local + | multicast_global + | multicast_link_local + | multicast_realm_local + | multicast_site_local + | multicast_organization_local; + + if ($mask & unspecified) == unspecified { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + if ($mask & unique_local) == unique_local { + assert!(ip!($s).is_unique_local()); + } else { + assert!(!ip!($s).is_unique_local()); + } + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + if ($mask & unicast_link_local) == unicast_link_local { + assert!(ip!($s).is_unicast_link_local()); + } else { + assert!(!ip!($s).is_unicast_link_local()); + } + if ($mask & unicast_global) == unicast_global { + assert!(ip!($s).is_unicast_global()); + } else { + assert!(!ip!($s).is_unicast_global()); + } + if ($mask & documentation) == documentation { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + if ($mask & benchmarking) == benchmarking { + assert!(ip!($s).is_benchmarking()); + } else { + assert!(!ip!($s).is_benchmarking()); + } + if ($mask & multicast) != 0 { + assert!(ip!($s).multicast_scope().is_some()); + assert!(ip!($s).is_multicast()); + } else { + assert!(ip!($s).multicast_scope().is_none()); + assert!(!ip!($s).is_multicast()); + } + if ($mask & multicast_interface_local) == multicast_interface_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::InterfaceLocal); + } + if ($mask & multicast_link_local) == multicast_link_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::LinkLocal); + } + if ($mask & multicast_realm_local) == multicast_realm_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::RealmLocal); + } + if ($mask & multicast_admin_local) == multicast_admin_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::AdminLocal); + } + if ($mask & multicast_site_local) == multicast_site_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::SiteLocal); + } + if ($mask & multicast_organization_local) == multicast_organization_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::OrganizationLocal); + } + if ($mask & multicast_global) == multicast_global { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::Global); + } + } + } + + let unspecified: u32 = 1 << 0; + let loopback: u32 = 1 << 1; + let unique_local: u32 = 1 << 2; + let global: u32 = 1 << 3; + let unicast_link_local: u32 = 1 << 4; + let unicast_global: u32 = 1 << 7; + let documentation: u32 = 1 << 8; + let benchmarking: u32 = 1 << 16; + let multicast_interface_local: u32 = 1 << 9; + let multicast_link_local: u32 = 1 << 10; + let multicast_realm_local: u32 = 1 << 11; + let multicast_admin_local: u32 = 1 << 12; + let multicast_site_local: u32 = 1 << 13; + let multicast_organization_local: u32 = 1 << 14; + let multicast_global: u32 = 1 << 15; + + check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified); + + check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback); + + check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global); + + check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global); + + check!( + "::ffff:127.0.0.1", + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1], + unicast_global + ); + + check!( + "64:ff9b:1::", + &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_global + ); + + check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); + + check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); + + check!( + "2001:1::1", + &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + global | unicast_global + ); + + check!( + "2001:1::2", + &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], + global | unicast_global + ); + + check!( + "2001:3::", + &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); + + check!( + "2001:4:112::", + &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); + + check!( + "2001:20::", + &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); + + check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); + + check!( + "2001:200::", + &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); + + check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local); + + check!( + "fdff:ffff::", + &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unique_local + ); + + check!( + "fe80:ffff::", + &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local + ); + + check!("fe80::", &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local); + + check!( + "febf:ffff::", + &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local + ); + + check!("febf::", &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local); + + check!( + "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + &[ + 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff + ], + unicast_link_local + ); + + check!( + "fe80::ffff:ffff:ffff:ffff", + &[ + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff + ], + unicast_link_local + ); + + check!( + "fe80:0:0:1::", + &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local + ); + + check!( + "fec0::", + &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_global | global + ); + + check!( + "ff01::", + &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_interface_local | global + ); + + check!( + "ff02::", + &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_link_local | global + ); + + check!( + "ff03::", + &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_realm_local | global + ); + + check!( + "ff04::", + &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_admin_local | global + ); + + check!( + "ff05::", + &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_site_local | global + ); + + check!( + "ff08::", + &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_organization_local | global + ); + + check!( + "ff0e::", + &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_global | global + ); + + check!( + "2001:db8:85a3::8a2e:370:7334", + &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], + documentation + ); + + check!( + "2001:2::ac32:23ff:21", + &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21], + benchmarking + ); + + check!( + "102:304:506:708:90a:b0c:d0e:f10", + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + global | unicast_global + ); +} + +#[test] +fn test_ipv4_to_int() { + let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44); + assert_eq!(u32::from(a), 0x11223344); +} + +#[test] +fn test_int_to_ipv4() { + let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44); + assert_eq!(Ipv4Addr::from(0x11223344), a); +} + +#[test] +fn test_ipv6_to_int() { + let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11); + assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128); +} + +#[test] +fn test_int_to_ipv6() { + let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11); + assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a); +} + +#[test] +fn ipv4_from_constructors() { + assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1)); + assert!(Ipv4Addr::LOCALHOST.is_loopback()); + assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0)); + assert!(Ipv4Addr::UNSPECIFIED.is_unspecified()); + assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255)); + assert!(Ipv4Addr::BROADCAST.is_broadcast()); +} + +#[test] +fn ipv6_from_constructors() { + assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + assert!(Ipv6Addr::LOCALHOST.is_loopback()); + assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); + assert!(Ipv6Addr::UNSPECIFIED.is_unspecified()); +} + +#[test] +fn ipv4_from_octets() { + assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1)) +} + +#[test] +fn ipv6_from_segments() { + let from_u16s = + Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]); + let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff); + assert_eq!(new, from_u16s); +} + +#[test] +fn ipv6_from_octets() { + let from_u16s = + Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]); + let from_u8s = Ipv6Addr::from([ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, + 0xff, + ]); + assert_eq!(from_u16s, from_u8s); +} + +#[test] +fn cmp() { + let v41 = Ipv4Addr::new(100, 64, 3, 3); + let v42 = Ipv4Addr::new(192, 0, 2, 2); + let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap(); + let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap(); + assert!(v41 < v42); + assert!(v61 < v62); + + assert_eq!(v41, IpAddr::V4(v41)); + assert_eq!(v61, IpAddr::V6(v61)); + assert!(v41 != IpAddr::V4(v42)); + assert!(v61 != IpAddr::V6(v62)); + + assert!(v41 < IpAddr::V4(v42)); + assert!(v61 < IpAddr::V6(v62)); + assert!(IpAddr::V4(v41) < v42); + assert!(IpAddr::V6(v61) < v62); + + assert!(v41 < IpAddr::V6(v61)); + assert!(IpAddr::V4(v41) < v61); +} + +#[test] +fn is_v4() { + let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3)); + assert!(ip.is_ipv4()); + assert!(!ip.is_ipv6()); +} + +#[test] +fn is_v6() { + let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678)); + assert!(!ip.is_ipv4()); + assert!(ip.is_ipv6()); +} + +#[test] +fn ipv4_const() { + // test that the methods of `Ipv4Addr` are usable in a const context + + const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); + assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST); + + const OCTETS: [u8; 4] = IP_ADDRESS.octets(); + assert_eq!(OCTETS, [127, 0, 0, 1]); + + const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); + assert!(!IS_UNSPECIFIED); + + const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback(); + assert!(IS_LOOPBACK); + + const IS_PRIVATE: bool = IP_ADDRESS.is_private(); + assert!(!IS_PRIVATE); + + const IS_LINK_LOCAL: bool = IP_ADDRESS.is_link_local(); + assert!(!IS_LINK_LOCAL); + + const IS_GLOBAL: bool = IP_ADDRESS.is_global(); + assert!(!IS_GLOBAL); + + const IS_SHARED: bool = IP_ADDRESS.is_shared(); + assert!(!IS_SHARED); + + const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking(); + assert!(!IS_BENCHMARKING); + + const IS_RESERVED: bool = IP_ADDRESS.is_reserved(); + assert!(!IS_RESERVED); + + const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); + assert!(!IS_MULTICAST); + + const IS_BROADCAST: bool = IP_ADDRESS.is_broadcast(); + assert!(!IS_BROADCAST); + + const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation(); + assert!(!IS_DOCUMENTATION); + + const IP_V6_COMPATIBLE: Ipv6Addr = IP_ADDRESS.to_ipv6_compatible(); + assert_eq!( + IP_V6_COMPATIBLE, + Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1]) + ); + + const IP_V6_MAPPED: Ipv6Addr = IP_ADDRESS.to_ipv6_mapped(); + assert_eq!( + IP_V6_MAPPED, + Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1]) + ); +} + +#[test] +fn ipv6_const() { + // test that the methods of `Ipv6Addr` are usable in a const context + + const IP_ADDRESS: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); + assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST); + + const SEGMENTS: [u16; 8] = IP_ADDRESS.segments(); + assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]); + + const OCTETS: [u8; 16] = IP_ADDRESS.octets(); + assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); + + const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); + assert!(!IS_UNSPECIFIED); + + const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback(); + assert!(IS_LOOPBACK); + + const IS_GLOBAL: bool = IP_ADDRESS.is_global(); + assert!(!IS_GLOBAL); + + const IS_UNIQUE_LOCAL: bool = IP_ADDRESS.is_unique_local(); + assert!(!IS_UNIQUE_LOCAL); + + const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local(); + assert!(!IS_UNICAST_LINK_LOCAL); + + const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation(); + assert!(!IS_DOCUMENTATION); + + const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking(); + assert!(!IS_BENCHMARKING); + + const IS_UNICAST_GLOBAL: bool = IP_ADDRESS.is_unicast_global(); + assert!(!IS_UNICAST_GLOBAL); + + const MULTICAST_SCOPE: Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope(); + assert_eq!(MULTICAST_SCOPE, None); + + const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); + assert!(!IS_MULTICAST); + + const IP_V4: Option<Ipv4Addr> = IP_ADDRESS.to_ipv4(); + assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1)); +} + +#[test] +fn ip_const() { + // test that the methods of `IpAddr` are usable in a const context + + const IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); + + const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); + assert!(!IS_UNSPECIFIED); + + const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback(); + assert!(IS_LOOPBACK); + + const IS_GLOBAL: bool = IP_ADDRESS.is_global(); + assert!(!IS_GLOBAL); + + const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); + assert!(!IS_MULTICAST); + + const IS_IP_V4: bool = IP_ADDRESS.is_ipv4(); + assert!(IS_IP_V4); + + const IS_IP_V6: bool = IP_ADDRESS.is_ipv6(); + assert!(!IS_IP_V6); +} + +#[test] +fn structural_match() { + // test that all IP types can be structurally matched upon + + const IPV4: Ipv4Addr = Ipv4Addr::LOCALHOST; + match IPV4 { + Ipv4Addr::LOCALHOST => {} + _ => unreachable!(), + } + + const IPV6: Ipv6Addr = Ipv6Addr::LOCALHOST; + match IPV6 { + Ipv6Addr::LOCALHOST => {} + _ => unreachable!(), + } + + const IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); + match IP { + IpAddr::V4(Ipv4Addr::LOCALHOST) => {} + _ => unreachable!(), + } +} diff --git a/library/core/tests/net/mod.rs b/library/core/tests/net/mod.rs new file mode 100644 index 00000000000..8f17bbe5548 --- /dev/null +++ b/library/core/tests/net/mod.rs @@ -0,0 +1,13 @@ +use core::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; + +mod ip_addr; +mod parser; +mod socket_addr; + +pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr { + SocketAddr::V4(SocketAddrV4::new(a, p)) +} + +pub fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr { + SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0)) +} diff --git a/library/std/src/net/parser/tests.rs b/library/core/tests/net/parser.rs index 6d2d48ecad0..36b87d7c1f5 100644 --- a/library/std/src/net/parser/tests.rs +++ b/library/core/tests/net/parser.rs @@ -1,6 +1,6 @@ // FIXME: These tests are all excellent candidates for AFL fuzz testing -use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; -use crate::str::FromStr; +use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; +use core::str::FromStr; const PORT: u16 = 8080; const SCOPE_ID: u32 = 1337; diff --git a/library/core/tests/net/socket_addr.rs b/library/core/tests/net/socket_addr.rs new file mode 100644 index 00000000000..68c7cd94d32 --- /dev/null +++ b/library/core/tests/net/socket_addr.rs @@ -0,0 +1,233 @@ +use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; + +#[test] +fn ipv4_socket_addr_to_string() { + // Shortest possible IPv4 length. + assert_eq!(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0).to_string(), "0.0.0.0:0"); + + // Longest possible IPv4 length. + assert_eq!( + SocketAddrV4::new(Ipv4Addr::new(255, 255, 255, 255), u16::MAX).to_string(), + "255.255.255.255:65535" + ); + + // Test padding. + assert_eq!( + &format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)), + "1.1.1.1:53 " + ); + assert_eq!( + &format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)), + " 1.1.1.1:53" + ); +} + +#[test] +fn ipv6_socket_addr_to_string() { + // IPv4-mapped address. + assert_eq!( + SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280), 8080, 0, 0) + .to_string(), + "[::ffff:192.0.2.128]:8080" + ); + + // IPv4-compatible address. + assert_eq!( + SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(), + "[::192.0.2.128]:8080" + ); + + // IPv6 address with no zero segments. + assert_eq!( + SocketAddrV6::new(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15), 80, 0, 0).to_string(), + "[8:9:a:b:c:d:e:f]:80" + ); + + // Shortest possible IPv6 length. + assert_eq!(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0).to_string(), "[::]:0"); + + // Longest possible IPv6 length. + assert_eq!( + SocketAddrV6::new( + Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888), + u16::MAX, + u32::MAX, + u32::MAX, + ) + .to_string(), + "[1111:2222:3333:4444:5555:6666:7777:8888%4294967295]:65535" + ); + + // Test padding. + assert_eq!( + &format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)), + "[1:2:3:4:5:6:7:8]:9 " + ); + assert_eq!( + &format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)), + " [1:2:3:4:5:6:7:8]:9" + ); +} + +#[test] +fn set_ip() { + fn ip4(low: u8) -> Ipv4Addr { + Ipv4Addr::new(77, 88, 21, low) + } + fn ip6(low: u16) -> Ipv6Addr { + Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low) + } + + let mut v4 = SocketAddrV4::new(ip4(11), 80); + assert_eq!(v4.ip(), &ip4(11)); + v4.set_ip(ip4(12)); + assert_eq!(v4.ip(), &ip4(12)); + + let mut addr = SocketAddr::V4(v4); + assert_eq!(addr.ip(), IpAddr::V4(ip4(12))); + addr.set_ip(IpAddr::V4(ip4(13))); + assert_eq!(addr.ip(), IpAddr::V4(ip4(13))); + addr.set_ip(IpAddr::V6(ip6(14))); + assert_eq!(addr.ip(), IpAddr::V6(ip6(14))); + + let mut v6 = SocketAddrV6::new(ip6(1), 80, 0, 0); + assert_eq!(v6.ip(), &ip6(1)); + v6.set_ip(ip6(2)); + assert_eq!(v6.ip(), &ip6(2)); + + let mut addr = SocketAddr::V6(v6); + assert_eq!(addr.ip(), IpAddr::V6(ip6(2))); + addr.set_ip(IpAddr::V6(ip6(3))); + assert_eq!(addr.ip(), IpAddr::V6(ip6(3))); + addr.set_ip(IpAddr::V4(ip4(4))); + assert_eq!(addr.ip(), IpAddr::V4(ip4(4))); +} + +#[test] +fn set_port() { + let mut v4 = SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80); + assert_eq!(v4.port(), 80); + v4.set_port(443); + assert_eq!(v4.port(), 443); + + let mut addr = SocketAddr::V4(v4); + assert_eq!(addr.port(), 443); + addr.set_port(8080); + assert_eq!(addr.port(), 8080); + + let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 0); + assert_eq!(v6.port(), 80); + v6.set_port(443); + assert_eq!(v6.port(), 443); + + let mut addr = SocketAddr::V6(v6); + assert_eq!(addr.port(), 443); + addr.set_port(8080); + assert_eq!(addr.port(), 8080); +} + +#[test] +fn set_flowinfo() { + let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0); + assert_eq!(v6.flowinfo(), 10); + v6.set_flowinfo(20); + assert_eq!(v6.flowinfo(), 20); +} + +#[test] +fn set_scope_id() { + let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 10); + assert_eq!(v6.scope_id(), 10); + v6.set_scope_id(20); + assert_eq!(v6.scope_id(), 20); +} + +#[test] +fn is_v4() { + let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)); + assert!(v4.is_ipv4()); + assert!(!v4.is_ipv6()); +} + +#[test] +fn is_v6() { + let v6 = SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), + 80, + 10, + 0, + )); + assert!(!v6.is_ipv4()); + assert!(v6.is_ipv6()); +} + +#[test] +fn socket_v4_to_str() { + let socket = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 8080); + + assert_eq!(format!("{socket}"), "192.168.0.1:8080"); + assert_eq!(format!("{socket:<20}"), "192.168.0.1:8080 "); + assert_eq!(format!("{socket:>20}"), " 192.168.0.1:8080"); + assert_eq!(format!("{socket:^20}"), " 192.168.0.1:8080 "); + assert_eq!(format!("{socket:.10}"), "192.168.0."); +} + +#[test] +fn socket_v6_to_str() { + let mut socket = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0); + + assert_eq!(format!("{socket}"), "[2a02:6b8:0:1::1]:53"); + assert_eq!(format!("{socket:<24}"), "[2a02:6b8:0:1::1]:53 "); + assert_eq!(format!("{socket:>24}"), " [2a02:6b8:0:1::1]:53"); + assert_eq!(format!("{socket:^24}"), " [2a02:6b8:0:1::1]:53 "); + assert_eq!(format!("{socket:.15}"), "[2a02:6b8:0:1::"); + + socket.set_scope_id(5); + + assert_eq!(format!("{socket}"), "[2a02:6b8:0:1::1%5]:53"); + assert_eq!(format!("{socket:<24}"), "[2a02:6b8:0:1::1%5]:53 "); + assert_eq!(format!("{socket:>24}"), " [2a02:6b8:0:1::1%5]:53"); + assert_eq!(format!("{socket:^24}"), " [2a02:6b8:0:1::1%5]:53 "); + assert_eq!(format!("{socket:.18}"), "[2a02:6b8:0:1::1%5"); +} + +#[test] +fn compare() { + let v4_1 = "224.120.45.1:23456".parse::<SocketAddrV4>().unwrap(); + let v4_2 = "224.210.103.5:12345".parse::<SocketAddrV4>().unwrap(); + let v4_3 = "224.210.103.5:23456".parse::<SocketAddrV4>().unwrap(); + let v6_1 = "[2001:db8:f00::1002]:23456".parse::<SocketAddrV6>().unwrap(); + let v6_2 = "[2001:db8:f00::2001]:12345".parse::<SocketAddrV6>().unwrap(); + let v6_3 = "[2001:db8:f00::2001]:23456".parse::<SocketAddrV6>().unwrap(); + + // equality + assert_eq!(v4_1, v4_1); + assert_eq!(v6_1, v6_1); + assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1)); + assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1)); + assert!(v4_1 != v4_2); + assert!(v6_1 != v6_2); + + // compare different addresses + assert!(v4_1 < v4_2); + assert!(v6_1 < v6_2); + assert!(v4_2 > v4_1); + assert!(v6_2 > v6_1); + + // compare the same address with different ports + assert!(v4_2 < v4_3); + assert!(v6_2 < v6_3); + assert!(v4_3 > v4_2); + assert!(v6_3 > v6_2); + + // compare different addresses with the same port + assert!(v4_1 < v4_3); + assert!(v6_1 < v6_3); + assert!(v4_3 > v4_1); + assert!(v6_3 > v6_1); + + // compare with an inferred right-hand side + assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap()); + assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap()); + assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap()); +} diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index a0ca919a851..007f8442533 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -215,11 +215,13 @@ fn nonzero_const() { const ONE: Option<NonZeroU8> = NonZeroU8::new(1); assert!(ONE.is_some()); + /* FIXME(#110395) const FROM_NONZERO_U8: u8 = u8::from(NONZERO_U8); assert_eq!(FROM_NONZERO_U8, 5); const NONZERO_CONVERT: NonZeroU32 = NonZeroU32::from(NONZERO_U8); assert_eq!(NONZERO_CONVERT.get(), 5); + */ } #[test] @@ -334,3 +336,21 @@ fn test_nonzero_uint_rem() { let x: u32 = 42u32 % nz; assert_eq!(x, 2u32); } + +#[test] +fn test_signed_nonzero_neg() { + assert_eq!((-NonZeroI8::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI8::new(-1).unwrap()).get(), 1); + + assert_eq!((-NonZeroI16::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI16::new(-1).unwrap()).get(), 1); + + assert_eq!((-NonZeroI32::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI32::new(-1).unwrap()).get(), 1); + + assert_eq!((-NonZeroI64::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI64::new(-1).unwrap()).get(), 1); + + assert_eq!((-NonZeroI128::new(1).unwrap()).get(), -1); + assert_eq!((-NonZeroI128::new(-1).unwrap()).get(), 1); +} diff --git a/library/core/tests/num/const_from.rs b/library/core/tests/num/const_from.rs index aca18ef39de..fa58e771879 100644 --- a/library/core/tests/num/const_from.rs +++ b/library/core/tests/num/const_from.rs @@ -1,3 +1,4 @@ +/* FIXME(#110395) #[test] fn from() { use core::convert::TryFrom; @@ -23,3 +24,4 @@ fn from() { const I16_FROM_U16: Result<i16, TryFromIntError> = i16::try_from(1u16); assert_eq!(I16_FROM_U16, Ok(1i16)); } +*/ diff --git a/library/core/tests/num/dec2flt/mod.rs b/library/core/tests/num/dec2flt/mod.rs index a2b9bb551e6..874e0ec7093 100644 --- a/library/core/tests/num/dec2flt/mod.rs +++ b/library/core/tests/num/dec2flt/mod.rs @@ -127,14 +127,3 @@ fn massive_exponent() { assert_eq!(format!("1e-{max}000").parse(), Ok(0.0)); assert_eq!(format!("1e{max}000").parse(), Ok(f64::INFINITY)); } - -#[test] -fn borderline_overflow() { - let mut s = "0.".to_string(); - for _ in 0..375 { - s.push('3'); - } - // At the time of this writing, this returns Err(..), but this is a bug that should be fixed. - // It makes no sense to enshrine that in a test, the important part is that it doesn't panic. - let _ = s.parse::<f64>(); -} diff --git a/library/core/tests/num/dec2flt/parse.rs b/library/core/tests/num/dec2flt/parse.rs index edc77377d58..4a5d24ba7d5 100644 --- a/library/core/tests/num/dec2flt/parse.rs +++ b/library/core/tests/num/dec2flt/parse.rs @@ -32,7 +32,7 @@ fn invalid_chars() { } fn parse_positive(s: &[u8]) -> Option<Number> { - parse_number(s, false) + parse_number(s) } #[test] diff --git a/library/core/tests/num/ieee754.rs b/library/core/tests/num/ieee754.rs index f6e5dfc98c7..48ab75b6f17 100644 --- a/library/core/tests/num/ieee754.rs +++ b/library/core/tests/num/ieee754.rs @@ -39,7 +39,6 @@ macro_rules! assert_biteq { // ToString uses the default fmt::Display impl without special concerns, and bypasses other parts // of the formatting infrastructure, which makes it ideal for testing here. -#[allow(unused_macros)] macro_rules! roundtrip { ($f:expr => $t:ty) => { ($f).to_string().parse::<$t>().unwrap() diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 18c55e43aac..439bbe66997 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -364,6 +364,32 @@ macro_rules! int_module { assert_eq!((0 as $T).borrowing_sub($T::MIN, false), ($T::MIN, true)); assert_eq!((0 as $T).borrowing_sub($T::MIN, true), ($T::MAX, false)); } + + #[test] + fn test_midpoint() { + assert_eq!(<$T>::midpoint(1, 3), 2); + assert_eq!(<$T>::midpoint(3, 1), 2); + + assert_eq!(<$T>::midpoint(0, 0), 0); + assert_eq!(<$T>::midpoint(0, 2), 1); + assert_eq!(<$T>::midpoint(2, 0), 1); + assert_eq!(<$T>::midpoint(2, 2), 2); + + assert_eq!(<$T>::midpoint(1, 4), 2); + assert_eq!(<$T>::midpoint(4, 1), 2); + assert_eq!(<$T>::midpoint(3, 4), 3); + assert_eq!(<$T>::midpoint(4, 3), 3); + + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), -1); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), -1); + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); + + assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3); + } } }; } diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index c79e909e41d..3f3659ba837 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -170,7 +170,7 @@ fn test_can_not_overflow() { for base in 2..=36 { let num = (<$t>::MAX as u128) + 1; - // Calcutate the string length for the smallest overflowing number: + // Calculate the string length for the smallest overflowing number: let max_len_string = format_radix(num, base as u128); // Ensure that string length is deemed to potentially overflow: assert!(can_overflow::<$t>(base, &max_len_string)); @@ -724,7 +724,7 @@ assume_usize_width! { } macro_rules! test_float { - ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { + ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr) => { mod $modname { #[test] fn min() { @@ -845,6 +845,38 @@ macro_rules! test_float { assert!(($nan as $fty).maximum($nan).is_nan()); } #[test] + fn midpoint() { + assert_eq!((0.5 as $fty).midpoint(0.5), 0.5); + assert_eq!((0.5 as $fty).midpoint(2.5), 1.5); + assert_eq!((3.0 as $fty).midpoint(4.0), 3.5); + assert_eq!((-3.0 as $fty).midpoint(4.0), 0.5); + assert_eq!((3.0 as $fty).midpoint(-4.0), -0.5); + assert_eq!((-3.0 as $fty).midpoint(-4.0), -3.5); + assert_eq!((0.0 as $fty).midpoint(0.0), 0.0); + assert_eq!((-0.0 as $fty).midpoint(-0.0), -0.0); + assert_eq!((-5.0 as $fty).midpoint(5.0), 0.0); + assert_eq!(($max as $fty).midpoint($min), 0.0); + assert_eq!(($min as $fty).midpoint($max), -0.0); + assert_eq!(($max as $fty).midpoint($min_pos), $max / 2.); + assert_eq!((-$max as $fty).midpoint($min_pos), -$max / 2.); + assert_eq!(($max as $fty).midpoint(-$min_pos), $max / 2.); + assert_eq!((-$max as $fty).midpoint(-$min_pos), -$max / 2.); + assert_eq!(($min_pos as $fty).midpoint($max), $max / 2.); + assert_eq!(($min_pos as $fty).midpoint(-$max), -$max / 2.); + assert_eq!((-$min_pos as $fty).midpoint($max), $max / 2.); + assert_eq!((-$min_pos as $fty).midpoint(-$max), -$max / 2.); + assert_eq!(($max as $fty).midpoint($max), $max); + assert_eq!(($min_pos as $fty).midpoint($min_pos), $min_pos); + assert_eq!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos); + assert_eq!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5); + assert_eq!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5); + assert_eq!(($inf as $fty).midpoint($inf), $inf); + assert_eq!(($neginf as $fty).midpoint($neginf), $neginf); + assert!(($nan as $fty).midpoint(1.0).is_nan()); + assert!((1.0 as $fty).midpoint($nan).is_nan()); + assert!(($nan as $fty).midpoint($nan).is_nan()); + } + #[test] fn rem_euclid() { let a: $fty = 42.0; assert!($inf.rem_euclid(a).is_nan()); @@ -867,5 +899,23 @@ macro_rules! test_float { }; } -test_float!(f32, f32, f32::INFINITY, f32::NEG_INFINITY, f32::NAN); -test_float!(f64, f64, f64::INFINITY, f64::NEG_INFINITY, f64::NAN); +test_float!( + f32, + f32, + f32::INFINITY, + f32::NEG_INFINITY, + f32::NAN, + f32::MIN, + f32::MAX, + f32::MIN_POSITIVE +); +test_float!( + f64, + f64, + f64::INFINITY, + f64::NEG_INFINITY, + f64::NAN, + f64::MIN, + f64::MAX, + f64::MIN_POSITIVE +); diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index 15ae9f2324f..7d6203db0b9 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -252,6 +252,32 @@ macro_rules! uint_module { assert_eq!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false)); assert_eq!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true)); } + + #[test] + fn test_midpoint() { + assert_eq!(<$T>::midpoint(1, 3), 2); + assert_eq!(<$T>::midpoint(3, 1), 2); + + assert_eq!(<$T>::midpoint(0, 0), 0); + assert_eq!(<$T>::midpoint(0, 2), 1); + assert_eq!(<$T>::midpoint(2, 0), 1); + assert_eq!(<$T>::midpoint(2, 2), 2); + + assert_eq!(<$T>::midpoint(1, 4), 2); + assert_eq!(<$T>::midpoint(4, 1), 2); + assert_eq!(<$T>::midpoint(3, 4), 3); + assert_eq!(<$T>::midpoint(4, 3), 3); + + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2); + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); + + assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3); + } } }; } diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index dca6321cf62..5defeb50d40 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -88,6 +88,7 @@ fn test_and() { assert_eq!(x.and(Some(2)), None); assert_eq!(x.and(None::<isize>), None); + /* FIXME(#110395) const FOO: Option<isize> = Some(1); const A: Option<isize> = FOO.and(Some(2)); const B: Option<isize> = FOO.and(None); @@ -99,6 +100,7 @@ fn test_and() { const D: Option<isize> = BAR.and(None); assert_eq!(C, None); assert_eq!(D, None); + */ } #[test] @@ -119,6 +121,7 @@ fn test_and_then() { assert_eq!(x.and_then(plus_one), None); assert_eq!(x.and_then(none), None); + /* FIXME(#110395) const FOO: Option<isize> = Some(1); const A: Option<isize> = FOO.and_then(plus_one); const B: Option<isize> = FOO.and_then(none); @@ -130,6 +133,7 @@ fn test_and_then() { const D: Option<isize> = BAR.and_then(none); assert_eq!(C, None); assert_eq!(D, None); + */ } #[test] @@ -142,6 +146,7 @@ fn test_or() { assert_eq!(x.or(Some(2)), Some(2)); assert_eq!(x.or(None), None); + /* FIXME(#110395) const FOO: Option<isize> = Some(1); const A: Option<isize> = FOO.or(Some(2)); const B: Option<isize> = FOO.or(None); @@ -153,6 +158,7 @@ fn test_or() { const D: Option<isize> = BAR.or(None); assert_eq!(C, Some(2)); assert_eq!(D, None); + */ } #[test] @@ -173,6 +179,7 @@ fn test_or_else() { assert_eq!(x.or_else(two), Some(2)); assert_eq!(x.or_else(none), None); +/* FIXME(#110395) const FOO: Option<isize> = Some(1); const A: Option<isize> = FOO.or_else(two); const B: Option<isize> = FOO.or_else(none); @@ -184,6 +191,7 @@ fn test_or_else() { const D: Option<isize> = BAR.or_else(none); assert_eq!(C, Some(2)); assert_eq!(D, None); +*/ } #[test] @@ -215,10 +223,12 @@ fn test_unwrap_or() { let x: Option<isize> = None; assert_eq!(x.unwrap_or(2), 2); + /* FIXME(#110395) const A: isize = Some(1).unwrap_or(2); const B: isize = None.unwrap_or(2); assert_eq!(A, 1); assert_eq!(B, 2); + */ } #[test] @@ -233,10 +243,12 @@ fn test_unwrap_or_else() { let x: Option<isize> = None; assert_eq!(x.unwrap_or_else(two), 2); + /* FIXME(#110395) const A: isize = Some(1).unwrap_or_else(two); const B: isize = None.unwrap_or_else(two); assert_eq!(A, 1); assert_eq!(B, 2); + */ } #[test] @@ -439,14 +451,15 @@ fn option_const() { const OPTION: Option<usize> = Some(32); assert_eq!(OPTION, Some(32)); - const OPTION_FROM: Option<usize> = Option::from(32); - assert_eq!(OPTION_FROM, Some(32)); + // FIXME(#110395) + // const OPTION_FROM: Option<usize> = Option::from(32); + // assert_eq!(OPTION_FROM, Some(32)); const REF: Option<&usize> = OPTION.as_ref(); assert_eq!(REF, Some(&32)); - const REF_FROM: Option<&usize> = Option::from(&OPTION); - assert_eq!(REF_FROM, Some(&32)); + // const REF_FROM: Option<&usize> = Option::from(&OPTION); + // assert_eq!(REF_FROM, Some(&32)); const IS_SOME: bool = OPTION.is_some(); assert!(IS_SOME); @@ -474,7 +487,7 @@ const fn option_const_mut() { None => unreachable!(), } } - +/* FIXME(const-hack) { let as_mut: Option<&mut usize> = Option::from(&mut option); match as_mut { @@ -482,6 +495,7 @@ const fn option_const_mut() { None => unreachable!(), } } +*/ } #[test] diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 39559cdbb5e..88f54591bb4 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1,6 +1,7 @@ use core::cell::Cell; use core::cmp::Ordering; use core::mem::MaybeUninit; +use core::num::NonZeroUsize; use core::result::Result::{Err, Ok}; use core::slice; @@ -142,20 +143,20 @@ fn test_iterator_advance_by() { for i in 0..=v.len() { let mut iter = v.iter(); - iter.advance_by(i).unwrap(); + assert_eq!(iter.advance_by(i), Ok(())); assert_eq!(iter.as_slice(), &v[i..]); } let mut iter = v.iter(); - assert_eq!(iter.advance_by(v.len() + 1), Err(v.len())); + assert_eq!(iter.advance_by(v.len() + 1), Err(NonZeroUsize::new(1).unwrap())); assert_eq!(iter.as_slice(), &[]); let mut iter = v.iter(); - iter.advance_by(3).unwrap(); + assert_eq!(iter.advance_by(3), Ok(())); assert_eq!(iter.as_slice(), &v[3..]); - iter.advance_by(2).unwrap(); + assert_eq!(iter.advance_by(2), Ok(())); assert_eq!(iter.as_slice(), &[]); - iter.advance_by(0).unwrap(); + assert_eq!(iter.advance_by(0), Ok(())); } #[test] @@ -164,20 +165,20 @@ fn test_iterator_advance_back_by() { for i in 0..=v.len() { let mut iter = v.iter(); - iter.advance_back_by(i).unwrap(); + assert_eq!(iter.advance_back_by(i), Ok(())); assert_eq!(iter.as_slice(), &v[..v.len() - i]); } let mut iter = v.iter(); - assert_eq!(iter.advance_back_by(v.len() + 1), Err(v.len())); + assert_eq!(iter.advance_back_by(v.len() + 1), Err(NonZeroUsize::new(1).unwrap())); assert_eq!(iter.as_slice(), &[]); let mut iter = v.iter(); - iter.advance_back_by(3).unwrap(); + assert_eq!(iter.advance_back_by(3), Ok(())); assert_eq!(iter.as_slice(), &v[..v.len() - 3]); - iter.advance_back_by(2).unwrap(); + assert_eq!(iter.advance_back_by(2), Ok(())); assert_eq!(iter.as_slice(), &[]); - iter.advance_back_by(0).unwrap(); + assert_eq!(iter.advance_back_by(0), Ok(())); } #[test] diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs index 2975c81f8fe..872611937cc 100644 --- a/library/core/tests/time.rs +++ b/library/core/tests/time.rs @@ -425,14 +425,16 @@ fn duration_const() { const SECONDS_F32: f32 = Duration::SECOND.as_secs_f32(); assert_eq!(SECONDS_F32, 1.0); - const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0); - assert_eq!(FROM_SECONDS_F32, Duration::SECOND); + // FIXME(#110395) + // const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0); + // assert_eq!(FROM_SECONDS_F32, Duration::SECOND); const SECONDS_F64: f64 = Duration::SECOND.as_secs_f64(); assert_eq!(SECONDS_F64, 1.0); - const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0); - assert_eq!(FROM_SECONDS_F64, Duration::SECOND); + // FIXME(#110395) + // const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0); + // assert_eq!(FROM_SECONDS_F64, Duration::SECOND); const MILLIS: u128 = Duration::SECOND.as_millis(); assert_eq!(MILLIS, 1_000); @@ -463,6 +465,7 @@ fn duration_const() { const CHECKED_MUL: Option<Duration> = Duration::SECOND.checked_mul(1); assert_eq!(CHECKED_MUL, Some(Duration::SECOND)); +/* FIXME(#110395) const MUL_F32: Duration = Duration::SECOND.mul_f32(1.0); assert_eq!(MUL_F32, Duration::SECOND); @@ -477,6 +480,7 @@ fn duration_const() { const DIV_F64: Duration = Duration::SECOND.div_f64(1.0); assert_eq!(DIV_F64, Duration::SECOND); +*/ const DIV_DURATION_F32: f32 = Duration::SECOND.div_duration_f32(Duration::SECOND); assert_eq!(DIV_DURATION_F32, 1.0); diff --git a/library/panic_abort/src/android.rs b/library/panic_abort/src/android.rs index 0fd824f8a45..20b5b6b5146 100644 --- a/library/panic_abort/src/android.rs +++ b/library/panic_abort/src/android.rs @@ -15,7 +15,7 @@ type SetAbortMessageType = unsafe extern "C" fn(*const libc::c_char) -> (); // // Weakly resolve the symbol for android_set_abort_message. This function is only available // for API >= 21. -pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) { +pub(crate) unsafe fn android_set_abort_message(payload: &mut dyn BoxMeUp) { let func_addr = libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char) as usize; @@ -23,7 +23,7 @@ pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) { return; } - let payload = (*payload).get(); + let payload = payload.get(); let msg = match payload.downcast_ref::<&'static str>() { Some(msg) => msg.as_bytes(), None => match payload.downcast_ref::<String>() { diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index a3cebf99c53..b193d79b0e1 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -29,7 +29,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen // "Leak" the payload and shim to the relevant abort on the platform in question. #[rustc_std_internal_symbol] -pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { +pub unsafe fn __rust_start_panic(_payload: &mut dyn BoxMeUp) -> u32 { // Android has the ability to attach a message as part of the abort. #[cfg(target_os = "android")] android::android_set_abort_message(_payload); diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index c6d42308596..af18e19337c 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -47,7 +47,7 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo { name: b"rust_panic\0".as_ptr(), }; -// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization. +// NOTE(nbdd0121): The `canary` field is part of stable ABI. #[repr(C)] struct Exception { // See `gcc.rs` on why this is present. We already have a static here so just use it. diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 0b7a873a691..08858dd92be 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -48,8 +48,8 @@ use unwind as uw; static CANARY: u8 = 0; // NOTE(nbdd0121) -// Once `c_unwind` feature is stabilized, there will be ABI stability requirement -// on this struct. The first two field must be `_Unwind_Exception` and `canary`, +// There is an ABI stability requirement on this struct. +// The first two field must be `_Unwind_Exception` and `canary`, // as it may be accessed by a different version of the std with a different compiler. #[repr(C)] struct Exception { diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index ea3c9a7a663..ce78ab82ef9 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -99,8 +99,8 @@ pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any // Entry point for raising an exception, just delegates to the platform-specific // implementation. #[rustc_std_internal_symbol] -pub unsafe fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 { - let payload = Box::from_raw((*payload).take_box()); +pub unsafe fn __rust_start_panic(payload: &mut dyn BoxMeUp) -> u32 { + let payload = Box::from_raw(payload.take_box()); imp::panic(payload) } diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 651115a8248..99db00e5490 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -52,7 +52,7 @@ use core::mem::{self, ManuallyDrop}; use core::ptr; use libc::{c_int, c_uint, c_void}; -// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization. +// NOTE(nbdd0121): The `canary` field is part of stable ABI. #[repr(C)] struct Exception { // See `gcc.rs` on why this is present. We already have a static here so just use it. diff --git a/library/portable-simd/.github/workflows/ci.yml b/library/portable-simd/.github/workflows/ci.yml index d50dfa1be4c..acd47a3da72 100644 --- a/library/portable-simd/.github/workflows/ci.yml +++ b/library/portable-simd/.github/workflows/ci.yml @@ -241,6 +241,10 @@ jobs: - "--features std" - "--features generic_const_exprs" - "--features std --features generic_const_exprs" + - "--features all_lane_counts" + - "--features all_lane_counts --features std" + - "--features all_lane_counts --features generic_const_exprs" + - "--features all_lane_counts --features std --features generic_const_exprs" steps: - uses: actions/checkout@v2 diff --git a/library/portable-simd/README.md b/library/portable-simd/README.md index db0af2da606..e8ac600debe 100644 --- a/library/portable-simd/README.md +++ b/library/portable-simd/README.md @@ -24,19 +24,10 @@ or by setting up `rustup default nightly` or else with `cargo +nightly {build,te ```bash cargo new hellosimd ``` -to create a new crate. Edit `hellosimd/Cargo.toml` to be -```toml -[package] -name = "hellosimd" -version = "0.1.0" -edition = "2018" -[dependencies] -core_simd = { git = "https://github.com/rust-lang/portable-simd" } -``` - -and finally write this in `src/main.rs`: +to create a new crate. Finally write this in `src/main.rs`: ```rust -use core_simd::*; +#![feature(portable_simd)] +use std::simd::f32x4; fn main() { let a = f32x4::splat(10.0); let b = f32x4::from_array([1.0, 2.0, 3.0, 4.0]); @@ -44,24 +35,23 @@ fn main() { } ``` -Explanation: We import all the bindings from the crate with the first line. Then, we construct our SIMD vectors with methods like `splat` or `from_array`. Finally, we can use operators on them like `+` and the appropriate SIMD instructions will be carried out. When we run `cargo run` you should get `[11.0, 12.0, 13.0, 14.0]`. - -## Code Organization +Explanation: We construct our SIMD vectors with methods like `splat` or `from_array`. Next, we can use operators like `+` on them, and the appropriate SIMD instructions will be carried out. When we run `cargo run` you should get `[11.0, 12.0, 13.0, 14.0]`. -Currently the crate is organized so that each element type is a file, and then the 64-bit, 128-bit, 256-bit, and 512-bit vectors using those types are contained in said file. +## Supported vectors -All types are then exported as a single, flat module. +Currently, vectors may have up to 64 elements, but aliases are provided only up to 512-bit vectors. Depending on the size of the primitive type, the number of lanes the vector will have varies. For example, 128-bit vectors have four `f32` lanes and two `f64` lanes. The supported element types are as follows: * **Floating Point:** `f32`, `f64` -* **Signed Integers:** `i8`, `i16`, `i32`, `i64`, `i128`, `isize` -* **Unsigned Integers:** `u8`, `u16`, `u32`, `u64`, `u128`, `usize` -* **Masks:** `mask8`, `mask16`, `mask32`, `mask64`, `mask128`, `masksize` +* **Signed Integers:** `i8`, `i16`, `i32`, `i64`, `isize` (`i128` excluded) +* **Unsigned Integers:** `u8`, `u16`, `u32`, `u64`, `usize` (`u128` excluded) +* **Pointers:** `*const T` and `*mut T` (zero-sized metadata only) +* **Masks:** 8-bit, 16-bit, 32-bit, 64-bit, and `usize`-sized masks -Floating point, signed integers, and unsigned integers are the [primitive types](https://doc.rust-lang.org/core/primitive/index.html) you're already used to. -The `mask` types are "truthy" values, but they use the number of bits in their name instead of just 1 bit like a normal `bool` uses. +Floating point, signed integers, unsigned integers, and pointers are the [primitive types](https://doc.rust-lang.org/core/primitive/index.html) you're already used to. +The mask types have elements that are "truthy" values, like `bool`, but have an unspecified layout because different architectures prefer different layouts for mask types. [simd-guide]: ./beginners-guide.md [zulip-project-portable-simd]: https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd diff --git a/library/portable-simd/crates/core_simd/Cargo.toml b/library/portable-simd/crates/core_simd/Cargo.toml index 8a29cf15696..d1a3a515a7e 100644 --- a/library/portable-simd/crates/core_simd/Cargo.toml +++ b/library/portable-simd/crates/core_simd/Cargo.toml @@ -13,12 +13,11 @@ default = ["as_crate"] as_crate = [] std = [] generic_const_exprs = [] +all_lane_counts = [] -[target.'cfg(target_arch = "wasm32")'.dev-dependencies.wasm-bindgen] -version = "0.2" - -[dev-dependencies.wasm-bindgen-test] -version = "0.3" +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +wasm-bindgen = "0.2" +wasm-bindgen-test = "0.3" [dev-dependencies.proptest] version = "0.10" diff --git a/library/portable-simd/crates/core_simd/examples/README.md b/library/portable-simd/crates/core_simd/examples/README.md new file mode 100644 index 00000000000..82747f1b5a6 --- /dev/null +++ b/library/portable-simd/crates/core_simd/examples/README.md @@ -0,0 +1,13 @@ +### `stdsimd` examples + +This crate is a port of example uses of `stdsimd`, mostly taken from the `packed_simd` crate. + +The examples contain, as in the case of `dot_product.rs`, multiple ways of solving the problem, in order to show idiomatic uses of SIMD and iteration of performance designs. + +Run the tests with the command + +``` +cargo run --example dot_product +``` + +and verify the code for `dot_product.rs` on your machine. diff --git a/library/portable-simd/crates/core_simd/examples/dot_product.rs b/library/portable-simd/crates/core_simd/examples/dot_product.rs new file mode 100644 index 00000000000..391f08f55a0 --- /dev/null +++ b/library/portable-simd/crates/core_simd/examples/dot_product.rs @@ -0,0 +1,169 @@ +// Code taken from the `packed_simd` crate +// Run this code with `cargo test --example dot_product` +//use std::iter::zip; + +#![feature(array_chunks)] +#![feature(slice_as_chunks)] +// Add these imports to use the stdsimd library +#![feature(portable_simd)] +use core_simd::simd::*; + +// This is your barebones dot product implementation: +// Take 2 vectors, multiply them element wise and *then* +// go along the resulting array and add up the result. +// In the next example we will see if there +// is any difference to adding and multiplying in tandem. +pub fn dot_prod_scalar_0(a: &[f32], b: &[f32]) -> f32 { + assert_eq!(a.len(), b.len()); + + a.iter().zip(b.iter()).map(|(a, b)| a * b).sum() +} + +// When dealing with SIMD, it is very important to think about the amount +// of data movement and when it happens. We're going over simple computation examples here, and yet +// it is not trivial to understand what may or may not contribute to performance +// changes. Eventually, you will need tools to inspect the generated assembly and confirm your +// hypothesis and benchmarks - we will mention them later on. +// With the use of `fold`, we're doing a multiplication, +// and then adding it to the sum, one element from both vectors at a time. +pub fn dot_prod_scalar_1(a: &[f32], b: &[f32]) -> f32 { + assert_eq!(a.len(), b.len()); + a.iter() + .zip(b.iter()) + .fold(0.0, |a, zipped| a + zipped.0 * zipped.1) +} + +// We now move on to the SIMD implementations: notice the following constructs: +// `array_chunks::<4>`: mapping this over the vector will let use construct SIMD vectors +// `f32x4::from_array`: construct the SIMD vector from a slice +// `(a * b).reduce_sum()`: Multiply both f32x4 vectors together, and then reduce them. +// This approach essentially uses SIMD to produce a vector of length N/4 of all the products, +// and then add those with `sum()`. This is suboptimal. +// TODO: ASCII diagrams +pub fn dot_prod_simd_0(a: &[f32], b: &[f32]) -> f32 { + assert_eq!(a.len(), b.len()); + // TODO handle remainder when a.len() % 4 != 0 + a.array_chunks::<4>() + .map(|&a| f32x4::from_array(a)) + .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .map(|(a, b)| (a * b).reduce_sum()) + .sum() +} + +// There's some simple ways to improve the previous code: +// 1. Make a `zero` `f32x4` SIMD vector that we will be accumulating into +// So that there is only one `sum()` reduction when the last `f32x4` has been processed +// 2. Exploit Fused Multiply Add so that the multiplication, addition and sinking into the reduciton +// happen in the same step. +// If the arrays are large, minimizing the data shuffling will lead to great perf. +// If the arrays are small, handling the remainder elements when the length isn't a multiple of 4 +// Can become a problem. +pub fn dot_prod_simd_1(a: &[f32], b: &[f32]) -> f32 { + assert_eq!(a.len(), b.len()); + // TODO handle remainder when a.len() % 4 != 0 + a.array_chunks::<4>() + .map(|&a| f32x4::from_array(a)) + .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .fold(f32x4::splat(0.0), |acc, zipped| acc + zipped.0 * zipped.1) + .reduce_sum() +} + +// A lot of knowledgeable use of SIMD comes from knowing specific instructions that are +// available - let's try to use the `mul_add` instruction, which is the fused-multiply-add we were looking for. +use std_float::StdFloat; +pub fn dot_prod_simd_2(a: &[f32], b: &[f32]) -> f32 { + assert_eq!(a.len(), b.len()); + // TODO handle remainder when a.len() % 4 != 0 + let mut res = f32x4::splat(0.0); + a.array_chunks::<4>() + .map(|&a| f32x4::from_array(a)) + .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .for_each(|(a, b)| { + res = a.mul_add(b, res); + }); + res.reduce_sum() +} + +// Finally, we will write the same operation but handling the loop remainder. +const LANES: usize = 4; +pub fn dot_prod_simd_3(a: &[f32], b: &[f32]) -> f32 { + assert_eq!(a.len(), b.len()); + + let (a_extra, a_chunks) = a.as_rchunks(); + let (b_extra, b_chunks) = b.as_rchunks(); + + // These are always true, but for emphasis: + assert_eq!(a_chunks.len(), b_chunks.len()); + assert_eq!(a_extra.len(), b_extra.len()); + + let mut sums = [0.0; LANES]; + for ((x, y), d) in std::iter::zip(a_extra, b_extra).zip(&mut sums) { + *d = x * y; + } + + let mut sums = f32x4::from_array(sums); + std::iter::zip(a_chunks, b_chunks).for_each(|(x, y)| { + sums += f32x4::from_array(*x) * f32x4::from_array(*y); + }); + + sums.reduce_sum() +} + +// Finally, we present an iterator version for handling remainders in a scalar fashion at the end of the loop. +// Unfortunately, this is allocating 1 `XMM` register on the order of `~len(a)` - we'll see how we can get around it in the +// next example. +pub fn dot_prod_simd_4(a: &[f32], b: &[f32]) -> f32 { + let mut sum = a + .array_chunks::<4>() + .map(|&a| f32x4::from_array(a)) + .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .map(|(a, b)| a * b) + .fold(f32x4::splat(0.0), std::ops::Add::add) + .reduce_sum(); + let remain = a.len() - (a.len() % 4); + sum += a[remain..] + .iter() + .zip(&b[remain..]) + .map(|(a, b)| a * b) + .sum::<f32>(); + sum +} + +// This version allocates a single `XMM` register for accumulation, and the folds don't allocate on top of that. +// Notice the the use of `mul_add`, which can do a multiply and an add operation ber iteration. +pub fn dot_prod_simd_5(a: &[f32], b: &[f32]) -> f32 { + a.array_chunks::<4>() + .map(|&a| f32x4::from_array(a)) + .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .fold(f32x4::splat(0.), |acc, (a, b)| a.mul_add(b, acc)) + .reduce_sum() +} + +fn main() { + // Empty main to make cargo happy +} + +#[cfg(test)] +mod tests { + #[test] + fn smoke_test() { + use super::*; + let a: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; + let b: Vec<f32> = vec![-8.0, -7.0, -6.0, -5.0, 4.0, 3.0, 2.0, 1.0]; + let x: Vec<f32> = [0.5; 1003].to_vec(); + let y: Vec<f32> = [2.0; 1003].to_vec(); + + // Basic check + assert_eq!(0.0, dot_prod_scalar_0(&a, &b)); + assert_eq!(0.0, dot_prod_scalar_1(&a, &b)); + assert_eq!(0.0, dot_prod_simd_0(&a, &b)); + assert_eq!(0.0, dot_prod_simd_1(&a, &b)); + assert_eq!(0.0, dot_prod_simd_2(&a, &b)); + assert_eq!(0.0, dot_prod_simd_3(&a, &b)); + assert_eq!(0.0, dot_prod_simd_4(&a, &b)); + assert_eq!(0.0, dot_prod_simd_5(&a, &b)); + + // We can handle vectors that are non-multiples of 4 + assert_eq!(1003.0, dot_prod_simd_3(&x, &y)); + } +} diff --git a/library/portable-simd/crates/core_simd/src/alias.rs b/library/portable-simd/crates/core_simd/src/alias.rs new file mode 100644 index 00000000000..23f121c4619 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/alias.rs @@ -0,0 +1,227 @@ +macro_rules! number { + { 1 } => { "one" }; + { 2 } => { "two" }; + { 4 } => { "four" }; + { 8 } => { "eight" }; + { $x:literal } => { stringify!($x) }; +} + +macro_rules! plural { + { 1 } => { "" }; + { $x:literal } => { "s" }; +} + +macro_rules! alias { + { + $( + $element_ty:ty = { + $($alias:ident $num_elements:tt)* + } + )* + } => { + $( + $( + #[doc = concat!("A SIMD vector with ", number!($num_elements), " element", plural!($num_elements), " of type [`", stringify!($element_ty), "`].")] + #[allow(non_camel_case_types)] + pub type $alias = $crate::simd::Simd<$element_ty, $num_elements>; + )* + )* + } +} + +macro_rules! mask_alias { + { + $( + $element_ty:ty : $size:literal = { + $($alias:ident $num_elements:tt)* + } + )* + } => { + $( + $( + #[doc = concat!("A SIMD mask with ", number!($num_elements), " element", plural!($num_elements), " for vectors with ", $size, " element types.")] + /// + #[doc = concat!( + "The layout of this type is unspecified, and may change between platforms and/or Rust versions, and code should not assume that it is equivalent to `[", + stringify!($element_ty), "; ", $num_elements, "]`." + )] + #[allow(non_camel_case_types)] + pub type $alias = $crate::simd::Mask<$element_ty, $num_elements>; + )* + )* + } +} + +alias! { + i8 = { + i8x1 1 + i8x2 2 + i8x4 4 + i8x8 8 + i8x16 16 + i8x32 32 + i8x64 64 + } + + i16 = { + i16x1 1 + i16x2 2 + i16x4 4 + i16x8 8 + i16x16 16 + i16x32 32 + i16x64 64 + } + + i32 = { + i32x1 1 + i32x2 2 + i32x4 4 + i32x8 8 + i32x16 16 + i32x32 32 + i32x64 64 + } + + i64 = { + i64x1 1 + i64x2 2 + i64x4 4 + i64x8 8 + i64x16 16 + i64x32 32 + i64x64 64 + } + + isize = { + isizex1 1 + isizex2 2 + isizex4 4 + isizex8 8 + isizex16 16 + isizex32 32 + isizex64 64 + } + + u8 = { + u8x1 1 + u8x2 2 + u8x4 4 + u8x8 8 + u8x16 16 + u8x32 32 + u8x64 64 + } + + u16 = { + u16x1 1 + u16x2 2 + u16x4 4 + u16x8 8 + u16x16 16 + u16x32 32 + u16x64 64 + } + + u32 = { + u32x1 1 + u32x2 2 + u32x4 4 + u32x8 8 + u32x16 16 + u32x32 32 + u32x64 64 + } + + u64 = { + u64x1 1 + u64x2 2 + u64x4 4 + u64x8 8 + u64x16 16 + u64x32 32 + u64x64 64 + } + + usize = { + usizex1 1 + usizex2 2 + usizex4 4 + usizex8 8 + usizex16 16 + usizex32 32 + usizex64 64 + } + + f32 = { + f32x1 1 + f32x2 2 + f32x4 4 + f32x8 8 + f32x16 16 + f32x32 32 + f32x64 64 + } + + f64 = { + f64x1 1 + f64x2 2 + f64x4 4 + f64x8 8 + f64x16 16 + f64x32 32 + f64x64 64 + } +} + +mask_alias! { + i8 : "8-bit" = { + mask8x1 1 + mask8x2 2 + mask8x4 4 + mask8x8 8 + mask8x16 16 + mask8x32 32 + mask8x64 64 + } + + i16 : "16-bit" = { + mask16x1 1 + mask16x2 2 + mask16x4 4 + mask16x8 8 + mask16x16 16 + mask16x32 32 + mask16x64 64 + } + + i32 : "32-bit" = { + mask32x1 1 + mask32x2 2 + mask32x4 4 + mask32x8 8 + mask32x16 16 + mask32x32 32 + mask32x64 64 + } + + i64 : "64-bit" = { + mask64x1 1 + mask64x2 2 + mask64x4 4 + mask64x8 8 + mask64x16 16 + mask64x32 32 + mask64x64 64 + } + + isize : "pointer-sized" = { + masksizex1 1 + masksizex2 2 + masksizex4 4 + masksizex8 8 + masksizex16 16 + masksizex32 32 + masksizex64 64 + } +} diff --git a/library/portable-simd/crates/core_simd/src/cast.rs b/library/portable-simd/crates/core_simd/src/cast.rs new file mode 100644 index 00000000000..65a3f845ffc --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/cast.rs @@ -0,0 +1,55 @@ +use crate::simd::SimdElement; + +/// Supporting trait for `Simd::cast`. Typically doesn't need to be used directly. +/// +/// # Safety +/// Implementing this trait asserts that the type is a valid vector element for the `simd_cast` or +/// `simd_as` intrinsics. +pub unsafe trait SimdCast: SimdElement {} + +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for i8 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for i16 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for i32 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for i64 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for isize {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for u8 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for u16 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for u32 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for u64 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for usize {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for f32 {} +// Safety: primitive number types can be cast to other primitive number types +unsafe impl SimdCast for f64 {} + +/// Supporting trait for `Simd::cast_ptr`. Typically doesn't need to be used directly. +/// +/// # Safety +/// Implementing this trait asserts that the type is a valid vector element for the `simd_cast_ptr` +/// intrinsic. +pub unsafe trait SimdCastPtr<T> {} + +// Safety: pointers can be cast to other pointer types +unsafe impl<T, U> SimdCastPtr<T> for *const U +where + U: core::ptr::Pointee, + T: core::ptr::Pointee<Metadata = U::Metadata>, +{ +} +// Safety: pointers can be cast to other pointer types +unsafe impl<T, U> SimdCastPtr<T> for *mut U +where + U: core::ptr::Pointee, + T: core::ptr::Pointee<Metadata = U::Metadata>, +{ +} diff --git a/library/portable-simd/crates/core_simd/src/elements.rs b/library/portable-simd/crates/core_simd/src/elements.rs index 701eb66b248..dc7f52a4d57 100644 --- a/library/portable-simd/crates/core_simd/src/elements.rs +++ b/library/portable-simd/crates/core_simd/src/elements.rs @@ -1,11 +1,15 @@ +mod const_ptr; mod float; mod int; +mod mut_ptr; mod uint; mod sealed { pub trait Sealed {} } +pub use const_ptr::*; pub use float::*; pub use int::*; +pub use mut_ptr::*; pub use uint::*; diff --git a/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs b/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs new file mode 100644 index 00000000000..0ef9802b5e2 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs @@ -0,0 +1,141 @@ +use super::sealed::Sealed; +use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SupportedLaneCount}; + +/// Operations on SIMD vectors of constant pointers. +pub trait SimdConstPtr: Copy + Sealed { + /// Vector of `usize` with the same number of lanes. + type Usize; + + /// Vector of `isize` with the same number of lanes. + type Isize; + + /// Vector of mutable pointers to the same type. + type MutPtr; + + /// Mask type used for manipulating this SIMD vector type. + type Mask; + + /// Returns `true` for each lane that is null. + fn is_null(self) -> Self::Mask; + + /// Changes constness without changing the type. + /// + /// Equivalent to calling [`pointer::cast_mut`] on each lane. + fn cast_mut(self) -> Self::MutPtr; + + /// Gets the "address" portion of the pointer. + /// + /// This method discards pointer semantic metadata, so the result cannot be + /// directly cast into a valid pointer. + /// + /// This method semantically discards *provenance* and + /// *address-space* information. To properly restore that information, use [`Self::with_addr`]. + /// + /// Equivalent to calling [`pointer::addr`] on each lane. + fn addr(self) -> Self::Usize; + + /// Creates a new pointer with the given address. + /// + /// This performs the same operation as a cast, but copies the *address-space* and + /// *provenance* of `self` to the new pointer. + /// + /// Equivalent to calling [`pointer::with_addr`] on each lane. + fn with_addr(self, addr: Self::Usize) -> Self; + + /// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use + /// in [`Self::from_exposed_addr`]. + fn expose_addr(self) -> Self::Usize; + + /// Convert an address back to a pointer, picking up a previously "exposed" provenance. + /// + /// Equivalent to calling [`core::ptr::from_exposed_addr`] on each lane. + fn from_exposed_addr(addr: Self::Usize) -> Self; + + /// Calculates the offset from a pointer using wrapping arithmetic. + /// + /// Equivalent to calling [`pointer::wrapping_offset`] on each lane. + fn wrapping_offset(self, offset: Self::Isize) -> Self; + + /// Calculates the offset from a pointer using wrapping arithmetic. + /// + /// Equivalent to calling [`pointer::wrapping_add`] on each lane. + fn wrapping_add(self, count: Self::Usize) -> Self; + + /// Calculates the offset from a pointer using wrapping arithmetic. + /// + /// Equivalent to calling [`pointer::wrapping_sub`] on each lane. + fn wrapping_sub(self, count: Self::Usize) -> Self; +} + +impl<T, const LANES: usize> Sealed for Simd<*const T, LANES> where + LaneCount<LANES>: SupportedLaneCount +{ +} + +impl<T, const LANES: usize> SimdConstPtr for Simd<*const T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, +{ + type Usize = Simd<usize, LANES>; + type Isize = Simd<isize, LANES>; + type MutPtr = Simd<*mut T, LANES>; + type Mask = Mask<isize, LANES>; + + #[inline] + fn is_null(self) -> Self::Mask { + Simd::splat(core::ptr::null()).simd_eq(self) + } + + #[inline] + fn cast_mut(self) -> Self::MutPtr { + self.cast_ptr() + } + + #[inline] + fn addr(self) -> Self::Usize { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the + // provenance). + unsafe { core::mem::transmute_copy(&self) } + } + + #[inline] + fn with_addr(self, addr: Self::Usize) -> Self { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + // + // In the mean-time, this operation is defined to be "as if" it was + // a wrapping_offset, so we can emulate it as such. This should properly + // restore pointer provenance even under today's compiler. + self.cast_ptr::<*const u8>() + .wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>()) + .cast_ptr() + } + + #[inline] + fn expose_addr(self) -> Self::Usize { + // Safety: `self` is a pointer vector + unsafe { intrinsics::simd_expose_addr(self) } + } + + #[inline] + fn from_exposed_addr(addr: Self::Usize) -> Self { + // Safety: `self` is a pointer vector + unsafe { intrinsics::simd_from_exposed_addr(addr) } + } + + #[inline] + fn wrapping_offset(self, count: Self::Isize) -> Self { + // Safety: simd_arith_offset takes a vector of pointers and a vector of offsets + unsafe { intrinsics::simd_arith_offset(self, count) } + } + + #[inline] + fn wrapping_add(self, count: Self::Usize) -> Self { + self.wrapping_offset(count.cast()) + } + + #[inline] + fn wrapping_sub(self, count: Self::Usize) -> Self { + self.wrapping_offset(-count.cast::<isize>()) + } +} diff --git a/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs new file mode 100644 index 00000000000..d87986b4a09 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs @@ -0,0 +1,136 @@ +use super::sealed::Sealed; +use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SupportedLaneCount}; + +/// Operations on SIMD vectors of mutable pointers. +pub trait SimdMutPtr: Copy + Sealed { + /// Vector of `usize` with the same number of lanes. + type Usize; + + /// Vector of `isize` with the same number of lanes. + type Isize; + + /// Vector of constant pointers to the same type. + type ConstPtr; + + /// Mask type used for manipulating this SIMD vector type. + type Mask; + + /// Returns `true` for each lane that is null. + fn is_null(self) -> Self::Mask; + + /// Changes constness without changing the type. + /// + /// Equivalent to calling [`pointer::cast_const`] on each lane. + fn cast_const(self) -> Self::ConstPtr; + + /// Gets the "address" portion of the pointer. + /// + /// This method discards pointer semantic metadata, so the result cannot be + /// directly cast into a valid pointer. + /// + /// Equivalent to calling [`pointer::addr`] on each lane. + fn addr(self) -> Self::Usize; + + /// Creates a new pointer with the given address. + /// + /// This performs the same operation as a cast, but copies the *address-space* and + /// *provenance* of `self` to the new pointer. + /// + /// Equivalent to calling [`pointer::with_addr`] on each lane. + fn with_addr(self, addr: Self::Usize) -> Self; + + /// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use + /// in [`Self::from_exposed_addr`]. + fn expose_addr(self) -> Self::Usize; + + /// Convert an address back to a pointer, picking up a previously "exposed" provenance. + /// + /// Equivalent to calling [`core::ptr::from_exposed_addr_mut`] on each lane. + fn from_exposed_addr(addr: Self::Usize) -> Self; + + /// Calculates the offset from a pointer using wrapping arithmetic. + /// + /// Equivalent to calling [`pointer::wrapping_offset`] on each lane. + fn wrapping_offset(self, offset: Self::Isize) -> Self; + + /// Calculates the offset from a pointer using wrapping arithmetic. + /// + /// Equivalent to calling [`pointer::wrapping_add`] on each lane. + fn wrapping_add(self, count: Self::Usize) -> Self; + + /// Calculates the offset from a pointer using wrapping arithmetic. + /// + /// Equivalent to calling [`pointer::wrapping_sub`] on each lane. + fn wrapping_sub(self, count: Self::Usize) -> Self; +} + +impl<T, const LANES: usize> Sealed for Simd<*mut T, LANES> where LaneCount<LANES>: SupportedLaneCount +{} + +impl<T, const LANES: usize> SimdMutPtr for Simd<*mut T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, +{ + type Usize = Simd<usize, LANES>; + type Isize = Simd<isize, LANES>; + type ConstPtr = Simd<*const T, LANES>; + type Mask = Mask<isize, LANES>; + + #[inline] + fn is_null(self) -> Self::Mask { + Simd::splat(core::ptr::null_mut()).simd_eq(self) + } + + #[inline] + fn cast_const(self) -> Self::ConstPtr { + self.cast_ptr() + } + + #[inline] + fn addr(self) -> Self::Usize { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the + // provenance). + unsafe { core::mem::transmute_copy(&self) } + } + + #[inline] + fn with_addr(self, addr: Self::Usize) -> Self { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + // + // In the mean-time, this operation is defined to be "as if" it was + // a wrapping_offset, so we can emulate it as such. This should properly + // restore pointer provenance even under today's compiler. + self.cast_ptr::<*mut u8>() + .wrapping_offset(addr.cast::<isize>() - self.addr().cast::<isize>()) + .cast_ptr() + } + + #[inline] + fn expose_addr(self) -> Self::Usize { + // Safety: `self` is a pointer vector + unsafe { intrinsics::simd_expose_addr(self) } + } + + #[inline] + fn from_exposed_addr(addr: Self::Usize) -> Self { + // Safety: `self` is a pointer vector + unsafe { intrinsics::simd_from_exposed_addr(addr) } + } + + #[inline] + fn wrapping_offset(self, count: Self::Isize) -> Self { + // Safety: simd_arith_offset takes a vector of pointers and a vector of offsets + unsafe { intrinsics::simd_arith_offset(self, count) } + } + + #[inline] + fn wrapping_add(self, count: Self::Usize) -> Self { + self.wrapping_offset(count.cast()) + } + + #[inline] + fn wrapping_sub(self, count: Self::Usize) -> Self { + self.wrapping_offset(-count.cast::<isize>()) + } +} diff --git a/library/portable-simd/crates/core_simd/src/eq.rs b/library/portable-simd/crates/core_simd/src/eq.rs index c7111f720a8..80763c07272 100644 --- a/library/portable-simd/crates/core_simd/src/eq.rs +++ b/library/portable-simd/crates/core_simd/src/eq.rs @@ -1,4 +1,6 @@ -use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{ + intrinsics, LaneCount, Mask, Simd, SimdConstPtr, SimdElement, SimdMutPtr, SupportedLaneCount, +}; /// Parallel `PartialEq`. pub trait SimdPartialEq { @@ -71,3 +73,37 @@ macro_rules! impl_mask { } impl_mask! { i8, i16, i32, i64, isize } + +impl<T, const LANES: usize> SimdPartialEq for Simd<*const T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, +{ + type Mask = Mask<isize, LANES>; + + #[inline] + fn simd_eq(self, other: Self) -> Self::Mask { + self.addr().simd_eq(other.addr()) + } + + #[inline] + fn simd_ne(self, other: Self) -> Self::Mask { + self.addr().simd_ne(other.addr()) + } +} + +impl<T, const LANES: usize> SimdPartialEq for Simd<*mut T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, +{ + type Mask = Mask<isize, LANES>; + + #[inline] + fn simd_eq(self, other: Self) -> Self::Mask { + self.addr().simd_eq(other.addr()) + } + + #[inline] + fn simd_ne(self, other: Self) -> Self::Mask { + self.addr().simd_ne(other.addr()) + } +} diff --git a/library/portable-simd/crates/core_simd/src/fmt.rs b/library/portable-simd/crates/core_simd/src/fmt.rs index dbd9839c4bf..b7317969cbb 100644 --- a/library/portable-simd/crates/core_simd/src/fmt.rs +++ b/library/portable-simd/crates/core_simd/src/fmt.rs @@ -1,39 +1,21 @@ use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; use core::fmt; -macro_rules! impl_fmt_trait { - { $($trait:ident,)* } => { - $( - impl<T, const LANES: usize> fmt::$trait for Simd<T, LANES> - where - LaneCount<LANES>: SupportedLaneCount, - T: SimdElement + fmt::$trait, - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[repr(transparent)] - struct Wrapper<'a, T: fmt::$trait>(&'a T); - - impl<T: fmt::$trait> fmt::Debug for Wrapper<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } - } - - f.debug_list() - .entries(self.as_array().iter().map(|x| Wrapper(x))) - .finish() - } - } - )* +impl<T, const LANES: usize> fmt::Debug for Simd<T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, + T: SimdElement + fmt::Debug, +{ + /// A `Simd<T, N>` has a debug format like the one for `[T]`: + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let floats = Simd::<f32, 4>::splat(-1.0); + /// assert_eq!(format!("{:?}", [-1.0; 4]), format!("{:?}", floats)); + /// ``` + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + <[T] as fmt::Debug>::fmt(self.as_array(), f) } } - -impl_fmt_trait! { - Debug, - Binary, - LowerExp, - UpperExp, - Octal, - LowerHex, - UpperHex, -} diff --git a/library/portable-simd/crates/core_simd/src/intrinsics.rs b/library/portable-simd/crates/core_simd/src/intrinsics.rs index 704e6ed0159..dd6698e2ba5 100644 --- a/library/portable-simd/crates/core_simd/src/intrinsics.rs +++ b/library/portable-simd/crates/core_simd/src/intrinsics.rs @@ -61,9 +61,6 @@ extern "platform-intrinsic" { /// xor pub(crate) fn simd_xor<T>(x: T, y: T) -> T; - /// getelementptr (without inbounds) - pub(crate) fn simd_arith_offset<T, U>(ptrs: T, offsets: U) -> T; - /// fptoui/fptosi/uitofp/sitofp /// casting floats to integers is truncating, so it is safe to convert values like e.g. 1.5 /// but the truncated value must fit in the target type or the result is poison. @@ -150,4 +147,17 @@ extern "platform-intrinsic" { pub(crate) fn simd_select<M, T>(m: M, yes: T, no: T) -> T; #[allow(unused)] pub(crate) fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T; + + /// getelementptr (without inbounds) + /// equivalent to wrapping_offset + pub(crate) fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T; + + /// equivalent to `T as U` semantics, specifically for pointers + pub(crate) fn simd_cast_ptr<T, U>(ptr: T) -> U; + + /// expose a pointer as an address + pub(crate) fn simd_expose_addr<T, U>(ptr: T) -> U; + + /// convert an exposed address back to a pointer + pub(crate) fn simd_from_exposed_addr<T, U>(addr: T) -> U; } diff --git a/library/portable-simd/crates/core_simd/src/lane_count.rs b/library/portable-simd/crates/core_simd/src/lane_count.rs index 63723e2ec13..2b91eb9e800 100644 --- a/library/portable-simd/crates/core_simd/src/lane_count.rs +++ b/library/portable-simd/crates/core_simd/src/lane_count.rs @@ -23,24 +23,20 @@ pub trait SupportedLaneCount: Sealed { impl<const LANES: usize> Sealed for LaneCount<LANES> {} -impl SupportedLaneCount for LaneCount<1> { - type BitMask = [u8; 1]; -} -impl SupportedLaneCount for LaneCount<2> { - type BitMask = [u8; 1]; -} -impl SupportedLaneCount for LaneCount<4> { - type BitMask = [u8; 1]; -} -impl SupportedLaneCount for LaneCount<8> { - type BitMask = [u8; 1]; -} -impl SupportedLaneCount for LaneCount<16> { - type BitMask = [u8; 2]; -} -impl SupportedLaneCount for LaneCount<32> { - type BitMask = [u8; 4]; -} -impl SupportedLaneCount for LaneCount<64> { - type BitMask = [u8; 8]; +macro_rules! supported_lane_count { + ($($lanes:literal),+) => { + $( + impl SupportedLaneCount for LaneCount<$lanes> { + type BitMask = [u8; ($lanes + 7) / 8]; + } + )+ + }; } + +supported_lane_count!(1, 2, 4, 8, 16, 32, 64); +#[cfg(feature = "all_lane_counts")] +supported_lane_count!( + 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63 +); diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs index 715f258f617..e5307de2155 100644 --- a/library/portable-simd/crates/core_simd/src/lib.rs +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -1,5 +1,8 @@ #![no_std] #![feature( + const_refs_to_cell, + const_maybe_uninit_as_mut_ptr, + const_mut_refs, convert_float_to_int, decl_macro, intra_doc_pointers, @@ -7,7 +10,9 @@ repr_simd, simd_ffi, staged_api, - stdsimd + stdsimd, + strict_provenance, + ptr_metadata )] #![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))] #![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))] @@ -19,4 +24,3 @@ #[path = "mod.rs"] mod core_simd; pub use self::core_simd::simd; -pub use simd::*; diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs index c36c336d8a2..e58df80fca8 100644 --- a/library/portable-simd/crates/core_simd/src/masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks.rs @@ -55,6 +55,7 @@ pub unsafe trait MaskElement: SimdElement + Sealed {} macro_rules! impl_element { { $ty:ty } => { impl Sealed for $ty { + #[inline] fn valid<const LANES: usize>(value: Simd<Self, LANES>) -> bool where LaneCount<LANES>: SupportedLaneCount, @@ -62,6 +63,7 @@ macro_rules! impl_element { (value.simd_eq(Simd::splat(0 as _)) | value.simd_eq(Simd::splat(-1 as _))).all() } + #[inline] fn eq(self, other: Self) -> bool { self == other } const TRUE: Self = -1; @@ -83,7 +85,9 @@ impl_element! { isize } /// /// Masks represent boolean inclusion/exclusion on a per-lane basis. /// -/// The layout of this type is unspecified. +/// The layout of this type is unspecified, and may change between platforms +/// and/or Rust versions, and code should not assume that it is equivalent to +/// `[T; LANES]`. #[repr(transparent)] pub struct Mask<T, const LANES: usize>(mask_impl::Mask<T, LANES>) where @@ -102,6 +106,7 @@ where T: MaskElement, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn clone(&self) -> Self { *self } @@ -113,11 +118,13 @@ where LaneCount<LANES>: SupportedLaneCount, { /// Construct a mask by setting all lanes to the given value. + #[inline] pub fn splat(value: bool) -> Self { Self(mask_impl::Mask::splat(value)) } /// Converts an array of bools to a SIMD mask. + #[inline] pub fn from_array(array: [bool; LANES]) -> Self { // SAFETY: Rust's bool has a layout of 1 byte (u8) with a value of // true: 0b_0000_0001 @@ -134,6 +141,7 @@ where } /// Converts a SIMD mask to an array of bools. + #[inline] pub fn to_array(self) -> [bool; LANES] { // This follows mostly the same logic as from_array. // SAFETY: Rust's bool has a layout of 1 byte (u8) with a value of @@ -261,6 +269,7 @@ where T: MaskElement, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn from(array: [bool; LANES]) -> Self { Self::from_array(array) } @@ -271,6 +280,7 @@ where T: MaskElement, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn from(vector: Mask<T, LANES>) -> Self { vector.to_array() } @@ -520,60 +530,6 @@ where } } -/// A mask for SIMD vectors with eight elements of 8 bits. -pub type mask8x8 = Mask<i8, 8>; - -/// A mask for SIMD vectors with 16 elements of 8 bits. -pub type mask8x16 = Mask<i8, 16>; - -/// A mask for SIMD vectors with 32 elements of 8 bits. -pub type mask8x32 = Mask<i8, 32>; - -/// A mask for SIMD vectors with 64 elements of 8 bits. -pub type mask8x64 = Mask<i8, 64>; - -/// A mask for SIMD vectors with four elements of 16 bits. -pub type mask16x4 = Mask<i16, 4>; - -/// A mask for SIMD vectors with eight elements of 16 bits. -pub type mask16x8 = Mask<i16, 8>; - -/// A mask for SIMD vectors with 16 elements of 16 bits. -pub type mask16x16 = Mask<i16, 16>; - -/// A mask for SIMD vectors with 32 elements of 16 bits. -pub type mask16x32 = Mask<i16, 32>; - -/// A mask for SIMD vectors with two elements of 32 bits. -pub type mask32x2 = Mask<i32, 2>; - -/// A mask for SIMD vectors with four elements of 32 bits. -pub type mask32x4 = Mask<i32, 4>; - -/// A mask for SIMD vectors with eight elements of 32 bits. -pub type mask32x8 = Mask<i32, 8>; - -/// A mask for SIMD vectors with 16 elements of 32 bits. -pub type mask32x16 = Mask<i32, 16>; - -/// A mask for SIMD vectors with two elements of 64 bits. -pub type mask64x2 = Mask<i64, 2>; - -/// A mask for SIMD vectors with four elements of 64 bits. -pub type mask64x4 = Mask<i64, 4>; - -/// A mask for SIMD vectors with eight elements of 64 bits. -pub type mask64x8 = Mask<i64, 8>; - -/// A mask for SIMD vectors with two elements of pointer width. -pub type masksizex2 = Mask<isize, 2>; - -/// A mask for SIMD vectors with four elements of pointer width. -pub type masksizex4 = Mask<isize, 4>; - -/// A mask for SIMD vectors with eight elements of pointer width. -pub type masksizex8 = Mask<isize, 8>; - macro_rules! impl_from { { $from:ty => $($to:ty),* } => { $( @@ -581,6 +537,7 @@ macro_rules! impl_from { where LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn from(value: Mask<$from, LANES>) -> Self { value.cast() } diff --git a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs index 365ecc0a325..20465ba9b07 100644 --- a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs +++ b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs @@ -26,6 +26,7 @@ where T: MaskElement, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn clone(&self) -> Self { *self } @@ -36,6 +37,7 @@ where T: MaskElement, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn eq(&self, other: &Self) -> bool { self.0.as_ref() == other.0.as_ref() } @@ -46,6 +48,7 @@ where T: MaskElement, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { self.0.as_ref().partial_cmp(other.0.as_ref()) } @@ -63,6 +66,7 @@ where T: MaskElement, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.0.as_ref().cmp(other.0.as_ref()) } diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs index adf0fcbeae2..1d13c45b8e7 100644 --- a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs @@ -37,6 +37,7 @@ where T: MaskElement + PartialEq, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) } @@ -47,6 +48,7 @@ where T: MaskElement + PartialOrd, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { self.0.partial_cmp(&other.0) } @@ -64,6 +66,7 @@ where T: MaskElement + Ord, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.0.cmp(&other.0) } @@ -257,11 +260,12 @@ where } } -impl<T, const LANES: usize> core::convert::From<Mask<T, LANES>> for Simd<T, LANES> +impl<T, const LANES: usize> From<Mask<T, LANES>> for Simd<T, LANES> where T: MaskElement, LaneCount<LANES>: SupportedLaneCount, { + #[inline] fn from(value: Mask<T, LANES>) -> Self { value.0 } diff --git a/library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs index 2235f016c71..fc7d6b781f2 100644 --- a/library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs +++ b/library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs @@ -48,10 +48,12 @@ macro_rules! impl_integer_intrinsic { impl<T: MaskElement> ToBitMask for Mask<T, $lanes> { type BitMask = $int; + #[inline] fn to_bitmask(self) -> $int { self.0.to_bitmask_integer() } + #[inline] fn from_bitmask(bitmask: $int) -> Self { Self(mask_impl::Mask::from_bitmask_integer(bitmask)) } @@ -83,10 +85,12 @@ where { const BYTES: usize = bitmask_len(LANES); + #[inline] fn to_bitmask_array(self) -> [u8; Self::BYTES] { self.0.to_bitmask_array() } + #[inline] fn from_bitmask_array(bitmask: [u8; Self::BYTES]) -> Self { Mask(mask_impl::Mask::from_bitmask_array(bitmask)) } diff --git a/library/portable-simd/crates/core_simd/src/mod.rs b/library/portable-simd/crates/core_simd/src/mod.rs index b472aa3abe2..35c659b7a42 100644 --- a/library/portable-simd/crates/core_simd/src/mod.rs +++ b/library/portable-simd/crates/core_simd/src/mod.rs @@ -6,6 +6,8 @@ pub(crate) mod intrinsics; #[cfg(feature = "generic_const_exprs")] mod to_bytes; +mod alias; +mod cast; mod elements; mod eq; mod fmt; @@ -15,6 +17,7 @@ mod masks; mod ops; mod ord; mod select; +mod swizzle_dyn; mod vector; mod vendor; @@ -22,11 +25,14 @@ mod vendor; pub mod simd { pub(crate) use crate::core_simd::intrinsics; + pub use crate::core_simd::alias::*; + pub use crate::core_simd::cast::*; pub use crate::core_simd::elements::*; pub use crate::core_simd::eq::*; pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount}; pub use crate::core_simd::masks::*; pub use crate::core_simd::ord::*; pub use crate::core_simd::swizzle::*; + pub use crate::core_simd::swizzle_dyn::*; pub use crate::core_simd::vector::*; } diff --git a/library/portable-simd/crates/core_simd/src/ops/deref.rs b/library/portable-simd/crates/core_simd/src/ops/deref.rs index 9883a74c92d..302bf148bd3 100644 --- a/library/portable-simd/crates/core_simd/src/ops/deref.rs +++ b/library/portable-simd/crates/core_simd/src/ops/deref.rs @@ -71,7 +71,7 @@ macro_rules! deref_ops { #[inline] #[must_use = "operator returns a new vector without mutating the inputs"] - fn $call(self, rhs: &$simd) -> Self::Output { + fn $call(self, rhs: &'rhs $simd) -> Self::Output { (*self).$call(*rhs) } } diff --git a/library/portable-simd/crates/core_simd/src/ord.rs b/library/portable-simd/crates/core_simd/src/ord.rs index 9a87bc2e344..1ae9cd061fb 100644 --- a/library/portable-simd/crates/core_simd/src/ord.rs +++ b/library/portable-simd/crates/core_simd/src/ord.rs @@ -1,4 +1,6 @@ -use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SupportedLaneCount}; +use crate::simd::{ + intrinsics, LaneCount, Mask, Simd, SimdConstPtr, SimdMutPtr, SimdPartialEq, SupportedLaneCount, +}; /// Parallel `PartialOrd`. pub trait SimdPartialOrd: SimdPartialEq { @@ -211,3 +213,101 @@ macro_rules! impl_mask { } impl_mask! { i8, i16, i32, i64, isize } + +impl<T, const LANES: usize> SimdPartialOrd for Simd<*const T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, +{ + #[inline] + fn simd_lt(self, other: Self) -> Self::Mask { + self.addr().simd_lt(other.addr()) + } + + #[inline] + fn simd_le(self, other: Self) -> Self::Mask { + self.addr().simd_le(other.addr()) + } + + #[inline] + fn simd_gt(self, other: Self) -> Self::Mask { + self.addr().simd_gt(other.addr()) + } + + #[inline] + fn simd_ge(self, other: Self) -> Self::Mask { + self.addr().simd_ge(other.addr()) + } +} + +impl<T, const LANES: usize> SimdOrd for Simd<*const T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, +{ + #[inline] + fn simd_max(self, other: Self) -> Self { + self.simd_lt(other).select(other, self) + } + + #[inline] + fn simd_min(self, other: Self) -> Self { + self.simd_gt(other).select(other, self) + } + + #[inline] + fn simd_clamp(self, min: Self, max: Self) -> Self { + assert!( + min.simd_le(max).all(), + "each lane in `min` must be less than or equal to the corresponding lane in `max`", + ); + self.simd_max(min).simd_min(max) + } +} + +impl<T, const LANES: usize> SimdPartialOrd for Simd<*mut T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, +{ + #[inline] + fn simd_lt(self, other: Self) -> Self::Mask { + self.addr().simd_lt(other.addr()) + } + + #[inline] + fn simd_le(self, other: Self) -> Self::Mask { + self.addr().simd_le(other.addr()) + } + + #[inline] + fn simd_gt(self, other: Self) -> Self::Mask { + self.addr().simd_gt(other.addr()) + } + + #[inline] + fn simd_ge(self, other: Self) -> Self::Mask { + self.addr().simd_ge(other.addr()) + } +} + +impl<T, const LANES: usize> SimdOrd for Simd<*mut T, LANES> +where + LaneCount<LANES>: SupportedLaneCount, +{ + #[inline] + fn simd_max(self, other: Self) -> Self { + self.simd_lt(other).select(other, self) + } + + #[inline] + fn simd_min(self, other: Self) -> Self { + self.simd_gt(other).select(other, self) + } + + #[inline] + fn simd_clamp(self, min: Self, max: Self) -> Self { + assert!( + min.simd_le(max).all(), + "each lane in `min` must be less than or equal to the corresponding lane in `max`", + ); + self.simd_max(min).simd_min(max) + } +} diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs index 22999d24950..68f20516cf5 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle.rs @@ -265,16 +265,13 @@ where /// Interleave two vectors. /// - /// Produces two vectors with lanes taken alternately from `self` and `other`. + /// The resulting vectors contain lanes taken alternatively from `self` and `other`, first + /// filling the first result, and then the second. /// - /// The first result contains the first `LANES / 2` lanes from `self` and `other`, - /// alternating, starting with the first lane of `self`. - /// - /// The second result contains the last `LANES / 2` lanes from `self` and `other`, - /// alternating, starting with the lane `LANES / 2` from the start of `self`. + /// The reverse of this operation is [`Simd::deinterleave`]. /// /// ``` - /// #![feature(portable_simd)] + /// # #![feature(portable_simd)] /// # use core::simd::Simd; /// let a = Simd::from_array([0, 1, 2, 3]); /// let b = Simd::from_array([4, 5, 6, 7]); @@ -285,29 +282,17 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn interleave(self, other: Self) -> (Self, Self) { - const fn lo<const LANES: usize>() -> [Which; LANES] { - let mut idx = [Which::First(0); LANES]; - let mut i = 0; - while i < LANES { - let offset = i / 2; - idx[i] = if i % 2 == 0 { - Which::First(offset) - } else { - Which::Second(offset) - }; - i += 1; - } - idx - } - const fn hi<const LANES: usize>() -> [Which; LANES] { + const fn interleave<const LANES: usize>(high: bool) -> [Which; LANES] { let mut idx = [Which::First(0); LANES]; let mut i = 0; while i < LANES { - let offset = (LANES + i) / 2; - idx[i] = if i % 2 == 0 { - Which::First(offset) + // Treat the source as a concatenated vector + let dst_index = if high { i + LANES } else { i }; + let src_index = dst_index / 2 + (dst_index % 2) * LANES; + idx[i] = if src_index < LANES { + Which::First(src_index) } else { - Which::Second(offset) + Which::Second(src_index % LANES) }; i += 1; } @@ -318,11 +303,11 @@ where struct Hi; impl<const LANES: usize> Swizzle2<LANES, LANES> for Lo { - const INDEX: [Which; LANES] = lo::<LANES>(); + const INDEX: [Which; LANES] = interleave::<LANES>(false); } impl<const LANES: usize> Swizzle2<LANES, LANES> for Hi { - const INDEX: [Which; LANES] = hi::<LANES>(); + const INDEX: [Which; LANES] = interleave::<LANES>(true); } (Lo::swizzle2(self, other), Hi::swizzle2(self, other)) @@ -336,8 +321,10 @@ where /// The second result takes every other lane of `self` and then `other`, starting with /// the second lane. /// + /// The reverse of this operation is [`Simd::interleave`]. + /// /// ``` - /// #![feature(portable_simd)] + /// # #![feature(portable_simd)] /// # use core::simd::Simd; /// let a = Simd::from_array([0, 4, 1, 5]); /// let b = Simd::from_array([2, 6, 3, 7]); @@ -348,22 +335,17 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn deinterleave(self, other: Self) -> (Self, Self) { - const fn even<const LANES: usize>() -> [Which; LANES] { - let mut idx = [Which::First(0); LANES]; - let mut i = 0; - while i < LANES / 2 { - idx[i] = Which::First(2 * i); - idx[i + LANES / 2] = Which::Second(2 * i); - i += 1; - } - idx - } - const fn odd<const LANES: usize>() -> [Which; LANES] { + const fn deinterleave<const LANES: usize>(second: bool) -> [Which; LANES] { let mut idx = [Which::First(0); LANES]; let mut i = 0; - while i < LANES / 2 { - idx[i] = Which::First(2 * i + 1); - idx[i + LANES / 2] = Which::Second(2 * i + 1); + while i < LANES { + // Treat the source as a concatenated vector + let src_index = i * 2 + second as usize; + idx[i] = if src_index < LANES { + Which::First(src_index) + } else { + Which::Second(src_index % LANES) + }; i += 1; } idx @@ -373,11 +355,11 @@ where struct Odd; impl<const LANES: usize> Swizzle2<LANES, LANES> for Even { - const INDEX: [Which; LANES] = even::<LANES>(); + const INDEX: [Which; LANES] = deinterleave::<LANES>(false); } impl<const LANES: usize> Swizzle2<LANES, LANES> for Odd { - const INDEX: [Which; LANES] = odd::<LANES>(); + const INDEX: [Which; LANES] = deinterleave::<LANES>(true); } (Even::swizzle2(self, other), Odd::swizzle2(self, other)) diff --git a/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs b/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs new file mode 100644 index 00000000000..6065d645937 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs @@ -0,0 +1,157 @@ +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use core::mem; + +impl<const N: usize> Simd<u8, N> +where + LaneCount<N>: SupportedLaneCount, +{ + /// Swizzle a vector of bytes according to the index vector. + /// Indices within range select the appropriate byte. + /// Indices "out of bounds" instead select 0. + /// + /// Note that the current implementation is selected during build-time + /// of the standard library, so `cargo build -Zbuild-std` may be necessary + /// to unlock better performance, especially for larger vectors. + /// A planned compiler improvement will enable using `#[target_feature]` instead. + #[inline] + pub fn swizzle_dyn(self, idxs: Simd<u8, N>) -> Self { + #![allow(unused_imports, unused_unsafe)] + #[cfg(target_arch = "aarch64")] + use core::arch::aarch64::{uint8x8_t, vqtbl1q_u8, vtbl1_u8}; + #[cfg(all(target_arch = "arm", target_feature = "v7", target_feature = "neon"))] + use core::arch::arm::{uint8x8_t, vtbl1_u8}; + #[cfg(target_arch = "wasm32")] + use core::arch::wasm32 as wasm; + #[cfg(target_arch = "x86")] + use core::arch::x86; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64 as x86; + // SAFETY: Intrinsics covered by cfg + unsafe { + match N { + #[cfg(target_feature = "neon")] + 8 => transize(vtbl1_u8, self, idxs), + #[cfg(target_feature = "ssse3")] + 16 => transize(x86::_mm_shuffle_epi8, self, idxs), + #[cfg(target_feature = "simd128")] + 16 => transize(wasm::i8x16_swizzle, self, idxs), + #[cfg(all(target_arch = "aarch64", target_feature = "neon"))] + 16 => transize(vqtbl1q_u8, self, idxs), + #[cfg(all(target_feature = "avx2", not(target_feature = "avx512vbmi")))] + 32 => transize_raw(avx2_pshufb, self, idxs), + #[cfg(target_feature = "avx512vl,avx512vbmi")] + 32 => transize(x86::_mm256_permutexvar_epi8, self, idxs), + // Notable absence: avx512bw shuffle + // If avx512bw is available, odds of avx512vbmi are good + // FIXME: initial AVX512VBMI variant didn't actually pass muster + // #[cfg(target_feature = "avx512vbmi")] + // 64 => transize(x86::_mm512_permutexvar_epi8, self, idxs), + _ => { + let mut array = [0; N]; + for (i, k) in idxs.to_array().into_iter().enumerate() { + if (k as usize) < N { + array[i] = self[k as usize]; + }; + } + array.into() + } + } + } + } +} + +/// "vpshufb like it was meant to be" on AVX2 +/// +/// # Safety +/// This requires AVX2 to work +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx2")] +#[allow(unused)] +#[inline] +#[allow(clippy::let_and_return)] +unsafe fn avx2_pshufb(bytes: Simd<u8, 32>, idxs: Simd<u8, 32>) -> Simd<u8, 32> { + use crate::simd::SimdPartialOrd; + #[cfg(target_arch = "x86")] + use core::arch::x86; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64 as x86; + use x86::_mm256_permute2x128_si256 as avx2_cross_shuffle; + use x86::_mm256_shuffle_epi8 as avx2_half_pshufb; + let mid = Simd::splat(16u8); + let high = mid + mid; + // SAFETY: Caller promised AVX2 + unsafe { + // This is ordering sensitive, and LLVM will order these how you put them. + // Most AVX2 impls use ~5 "ports", and only 1 or 2 are capable of permutes. + // But the "compose" step will lower to ops that can also use at least 1 other port. + // So this tries to break up permutes so composition flows through "open" ports. + // Comparative benches should be done on multiple AVX2 CPUs before reordering this + + let hihi = avx2_cross_shuffle::<0x11>(bytes.into(), bytes.into()); + let hi_shuf = Simd::from(avx2_half_pshufb( + hihi, // duplicate the vector's top half + idxs.into(), // so that using only 4 bits of an index still picks bytes 16-31 + )); + // A zero-fill during the compose step gives the "all-Neon-like" OOB-is-0 semantics + let compose = idxs.simd_lt(high).select(hi_shuf, Simd::splat(0)); + let lolo = avx2_cross_shuffle::<0x00>(bytes.into(), bytes.into()); + let lo_shuf = Simd::from(avx2_half_pshufb(lolo, idxs.into())); + // Repeat, then pick indices < 16, overwriting indices 0-15 from previous compose step + let compose = idxs.simd_lt(mid).select(lo_shuf, compose); + compose + } +} + +/// This sets up a call to an architecture-specific function, and in doing so +/// it persuades rustc that everything is the correct size. Which it is. +/// This would not be needed if one could convince Rust that, by matching on N, +/// N is that value, and thus it would be valid to substitute e.g. 16. +/// +/// # Safety +/// The correctness of this function hinges on the sizes agreeing in actuality. +#[allow(dead_code)] +#[inline(always)] +unsafe fn transize<T, const N: usize>( + f: unsafe fn(T, T) -> T, + bytes: Simd<u8, N>, + idxs: Simd<u8, N>, +) -> Simd<u8, N> +where + LaneCount<N>: SupportedLaneCount, +{ + let idxs = zeroing_idxs(idxs); + // SAFETY: Same obligation to use this function as to use mem::transmute_copy. + unsafe { mem::transmute_copy(&f(mem::transmute_copy(&bytes), mem::transmute_copy(&idxs))) } +} + +/// Make indices that yield 0 for this architecture +#[inline(always)] +fn zeroing_idxs<const N: usize>(idxs: Simd<u8, N>) -> Simd<u8, N> +where + LaneCount<N>: SupportedLaneCount, +{ + // On x86, make sure the top bit is set. + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + let idxs = { + use crate::simd::SimdPartialOrd; + idxs.simd_lt(Simd::splat(N as u8)) + .select(idxs, Simd::splat(u8::MAX)) + }; + // Simply do nothing on most architectures. + idxs +} + +/// As transize but no implicit call to `zeroing_idxs`. +#[allow(dead_code)] +#[inline(always)] +unsafe fn transize_raw<T, const N: usize>( + f: unsafe fn(T, T) -> T, + bytes: Simd<u8, N>, + idxs: Simd<u8, N>, +) -> Simd<u8, N> +where + LaneCount<N>: SupportedLaneCount, +{ + // SAFETY: Same obligation to use this function as to use mem::transmute_copy. + unsafe { mem::transmute_copy(&f(mem::transmute_copy(&bytes), mem::transmute_copy(&idxs))) } +} diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs index 78f56402eba..3809cc96151 100644 --- a/library/portable-simd/crates/core_simd/src/vector.rs +++ b/library/portable-simd/crates/core_simd/src/vector.rs @@ -1,60 +1,63 @@ -mod float; -mod int; -mod uint; - -pub use float::*; -pub use int::*; -pub use uint::*; - -// Vectors of pointers are not for public use at the current time. -pub(crate) mod ptr; - use crate::simd::{ - intrinsics, LaneCount, Mask, MaskElement, SimdPartialOrd, SupportedLaneCount, Swizzle, + intrinsics, LaneCount, Mask, MaskElement, SimdCast, SimdCastPtr, SimdConstPtr, SimdMutPtr, + SimdPartialOrd, SupportedLaneCount, Swizzle, }; +use core::convert::{TryFrom, TryInto}; -/// A SIMD vector of `LANES` elements of type `T`. `Simd<T, N>` has the same shape as [`[T; N]`](array), but operates like `T`. +/// A SIMD vector with the shape of `[T; N]` but the operations of `T`. /// -/// Two vectors of the same type and length will, by convention, support the operators (+, *, etc.) that `T` does. -/// These take the lanes at each index on the left-hand side and right-hand side, perform the operation, -/// and return the result in the same lane in a vector of equal size. For a given operator, this is equivalent to zipping -/// the two arrays together and mapping the operator over each lane. +/// `Simd<T, N>` supports the operators (+, *, etc.) that `T` does in "elementwise" fashion. +/// These take the element at each index from the left-hand side and right-hand side, +/// perform the operation, then return the result in the same index in a vector of equal size. +/// However, `Simd` differs from normal iteration and normal arrays: +/// - `Simd<T, N>` executes `N` operations in a single step with no `break`s +/// - `Simd<T, N>` can have an alignment greater than `T`, for better mechanical sympathy +/// +/// By always imposing these constraints on `Simd`, it is easier to compile elementwise operations +/// into machine instructions that can themselves be executed in parallel. /// /// ```rust -/// # #![feature(array_zip, portable_simd)] +/// # #![feature(portable_simd)] /// # use core::simd::{Simd}; -/// let a0: [i32; 4] = [-2, 0, 2, 4]; -/// let a1 = [10, 9, 8, 7]; -/// let zm_add = a0.zip(a1).map(|(lhs, rhs)| lhs + rhs); -/// let zm_mul = a0.zip(a1).map(|(lhs, rhs)| lhs * rhs); +/// # use core::array; +/// let a: [i32; 4] = [-2, 0, 2, 4]; +/// let b = [10, 9, 8, 7]; +/// let sum = array::from_fn(|i| a[i] + b[i]); +/// let prod = array::from_fn(|i| a[i] * b[i]); /// -/// // `Simd<T, N>` implements `From<[T; N]> -/// let (v0, v1) = (Simd::from(a0), Simd::from(a1)); +/// // `Simd<T, N>` implements `From<[T; N]>` +/// let (v, w) = (Simd::from(a), Simd::from(b)); /// // Which means arrays implement `Into<Simd<T, N>>`. -/// assert_eq!(v0 + v1, zm_add.into()); -/// assert_eq!(v0 * v1, zm_mul.into()); +/// assert_eq!(v + w, sum.into()); +/// assert_eq!(v * w, prod.into()); /// ``` /// -/// `Simd` with integers has the quirk that these operations are also inherently wrapping, as if `T` was [`Wrapping<T>`]. +/// +/// `Simd` with integer elements treats operators as wrapping, as if `T` was [`Wrapping<T>`]. /// Thus, `Simd` does not implement `wrapping_add`, because that is the default behavior. /// This means there is no warning on overflows, even in "debug" builds. /// For most applications where `Simd` is appropriate, it is "not a bug" to wrap, /// and even "debug builds" are unlikely to tolerate the loss of performance. /// You may want to consider using explicitly checked arithmetic if such is required. -/// Division by zero still causes a panic, so you may want to consider using floating point numbers if that is unacceptable. +/// Division by zero on integers still causes a panic, so +/// you may want to consider using `f32` or `f64` if that is unacceptable. /// /// [`Wrapping<T>`]: core::num::Wrapping /// /// # Layout -/// `Simd<T, N>` has a layout similar to `[T; N]` (identical "shapes"), but with a greater alignment. +/// `Simd<T, N>` has a layout similar to `[T; N]` (identical "shapes"), with a greater alignment. /// `[T; N]` is aligned to `T`, but `Simd<T, N>` will have an alignment based on both `T` and `N`. -/// It is thus sound to [`transmute`] `Simd<T, N>` to `[T; N]`, and will typically optimize to zero cost, -/// but the reverse transmutation is more likely to require a copy the compiler cannot simply elide. +/// Thus it is sound to [`transmute`] `Simd<T, N>` to `[T; N]` and should optimize to "zero cost", +/// but the reverse transmutation may require a copy the compiler cannot simply elide. /// /// # ABI "Features" -/// Due to Rust's safety guarantees, `Simd<T, N>` is currently passed to and from functions via memory, not SIMD registers, -/// except as an optimization. `#[inline]` hints are recommended on functions that accept `Simd<T, N>` or return it. -/// The need for this may be corrected in the future. +/// Due to Rust's safety guarantees, `Simd<T, N>` is currently passed and returned via memory, +/// not SIMD registers, except as an optimization. Using `#[inline]` on functions that accept +/// `Simd<T, N>` or return it is recommended, at the cost of code generation time, as +/// inlining SIMD-using functions can omit a large function prolog or epilog and thus +/// improve both speed and code size. The need for this may be corrected in the future. +/// +/// Using `#[inline(always)]` still requires additional care. /// /// # Safe SIMD with Unsafe Rust /// @@ -65,18 +68,22 @@ use crate::simd::{ /// Thus, when using `unsafe` Rust to read and write `Simd<T, N>` through [raw pointers], it is a good idea to first try with /// [`read_unaligned`] and [`write_unaligned`]. This is because: /// - [`read`] and [`write`] require full alignment (in this case, `Simd<T, N>`'s alignment) -/// - the likely source for reading or destination for writing `Simd<T, N>` is [`[T]`](slice) and similar types, aligned to `T` -/// - combining these actions would violate the `unsafe` contract and explode the program into a puff of **undefined behavior** -/// - the compiler can implicitly adjust layouts to make unaligned reads or writes fully aligned if it sees the optimization -/// - most contemporary processors suffer no performance penalty for "unaligned" reads and writes that are aligned at runtime +/// - `Simd<T, N>` is often read from or written to [`[T]`](slice) and other types aligned to `T` +/// - combining these actions violates the `unsafe` contract and explodes the program into +/// a puff of **undefined behavior** +/// - the compiler can implicitly adjust layouts to make unaligned reads or writes fully aligned +/// if it sees the optimization +/// - most contemporary processors with "aligned" and "unaligned" read and write instructions +/// exhibit no performance difference if the "unaligned" variant is aligned at runtime /// -/// By imposing less obligations, unaligned functions are less likely to make the program unsound, +/// Less obligations mean unaligned reads and writes are less likely to make the program unsound, /// and may be just as fast as stricter alternatives. -/// When trying to guarantee alignment, [`[T]::as_simd`][as_simd] is an option for converting `[T]` to `[Simd<T, N>]`, -/// and allows soundly operating on an aligned SIMD body, but it may cost more time when handling the scalar head and tail. -/// If these are not sufficient, then it is most ideal to design data structures to be already aligned -/// to the `Simd<T, N>` you wish to use before using `unsafe` Rust to read or write. -/// More conventional ways to compensate for these facts, like materializing `Simd` to or from an array first, +/// When trying to guarantee alignment, [`[T]::as_simd`][as_simd] is an option for +/// converting `[T]` to `[Simd<T, N>]`, and allows soundly operating on an aligned SIMD body, +/// but it may cost more time when handling the scalar head and tail. +/// If these are not enough, it is most ideal to design data structures to be already aligned +/// to `mem::align_of::<Simd<T, N>>()` before using `unsafe` Rust to read or write. +/// Other ways to compensate for these facts, like materializing `Simd` to or from an array first, /// are handled by safe methods like [`Simd::from_array`] and [`Simd::from_slice`]. /// /// [`transmute`]: core::mem::transmute @@ -86,21 +93,26 @@ use crate::simd::{ /// [`read`]: pointer::read /// [`write`]: pointer::write /// [as_simd]: slice::as_simd +// +// NOTE: Accessing the inner array directly in any way (e.g. by using the `.0` field syntax) or +// directly constructing an instance of the type (i.e. `let vector = Simd(array)`) should be +// avoided, as it will likely become illegal on `#[repr(simd)]` structs in the future. It also +// causes rustc to emit illegal LLVM IR in some cases. #[repr(simd)] -pub struct Simd<T, const LANES: usize>([T; LANES]) +pub struct Simd<T, const N: usize>([T; N]) where - T: SimdElement, - LaneCount<LANES>: SupportedLaneCount; + LaneCount<N>: SupportedLaneCount, + T: SimdElement; -impl<T, const LANES: usize> Simd<T, LANES> +impl<T, const N: usize> Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement, { - /// Number of lanes in this vector. - pub const LANES: usize = LANES; + /// Number of elements in this vector. + pub const LANES: usize = N; - /// Returns the number of lanes in this SIMD vector. + /// Returns the number of elements in this SIMD vector. /// /// # Examples /// @@ -111,10 +123,10 @@ where /// assert_eq!(v.lanes(), 4); /// ``` pub const fn lanes(&self) -> usize { - LANES + Self::LANES } - /// Constructs a new SIMD vector with all lanes set to the given value. + /// Constructs a new SIMD vector with all elements set to the given value. /// /// # Examples /// @@ -125,11 +137,11 @@ where /// assert_eq!(v.as_array(), &[8, 8, 8, 8]); /// ``` pub fn splat(value: T) -> Self { - // This is preferred over `[value; LANES]`, since it's explicitly a splat: + // This is preferred over `[value; N]`, since it's explicitly a splat: // https://github.com/rust-lang/rust/issues/97804 struct Splat; - impl<const LANES: usize> Swizzle<1, LANES> for Splat { - const INDEX: [usize; LANES] = [0; LANES]; + impl<const N: usize> Swizzle<1, N> for Splat { + const INDEX: [usize; N] = [0; N]; } Splat::swizzle(Simd::<T, 1>::from([value])) } @@ -144,32 +156,100 @@ where /// let v: u64x4 = Simd::from_array([0, 1, 2, 3]); /// assert_eq!(v.as_array(), &[0, 1, 2, 3]); /// ``` - pub const fn as_array(&self) -> &[T; LANES] { - &self.0 + pub const fn as_array(&self) -> &[T; N] { + // SAFETY: `Simd<T, N>` is just an overaligned `[T; N]` with + // potential padding at the end, so pointer casting to a + // `&[T; N]` is safe. + // + // NOTE: This deliberately doesn't just use `&self.0`, see the comment + // on the struct definition for details. + unsafe { &*(self as *const Self as *const [T; N]) } } /// Returns a mutable array reference containing the entire SIMD vector. - pub fn as_mut_array(&mut self) -> &mut [T; LANES] { - &mut self.0 + pub fn as_mut_array(&mut self) -> &mut [T; N] { + // SAFETY: `Simd<T, N>` is just an overaligned `[T; N]` with + // potential padding at the end, so pointer casting to a + // `&mut [T; N]` is safe. + // + // NOTE: This deliberately doesn't just use `&mut self.0`, see the comment + // on the struct definition for details. + unsafe { &mut *(self as *mut Self as *mut [T; N]) } + } + + /// Load a vector from an array of `T`. + /// + /// This function is necessary since `repr(simd)` has padding for non-power-of-2 vectors (at the time of writing). + /// With padding, `read_unaligned` will read past the end of an array of N elements. + /// + /// # Safety + /// Reading `ptr` must be safe, as if by `<*const [T; N]>::read_unaligned`. + const unsafe fn load(ptr: *const [T; N]) -> Self { + // There are potentially simpler ways to write this function, but this should result in + // LLVM `load <N x T>` + + let mut tmp = core::mem::MaybeUninit::<Self>::uninit(); + // SAFETY: `Simd<T, N>` always contains `N` elements of type `T`. It may have padding + // which does not need to be initialized. The safety of reading `ptr` is ensured by the + // caller. + unsafe { + core::ptr::copy_nonoverlapping(ptr, tmp.as_mut_ptr().cast(), 1); + tmp.assume_init() + } + } + + /// Store a vector to an array of `T`. + /// + /// See `load` as to why this function is necessary. + /// + /// # Safety + /// Writing to `ptr` must be safe, as if by `<*mut [T; N]>::write_unaligned`. + const unsafe fn store(self, ptr: *mut [T; N]) { + // There are potentially simpler ways to write this function, but this should result in + // LLVM `store <N x T>` + + // Creating a temporary helps LLVM turn the memcpy into a store. + let tmp = self; + // SAFETY: `Simd<T, N>` always contains `N` elements of type `T`. The safety of writing + // `ptr` is ensured by the caller. + unsafe { core::ptr::copy_nonoverlapping(tmp.as_array(), ptr, 1) } } /// Converts an array to a SIMD vector. - pub const fn from_array(array: [T; LANES]) -> Self { - Self(array) + pub const fn from_array(array: [T; N]) -> Self { + // SAFETY: `&array` is safe to read. + // + // FIXME: We currently use a pointer load instead of `transmute_copy` because `repr(simd)` + // results in padding for non-power-of-2 vectors (so vectors are larger than arrays). + // + // NOTE: This deliberately doesn't just use `Self(array)`, see the comment + // on the struct definition for details. + unsafe { Self::load(&array) } } /// Converts a SIMD vector to an array. - pub const fn to_array(self) -> [T; LANES] { - self.0 + pub const fn to_array(self) -> [T; N] { + let mut tmp = core::mem::MaybeUninit::uninit(); + // SAFETY: writing to `tmp` is safe and initializes it. + // + // FIXME: We currently use a pointer store instead of `transmute_copy` because `repr(simd)` + // results in padding for non-power-of-2 vectors (so vectors are larger than arrays). + // + // NOTE: This deliberately doesn't just use `self.0`, see the comment + // on the struct definition for details. + unsafe { + self.store(tmp.as_mut_ptr()); + tmp.assume_init() + } } - /// Converts a slice to a SIMD vector containing `slice[..LANES]`. + /// Converts a slice to a SIMD vector containing `slice[..N]`. /// /// # Panics /// - /// Panics if the slice's length is less than the vector's `Simd::LANES`. + /// Panics if the slice's length is less than the vector's `Simd::N`. /// - /// # Examples + /// # Example /// /// ``` /// # #![feature(portable_simd)] @@ -180,22 +260,49 @@ where /// ``` #[must_use] pub const fn from_slice(slice: &[T]) -> Self { - assert!(slice.len() >= LANES, "slice length must be at least the number of lanes"); - let mut array = [slice[0]; LANES]; - let mut i = 0; - while i < LANES { - array[i] = slice[i]; - i += 1; - } - Self(array) + assert!( + slice.len() >= Self::LANES, + "slice length must be at least the number of elements" + ); + // SAFETY: We just checked that the slice contains + // at least `N` elements. + unsafe { Self::load(slice.as_ptr().cast()) } + } + + /// Writes a SIMD vector to the first `N` elements of a slice. + /// + /// # Panics + /// + /// Panics if the slice's length is less than the vector's `Simd::N`. + /// + /// # Example + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::u32x4; + /// let mut dest = vec![0; 6]; + /// let v = u32x4::from_array([1, 2, 3, 4]); + /// v.copy_to_slice(&mut dest); + /// assert_eq!(&dest, &[1, 2, 3, 4, 0, 0]); + /// ``` + pub fn copy_to_slice(self, slice: &mut [T]) { + assert!( + slice.len() >= Self::LANES, + "slice length must be at least the number of elements" + ); + // SAFETY: We just checked that the slice contains + // at least `N` elements. + unsafe { self.store(slice.as_mut_ptr().cast()) } } - /// Performs lanewise conversion of a SIMD vector's elements to another SIMD-valid type. + /// Performs elementwise conversion of a SIMD vector's elements to another SIMD-valid type. /// - /// This follows the semantics of Rust's `as` conversion for casting - /// integers to unsigned integers (interpreting as the other type, so `-1` to `MAX`), - /// and from floats to integers (truncating, or saturating at the limits) for each lane, - /// or vice versa. + /// This follows the semantics of Rust's `as` conversion for casting integers between + /// signed and unsigned (interpreting integers as 2s complement, so `-1` to `U::MAX` and + /// `1 << (U::BITS -1)` becoming `I::MIN` ), and from floats to integers (truncating, + /// or saturating at the limits) for each element. /// /// # Examples /// ``` @@ -215,11 +322,26 @@ where /// ``` #[must_use] #[inline] - pub fn cast<U: SimdElement>(self) -> Simd<U, LANES> { - // Safety: The input argument is a vector of a valid SIMD element type. + pub fn cast<U: SimdCast>(self) -> Simd<U, N> + where + T: SimdCast, + { + // Safety: supported types are guaranteed by SimdCast unsafe { intrinsics::simd_as(self) } } + /// Casts a vector of pointers to another pointer type. + #[must_use] + #[inline] + pub fn cast_ptr<U>(self) -> Simd<U, N> + where + T: SimdCastPtr<U>, + U: SimdElement, + { + // Safety: supported types are guaranteed by SimdCastPtr + unsafe { intrinsics::simd_cast_ptr(self) } + } + /// Rounds toward zero and converts to the same-width integer type, assuming that /// the value is finite and fits in that type. /// @@ -235,90 +357,90 @@ where /// /// [cast]: Simd::cast #[inline] - pub unsafe fn to_int_unchecked<I>(self) -> Simd<I, LANES> + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn to_int_unchecked<I>(self) -> Simd<I, N> where - T: core::convert::FloatToInt<I>, - I: SimdElement, + T: core::convert::FloatToInt<I> + SimdCast, + I: SimdCast, { - // Safety: `self` is a vector, and `FloatToInt` ensures the type can be casted to - // an integer. + // Safety: supported types are guaranteed by SimdCast, the caller is responsible for the extra invariants unsafe { intrinsics::simd_cast(self) } } /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. - /// If an index is out-of-bounds, the lane is instead selected from the `or` vector. + /// If an index is out-of-bounds, the element is instead selected from the `or` vector. /// /// # Examples /// ``` /// # #![feature(portable_simd)] /// # use core::simd::Simd; /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; - /// let idxs = Simd::from_array([9, 3, 0, 5]); + /// let idxs = Simd::from_array([9, 3, 0, 5]); // Note the index that is out-of-bounds /// let alt = Simd::from_array([-5, -4, -3, -2]); /// - /// let result = Simd::gather_or(&vec, idxs, alt); // Note the lane that is out-of-bounds. + /// let result = Simd::gather_or(&vec, idxs, alt); /// assert_eq!(result, Simd::from_array([-5, 13, 10, 15])); /// ``` #[must_use] #[inline] - pub fn gather_or(slice: &[T], idxs: Simd<usize, LANES>, or: Self) -> Self { + pub fn gather_or(slice: &[T], idxs: Simd<usize, N>, or: Self) -> Self { Self::gather_select(slice, Mask::splat(true), idxs, or) } - /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. - /// If an index is out-of-bounds, the lane is set to the default value for the type. + /// Reads from indices in `slice` to construct a SIMD vector. + /// If an index is out-of-bounds, the element is set to the default given by `T: Default`. /// /// # Examples /// ``` /// # #![feature(portable_simd)] /// # use core::simd::Simd; /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; - /// let idxs = Simd::from_array([9, 3, 0, 5]); + /// let idxs = Simd::from_array([9, 3, 0, 5]); // Note the index that is out-of-bounds /// - /// let result = Simd::gather_or_default(&vec, idxs); // Note the lane that is out-of-bounds. + /// let result = Simd::gather_or_default(&vec, idxs); /// assert_eq!(result, Simd::from_array([0, 13, 10, 15])); /// ``` #[must_use] #[inline] - pub fn gather_or_default(slice: &[T], idxs: Simd<usize, LANES>) -> Self + pub fn gather_or_default(slice: &[T], idxs: Simd<usize, N>) -> Self where T: Default, { Self::gather_or(slice, idxs, Self::splat(T::default())) } - /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. - /// The mask `enable`s all `true` lanes and disables all `false` lanes. - /// If an index is disabled or is out-of-bounds, the lane is selected from the `or` vector. + /// Reads from indices in `slice` to construct a SIMD vector. + /// The mask `enable`s all `true` indices and disables all `false` indices. + /// If an index is disabled or is out-of-bounds, the element is selected from the `or` vector. /// /// # Examples /// ``` /// # #![feature(portable_simd)] /// # use core::simd::{Simd, Mask}; /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; - /// let idxs = Simd::from_array([9, 3, 0, 5]); + /// let idxs = Simd::from_array([9, 3, 0, 5]); // Includes an out-of-bounds index /// let alt = Simd::from_array([-5, -4, -3, -2]); - /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane. + /// let enable = Mask::from_array([true, true, true, false]); // Includes a masked element /// - /// let result = Simd::gather_select(&vec, enable, idxs, alt); // Note the lane that is out-of-bounds. + /// let result = Simd::gather_select(&vec, enable, idxs, alt); /// assert_eq!(result, Simd::from_array([-5, 13, 10, -2])); /// ``` #[must_use] #[inline] pub fn gather_select( slice: &[T], - enable: Mask<isize, LANES>, - idxs: Simd<usize, LANES>, + enable: Mask<isize, N>, + idxs: Simd<usize, N>, or: Self, ) -> Self { - let enable: Mask<isize, LANES> = enable & idxs.simd_lt(Simd::splat(slice.len())); - // Safety: We have masked-off out-of-bounds lanes. + let enable: Mask<isize, N> = enable & idxs.simd_lt(Simd::splat(slice.len())); + // Safety: We have masked-off out-of-bounds indices. unsafe { Self::gather_select_unchecked(slice, enable, idxs, or) } } - /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. - /// The mask `enable`s all `true` lanes and disables all `false` lanes. - /// If an index is disabled, the lane is selected from the `or` vector. + /// Reads from indices in `slice` to construct a SIMD vector. + /// The mask `enable`s all `true` indices and disables all `false` indices. + /// If an index is disabled, the element is selected from the `or` vector. /// /// # Safety /// @@ -332,57 +454,123 @@ where /// # #[cfg(not(feature = "as_crate"))] use core::simd; /// # use simd::{Simd, SimdPartialOrd, Mask}; /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; - /// let idxs = Simd::from_array([9, 3, 0, 5]); + /// let idxs = Simd::from_array([9, 3, 0, 5]); // Includes an out-of-bounds index /// let alt = Simd::from_array([-5, -4, -3, -2]); - /// let enable = Mask::from_array([true, true, true, false]); // Note the final mask lane. + /// let enable = Mask::from_array([true, true, true, false]); // Includes a masked element /// // If this mask was used to gather, it would be unsound. Let's fix that. /// let enable = enable & idxs.simd_lt(Simd::splat(vec.len())); /// - /// // We have masked the OOB lane, so it's safe to gather now. + /// // The out-of-bounds index has been masked, so it's safe to gather now. /// let result = unsafe { Simd::gather_select_unchecked(&vec, enable, idxs, alt) }; /// assert_eq!(result, Simd::from_array([-5, 13, 10, -2])); /// ``` /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html #[must_use] #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn gather_select_unchecked( slice: &[T], - enable: Mask<isize, LANES>, - idxs: Simd<usize, LANES>, + enable: Mask<isize, N>, + idxs: Simd<usize, N>, or: Self, ) -> Self { - let base_ptr = crate::simd::ptr::SimdConstPtr::splat(slice.as_ptr()); + let base_ptr = Simd::<*const T, N>::splat(slice.as_ptr()); // Ferris forgive me, I have done pointer arithmetic here. let ptrs = base_ptr.wrapping_add(idxs); - // Safety: The ptrs have been bounds-masked to prevent memory-unsafe reads insha'allah - unsafe { intrinsics::simd_gather(or, ptrs, enable.to_int()) } + // Safety: The caller is responsible for determining the indices are okay to read + unsafe { Self::gather_select_ptr(ptrs, enable, or) } + } + + /// Read elementwise from pointers into a SIMD vector. + /// + /// # Safety + /// + /// Each read must satisfy the same conditions as [`core::ptr::read`]. + /// + /// # Example + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::{Simd, SimdConstPtr}; + /// let values = [6, 2, 4, 9]; + /// let offsets = Simd::from_array([1, 0, 0, 3]); + /// let source = Simd::splat(values.as_ptr()).wrapping_add(offsets); + /// let gathered = unsafe { Simd::gather_ptr(source) }; + /// assert_eq!(gathered, Simd::from_array([2, 6, 6, 9])); + /// ``` + #[must_use] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn gather_ptr(source: Simd<*const T, N>) -> Self + where + T: Default, + { + // TODO: add an intrinsic that doesn't use a passthru vector, and remove the T: Default bound + // Safety: The caller is responsible for upholding all invariants + unsafe { Self::gather_select_ptr(source, Mask::splat(true), Self::default()) } + } + + /// Conditionally read elementwise from pointers into a SIMD vector. + /// The mask `enable`s all `true` pointers and disables all `false` pointers. + /// If a pointer is disabled, the element is selected from the `or` vector, + /// and no read is performed. + /// + /// # Safety + /// + /// Enabled elements must satisfy the same conditions as [`core::ptr::read`]. + /// + /// # Example + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::{Mask, Simd, SimdConstPtr}; + /// let values = [6, 2, 4, 9]; + /// let enable = Mask::from_array([true, true, false, true]); + /// let offsets = Simd::from_array([1, 0, 0, 3]); + /// let source = Simd::splat(values.as_ptr()).wrapping_add(offsets); + /// let gathered = unsafe { Simd::gather_select_ptr(source, enable, Simd::splat(0)) }; + /// assert_eq!(gathered, Simd::from_array([2, 6, 0, 9])); + /// ``` + #[must_use] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn gather_select_ptr( + source: Simd<*const T, N>, + enable: Mask<isize, N>, + or: Self, + ) -> Self { + // Safety: The caller is responsible for upholding all invariants + unsafe { intrinsics::simd_gather(or, source, enable.to_int()) } } /// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`. - /// If two lanes in the scattered vector would write to the same index - /// only the last lane is guaranteed to actually be written. + /// If an index is out-of-bounds, the write is suppressed without panicking. + /// If two elements in the scattered vector would write to the same index + /// only the last element is guaranteed to actually be written. /// /// # Examples /// ``` /// # #![feature(portable_simd)] /// # use core::simd::Simd; /// let mut vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; - /// let idxs = Simd::from_array([9, 3, 0, 0]); + /// let idxs = Simd::from_array([9, 3, 0, 0]); // Note the duplicate index. /// let vals = Simd::from_array([-27, 82, -41, 124]); /// - /// vals.scatter(&mut vec, idxs); // index 0 receives two writes. + /// vals.scatter(&mut vec, idxs); // two logical writes means the last wins. /// assert_eq!(vec, vec![124, 11, 12, 82, 14, 15, 16, 17, 18]); /// ``` #[inline] - pub fn scatter(self, slice: &mut [T], idxs: Simd<usize, LANES>) { + pub fn scatter(self, slice: &mut [T], idxs: Simd<usize, N>) { self.scatter_select(slice, Mask::splat(true), idxs) } - /// Writes the values in a SIMD vector to multiple potentially discontiguous indices in `slice`. - /// The mask `enable`s all `true` lanes and disables all `false` lanes. - /// If an enabled index is out-of-bounds, the lane is not written. - /// If two enabled lanes in the scattered vector would write to the same index, - /// only the last lane is guaranteed to actually be written. + /// Writes values from a SIMD vector to multiple potentially discontiguous indices in `slice`. + /// The mask `enable`s all `true` indices and disables all `false` indices. + /// If an enabled index is out-of-bounds, the write is suppressed without panicking. + /// If two enabled elements in the scattered vector would write to the same index, + /// only the last element is guaranteed to actually be written. /// /// # Examples /// ``` @@ -391,29 +579,24 @@ where /// # #[cfg(not(feature = "as_crate"))] use core::simd; /// # use simd::{Simd, Mask}; /// let mut vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; - /// let idxs = Simd::from_array([9, 3, 0, 0]); + /// let idxs = Simd::from_array([9, 3, 0, 0]); // Includes an out-of-bounds index /// let vals = Simd::from_array([-27, 82, -41, 124]); - /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane. + /// let enable = Mask::from_array([true, true, true, false]); // Includes a masked element /// - /// vals.scatter_select(&mut vec, enable, idxs); // index 0's second write is masked, thus omitted. + /// vals.scatter_select(&mut vec, enable, idxs); // The last write is masked, thus omitted. /// assert_eq!(vec, vec![-41, 11, 12, 82, 14, 15, 16, 17, 18]); /// ``` #[inline] - pub fn scatter_select( - self, - slice: &mut [T], - enable: Mask<isize, LANES>, - idxs: Simd<usize, LANES>, - ) { - let enable: Mask<isize, LANES> = enable & idxs.simd_lt(Simd::splat(slice.len())); - // Safety: We have masked-off out-of-bounds lanes. + pub fn scatter_select(self, slice: &mut [T], enable: Mask<isize, N>, idxs: Simd<usize, N>) { + let enable: Mask<isize, N> = enable & idxs.simd_lt(Simd::splat(slice.len())); + // Safety: We have masked-off out-of-bounds indices. unsafe { self.scatter_select_unchecked(slice, enable, idxs) } } - /// Writes the values in a SIMD vector to multiple potentially discontiguous indices in `slice`. - /// The mask `enable`s all `true` lanes and disables all `false` lanes. - /// If two enabled lanes in the scattered vector would write to the same index, - /// only the last lane is guaranteed to actually be written. + /// Writes values from a SIMD vector to multiple potentially discontiguous indices in `slice`. + /// The mask `enable`s all `true` indices and disables all `false` indices. + /// If two enabled elements in the scattered vector would write to the same index, + /// only the last element is guaranteed to actually be written. /// /// # Safety /// @@ -429,22 +612,23 @@ where /// let mut vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; /// let idxs = Simd::from_array([9, 3, 0, 0]); /// let vals = Simd::from_array([-27, 82, -41, 124]); - /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane. + /// let enable = Mask::from_array([true, true, true, false]); // Masks the final index /// // If this mask was used to scatter, it would be unsound. Let's fix that. /// let enable = enable & idxs.simd_lt(Simd::splat(vec.len())); /// - /// // We have masked the OOB lane, so it's safe to scatter now. + /// // We have masked the OOB index, so it's safe to scatter now. /// unsafe { vals.scatter_select_unchecked(&mut vec, enable, idxs); } - /// // index 0's second write is masked, thus was omitted. + /// // The second write to index 0 was masked, thus omitted. /// assert_eq!(vec, vec![-41, 11, 12, 82, 14, 15, 16, 17, 18]); /// ``` /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn scatter_select_unchecked( self, slice: &mut [T], - enable: Mask<isize, LANES>, - idxs: Simd<usize, LANES>, + enable: Mask<isize, N>, + idxs: Simd<usize, N>, ) { // Safety: This block works with *mut T derived from &mut 'a [T], // which means it is delicate in Rust's borrowing model, circa 2021: @@ -458,36 +642,89 @@ where // 3. &mut [T] which will become our base ptr. unsafe { // Now Entering ☢️ *mut T Zone - let base_ptr = crate::simd::ptr::SimdMutPtr::splat(slice.as_mut_ptr()); + let base_ptr = Simd::<*mut T, N>::splat(slice.as_mut_ptr()); // Ferris forgive me, I have done pointer arithmetic here. let ptrs = base_ptr.wrapping_add(idxs); // The ptrs have been bounds-masked to prevent memory-unsafe writes insha'allah - intrinsics::simd_scatter(self, ptrs, enable.to_int()) + self.scatter_select_ptr(ptrs, enable); // Cleared ☢️ *mut T Zone } } + + /// Write pointers elementwise into a SIMD vector. + /// + /// # Safety + /// + /// Each write must satisfy the same conditions as [`core::ptr::write`]. + /// + /// # Example + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::{Simd, SimdMutPtr}; + /// let mut values = [0; 4]; + /// let offset = Simd::from_array([3, 2, 1, 0]); + /// let ptrs = Simd::splat(values.as_mut_ptr()).wrapping_add(offset); + /// unsafe { Simd::from_array([6, 3, 5, 7]).scatter_ptr(ptrs); } + /// assert_eq!(values, [7, 5, 3, 6]); + /// ``` + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn scatter_ptr(self, dest: Simd<*mut T, N>) { + // Safety: The caller is responsible for upholding all invariants + unsafe { self.scatter_select_ptr(dest, Mask::splat(true)) } + } + + /// Conditionally write pointers elementwise into a SIMD vector. + /// The mask `enable`s all `true` pointers and disables all `false` pointers. + /// If a pointer is disabled, the write to its pointee is skipped. + /// + /// # Safety + /// + /// Enabled pointers must satisfy the same conditions as [`core::ptr::write`]. + /// + /// # Example + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::{Mask, Simd, SimdMutPtr}; + /// let mut values = [0; 4]; + /// let offset = Simd::from_array([3, 2, 1, 0]); + /// let ptrs = Simd::splat(values.as_mut_ptr()).wrapping_add(offset); + /// let enable = Mask::from_array([true, true, false, false]); + /// unsafe { Simd::from_array([6, 3, 5, 7]).scatter_select_ptr(ptrs, enable); } + /// assert_eq!(values, [0, 0, 3, 6]); + /// ``` + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn scatter_select_ptr(self, dest: Simd<*mut T, N>, enable: Mask<isize, N>) { + // Safety: The caller is responsible for upholding all invariants + unsafe { intrinsics::simd_scatter(self, dest, enable.to_int()) } + } } -impl<T, const LANES: usize> Copy for Simd<T, LANES> +impl<T, const N: usize> Copy for Simd<T, N> where + LaneCount<N>: SupportedLaneCount, T: SimdElement, - LaneCount<LANES>: SupportedLaneCount, { } -impl<T, const LANES: usize> Clone for Simd<T, LANES> +impl<T, const N: usize> Clone for Simd<T, N> where + LaneCount<N>: SupportedLaneCount, T: SimdElement, - LaneCount<LANES>: SupportedLaneCount, { fn clone(&self) -> Self { *self } } -impl<T, const LANES: usize> Default for Simd<T, LANES> +impl<T, const N: usize> Default for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement + Default, { #[inline] @@ -496,20 +733,20 @@ where } } -impl<T, const LANES: usize> PartialEq for Simd<T, LANES> +impl<T, const N: usize> PartialEq for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement + PartialEq, { #[inline] fn eq(&self, other: &Self) -> bool { // Safety: All SIMD vectors are SimdPartialEq, and the comparison produces a valid mask. let mask = unsafe { - let tfvec: Simd<<T as SimdElement>::Mask, LANES> = intrinsics::simd_eq(*self, *other); + let tfvec: Simd<<T as SimdElement>::Mask, N> = intrinsics::simd_eq(*self, *other); Mask::from_int_unchecked(tfvec) }; - // Two vectors are equal if all lanes tested true for vertical equality. + // Two vectors are equal if all elements are equal when compared elementwise mask.all() } @@ -518,18 +755,18 @@ where fn ne(&self, other: &Self) -> bool { // Safety: All SIMD vectors are SimdPartialEq, and the comparison produces a valid mask. let mask = unsafe { - let tfvec: Simd<<T as SimdElement>::Mask, LANES> = intrinsics::simd_ne(*self, *other); + let tfvec: Simd<<T as SimdElement>::Mask, N> = intrinsics::simd_ne(*self, *other); Mask::from_int_unchecked(tfvec) }; - // Two vectors are non-equal if any lane tested true for vertical non-equality. + // Two vectors are non-equal if any elements are non-equal when compared elementwise mask.any() } } -impl<T, const LANES: usize> PartialOrd for Simd<T, LANES> +impl<T, const N: usize> PartialOrd for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement + PartialOrd, { #[inline] @@ -539,16 +776,16 @@ where } } -impl<T, const LANES: usize> Eq for Simd<T, LANES> +impl<T, const N: usize> Eq for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement + Eq, { } -impl<T, const LANES: usize> Ord for Simd<T, LANES> +impl<T, const N: usize> Ord for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement + Ord, { #[inline] @@ -558,9 +795,9 @@ where } } -impl<T, const LANES: usize> core::hash::Hash for Simd<T, LANES> +impl<T, const N: usize> core::hash::Hash for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement + core::hash::Hash, { #[inline] @@ -573,72 +810,96 @@ where } // array references -impl<T, const LANES: usize> AsRef<[T; LANES]> for Simd<T, LANES> +impl<T, const N: usize> AsRef<[T; N]> for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement, { #[inline] - fn as_ref(&self) -> &[T; LANES] { - &self.0 + fn as_ref(&self) -> &[T; N] { + self.as_array() } } -impl<T, const LANES: usize> AsMut<[T; LANES]> for Simd<T, LANES> +impl<T, const N: usize> AsMut<[T; N]> for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement, { #[inline] - fn as_mut(&mut self) -> &mut [T; LANES] { - &mut self.0 + fn as_mut(&mut self) -> &mut [T; N] { + self.as_mut_array() } } // slice references -impl<T, const LANES: usize> AsRef<[T]> for Simd<T, LANES> +impl<T, const N: usize> AsRef<[T]> for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement, { #[inline] fn as_ref(&self) -> &[T] { - &self.0 + self.as_array() } } -impl<T, const LANES: usize> AsMut<[T]> for Simd<T, LANES> +impl<T, const N: usize> AsMut<[T]> for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement, { #[inline] fn as_mut(&mut self) -> &mut [T] { - &mut self.0 + self.as_mut_array() } } // vector/array conversion -impl<T, const LANES: usize> From<[T; LANES]> for Simd<T, LANES> +impl<T, const N: usize> From<[T; N]> for Simd<T, N> where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement, { - fn from(array: [T; LANES]) -> Self { - Self(array) + fn from(array: [T; N]) -> Self { + Self::from_array(array) } } -impl<T, const LANES: usize> From<Simd<T, LANES>> for [T; LANES] +impl<T, const N: usize> From<Simd<T, N>> for [T; N] where - LaneCount<LANES>: SupportedLaneCount, + LaneCount<N>: SupportedLaneCount, T: SimdElement, { - fn from(vector: Simd<T, LANES>) -> Self { + fn from(vector: Simd<T, N>) -> Self { vector.to_array() } } +impl<T, const N: usize> TryFrom<&[T]> for Simd<T, N> +where + LaneCount<N>: SupportedLaneCount, + T: SimdElement, +{ + type Error = core::array::TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<Self, core::array::TryFromSliceError> { + Ok(Self::from_array(slice.try_into()?)) + } +} + +impl<T, const N: usize> TryFrom<&mut [T]> for Simd<T, N> +where + LaneCount<N>: SupportedLaneCount, + T: SimdElement, +{ + type Error = core::array::TryFromSliceError; + + fn try_from(slice: &mut [T]) -> Result<Self, core::array::TryFromSliceError> { + Ok(Self::from_array(slice.try_into()?)) + } +} + mod sealed { pub trait Sealed {} } @@ -740,3 +1001,27 @@ impl Sealed for f64 {} unsafe impl SimdElement for f64 { type Mask = i64; } + +impl<T> Sealed for *const T {} + +// Safety: (thin) const pointers are valid SIMD element types, and are supported by this API +// +// Fat pointers may be supported in the future. +unsafe impl<T> SimdElement for *const T +where + T: core::ptr::Pointee<Metadata = ()>, +{ + type Mask = isize; +} + +impl<T> Sealed for *mut T {} + +// Safety: (thin) mut pointers are valid SIMD element types, and are supported by this API +// +// Fat pointers may be supported in the future. +unsafe impl<T> SimdElement for *mut T +where + T: core::ptr::Pointee<Metadata = ()>, +{ + type Mask = isize; +} diff --git a/library/portable-simd/crates/core_simd/src/vector/float.rs b/library/portable-simd/crates/core_simd/src/vector/float.rs deleted file mode 100644 index f836c99b1e2..00000000000 --- a/library/portable-simd/crates/core_simd/src/vector/float.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![allow(non_camel_case_types)] - -use crate::simd::Simd; - -/// A 64-bit SIMD vector with two elements of type `f32`. -pub type f32x2 = Simd<f32, 2>; - -/// A 128-bit SIMD vector with four elements of type `f32`. -pub type f32x4 = Simd<f32, 4>; - -/// A 256-bit SIMD vector with eight elements of type `f32`. -pub type f32x8 = Simd<f32, 8>; - -/// A 512-bit SIMD vector with 16 elements of type `f32`. -pub type f32x16 = Simd<f32, 16>; - -/// A 128-bit SIMD vector with two elements of type `f64`. -pub type f64x2 = Simd<f64, 2>; - -/// A 256-bit SIMD vector with four elements of type `f64`. -pub type f64x4 = Simd<f64, 4>; - -/// A 512-bit SIMD vector with eight elements of type `f64`. -pub type f64x8 = Simd<f64, 8>; diff --git a/library/portable-simd/crates/core_simd/src/vector/int.rs b/library/portable-simd/crates/core_simd/src/vector/int.rs deleted file mode 100644 index 20e56c7dc64..00000000000 --- a/library/portable-simd/crates/core_simd/src/vector/int.rs +++ /dev/null @@ -1,63 +0,0 @@ -#![allow(non_camel_case_types)] - -use crate::simd::Simd; - -/// A SIMD vector with two elements of type `isize`. -pub type isizex2 = Simd<isize, 2>; - -/// A SIMD vector with four elements of type `isize`. -pub type isizex4 = Simd<isize, 4>; - -/// A SIMD vector with eight elements of type `isize`. -pub type isizex8 = Simd<isize, 8>; - -/// A 32-bit SIMD vector with two elements of type `i16`. -pub type i16x2 = Simd<i16, 2>; - -/// A 64-bit SIMD vector with four elements of type `i16`. -pub type i16x4 = Simd<i16, 4>; - -/// A 128-bit SIMD vector with eight elements of type `i16`. -pub type i16x8 = Simd<i16, 8>; - -/// A 256-bit SIMD vector with 16 elements of type `i16`. -pub type i16x16 = Simd<i16, 16>; - -/// A 512-bit SIMD vector with 32 elements of type `i16`. -pub type i16x32 = Simd<i16, 32>; - -/// A 64-bit SIMD vector with two elements of type `i32`. -pub type i32x2 = Simd<i32, 2>; - -/// A 128-bit SIMD vector with four elements of type `i32`. -pub type i32x4 = Simd<i32, 4>; - -/// A 256-bit SIMD vector with eight elements of type `i32`. -pub type i32x8 = Simd<i32, 8>; - -/// A 512-bit SIMD vector with 16 elements of type `i32`. -pub type i32x16 = Simd<i32, 16>; - -/// A 128-bit SIMD vector with two elements of type `i64`. -pub type i64x2 = Simd<i64, 2>; - -/// A 256-bit SIMD vector with four elements of type `i64`. -pub type i64x4 = Simd<i64, 4>; - -/// A 512-bit SIMD vector with eight elements of type `i64`. -pub type i64x8 = Simd<i64, 8>; - -/// A 32-bit SIMD vector with four elements of type `i8`. -pub type i8x4 = Simd<i8, 4>; - -/// A 64-bit SIMD vector with eight elements of type `i8`. -pub type i8x8 = Simd<i8, 8>; - -/// A 128-bit SIMD vector with 16 elements of type `i8`. -pub type i8x16 = Simd<i8, 16>; - -/// A 256-bit SIMD vector with 32 elements of type `i8`. -pub type i8x32 = Simd<i8, 32>; - -/// A 512-bit SIMD vector with 64 elements of type `i8`. -pub type i8x64 = Simd<i8, 64>; diff --git a/library/portable-simd/crates/core_simd/src/vector/ptr.rs b/library/portable-simd/crates/core_simd/src/vector/ptr.rs deleted file mode 100644 index fa756344db9..00000000000 --- a/library/portable-simd/crates/core_simd/src/vector/ptr.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! Private implementation details of public gather/scatter APIs. -use crate::simd::intrinsics; -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; - -/// A vector of *const T. -#[derive(Debug, Copy, Clone)] -#[repr(simd)] -pub(crate) struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]); - -impl<T, const LANES: usize> SimdConstPtr<T, LANES> -where - LaneCount<LANES>: SupportedLaneCount, - T: Sized, -{ - #[inline] - #[must_use] - pub fn splat(ptr: *const T) -> Self { - Self([ptr; LANES]) - } - - #[inline] - #[must_use] - pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self { - // Safety: this intrinsic doesn't have a precondition - unsafe { intrinsics::simd_arith_offset(self, addend) } - } -} - -/// A vector of *mut T. Be very careful around potential aliasing. -#[derive(Debug, Copy, Clone)] -#[repr(simd)] -pub(crate) struct SimdMutPtr<T, const LANES: usize>([*mut T; LANES]); - -impl<T, const LANES: usize> SimdMutPtr<T, LANES> -where - LaneCount<LANES>: SupportedLaneCount, - T: Sized, -{ - #[inline] - #[must_use] - pub fn splat(ptr: *mut T) -> Self { - Self([ptr; LANES]) - } - - #[inline] - #[must_use] - pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self { - // Safety: this intrinsic doesn't have a precondition - unsafe { intrinsics::simd_arith_offset(self, addend) } - } -} diff --git a/library/portable-simd/crates/core_simd/src/vector/uint.rs b/library/portable-simd/crates/core_simd/src/vector/uint.rs deleted file mode 100644 index b4a69c44363..00000000000 --- a/library/portable-simd/crates/core_simd/src/vector/uint.rs +++ /dev/null @@ -1,63 +0,0 @@ -#![allow(non_camel_case_types)] - -use crate::simd::Simd; - -/// A SIMD vector with two elements of type `usize`. -pub type usizex2 = Simd<usize, 2>; - -/// A SIMD vector with four elements of type `usize`. -pub type usizex4 = Simd<usize, 4>; - -/// A SIMD vector with eight elements of type `usize`. -pub type usizex8 = Simd<usize, 8>; - -/// A 32-bit SIMD vector with two elements of type `u16`. -pub type u16x2 = Simd<u16, 2>; - -/// A 64-bit SIMD vector with four elements of type `u16`. -pub type u16x4 = Simd<u16, 4>; - -/// A 128-bit SIMD vector with eight elements of type `u16`. -pub type u16x8 = Simd<u16, 8>; - -/// A 256-bit SIMD vector with 16 elements of type `u16`. -pub type u16x16 = Simd<u16, 16>; - -/// A 512-bit SIMD vector with 32 elements of type `u16`. -pub type u16x32 = Simd<u16, 32>; - -/// A 64-bit SIMD vector with two elements of type `u32`. -pub type u32x2 = Simd<u32, 2>; - -/// A 128-bit SIMD vector with four elements of type `u32`. -pub type u32x4 = Simd<u32, 4>; - -/// A 256-bit SIMD vector with eight elements of type `u32`. -pub type u32x8 = Simd<u32, 8>; - -/// A 512-bit SIMD vector with 16 elements of type `u32`. -pub type u32x16 = Simd<u32, 16>; - -/// A 128-bit SIMD vector with two elements of type `u64`. -pub type u64x2 = Simd<u64, 2>; - -/// A 256-bit SIMD vector with four elements of type `u64`. -pub type u64x4 = Simd<u64, 4>; - -/// A 512-bit SIMD vector with eight elements of type `u64`. -pub type u64x8 = Simd<u64, 8>; - -/// A 32-bit SIMD vector with four elements of type `u8`. -pub type u8x4 = Simd<u8, 4>; - -/// A 64-bit SIMD vector with eight elements of type `u8`. -pub type u8x8 = Simd<u8, 8>; - -/// A 128-bit SIMD vector with 16 elements of type `u8`. -pub type u8x16 = Simd<u8, 16>; - -/// A 256-bit SIMD vector with 32 elements of type `u8`. -pub type u8x32 = Simd<u8, 32>; - -/// A 512-bit SIMD vector with 64 elements of type `u8`. -pub type u8x64 = Simd<u8, 64>; diff --git a/library/portable-simd/crates/core_simd/tests/autoderef.rs b/library/portable-simd/crates/core_simd/tests/autoderef.rs index 9359da16ee5..3181826ef59 100644 --- a/library/portable-simd/crates/core_simd/tests/autoderef.rs +++ b/library/portable-simd/crates/core_simd/tests/autoderef.rs @@ -1,6 +1,6 @@ // Test that we handle all our "auto-deref" cases correctly. #![feature(portable_simd)] -use core_simd::f32x4; +use core_simd::simd::f32x4; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs index 795f9e27c44..faafa5fa51f 100644 --- a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs +++ b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs @@ -2,7 +2,7 @@ macro_rules! mask_tests { { $vector:ident, $lanes:literal } => { #[cfg(test)] mod $vector { - use core_simd::$vector as Vector; + use core_simd::simd::$vector as Vector; const LANES: usize = $lanes; #[cfg(target_arch = "wasm32")] diff --git a/library/portable-simd/crates/core_simd/tests/masks.rs b/library/portable-simd/crates/core_simd/tests/masks.rs index 673d0db93fe..9f8bad1c36c 100644 --- a/library/portable-simd/crates/core_simd/tests/masks.rs +++ b/library/portable-simd/crates/core_simd/tests/masks.rs @@ -13,11 +13,13 @@ macro_rules! test_mask_api { #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; + use core_simd::simd::Mask; + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn set_and_test() { let values = [true, false, false, true, false, false, true, false]; - let mut mask = core_simd::Mask::<$type, 8>::splat(false); + let mut mask = Mask::<$type, 8>::splat(false); for (lane, value) in values.iter().copied().enumerate() { mask.set(lane, value); } @@ -29,7 +31,7 @@ macro_rules! test_mask_api { #[test] #[should_panic] fn set_invalid_lane() { - let mut mask = core_simd::Mask::<$type, 8>::splat(false); + let mut mask = Mask::<$type, 8>::splat(false); mask.set(8, true); let _ = mask; } @@ -37,24 +39,24 @@ macro_rules! test_mask_api { #[test] #[should_panic] fn test_invalid_lane() { - let mask = core_simd::Mask::<$type, 8>::splat(false); + let mask = Mask::<$type, 8>::splat(false); let _ = mask.test(8); } #[test] fn any() { - assert!(!core_simd::Mask::<$type, 8>::splat(false).any()); - assert!(core_simd::Mask::<$type, 8>::splat(true).any()); - let mut v = core_simd::Mask::<$type, 8>::splat(false); + assert!(!Mask::<$type, 8>::splat(false).any()); + assert!(Mask::<$type, 8>::splat(true).any()); + let mut v = Mask::<$type, 8>::splat(false); v.set(2, true); assert!(v.any()); } #[test] fn all() { - assert!(!core_simd::Mask::<$type, 8>::splat(false).all()); - assert!(core_simd::Mask::<$type, 8>::splat(true).all()); - let mut v = core_simd::Mask::<$type, 8>::splat(false); + assert!(!Mask::<$type, 8>::splat(false).all()); + assert!(Mask::<$type, 8>::splat(true).all()); + let mut v = Mask::<$type, 8>::splat(false); v.set(2, true); assert!(!v.all()); } @@ -62,57 +64,57 @@ macro_rules! test_mask_api { #[test] fn roundtrip_int_conversion() { let values = [true, false, false, true, false, false, true, false]; - let mask = core_simd::Mask::<$type, 8>::from_array(values); + let mask = Mask::<$type, 8>::from_array(values); let int = mask.to_int(); assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); - assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask); + assert_eq!(Mask::<$type, 8>::from_int(int), mask); } #[test] fn roundtrip_bitmask_conversion() { - use core_simd::ToBitMask; + use core_simd::simd::ToBitMask; let values = [ true, false, false, true, false, false, true, false, true, true, false, false, false, false, false, true, ]; - let mask = core_simd::Mask::<$type, 16>::from_array(values); + let mask = Mask::<$type, 16>::from_array(values); let bitmask = mask.to_bitmask(); assert_eq!(bitmask, 0b1000001101001001); - assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask); + assert_eq!(Mask::<$type, 16>::from_bitmask(bitmask), mask); } #[test] fn roundtrip_bitmask_conversion_short() { - use core_simd::ToBitMask; + use core_simd::simd::ToBitMask; let values = [ false, false, false, true, ]; - let mask = core_simd::Mask::<$type, 4>::from_array(values); + let mask = Mask::<$type, 4>::from_array(values); let bitmask = mask.to_bitmask(); assert_eq!(bitmask, 0b1000); - assert_eq!(core_simd::Mask::<$type, 4>::from_bitmask(bitmask), mask); + assert_eq!(Mask::<$type, 4>::from_bitmask(bitmask), mask); let values = [true, false]; - let mask = core_simd::Mask::<$type, 2>::from_array(values); + let mask = Mask::<$type, 2>::from_array(values); let bitmask = mask.to_bitmask(); assert_eq!(bitmask, 0b01); - assert_eq!(core_simd::Mask::<$type, 2>::from_bitmask(bitmask), mask); + assert_eq!(Mask::<$type, 2>::from_bitmask(bitmask), mask); } #[test] fn cast() { - fn cast_impl<T: core_simd::MaskElement>() + fn cast_impl<T: core_simd::simd::MaskElement>() where - core_simd::Mask<$type, 8>: Into<core_simd::Mask<T, 8>>, + Mask<$type, 8>: Into<Mask<T, 8>>, { let values = [true, false, false, true, false, false, true, false]; - let mask = core_simd::Mask::<$type, 8>::from_array(values); + let mask = Mask::<$type, 8>::from_array(values); let cast_mask = mask.cast::<T>(); assert_eq!(values, cast_mask.to_array()); - let into_mask: core_simd::Mask<T, 8> = mask.into(); + let into_mask: Mask<T, 8> = mask.into(); assert_eq!(values, into_mask.to_array()); } @@ -126,15 +128,15 @@ macro_rules! test_mask_api { #[cfg(feature = "generic_const_exprs")] #[test] fn roundtrip_bitmask_array_conversion() { - use core_simd::ToBitMaskArray; + use core_simd::simd::ToBitMaskArray; let values = [ true, false, false, true, false, false, true, false, true, true, false, false, false, false, false, true, ]; - let mask = core_simd::Mask::<$type, 16>::from_array(values); + let mask = Mask::<$type, 16>::from_array(values); let bitmask = mask.to_bitmask_array(); assert_eq!(bitmask, [0b01001001, 0b10000011]); - assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask_array(bitmask), mask); + assert_eq!(Mask::<$type, 16>::from_bitmask_array(bitmask), mask); } } } @@ -150,9 +152,10 @@ mod mask_api { #[test] fn convert() { + use core_simd::simd::Mask; let values = [true, false, false, true, false, false, true, false]; assert_eq!( - core_simd::Mask::<i8, 8>::from_array(values), - core_simd::Mask::<i32, 8>::from_array(values).into() + Mask::<i8, 8>::from_array(values), + Mask::<i32, 8>::from_array(values).into() ); } diff --git a/library/portable-simd/crates/core_simd/tests/ops_macros.rs b/library/portable-simd/crates/core_simd/tests/ops_macros.rs index f759394d075..3a02f3f01e1 100644 --- a/library/portable-simd/crates/core_simd/tests/ops_macros.rs +++ b/library/portable-simd/crates/core_simd/tests/ops_macros.rs @@ -7,7 +7,7 @@ macro_rules! impl_unary_op_test { test_helpers::test_lanes! { fn $fn<const LANES: usize>() { test_helpers::test_unary_elementwise( - &<core_simd::Simd<$scalar, LANES> as core::ops::$trait>::$fn, + &<core_simd::simd::Simd<$scalar, LANES> as core::ops::$trait>::$fn, &$scalar_fn, &|_| true, ); @@ -27,7 +27,7 @@ macro_rules! impl_binary_op_test { { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $scalar_fn:expr } => { mod $fn { use super::*; - use core_simd::Simd; + use core_simd::simd::Simd; test_helpers::test_lanes! { fn normal<const LANES: usize>() { @@ -64,7 +64,7 @@ macro_rules! impl_binary_checked_op_test { { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $scalar_fn:expr, $check_fn:expr } => { mod $fn { use super::*; - use core_simd::Simd; + use core_simd::simd::Simd; test_helpers::test_lanes! { fn normal<const LANES: usize>() { @@ -173,7 +173,7 @@ macro_rules! impl_signed_tests { { $scalar:tt } => { mod $scalar { use core_simd::simd::SimdInt; - type Vector<const LANES: usize> = core_simd::Simd<Scalar, LANES>; + type Vector<const LANES: usize> = core_simd::simd::Simd<Scalar, LANES>; type Scalar = $scalar; impl_common_integer_tests! { Vector, Scalar } @@ -314,7 +314,7 @@ macro_rules! impl_unsigned_tests { { $scalar:tt } => { mod $scalar { use core_simd::simd::SimdUint; - type Vector<const LANES: usize> = core_simd::Simd<Scalar, LANES>; + type Vector<const LANES: usize> = core_simd::simd::Simd<Scalar, LANES>; type Scalar = $scalar; impl_common_integer_tests! { Vector, Scalar } @@ -348,8 +348,8 @@ macro_rules! impl_unsigned_tests { macro_rules! impl_float_tests { { $scalar:tt, $int_scalar:tt } => { mod $scalar { - use core_simd::SimdFloat; - type Vector<const LANES: usize> = core_simd::Simd<Scalar, LANES>; + use core_simd::simd::SimdFloat; + type Vector<const LANES: usize> = core_simd::simd::Simd<Scalar, LANES>; type Scalar = $scalar; impl_unary_op_test!(Scalar, Neg::neg); diff --git a/library/portable-simd/crates/core_simd/tests/pointers.rs b/library/portable-simd/crates/core_simd/tests/pointers.rs new file mode 100644 index 00000000000..0ae8f83b8b9 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/pointers.rs @@ -0,0 +1,111 @@ +#![feature(portable_simd, strict_provenance)] + +use core_simd::simd::{Simd, SimdConstPtr, SimdMutPtr}; + +macro_rules! common_tests { + { $constness:ident } => { + test_helpers::test_lanes! { + fn is_null<const LANES: usize>() { + test_helpers::test_unary_mask_elementwise( + &Simd::<*$constness u32, LANES>::is_null, + &<*$constness u32>::is_null, + &|_| true, + ); + } + + fn addr<const LANES: usize>() { + test_helpers::test_unary_elementwise( + &Simd::<*$constness u32, LANES>::addr, + &<*$constness u32>::addr, + &|_| true, + ); + } + + fn with_addr<const LANES: usize>() { + test_helpers::test_binary_elementwise( + &Simd::<*$constness u32, LANES>::with_addr, + &<*$constness u32>::with_addr, + &|_, _| true, + ); + } + + fn expose_addr<const LANES: usize>() { + test_helpers::test_unary_elementwise( + &Simd::<*$constness u32, LANES>::expose_addr, + &<*$constness u32>::expose_addr, + &|_| true, + ); + } + + fn wrapping_offset<const LANES: usize>() { + test_helpers::test_binary_elementwise( + &Simd::<*$constness u32, LANES>::wrapping_offset, + &<*$constness u32>::wrapping_offset, + &|_, _| true, + ); + } + + fn wrapping_add<const LANES: usize>() { + test_helpers::test_binary_elementwise( + &Simd::<*$constness u32, LANES>::wrapping_add, + &<*$constness u32>::wrapping_add, + &|_, _| true, + ); + } + + fn wrapping_sub<const LANES: usize>() { + test_helpers::test_binary_elementwise( + &Simd::<*$constness u32, LANES>::wrapping_sub, + &<*$constness u32>::wrapping_sub, + &|_, _| true, + ); + } + } + } +} + +mod const_ptr { + use super::*; + common_tests! { const } + + test_helpers::test_lanes! { + fn cast_mut<const LANES: usize>() { + test_helpers::test_unary_elementwise( + &Simd::<*const u32, LANES>::cast_mut, + &<*const u32>::cast_mut, + &|_| true, + ); + } + + fn from_exposed_addr<const LANES: usize>() { + test_helpers::test_unary_elementwise( + &Simd::<*const u32, LANES>::from_exposed_addr, + &core::ptr::from_exposed_addr::<u32>, + &|_| true, + ); + } + } +} + +mod mut_ptr { + use super::*; + common_tests! { mut } + + test_helpers::test_lanes! { + fn cast_const<const LANES: usize>() { + test_helpers::test_unary_elementwise( + &Simd::<*mut u32, LANES>::cast_const, + &<*mut u32>::cast_const, + &|_| true, + ); + } + + fn from_exposed_addr<const LANES: usize>() { + test_helpers::test_unary_elementwise( + &Simd::<*mut u32, LANES>::from_exposed_addr, + &core::ptr::from_exposed_addr_mut::<u32>, + &|_| true, + ); + } + } +} diff --git a/library/portable-simd/crates/core_simd/tests/round.rs b/library/portable-simd/crates/core_simd/tests/round.rs index 484fd5bf47d..8b9638ad466 100644 --- a/library/portable-simd/crates/core_simd/tests/round.rs +++ b/library/portable-simd/crates/core_simd/tests/round.rs @@ -5,7 +5,7 @@ macro_rules! float_rounding_test { mod $scalar { use std_float::StdFloat; - type Vector<const LANES: usize> = core_simd::Simd<$scalar, LANES>; + type Vector<const LANES: usize> = core_simd::simd::Simd<$scalar, LANES>; type Scalar = $scalar; type IntScalar = $int_scalar; diff --git a/library/portable-simd/crates/core_simd/tests/swizzle.rs b/library/portable-simd/crates/core_simd/tests/swizzle.rs index 51c63611aba..8cd7c33e823 100644 --- a/library/portable-simd/crates/core_simd/tests/swizzle.rs +++ b/library/portable-simd/crates/core_simd/tests/swizzle.rs @@ -1,5 +1,5 @@ #![feature(portable_simd)] -use core_simd::{Simd, Swizzle}; +use core_simd::simd::{Simd, Swizzle}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -60,3 +60,17 @@ fn interleave() { assert_eq!(even, a); assert_eq!(odd, b); } + +// portable-simd#298 +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn interleave_one() { + let a = Simd::from_array([0]); + let b = Simd::from_array([1]); + let (lo, hi) = a.interleave(b); + assert_eq!(lo.to_array(), [0]); + assert_eq!(hi.to_array(), [1]); + let (even, odd) = lo.deinterleave(hi); + assert_eq!(even, a); + assert_eq!(odd, b); +} diff --git a/library/portable-simd/crates/core_simd/tests/swizzle_dyn.rs b/library/portable-simd/crates/core_simd/tests/swizzle_dyn.rs new file mode 100644 index 00000000000..646cd5f3383 --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/swizzle_dyn.rs @@ -0,0 +1,74 @@ +#![feature(portable_simd)] +use core::{fmt, ops::RangeInclusive}; +use proptest; +use test_helpers::{self, biteq, make_runner, prop_assert_biteq}; + +fn swizzle_dyn_scalar_ver<const N: usize>(values: [u8; N], idxs: [u8; N]) -> [u8; N] { + let mut array = [0; N]; + for (i, k) in idxs.into_iter().enumerate() { + if (k as usize) < N { + array[i] = values[k as usize]; + }; + } + array +} + +test_helpers::test_lanes! { + fn swizzle_dyn<const N: usize>() { + match_simd_with_fallback( + &core_simd::simd::Simd::<u8, N>::swizzle_dyn, + &swizzle_dyn_scalar_ver, + &|_, _| true, + ); + } +} + +fn match_simd_with_fallback<Scalar, ScalarResult, Vector, VectorResult, const N: usize>( + fv: &dyn Fn(Vector, Vector) -> VectorResult, + fs: &dyn Fn([Scalar; N], [Scalar; N]) -> [ScalarResult; N], + check: &dyn Fn([Scalar; N], [Scalar; N]) -> bool, +) where + Scalar: Copy + fmt::Debug + SwizzleStrategy, + ScalarResult: Copy + biteq::BitEq + fmt::Debug + SwizzleStrategy, + Vector: Into<[Scalar; N]> + From<[Scalar; N]> + Copy, + VectorResult: Into<[ScalarResult; N]> + From<[ScalarResult; N]> + Copy, +{ + test_swizzles_2(&|x: [Scalar; N], y: [Scalar; N]| { + proptest::prop_assume!(check(x, y)); + let result_v: [ScalarResult; N] = fv(x.into(), y.into()).into(); + let result_s: [ScalarResult; N] = fs(x, y); + crate::prop_assert_biteq!(result_v, result_s); + Ok(()) + }); +} + +fn test_swizzles_2<A: fmt::Debug + SwizzleStrategy, B: fmt::Debug + SwizzleStrategy>( + f: &dyn Fn(A, B) -> proptest::test_runner::TestCaseResult, +) { + let mut runner = make_runner(); + runner + .run( + &(A::swizzled_strategy(), B::swizzled_strategy()), + |(a, b)| f(a, b), + ) + .unwrap(); +} + +pub trait SwizzleStrategy { + type Strategy: proptest::strategy::Strategy<Value = Self>; + fn swizzled_strategy() -> Self::Strategy; +} + +impl SwizzleStrategy for u8 { + type Strategy = RangeInclusive<u8>; + fn swizzled_strategy() -> Self::Strategy { + 0..=64 + } +} + +impl<T: fmt::Debug + SwizzleStrategy, const N: usize> SwizzleStrategy for [T; N] { + type Strategy = test_helpers::array::UniformArrayStrategy<T::Strategy, Self>; + fn swizzled_strategy() -> Self::Strategy { + Self::Strategy::new(T::swizzled_strategy()) + } +} diff --git a/library/portable-simd/crates/core_simd/tests/to_bytes.rs b/library/portable-simd/crates/core_simd/tests/to_bytes.rs index debb4335e2c..be0ee4349c5 100644 --- a/library/portable-simd/crates/core_simd/tests/to_bytes.rs +++ b/library/portable-simd/crates/core_simd/tests/to_bytes.rs @@ -2,7 +2,7 @@ #![allow(incomplete_features)] #![cfg(feature = "generic_const_exprs")] -use core_simd::Simd; +use core_simd::simd::Simd; #[test] fn byte_convert() { diff --git a/library/portable-simd/crates/core_simd/tests/try_from_slice.rs b/library/portable-simd/crates/core_simd/tests/try_from_slice.rs new file mode 100644 index 00000000000..859e3b94f2c --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/try_from_slice.rs @@ -0,0 +1,25 @@ +#![feature(portable_simd)] + +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::*; + +#[cfg(target_arch = "wasm32")] +wasm_bindgen_test_configure!(run_in_browser); + +use core_simd::simd::i32x4; + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn try_from_slice() { + // Equal length + assert_eq!( + i32x4::try_from([1, 2, 3, 4].as_slice()).unwrap(), + i32x4::from_array([1, 2, 3, 4]) + ); + + // Slice length > vector length + assert!(i32x4::try_from([1, 2, 3, 4, 5].as_slice()).is_err()); + + // Slice length < vector length + assert!(i32x4::try_from([1, 2, 3].as_slice()).is_err()); +} diff --git a/library/portable-simd/crates/test_helpers/Cargo.toml b/library/portable-simd/crates/test_helpers/Cargo.toml index a04b0961d7f..1d2bc8b519a 100644 --- a/library/portable-simd/crates/test_helpers/Cargo.toml +++ b/library/portable-simd/crates/test_helpers/Cargo.toml @@ -8,3 +8,6 @@ publish = false version = "0.10" default-features = false features = ["alloc"] + +[features] +all_lane_counts = [] diff --git a/library/portable-simd/crates/test_helpers/src/array.rs b/library/portable-simd/crates/test_helpers/src/array.rs index 5ffc9226976..984a427320d 100644 --- a/library/portable-simd/crates/test_helpers/src/array.rs +++ b/library/portable-simd/crates/test_helpers/src/array.rs @@ -41,6 +41,7 @@ where fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> { let tree: [S::Tree; LANES] = unsafe { + #[allow(clippy::uninit_assumed_init)] let mut tree: [MaybeUninit<S::Tree>; LANES] = MaybeUninit::uninit().assume_init(); for t in tree.iter_mut() { *t = MaybeUninit::new(self.strategy.new_tree(runner)?) @@ -60,6 +61,7 @@ impl<T: ValueTree, const LANES: usize> ValueTree for ArrayValueTree<[T; LANES]> fn current(&self) -> Self::Value { unsafe { + #[allow(clippy::uninit_assumed_init)] let mut value: [MaybeUninit<T::Value>; LANES] = MaybeUninit::uninit().assume_init(); for (tree_elem, value_elem) in self.tree.iter().zip(value.iter_mut()) { *value_elem = MaybeUninit::new(tree_elem.current()); diff --git a/library/portable-simd/crates/test_helpers/src/biteq.rs b/library/portable-simd/crates/test_helpers/src/biteq.rs index 00350e22418..7d91260d838 100644 --- a/library/portable-simd/crates/test_helpers/src/biteq.rs +++ b/library/portable-simd/crates/test_helpers/src/biteq.rs @@ -55,6 +55,26 @@ macro_rules! impl_float_biteq { impl_float_biteq! { f32, f64 } +impl<T> BitEq for *const T { + fn biteq(&self, other: &Self) -> bool { + self == other + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + +impl<T> BitEq for *mut T { + fn biteq(&self, other: &Self) -> bool { + self == other + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + impl<T: BitEq, const N: usize> BitEq for [T; N] { fn biteq(&self, other: &Self) -> bool { self.iter() diff --git a/library/portable-simd/crates/test_helpers/src/lib.rs b/library/portable-simd/crates/test_helpers/src/lib.rs index 141bee18a9a..b26cdc311a2 100644 --- a/library/portable-simd/crates/test_helpers/src/lib.rs +++ b/library/portable-simd/crates/test_helpers/src/lib.rs @@ -38,6 +38,28 @@ impl_num! { usize } impl_num! { f32 } impl_num! { f64 } +impl<T> DefaultStrategy for *const T { + type Strategy = proptest::strategy::Map<proptest::num::isize::Any, fn(isize) -> *const T>; + fn default_strategy() -> Self::Strategy { + fn map<T>(x: isize) -> *const T { + x as _ + } + use proptest::strategy::Strategy; + proptest::num::isize::ANY.prop_map(map) + } +} + +impl<T> DefaultStrategy for *mut T { + type Strategy = proptest::strategy::Map<proptest::num::isize::Any, fn(isize) -> *mut T>; + fn default_strategy() -> Self::Strategy { + fn map<T>(x: isize) -> *mut T { + x as _ + } + use proptest::strategy::Strategy; + proptest::num::isize::ANY.prop_map(map) + } +} + #[cfg(not(target_arch = "wasm32"))] impl DefaultStrategy for u128 { type Strategy = proptest::num::u128::Any; @@ -135,21 +157,21 @@ pub fn test_unary_elementwise<Scalar, ScalarResult, Vector, VectorResult, const fs: &dyn Fn(Scalar) -> ScalarResult, check: &dyn Fn([Scalar; LANES]) -> bool, ) where - Scalar: Copy + Default + core::fmt::Debug + DefaultStrategy, - ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy, + Scalar: Copy + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + biteq::BitEq + core::fmt::Debug + DefaultStrategy, Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy, VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, { test_1(&|x: [Scalar; LANES]| { proptest::prop_assume!(check(x)); let result_1: [ScalarResult; LANES] = fv(x.into()).into(); - let result_2: [ScalarResult; LANES] = { - let mut result = [ScalarResult::default(); LANES]; - for (i, o) in x.iter().zip(result.iter_mut()) { - *o = fs(*i); - } - result - }; + let result_2: [ScalarResult; LANES] = x + .iter() + .copied() + .map(fs) + .collect::<Vec<_>>() + .try_into() + .unwrap(); crate::prop_assert_biteq!(result_1, result_2); Ok(()) }); @@ -162,7 +184,7 @@ pub fn test_unary_mask_elementwise<Scalar, Vector, Mask, const LANES: usize>( fs: &dyn Fn(Scalar) -> bool, check: &dyn Fn([Scalar; LANES]) -> bool, ) where - Scalar: Copy + Default + core::fmt::Debug + DefaultStrategy, + Scalar: Copy + core::fmt::Debug + DefaultStrategy, Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy, Mask: Into<[bool; LANES]> + From<[bool; LANES]> + Copy, { @@ -196,9 +218,9 @@ pub fn test_binary_elementwise< fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult, check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES]) -> bool, ) where - Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy, - Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy, - ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy, + Scalar1: Copy + core::fmt::Debug + DefaultStrategy, + Scalar2: Copy + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + biteq::BitEq + core::fmt::Debug + DefaultStrategy, Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy, Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy, VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, @@ -206,13 +228,14 @@ pub fn test_binary_elementwise< test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| { proptest::prop_assume!(check(x, y)); let result_1: [ScalarResult; LANES] = fv(x.into(), y.into()).into(); - let result_2: [ScalarResult; LANES] = { - let mut result = [ScalarResult::default(); LANES]; - for ((i1, i2), o) in x.iter().zip(y.iter()).zip(result.iter_mut()) { - *o = fs(*i1, *i2); - } - result - }; + let result_2: [ScalarResult; LANES] = x + .iter() + .copied() + .zip(y.iter().copied()) + .map(|(x, y)| fs(x, y)) + .collect::<Vec<_>>() + .try_into() + .unwrap(); crate::prop_assert_biteq!(result_1, result_2); Ok(()) }); @@ -333,6 +356,39 @@ pub fn test_ternary_elementwise< ); } +#[doc(hidden)] +#[macro_export] +macro_rules! test_lanes_helper { + ($($(#[$meta:meta])* $fn_name:ident $lanes:literal;)+) => { + $( + #[test] + $(#[$meta])* + fn $fn_name() { + implementation::<$lanes>(); + } + )+ + }; + ( + $(#[$meta:meta])+; + $($(#[$meta_before:meta])+ $fn_name_before:ident $lanes_before:literal;)* + $fn_name:ident $lanes:literal; + $($fn_name_rest:ident $lanes_rest:literal;)* + ) => { + $crate::test_lanes_helper!( + $(#[$meta])+; + $($(#[$meta_before])+ $fn_name_before $lanes_before;)* + $(#[$meta])+ $fn_name $lanes; + $($fn_name_rest $lanes_rest;)* + ); + }; + ( + $(#[$meta_ignored:meta])+; + $($(#[$meta:meta])+ $fn_name:ident $lanes:literal;)+ + ) => { + $crate::test_lanes_helper!($($(#[$meta])+ $fn_name $lanes;)+); + }; +} + /// Expand a const-generic test into separate tests for each possible lane count. #[macro_export] macro_rules! test_lanes { @@ -345,57 +401,96 @@ macro_rules! test_lanes { fn implementation<const $lanes: usize>() where - core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount, + core_simd::simd::LaneCount<$lanes>: core_simd::simd::SupportedLaneCount, $body #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - fn lanes_1() { - implementation::<1>(); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - fn lanes_2() { - implementation::<2>(); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - fn lanes_4() { - implementation::<4>(); - } + $crate::test_lanes_helper!( + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]; + lanes_1 1; + lanes_2 2; + lanes_4 4; + ); - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow - fn lanes_8() { - implementation::<8>(); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + $crate::test_lanes_helper!( + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]; + lanes_8 8; + lanes_16 16; + lanes_32 32; + lanes_64 64; + ); + + #[cfg(feature = "all_lane_counts")] + $crate::test_lanes_helper!( + // test some odd and even non-power-of-2 lengths on miri + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]; + lanes_3 3; + lanes_5 5; + lanes_6 6; + ); + + #[cfg(feature = "all_lane_counts")] #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow - fn lanes_16() { - implementation::<16>(); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow - fn lanes_32() { - implementation::<32>(); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow - fn lanes_64() { - implementation::<64>(); - } + $crate::test_lanes_helper!( + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]; + lanes_7 7; + lanes_9 9; + lanes_10 10; + lanes_11 11; + lanes_12 12; + lanes_13 13; + lanes_14 14; + lanes_15 15; + lanes_17 17; + lanes_18 18; + lanes_19 19; + lanes_20 20; + lanes_21 21; + lanes_22 22; + lanes_23 23; + lanes_24 24; + lanes_25 25; + lanes_26 26; + lanes_27 27; + lanes_28 28; + lanes_29 29; + lanes_30 30; + lanes_31 31; + lanes_33 33; + lanes_34 34; + lanes_35 35; + lanes_36 36; + lanes_37 37; + lanes_38 38; + lanes_39 39; + lanes_40 40; + lanes_41 41; + lanes_42 42; + lanes_43 43; + lanes_44 44; + lanes_45 45; + lanes_46 46; + lanes_47 47; + lanes_48 48; + lanes_49 49; + lanes_50 50; + lanes_51 51; + lanes_52 52; + lanes_53 53; + lanes_54 54; + lanes_55 55; + lanes_56 56; + lanes_57 57; + lanes_58 58; + lanes_59 59; + lanes_60 60; + lanes_61 61; + lanes_62 62; + lanes_63 63; + ); } )* } @@ -413,50 +508,93 @@ macro_rules! test_lanes_panic { fn implementation<const $lanes: usize>() where - core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount, + core_simd::simd::LaneCount<$lanes>: core_simd::simd::SupportedLaneCount, $body - #[test] - #[should_panic] - fn lanes_1() { - implementation::<1>(); - } - - #[test] - #[should_panic] - fn lanes_2() { - implementation::<2>(); - } - - #[test] - #[should_panic] - fn lanes_4() { - implementation::<4>(); - } - - #[test] - #[should_panic] - fn lanes_8() { - implementation::<8>(); - } + $crate::test_lanes_helper!( + #[should_panic]; + lanes_1 1; + lanes_2 2; + lanes_4 4; + ); - #[test] - #[should_panic] - fn lanes_16() { - implementation::<16>(); - } - - #[test] - #[should_panic] - fn lanes_32() { - implementation::<32>(); - } - - #[test] - #[should_panic] - fn lanes_64() { - implementation::<64>(); - } + #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow + $crate::test_lanes_helper!( + #[should_panic]; + lanes_8 8; + lanes_16 16; + lanes_32 32; + lanes_64 64; + ); + + #[cfg(feature = "all_lane_counts")] + $crate::test_lanes_helper!( + // test some odd and even non-power-of-2 lengths on miri + #[should_panic]; + lanes_3 3; + lanes_5 5; + lanes_6 6; + ); + + #[cfg(feature = "all_lane_counts")] + #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow + $crate::test_lanes_helper!( + #[should_panic]; + lanes_7 7; + lanes_9 9; + lanes_10 10; + lanes_11 11; + lanes_12 12; + lanes_13 13; + lanes_14 14; + lanes_15 15; + lanes_17 17; + lanes_18 18; + lanes_19 19; + lanes_20 20; + lanes_21 21; + lanes_22 22; + lanes_23 23; + lanes_24 24; + lanes_25 25; + lanes_26 26; + lanes_27 27; + lanes_28 28; + lanes_29 29; + lanes_30 30; + lanes_31 31; + lanes_33 33; + lanes_34 34; + lanes_35 35; + lanes_36 36; + lanes_37 37; + lanes_38 38; + lanes_39 39; + lanes_40 40; + lanes_41 41; + lanes_42 42; + lanes_43 43; + lanes_44 44; + lanes_45 45; + lanes_46 46; + lanes_47 47; + lanes_48 48; + lanes_49 49; + lanes_50 50; + lanes_51 51; + lanes_52 52; + lanes_53 53; + lanes_54 54; + lanes_55 55; + lanes_56 56; + lanes_57 57; + lanes_58 58; + lanes_59 59; + lanes_60 60; + lanes_61 61; + lanes_62 62; + lanes_63 63; + ); } )* } diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs index 17bd0a1b336..f4e90544197 100644 --- a/library/proc_macro/src/bridge/fxhash.rs +++ b/library/proc_macro/src/bridge/fxhash.rs @@ -5,8 +5,6 @@ //! on the `rustc_hash` crate. use std::collections::HashMap; -use std::convert::TryInto; -use std::default::Default; use std::hash::BuildHasherDefault; use std::hash::Hasher; use std::mem::size_of; diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 4c1e196b5ad..caecda1bc63 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -14,6 +14,7 @@ use std::hash::Hash; use std::marker; use std::mem; use std::ops::Bound; +use std::ops::Range; use std::panic; use std::sync::atomic::AtomicUsize; use std::sync::Once; @@ -93,6 +94,7 @@ macro_rules! with_api { fn source_file($self: $S::Span) -> $S::SourceFile; fn parent($self: $S::Span) -> Option<$S::Span>; fn source($self: $S::Span) -> $S::Span; + fn byte_range($self: $S::Span) -> Range<usize>; fn start($self: $S::Span) -> LineColumn; fn end($self: $S::Span) -> LineColumn; fn before($self: $S::Span) -> $S::Span; @@ -335,6 +337,8 @@ pub enum LitKind { StrRaw(u8), ByteStr, ByteStrRaw(u8), + CStr, + CStrRaw(u8), Err, } @@ -348,6 +352,8 @@ rpc_encode_decode!( StrRaw(n), ByteStr, ByteStrRaw(n), + CStr, + CStrRaw(n), Err, } ); @@ -519,3 +525,7 @@ pub struct ExpnGlobals<Span> { compound_traits!( struct ExpnGlobals<Span> { def_site, call_site, mixed_site } ); + +compound_traits!( + struct Range<T> { start, end } +); diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 938935771d6..c64665b6ae0 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -44,10 +44,10 @@ mod diagnostic; pub use diagnostic::{Diagnostic, Level, MultiSpan}; use std::cmp::Ordering; -use std::ops::RangeBounds; +use std::ops::{Range, RangeBounds}; use std::path::PathBuf; use std::str::FromStr; -use std::{error, fmt, iter}; +use std::{error, fmt}; /// Determines whether proc_macro has been made accessible to the currently /// running program. @@ -310,7 +310,7 @@ impl ConcatStreamsHelper { /// Collects a number of token trees into a single stream. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] -impl iter::FromIterator<TokenTree> for TokenStream { +impl FromIterator<TokenTree> for TokenStream { fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { let iter = trees.into_iter(); let mut builder = ConcatTreesHelper::new(iter.size_hint().0); @@ -322,7 +322,7 @@ impl iter::FromIterator<TokenTree> for TokenStream { /// A "flattening" operation on token streams, collects token trees /// from multiple token streams into a single stream. #[stable(feature = "proc_macro_lib", since = "1.15.0")] -impl iter::FromIterator<TokenStream> for TokenStream { +impl FromIterator<TokenStream> for TokenStream { fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { let iter = streams.into_iter(); let mut builder = ConcatStreamsHelper::new(iter.size_hint().0); @@ -488,6 +488,12 @@ impl Span { Span(self.0.source()) } + /// Returns the span's byte position range in the source file. + #[unstable(feature = "proc_macro_span", issue = "54725")] + pub fn byte_range(&self) -> Range<usize> { + self.0.byte_range() + } + /// Gets the starting line/column in the source file for this span. #[unstable(feature = "proc_macro_span", issue = "54725")] pub fn start(&self) -> LineColumn { diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 349cd91c89e..1454b002556 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -15,19 +15,19 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.87" } +libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.91" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } -hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] } +hashbrown = { version = "0.13", default-features = false, features = ['rustc-dep-of-std'] } std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] } # Dependencies of the `backtrace` crate -addr2line = { version = "0.17.0", optional = true, default-features = false } +addr2line = { version = "0.19.0", optional = true, default-features = false } rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] } -miniz_oxide = { version = "0.5.0", optional = true, default-features = false } +miniz_oxide = { version = "0.6.0", optional = true, default-features = false } [dependencies.object] -version = "0.29.0" +version = "0.30.0" optional = true default-features = false features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] @@ -43,7 +43,7 @@ dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] } fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'] } [target.'cfg(target_os = "hermit")'.dependencies] -hermit-abi = { version = "0.2.6", features = ['rustc-dep-of-std'] } +hermit-abi = { version = "0.3.0", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false } diff --git a/library/std/build.rs b/library/std/build.rs index 8b1a06ee750..0fb03c8e88a 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -6,6 +6,9 @@ fn main() { if target.contains("freebsd") { if env::var("RUST_STD_FREEBSD_12_ABI").is_ok() { println!("cargo:rustc-cfg=freebsd12"); + } else if env::var("RUST_STD_FREEBSD_13_ABI").is_ok() { + println!("cargo:rustc-cfg=freebsd12"); + println!("cargo:rustc-cfg=freebsd13"); } } else if target.contains("linux") || target.contains("netbsd") @@ -31,6 +34,8 @@ fn main() { || target.contains("espidf") || target.contains("solid") || target.contains("nintendo-3ds") + || target.contains("vita") + || target.contains("nto") { // These platforms don't have any special requirements. } else { diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c5a5991cc81..ec774e62deb 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -93,7 +93,7 @@ pub use alloc_crate::alloc::*; /// /// ```rust /// use std::alloc::{System, GlobalAlloc, Layout}; -/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +/// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; /// /// struct Counter; /// @@ -103,14 +103,14 @@ pub use alloc_crate::alloc::*; /// unsafe fn alloc(&self, layout: Layout) -> *mut u8 { /// let ret = System.alloc(layout); /// if !ret.is_null() { -/// ALLOCATED.fetch_add(layout.size(), SeqCst); +/// ALLOCATED.fetch_add(layout.size(), Relaxed); /// } /// ret /// } /// /// unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { /// System.dealloc(ptr, layout); -/// ALLOCATED.fetch_sub(layout.size(), SeqCst); +/// ALLOCATED.fetch_sub(layout.size(), Relaxed); /// } /// } /// @@ -118,7 +118,7 @@ pub use alloc_crate::alloc::*; /// static A: Counter = Counter; /// /// fn main() { -/// println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst)); +/// println!("allocated bytes before main: {}", ALLOCATED.load(Relaxed)); /// } /// ``` /// diff --git a/library/std/src/ascii.rs b/library/std/src/ascii.rs index c29f015777f..b18ab50de12 100644 --- a/library/std/src/ascii.rs +++ b/library/std/src/ascii.rs @@ -16,6 +16,9 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use core::ascii::{escape_default, EscapeDefault}; +#[unstable(feature = "ascii_char", issue = "110998")] +pub use core::ascii::Char; + /// Extension methods for ASCII-subset only operations. /// /// Be aware that operations on seemingly non-ASCII characters can sometimes diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 742c4cc7c55..c722bad2e4f 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1446,7 +1446,6 @@ impl<'a, K, V> IterMut<'a, K, V> { /// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: IntoIterator::into_iter -/// [`IntoIterator`]: crate::iter::IntoIterator /// /// # Example /// @@ -3169,8 +3168,7 @@ impl DefaultHasher { } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -#[rustc_const_unstable(feature = "const_hash", issue = "104061")] -impl const Default for DefaultHasher { +impl Default for DefaultHasher { /// Creates a new `DefaultHasher` using [`new`]. /// See its documentation for more. /// @@ -3182,8 +3180,7 @@ impl const Default for DefaultHasher { } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -#[rustc_const_unstable(feature = "const_hash", issue = "104061")] -impl const Hasher for DefaultHasher { +impl Hasher for DefaultHasher { // The underlying `SipHasher13` doesn't override the other // `write_*` methods, so it's ok not to forward them here. diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index b59f89d321c..ac906e682d5 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -12,13 +12,6 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub}; use super::map::{map_try_reserve_error, RandomState}; -// Future Optimization (FIXME!) -// ============================ -// -// Iteration over zero sized values is a noop. There is no need -// for `bucket.val` in the case of HashSet. I suppose we would need HKT -// to get rid of it properly. - /// A [hash set] implemented as a `HashMap` where the value is `()`. /// /// As with the [`HashMap`] type, a `HashSet` requires that the elements @@ -1279,7 +1272,6 @@ pub struct Iter<'a, K: 'a> { /// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: IntoIterator::into_iter -/// [`IntoIterator`]: crate::iter::IntoIterator /// /// # Examples /// diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index ae2baba09e6..42f738acb9f 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -172,7 +172,8 @@ //! //! ## Iterators //! -//! Iterators are a powerful and robust mechanism used throughout Rust's +//! [Iterators][crate::iter] +//! are a powerful and robust mechanism used throughout Rust's //! standard libraries. Iterators provide a sequence of values in a generic, //! safe, efficient and convenient way. The contents of an iterator are usually //! *lazily* evaluated, so that only the values that are actually needed are @@ -252,7 +253,9 @@ //! //! Several other collection methods also return iterators to yield a sequence //! of results but avoid allocating an entire collection to store the result in. -//! This provides maximum flexibility as `collect` or `extend` can be called to +//! This provides maximum flexibility as +//! [`collect`][crate::iter::Iterator::collect] or +//! [`extend`][crate::iter::Extend::extend] can be called to //! "pipe" the sequence into any collection if desired. Otherwise, the sequence //! can be looped over with a `for` loop. The iterator can also be discarded //! after partial use, preventing the computation of the unused items. @@ -395,8 +398,6 @@ //! // ...but the key hasn't changed. b is still "baz", not "xyz". //! assert_eq!(map.keys().next().unwrap().b, "baz"); //! ``` -//! -//! [IntoIterator]: crate::iter::IntoIterator "iter::IntoIterator" #![stable(feature = "rust1", since = "1.0.0")] @@ -416,8 +417,10 @@ pub use alloc_crate::collections::{BTreeMap, BTreeSet, BinaryHeap}; pub use alloc_crate::collections::{LinkedList, VecDeque}; #[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] pub use self::hash_map::HashMap; #[stable(feature = "rust1", since = "1.0.0")] +#[doc(inline)] pub use self::hash_set::HashSet; #[stable(feature = "try_reserve", since = "1.57.0")] diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 183f9ab3b08..d372fa64065 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -236,21 +236,14 @@ fn _var(key: &OsStr) -> Result<String, VarError> { } /// Fetches the environment variable `key` from the current process, returning -/// [`None`] if the variable isn't set or there's another error. +/// [`None`] if the variable isn't set or if there is another error. /// -/// Note that the method will not check if the environment variable -/// is valid Unicode. If you want to have an error on invalid UTF-8, -/// use the [`var`] function instead. -/// -/// # Errors -/// -/// This function returns an error if the environment variable isn't set. -/// -/// This function may return an error if the environment variable's name contains +/// It may return `None` if the environment variable's name contains /// the equal sign character (`=`) or the NUL character. /// -/// This function may return an error if the environment variable's value contains -/// the NUL character. +/// Note that this function will not check if the environment variable +/// is valid Unicode. If you want to have an error on invalid UTF-8, +/// use the [`var`] function instead. /// /// # Examples /// @@ -895,6 +888,7 @@ pub mod consts { /// - x86_64 /// - arm /// - aarch64 + /// - loongarch64 /// - m68k /// - mips /// - mips64 diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 6b1f0cba82d..408244b2ce9 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -78,10 +78,14 @@ impl f32 { /// let f = 3.3_f32; /// let g = -3.3_f32; /// let h = -3.7_f32; + /// let i = 3.5_f32; + /// let j = 4.5_f32; /// /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// assert_eq!(h.round(), -4.0); + /// assert_eq!(i.round(), 4.0); + /// assert_eq!(j.round(), 5.0); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] @@ -91,6 +95,32 @@ impl f32 { unsafe { intrinsics::roundf32(self) } } + /// Returns the nearest integer to a number. Rounds half-way cases to the number + /// with an even least significant digit. + /// + /// # Examples + /// + /// ``` + /// #![feature(round_ties_even)] + /// + /// let f = 3.3_f32; + /// let g = -3.3_f32; + /// let h = 3.5_f32; + /// let i = 4.5_f32; + /// + /// assert_eq!(f.round_ties_even(), 3.0); + /// assert_eq!(g.round_ties_even(), -3.0); + /// assert_eq!(h.round_ties_even(), 4.0); + /// assert_eq!(i.round_ties_even(), 4.0); + /// ``` + #[rustc_allow_incoherent_impl] + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "round_ties_even", issue = "96710")] + #[inline] + pub fn round_ties_even(self) -> f32 { + unsafe { intrinsics::rintf32(self) } + } + /// Returns the integer part of `self`. /// This means that non-integer numbers are always truncated towards zero. /// @@ -551,8 +581,10 @@ impl f32 { unsafe { cmath::cbrtf(self) } } - /// Calculates the length of the hypotenuse of a right-angle triangle given - /// legs of length `x` and `y`. + /// Compute the distance between the origin and a point (`x`, `y`) on the + /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a + /// right-angle triangle with other sides having length `x.abs()` and + /// `y.abs()`. /// /// # Examples /// diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 6ee295de616..e949def00bb 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -209,6 +209,7 @@ fn test_ceil() { #[test] fn test_round() { + assert_approx_eq!(2.5f32.round(), 3.0f32); assert_approx_eq!(1.0f32.round(), 1.0f32); assert_approx_eq!(1.3f32.round(), 1.0f32); assert_approx_eq!(1.5f32.round(), 2.0f32); @@ -222,6 +223,21 @@ fn test_round() { } #[test] +fn test_round_ties_even() { + assert_approx_eq!(2.5f32.round_ties_even(), 2.0f32); + assert_approx_eq!(1.0f32.round_ties_even(), 1.0f32); + assert_approx_eq!(1.3f32.round_ties_even(), 1.0f32); + assert_approx_eq!(1.5f32.round_ties_even(), 2.0f32); + assert_approx_eq!(1.7f32.round_ties_even(), 2.0f32); + assert_approx_eq!(0.0f32.round_ties_even(), 0.0f32); + assert_approx_eq!((-0.0f32).round_ties_even(), -0.0f32); + assert_approx_eq!((-1.0f32).round_ties_even(), -1.0f32); + assert_approx_eq!((-1.3f32).round_ties_even(), -1.0f32); + assert_approx_eq!((-1.5f32).round_ties_even(), -2.0f32); + assert_approx_eq!((-1.7f32).round_ties_even(), -2.0f32); +} + +#[test] fn test_trunc() { assert_approx_eq!(1.0f32.trunc(), 1.0f32); assert_approx_eq!(1.3f32.trunc(), 1.0f32); diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 16359766b51..6782b861f11 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -78,10 +78,14 @@ impl f64 { /// let f = 3.3_f64; /// let g = -3.3_f64; /// let h = -3.7_f64; + /// let i = 3.5_f64; + /// let j = 4.5_f64; /// /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// assert_eq!(h.round(), -4.0); + /// assert_eq!(i.round(), 4.0); + /// assert_eq!(j.round(), 5.0); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] @@ -91,6 +95,32 @@ impl f64 { unsafe { intrinsics::roundf64(self) } } + /// Returns the nearest integer to a number. Rounds half-way cases to the number + /// with an even least significant digit. + /// + /// # Examples + /// + /// ``` + /// #![feature(round_ties_even)] + /// + /// let f = 3.3_f64; + /// let g = -3.3_f64; + /// let h = 3.5_f64; + /// let i = 4.5_f64; + /// + /// assert_eq!(f.round_ties_even(), 3.0); + /// assert_eq!(g.round_ties_even(), -3.0); + /// assert_eq!(h.round_ties_even(), 4.0); + /// assert_eq!(i.round_ties_even(), 4.0); + /// ``` + #[rustc_allow_incoherent_impl] + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "round_ties_even", issue = "96710")] + #[inline] + pub fn round_ties_even(self) -> f64 { + unsafe { intrinsics::rintf64(self) } + } + /// Returns the integer part of `self`. /// This means that non-integer numbers are always truncated towards zero. /// @@ -553,8 +583,10 @@ impl f64 { unsafe { cmath::cbrt(self) } } - /// Calculates the length of the hypotenuse of a right-angle triangle given - /// legs of length `x` and `y`. + /// Compute the distance between the origin and a point (`x`, `y`) on the + /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a + /// right-angle triangle with other sides having length `x.abs()` and + /// `y.abs()`. /// /// # Examples /// diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 5b039d445ce..53d351cceef 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -199,6 +199,7 @@ fn test_ceil() { #[test] fn test_round() { + assert_approx_eq!(2.5f64.round(), 3.0f64); assert_approx_eq!(1.0f64.round(), 1.0f64); assert_approx_eq!(1.3f64.round(), 1.0f64); assert_approx_eq!(1.5f64.round(), 2.0f64); @@ -212,6 +213,21 @@ fn test_round() { } #[test] +fn test_round_ties_even() { + assert_approx_eq!(2.5f64.round_ties_even(), 2.0f64); + assert_approx_eq!(1.0f64.round_ties_even(), 1.0f64); + assert_approx_eq!(1.3f64.round_ties_even(), 1.0f64); + assert_approx_eq!(1.5f64.round_ties_even(), 2.0f64); + assert_approx_eq!(1.7f64.round_ties_even(), 2.0f64); + assert_approx_eq!(0.0f64.round_ties_even(), 0.0f64); + assert_approx_eq!((-0.0f64).round_ties_even(), -0.0f64); + assert_approx_eq!((-1.0f64).round_ties_even(), -1.0f64); + assert_approx_eq!((-1.3f64).round_ties_even(), -1.0f64); + assert_approx_eq!((-1.5f64).round_ties_even(), -2.0f64); + assert_approx_eq!((-1.7f64).round_ties_even(), -2.0f64); +} + +#[test] fn test_trunc() { assert_approx_eq!(1.0f64.trunc(), 1.0f64); assert_approx_eq!(1.3f64.trunc(), 1.0f64); diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 80ed34157e6..5c0541d3caf 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -6,7 +6,6 @@ use crate::cmp; use crate::collections::TryReserveError; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::iter::Extend; use crate::ops; use crate::rc::Rc; use crate::str::FromStr; diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c550378e7d6..6640c7fb162 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -249,9 +249,9 @@ pub struct DirBuilder { pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> { fn inner(path: &Path) -> io::Result<Vec<u8>> { let mut file = File::open(path)?; - let size = file.metadata().map(|m| m.len()).unwrap_or(0); - let mut bytes = Vec::with_capacity(size as usize); - io::default_read_to_end(&mut file, &mut bytes)?; + let size = file.metadata().map(|m| m.len() as usize).ok(); + let mut bytes = Vec::with_capacity(size.unwrap_or(0)); + io::default_read_to_end(&mut file, &mut bytes, size)?; Ok(bytes) } inner(path.as_ref()) @@ -289,9 +289,9 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> { pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> { fn inner(path: &Path) -> io::Result<String> { let mut file = File::open(path)?; - let size = file.metadata().map(|m| m.len()).unwrap_or(0); - let mut string = String::with_capacity(size as usize); - io::default_read_to_string(&mut file, &mut string)?; + let size = file.metadata().map(|m| m.len() as usize).ok(); + let mut string = String::with_capacity(size.unwrap_or(0)); + io::default_read_to_string(&mut file, &mut string, size)?; Ok(string) } inner(path.as_ref()) @@ -709,6 +709,7 @@ impl File { // `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows. impl AsInner<fs_imp::File> for File { + #[inline] fn as_inner(&self) -> &fs_imp::File { &self.inner } @@ -732,12 +733,12 @@ impl fmt::Debug for File { } /// Indicates how much extra capacity is needed to read the rest of the file. -fn buffer_capacity_required(mut file: &File) -> usize { - let size = file.metadata().map(|m| m.len()).unwrap_or(0); - let pos = file.stream_position().unwrap_or(0); +fn buffer_capacity_required(mut file: &File) -> Option<usize> { + let size = file.metadata().map(|m| m.len()).ok()?; + let pos = file.stream_position().ok()?; // Don't worry about `usize` overflow because reading will fail regardless // in that case. - size.saturating_sub(pos) as usize + Some(size.saturating_sub(pos) as usize) } #[stable(feature = "rust1", since = "1.0.0")] @@ -761,14 +762,16 @@ impl Read for File { // Reserves space in the buffer based on the file size when available. fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { - buf.reserve(buffer_capacity_required(self)); - io::default_read_to_end(self, buf) + let size = buffer_capacity_required(self); + buf.reserve(size.unwrap_or(0)); + io::default_read_to_end(self, buf, size) } // Reserves space in the buffer based on the file size when available. fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { - buf.reserve(buffer_capacity_required(self)); - io::default_read_to_string(self, buf) + let size = buffer_capacity_required(self); + buf.reserve(size.unwrap_or(0)); + io::default_read_to_string(self, buf, size) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -817,14 +820,16 @@ impl Read for &File { // Reserves space in the buffer based on the file size when available. fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { - buf.reserve(buffer_capacity_required(self)); - io::default_read_to_end(self, buf) + let size = buffer_capacity_required(self); + buf.reserve(size.unwrap_or(0)); + io::default_read_to_end(self, buf, size) } // Reserves space in the buffer based on the file size when available. fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { - buf.reserve(buffer_capacity_required(self)); - io::default_read_to_string(self, buf) + let size = buffer_capacity_required(self); + buf.reserve(size.unwrap_or(0)); + io::default_read_to_string(self, buf, size) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1083,12 +1088,14 @@ impl OpenOptions { } impl AsInner<fs_imp::OpenOptions> for OpenOptions { + #[inline] fn as_inner(&self) -> &fs_imp::OpenOptions { &self.0 } } impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions { + #[inline] fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 } @@ -1348,6 +1355,7 @@ impl fmt::Debug for Metadata { } impl AsInner<fs_imp::FileAttr> for Metadata { + #[inline] fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 } @@ -1600,6 +1608,7 @@ impl FileType { } impl AsInner<fs_imp::FileType> for FileType { + #[inline] fn as_inner(&self) -> &fs_imp::FileType { &self.0 } @@ -1612,6 +1621,7 @@ impl FromInner<fs_imp::FilePermissions> for Permissions { } impl AsInner<fs_imp::FilePermissions> for Permissions { + #[inline] fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 } @@ -1766,6 +1776,7 @@ impl fmt::Debug for DirEntry { } impl AsInner<fs_imp::DirEntry> for DirEntry { + #[inline] fn as_inner(&self) -> &fs_imp::DirEntry { &self.0 } @@ -2280,6 +2291,11 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// /// See [`fs::remove_file`] and [`fs::remove_dir`]. /// +/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root path. +/// As a result, the directory you are deleting must exist, meaning that this function is not idempotent. +/// +/// Consider ignoring the error if validating the removal is not required for your use case. +/// /// [`fs::remove_file`]: remove_file /// [`fs::remove_dir`]: remove_dir /// @@ -2501,6 +2517,7 @@ impl DirBuilder { } impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder { + #[inline] fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder { &mut self.inner } @@ -2511,9 +2528,10 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `Ok(false)`. /// -/// As opposed to the [`Path::exists`] method, this one doesn't silently ignore errors -/// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission -/// denied on some of the parent directories.) +/// As opposed to the [`Path::exists`] method, this will only return `Ok(true)` or `Ok(false)` +/// if the path was _verified_ to exist or not exist. If its existence can neither be confirmed +/// nor denied, an `Err(_)` will be propagated instead. This can be the case if e.g. listing +/// permission is denied on one of the parent directories. /// /// Note that while this avoids some pitfalls of the `exists()` method, it still can not /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 839fdc96632..a8a0b9f122d 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -2,7 +2,8 @@ use crate::io::prelude::*; use crate::env; use crate::fs::{self, File, OpenOptions}; -use crate::io::{ErrorKind, SeekFrom}; +use crate::io::{BorrowedBuf, ErrorKind, SeekFrom}; +use crate::mem::MaybeUninit; use crate::path::Path; use crate::str; use crate::sync::Arc; @@ -402,6 +403,23 @@ fn file_test_io_seek_read_write() { } #[test] +fn file_test_read_buf() { + let tmpdir = tmpdir(); + let filename = &tmpdir.join("test"); + check!(fs::write(filename, &[1, 2, 3, 4])); + + let mut buf: [MaybeUninit<u8>; 128] = MaybeUninit::uninit_array(); + let mut buf = BorrowedBuf::from(buf.as_mut_slice()); + let mut file = check!(File::open(filename)); + check!(file.read_buf(buf.unfilled())); + assert_eq!(buf.filled(), &[1, 2, 3, 4]); + // File::read_buf should omit buffer initialization. + assert_eq!(buf.init_len(), 4); + + check!(fs::remove_file(filename)); +} + +#[test] fn file_test_stat_is_correct_on_is_file() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_stat_correct_on_is_file.txt"); @@ -901,6 +919,7 @@ fn symlink_noexist() { #[test] fn read_link() { + let tmpdir = tmpdir(); if cfg!(windows) { // directory symlink assert_eq!(check!(fs::read_link(r"C:\Users\All Users")), Path::new(r"C:\ProgramData")); @@ -915,8 +934,11 @@ fn read_link() { Path::new(r"C:\Users") ); } + // Check that readlink works with non-drive paths on Windows. + let link = tmpdir.join("link_unc"); + check!(symlink_dir(r"\\localhost\c$\", &link)); + assert_eq!(check!(fs::read_link(&link)), Path::new(r"\\localhost\c$\")); } - let tmpdir = tmpdir(); let link = tmpdir.join("link"); if !got_symlink_permission(&tmpdir) { return; @@ -1595,3 +1617,19 @@ fn test_read_dir_infinite_loop() { // Check for duplicate errors assert!(dir.filter(|e| e.is_err()).take(2).count() < 2); } + +#[test] +fn rename_directory() { + let tmpdir = tmpdir(); + let old_path = tmpdir.join("foo/bar/baz"); + fs::create_dir_all(&old_path).unwrap(); + let test_file = &old_path.join("temp.txt"); + + File::create(test_file).unwrap(); + + let new_path = tmpdir.join("quux/blat"); + fs::create_dir_all(&new_path).unwrap(); + fs::rename(&old_path, &new_path.join("newdir")).unwrap(); + assert!(new_path.join("newdir").is_dir()); + assert!(new_path.join("newdir/temp.txt").exists()); +} diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 6acb937e784..14c455d4fa3 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -339,7 +339,7 @@ impl<W: Write> BufWriter<W> { let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; // SAFETY: forget(self) prevents double dropping inner - let inner = unsafe { ptr::read(&mut self.inner) }; + let inner = unsafe { ptr::read(&self.inner) }; mem::forget(self); (inner, buf) diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index 4c1b7d57684..35a5291a347 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -831,9 +831,9 @@ fn partial_line_buffered_after_line_write() { assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3"); } -/// Test that, given a partial line that exceeds the length of -/// LineBuffer's buffer (that is, without a trailing newline), that that -/// line is written to the inner writer +/// Test that for calls to LineBuffer::write where the passed bytes do not contain +/// a newline and on their own are greater in length than the internal buffer, the +/// passed bytes are immediately written to the inner writer. #[test] fn long_line_flushed() { let writer = ProgrammableSink::default(); @@ -844,9 +844,10 @@ fn long_line_flushed() { } /// Test that, given a very long partial line *after* successfully -/// flushing a complete line, that that line is buffered unconditionally, -/// and no additional writes take place. This assures the property that -/// `write` should make at-most-one attempt to write new data. +/// flushing a complete line, the very long partial line is buffered +/// unconditionally, and no additional writes take place. This assures +/// the property that `write` should make at-most-one attempt to write +/// new data. #[test] fn line_long_tail_not_flushed() { let writer = ProgrammableSink::default(); diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index d98ab021cad..25c64240e74 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -34,7 +34,7 @@ use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; /// use std::fs::File; /// /// // a library function we've written -/// fn write_ten_bytes_at_end<W: Write + Seek>(writer: &mut W) -> io::Result<()> { +/// fn write_ten_bytes_at_end<W: Write + Seek>(mut writer: W) -> io::Result<()> { /// writer.seek(SeekFrom::End(-10))?; /// /// for i in 0..10 { diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 7f07e4fddef..34c0ce9dcf8 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -11,7 +11,6 @@ mod repr_unpacked; #[cfg(not(target_pointer_width = "64"))] use repr_unpacked::Repr; -use crate::convert::From; use crate::error; use crate::fmt; use crate::result; @@ -370,7 +369,7 @@ pub enum ErrorKind { // "Unusual" error kinds which do not correspond simply to (sets // of) OS error codes, should be added just above this comment. - // `Other` and `Uncategorised` should remain at the end: + // `Other` and `Uncategorized` should remain at the end: // /// A custom error that does not fall under any other I/O error kind. /// @@ -882,6 +881,13 @@ impl Error { /// Returns the corresponding [`ErrorKind`] for this error. /// + /// This may be a value set by Rust code constructing custom `io::Error`s, + /// or if this `io::Error` was sourced from the operating system, + /// it will be a value inferred from the system's error encoding. + /// See [`last_os_error`] for more details. + /// + /// [`last_os_error`]: Error::last_os_error + /// /// # Examples /// /// ``` @@ -892,7 +898,8 @@ impl Error { /// } /// /// fn main() { - /// // Will print "Uncategorized". + /// // As no error has (visibly) occurred, this may print anything! + /// // It likely prints a placeholder for unidentified (non-)errors. /// print_error(Error::last_os_error()); /// // Will print "AddrInUse". /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index e5048dcc8ac..a7428776d8f 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -9,6 +9,7 @@ use crate::io::{ self, BorrowedCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, }; use crate::mem; +use crate::str; // ============================================================================= // Forwarding implementations @@ -307,6 +308,17 @@ impl Read for &[u8] { *self = &self[len..]; Ok(len) } + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { + let content = str::from_utf8(self).map_err(|_| { + io::const_io_error!(ErrorKind::InvalidData, "stream did not contain valid UTF-8") + })?; + buf.push_str(content); + let len = self.len(); + *self = &self[len..]; + Ok(len) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -336,7 +348,7 @@ impl Write for &mut [u8] { #[inline] fn write(&mut self, data: &[u8]) -> io::Result<usize> { let amt = cmp::min(data.len(), self.len()); - let (a, b) = mem::replace(self, &mut []).split_at_mut(amt); + let (a, b) = mem::take(self).split_at_mut(amt); a.copy_from_slice(&data[..amt]); *self = b; Ok(amt) @@ -434,6 +446,33 @@ impl<A: Allocator> Read for VecDeque<u8, A> { self.drain(..n); Ok(()) } + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + // The total len is known upfront so we can reserve it in a single call. + let len = self.len(); + buf.reserve(len); + + let (front, back) = self.as_slices(); + buf.extend_from_slice(front); + buf.extend_from_slice(back); + self.clear(); + Ok(len) + } + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { + // We have to use a single contiguous slice because the `VecDequeue` might be split in the + // middle of an UTF-8 character. + let len = self.len(); + let content = self.make_contiguous(); + let string = str::from_utf8(content).map_err(|_| { + io::const_io_error!(ErrorKind::InvalidData, "stream did not contain valid UTF-8") + })?; + buf.push_str(string); + self.clear(); + Ok(len) + } } /// Write is implemented for `VecDeque<u8>` by appending to the `VecDeque`, growing it as needed. @@ -446,6 +485,21 @@ impl<A: Allocator> Write for VecDeque<u8, A> { } #[inline] + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { + let len = bufs.iter().map(|b| b.len()).sum(); + self.reserve(len); + for buf in bufs { + self.extend(&**buf); + } + Ok(len) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true + } + + #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.extend(buf); Ok(()) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index b2b6d86134b..9e09ce337bc 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -253,7 +253,7 @@ mod tests; use crate::cmp; use crate::fmt; -use crate::mem::replace; +use crate::mem::take; use crate::ops::{Deref, DerefMut}; use crate::slice; use crate::str; @@ -268,7 +268,7 @@ pub(crate) use self::stdio::attempt_print_to_stderr; #[unstable(feature = "internal_output_capture", issue = "none")] #[doc(no_inline, hidden)] pub use self::stdio::set_output_capture; -#[unstable(feature = "is_terminal", issue = "98070")] +#[stable(feature = "is_terminal", since = "1.70.0")] pub use self::stdio::IsTerminal; #[unstable(feature = "print_internals", issue = "none")] pub use self::stdio::{_eprint, _print}; @@ -357,9 +357,17 @@ where // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every // time is 4,500 times (!) slower than a default reservation size of 32 if the // reader has a very small amount of data to return. -pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> { +pub(crate) fn default_read_to_end<R: Read + ?Sized>( + r: &mut R, + buf: &mut Vec<u8>, + size_hint: Option<usize>, +) -> Result<usize> { let start_len = buf.len(); let start_cap = buf.capacity(); + // Optionally limit the maximum bytes read on each iteration. + // This adds an arbitrary fiddle factor to allow for more data than we expect. + let max_read_size = + size_hint.and_then(|s| s.checked_add(1024)?.checked_next_multiple_of(DEFAULT_BUF_SIZE)); let mut initialized = 0; // Extra initialized bytes from previous loop iteration loop { @@ -367,7 +375,12 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8> buf.reserve(32); // buf is full, need more space } - let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into(); + let mut spare = buf.spare_capacity_mut(); + if let Some(size) = max_read_size { + let len = cmp::min(spare.len(), size); + spare = &mut spare[..len] + } + let mut read_buf: BorrowedBuf<'_> = spare.into(); // SAFETY: These bytes were initialized but not filled in the previous loop unsafe { @@ -419,6 +432,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8> pub(crate) fn default_read_to_string<R: Read + ?Sized>( r: &mut R, buf: &mut String, + size_hint: Option<usize>, ) -> Result<usize> { // Note that we do *not* call `r.read_to_end()` here. We are passing // `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end` @@ -429,7 +443,7 @@ pub(crate) fn default_read_to_string<R: Read + ?Sized>( // To prevent extraneously checking the UTF-8-ness of the entire buffer // we pass it to our hardcoded `default_read_to_end` implementation which // we know is guaranteed to only read data into the end of the buffer. - unsafe { append_to_string(buf, |b| default_read_to_end(r, b)) } + unsafe { append_to_string(buf, |b| default_read_to_end(r, b, size_hint)) } } pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> @@ -709,7 +723,7 @@ pub trait Read { /// [`std::fs::read`]: crate::fs::read #[stable(feature = "rust1", since = "1.0.0")] fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { - default_read_to_end(self, buf) + default_read_to_end(self, buf, None) } /// Read all bytes until EOF in this source, appending them to `buf`. @@ -752,7 +766,7 @@ pub trait Read { /// [`std::fs::read_to_string`]: crate::fs::read_to_string #[stable(feature = "rust1", since = "1.0.0")] fn read_to_string(&mut self, buf: &mut String) -> Result<usize> { - default_read_to_string(self, buf) + default_read_to_string(self, buf, None) } /// Read the exact number of bytes required to fill `buf`. @@ -823,8 +837,22 @@ pub trait Read { /// Read the exact number of bytes required to fill `cursor`. /// - /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to - /// allow use with uninitialized buffers. + /// This is similar to the [`read_exact`](Read::read_exact) method, except + /// that it is passed a [`BorrowedCursor`] rather than `[u8]` to allow use + /// with uninitialized buffers. + /// + /// # Errors + /// + /// If this function encounters an error of the kind [`ErrorKind::Interrupted`] + /// then the error is ignored and the operation will continue. + /// + /// If this function encounters an "end of file" before completely filling + /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. + /// + /// If any other read error is encountered then this function immediately + /// returns. + /// + /// If this function returns an error, all bytes read will be appended to `cursor`. #[unstable(feature = "read_buf", issue = "78485")] fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> Result<()> { while cursor.capacity() > 0 { @@ -1172,7 +1200,7 @@ impl<'a> IoSliceMut<'a> { } } - *bufs = &mut replace(bufs, &mut [])[remove..]; + *bufs = &mut take(bufs)[remove..]; if bufs.is_empty() { assert!(n == accumulated_len, "advancing io slices beyond their length"); } else { @@ -1315,7 +1343,7 @@ impl<'a> IoSlice<'a> { } } - *bufs = &mut replace(bufs, &mut [])[remove..]; + *bufs = &mut take(bufs)[remove..]; if bufs.is_empty() { assert!(n == accumulated_len, "advancing io slices beyond their length"); } else { diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index cc1b423f2dd..89a2f6b2271 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -36,7 +36,7 @@ fn initialize_unfilled() { } #[test] -fn addvance_filled() { +fn advance_filled() { let buf: &mut [_] = &mut [0; 16]; let mut rbuf: BorrowedBuf<'_> = buf.into(); diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 14bfef4c7aa..9098d36ee53 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -8,7 +8,7 @@ use crate::io::prelude::*; use crate::cell::{Cell, RefCell}; use crate::fmt; use crate::fs::File; -use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines}; +use crate::io::{self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines}; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard}; use crate::sys::stdio; @@ -97,6 +97,10 @@ impl Read for StdinRaw { handle_ebadf(self.0.read(buf), 0) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + handle_ebadf(self.0.read_buf(buf), ()) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { handle_ebadf(self.0.read_vectored(bufs), 0) } @@ -418,6 +422,9 @@ impl Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.lock().read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.lock().read_buf(buf) + } fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.lock().read_vectored(bufs) } @@ -450,6 +457,10 @@ impl Read for StdinLock<'_> { self.inner.read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.inner.read_buf(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.inner.read_vectored(bufs) } @@ -1036,13 +1047,23 @@ pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) { } /// Trait to determine if a descriptor/handle refers to a terminal/tty. -#[unstable(feature = "is_terminal", issue = "98070")] +#[stable(feature = "is_terminal", since = "1.70.0")] pub trait IsTerminal: crate::sealed::Sealed { /// Returns `true` if the descriptor/handle refers to a terminal/tty. /// /// On platforms where Rust does not know how to detect a terminal yet, this will return /// `false`. This will also return `false` if an unexpected error occurred, such as from /// passing an invalid file descriptor. + /// + /// # Platform-specific behavior + /// + /// On Windows, in addition to detecting consoles, this currently uses some heuristics to + /// detect older msys/cygwin/mingw pseudo-terminals based on device name: devices with names + /// starting with `msys-` or `cygwin-` and ending in `-pty` will be considered terminals. + /// Note that this [may change in the future][changes]. + /// + /// [changes]: io#platform-specific-behavior + #[stable(feature = "is_terminal", since = "1.70.0")] fn is_terminal(&self) -> bool; } @@ -1051,7 +1072,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "1.70.0")] impl IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index f4a886d889a..6d30f5e6c6c 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -314,7 +314,7 @@ fn bench_read_to_end(b: &mut test::Bencher) { b.iter(|| { let mut lr = repeat(1).take(10000000); let mut vec = Vec::with_capacity(1024); - super::default_read_to_end(&mut lr, &mut vec) + super::default_read_to_end(&mut lr, &mut vec, None) }); } diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index e35145c4ade..eb46f4e54bb 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1568,7 +1568,7 @@ mod static_keyword {} /// /// # Style conventions /// -/// Structs are always written in CamelCase, with few exceptions. While the trailing comma on a +/// Structs are always written in UpperCamelCase, with few exceptions. While the trailing comma on a /// struct's list of fields can be omitted, it's usually kept for convenience in adding and /// removing fields down the line. /// @@ -1678,7 +1678,7 @@ mod super_keyword {} /// below `Iterator` is a **supertrait** and `ThreeIterator` is a **subtrait**: /// /// ```rust -/// trait ThreeIterator: std::iter::Iterator { +/// trait ThreeIterator: Iterator { /// fn next_three(&mut self) -> Option<[Self::Item; 3]>; /// } /// ``` @@ -1925,7 +1925,7 @@ mod type_keyword {} /// `unsafe_op_in_unsafe_fn` lint can be enabled to warn against that and require explicit unsafe /// blocks even inside `unsafe fn`. /// -/// See the [Rustnomicon] and the [Reference] for more information. +/// See the [Rustonomicon] and the [Reference] for more information. /// /// # Examples /// @@ -2129,7 +2129,7 @@ mod type_keyword {} /// [`impl`]: keyword.impl.html /// [raw pointers]: ../reference/types/pointer.html /// [memory safety]: ../book/ch19-01-unsafe-rust.html -/// [Rustnomicon]: ../nomicon/index.html +/// [Rustonomicon]: ../nomicon/index.html /// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html /// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library /// [Reference]: ../reference/unsafety.html @@ -2287,7 +2287,7 @@ mod use_keyword {} /// # #![allow(dead_code)] /// pub enum Cow<'a, B> /// where -/// B: 'a + ToOwned + ?Sized, +/// B: ToOwned + ?Sized, /// { /// Borrowed(&'a B), /// Owned(<B as ToOwned>::Owned), diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 363a2667174..318a46d1b63 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -232,8 +232,10 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) )] +#![cfg_attr(windows, feature(round_char_boundary))] // // Language features: +// tidy-alphabetical-start #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] @@ -253,11 +255,10 @@ #![feature(exhaustive_patterns)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] -#![feature(is_terminal)] #![feature(lang_items)] #![feature(let_chains)] -#![feature(linkage)] #![feature(link_cfg)] +#![feature(linkage)] #![feature(min_specialization)] #![feature(must_not_suspend)] #![feature(needs_panic_runtime)] @@ -271,9 +272,10 @@ #![feature(thread_local)] #![feature(try_blocks)] #![feature(utf8_chunks)] +// tidy-alphabetical-end // // Library features (core): -#![feature(atomic_mut_ptr)] +// tidy-alphabetical-start #![feature(char_internals)] #![feature(core_intrinsics)] #![feature(duration_constants)] @@ -287,10 +289,12 @@ #![feature(float_next_up_down)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] -#![feature(is_some_and)] +#![feature(int_roundings)] +#![feature(ip)] +#![feature(ip_in_core)] #![feature(maybe_uninit_slice)] +#![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] -#![feature(nonnull_slice_from_raw_parts)] #![feature(panic_can_unwind)] #![feature(panic_info_message)] #![feature(panic_internals)] @@ -301,30 +305,34 @@ #![feature(provide_any)] #![feature(ptr_as_uninit)] #![feature(raw_os_nonzero)] +#![feature(round_ties_even)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(std_internals)] #![feature(str_internals)] #![feature(strict_provenance)] -#![feature(maybe_uninit_uninit_array)] -#![feature(const_maybe_uninit_uninit_array)] -#![feature(const_waker)] +// tidy-alphabetical-end // // Library features (alloc): +// tidy-alphabetical-start #![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(get_mut_unchecked)] #![feature(map_try_insert)] #![feature(new_uninit)] +#![feature(slice_concat_trait)] #![feature(thin_box)] #![feature(try_reserve_kind)] #![feature(vec_into_raw_parts)] -#![feature(slice_concat_trait)] +// tidy-alphabetical-end // // Library features (unwind): +// tidy-alphabetical-start #![feature(panic_unwind)] +// tidy-alphabetical-end // // Only for re-exporting: +// tidy-alphabetical-start #![feature(assert_matches)] #![feature(async_iterator)] #![feature(c_variadic)] @@ -336,24 +344,29 @@ #![feature(custom_test_frameworks)] #![feature(edition_panic)] #![feature(format_args_nl)] +#![feature(get_many_mut)] +#![feature(lazy_cell)] #![feature(log_syntax)] -#![feature(once_cell)] #![feature(saturating_int_impl)] #![feature(stdsimd)] #![feature(test)] #![feature(trace_macros)] -#![feature(get_many_mut)] +// tidy-alphabetical-end // // Only used in tests/benchmarks: // // Only for const-ness: +// tidy-alphabetical-start #![feature(const_collections_with_hasher)] #![feature(const_hash)] #![feature(const_io_structs)] #![feature(const_ip)] #![feature(const_ipv4)] #![feature(const_ipv6)] +#![feature(const_maybe_uninit_uninit_array)] +#![feature(const_waker)] #![feature(thread_local_internals)] +// tidy-alphabetical-end // #![default_lib_allocator] diff --git a/library/std/src/net/ip_addr.rs b/library/std/src/net/ip_addr.rs index 07f08c1b586..e167fbd1b9c 100644 --- a/library/std/src/net/ip_addr.rs +++ b/library/std/src/net/ip_addr.rs @@ -2,2101 +2,40 @@ #[cfg(all(test, not(target_os = "emscripten")))] mod tests; -use crate::cmp::Ordering; -use crate::fmt::{self, Write}; -use crate::mem::transmute; use crate::sys::net::netc as c; use crate::sys_common::{FromInner, IntoInner}; -use super::display_buffer::DisplayBuffer; - -/// 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(not(test), rustc_diagnostic_item = "IpAddr")] #[stable(feature = "ip_addr", since = "1.7.0")] -#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] -pub enum IpAddr { - /// An IPv4 address. - #[stable(feature = "ip_addr", since = "1.7.0")] - V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr), - /// An IPv6 address. - #[stable(feature = "ip_addr", since = "1.7.0")] - V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr), -} +pub use core::net::IpAddr; -/// 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`]: crate::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)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Ipv4Addr { - octets: [u8; 4], -} +pub use core::net::{Ipv4Addr, Ipv6Addr}; -/// 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`]: crate::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)] -#[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)] #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ip", issue = "76205")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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 - /// ); - /// ``` - #[rustc_const_unstable(feature = "const_ip", issue = "76205")] - #[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); - /// ``` - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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"] - #[rustc_const_unstable(feature = "const_ip", issue = "76205")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] - #[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)); - /// ``` - #[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")] - #[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)); - /// ``` - #[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]); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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. - /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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) - /// ); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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)); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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] } - } -} - -#[stable(feature = "ip_addr", since = "1.7.0")] -impl fmt::Display for IpAddr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - IpAddr::V4(ip) => ip.fmt(fmt), - IpAddr::V6(ip) => ip.fmt(fmt), - } - } -} - -#[stable(feature = "ip_addr", since = "1.7.0")] -impl fmt::Debug for IpAddr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, fmt) - } -} - -#[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) - } -} - -#[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) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for Ipv4Addr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let octets = self.octets(); - - // If there are no alignment requirements, write the IP address directly to `f`. - // Otherwise, write it to a local buffer and then use `f.pad`. - if fmt.precision().is_none() && fmt.width().is_none() { - write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]) - } else { - const LONGEST_IPV4_ADDR: &str = "255.255.255.255"; - - let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new(); - // Buffer is long enough for the longest possible IPv4 address, so this should never fail. - write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap(); - - fmt.pad(buf.as_str()) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Ipv4Addr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, fmt) - } -} - -#[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, - } - } -} - -#[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, - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Ipv4Addr { - #[inline] - fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -#[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), - } - } -} - -#[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), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Ipv4Addr { - #[inline] - fn cmp(&self, other: &Ipv4Addr) -> Ordering { - self.octets.cmp(&other.octets) - } -} +pub use core::net::Ipv6MulticastScope; impl IntoInner<c::in_addr> for Ipv4Addr { #[inline] fn into_inner(self) -> c::in_addr { // `s_addr` is stored as BE on all machines and the array is in BE order. // So the native endian conversion method is used so that it's never swapped. - c::in_addr { s_addr: u32::from_ne_bytes(self.octets) } + c::in_addr { s_addr: u32::from_ne_bytes(self.octets()) } } } impl FromInner<c::in_addr> for Ipv4Addr { fn from_inner(addr: c::in_addr) -> Ipv4Addr { - Ipv4Addr { octets: addr.s_addr.to_ne_bytes() } - } -} - -#[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) - } -} - -#[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() } - } -} - -#[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 } - } -} - -#[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] - #[stable(feature = "rust1", since = "1.0.0")] - #[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")] - #[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")] - #[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]); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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. - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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); - /// ``` - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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's 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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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))); - /// ``` - #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] - #[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); - /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[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]); - /// ``` - #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] - #[stable(feature = "ipv6_to_octets", since = "1.12.0")] - #[must_use] - #[inline] - pub const fn octets(&self) -> [u8; 16] { - self.octets - } -} - -/// Write an Ipv6Addr, conforming to the canonical style described by -/// [RFC 5952](https://tools.ietf.org/html/rfc5952). -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for Ipv6Addr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // If there are no alignment requirements, write the IP address directly to `f`. - // Otherwise, write it to a local buffer and then use `f.pad`. - if f.precision().is_none() && f.width().is_none() { - let segments = self.segments(); - - // Special case for :: and ::1; otherwise they get written with the - // IPv4 formatter - if self.is_unspecified() { - f.write_str("::") - } else if self.is_loopback() { - f.write_str("::1") - } else if let Some(ipv4) = self.to_ipv4() { - match segments[5] { - // IPv4 Compatible address - 0 => write!(f, "::{}", ipv4), - // IPv4 Mapped address - 0xffff => write!(f, "::ffff:{}", ipv4), - _ => unreachable!(), - } - } else { - #[derive(Copy, Clone, Default)] - struct Span { - start: usize, - len: usize, - } - - // Find the inner 0 span - let zeroes = { - let mut longest = Span::default(); - let mut current = Span::default(); - - for (i, &segment) in segments.iter().enumerate() { - if segment == 0 { - if current.len == 0 { - current.start = i; - } - - current.len += 1; - - if current.len > longest.len { - longest = current; - } - } else { - current = Span::default(); - } - } - - longest - }; - - /// Write a colon-separated part of the address - #[inline] - fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result { - if let Some((first, tail)) = chunk.split_first() { - write!(f, "{:x}", first)?; - for segment in tail { - f.write_char(':')?; - write!(f, "{:x}", segment)?; - } - } - Ok(()) - } - - if zeroes.len > 1 { - fmt_subslice(f, &segments[..zeroes.start])?; - f.write_str("::")?; - fmt_subslice(f, &segments[zeroes.start + zeroes.len..]) - } else { - fmt_subslice(f, &segments) - } - } - } else { - const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; - - let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new(); - // Buffer is long enough for the longest possible IPv6 address, so this should never fail. - write!(buf, "{}", self).unwrap(); - - f.pad(buf.as_str()) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Ipv6Addr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, fmt) - } -} - -#[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, - } - } -} - -#[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, - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Ipv6Addr { - #[inline] - fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -#[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), - } - } -} - -#[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), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Ipv6Addr { - #[inline] - fn cmp(&self, other: &Ipv6Addr) -> Ordering { - self.segments().cmp(&other.segments()) + Ipv4Addr::from(addr.s_addr.to_ne_bytes()) } } impl IntoInner<c::in6_addr> for Ipv6Addr { fn into_inner(self) -> c::in6_addr { - c::in6_addr { s6_addr: self.octets } + c::in6_addr { s6_addr: self.octets() } } } impl FromInner<c::in6_addr> for Ipv6Addr { #[inline] fn from_inner(addr: c::in6_addr) -> Ipv6Addr { - Ipv6Addr { octets: addr.s6_addr } - } -} - -#[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) - } -} -#[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()) - } -} - -#[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 } - } -} - -#[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) - } -} - -#[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)) - } -} - -#[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)) + Ipv6Addr::from(addr.s6_addr) } } diff --git a/library/std/src/net/ip_addr/tests.rs b/library/std/src/net/ip_addr/tests.rs index 0eb59d45de7..ab99c0c2fcc 100644 --- a/library/std/src/net/ip_addr/tests.rs +++ b/library/std/src/net/ip_addr/tests.rs @@ -1,1039 +1,8 @@ -use crate::net::test::{sa4, sa6, tsa}; -use crate::net::*; -use crate::str::FromStr; - -#[test] -fn test_from_str_ipv4() { - assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse()); - assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse()); - assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse()); - - // out of range - let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok(); - assert_eq!(None, none); - // too short - let none: Option<Ipv4Addr> = "255.0.0".parse().ok(); - assert_eq!(None, none); - // too long - let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok(); - assert_eq!(None, none); - // no number between dots - let none: Option<Ipv4Addr> = "255.0..1".parse().ok(); - assert_eq!(None, none); - // octal - let none: Option<Ipv4Addr> = "255.0.0.01".parse().ok(); - assert_eq!(None, none); - // octal zero - let none: Option<Ipv4Addr> = "255.0.0.00".parse().ok(); - assert_eq!(None, none); - let none: Option<Ipv4Addr> = "255.0.00.0".parse().ok(); - assert_eq!(None, none); -} - -#[test] -fn test_from_str_ipv6() { - assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse()); - assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse()); - - assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse()); - assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse()); - - assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), "2a02:6b8::11:11".parse()); - - // too long group - let none: Option<Ipv6Addr> = "::00000".parse().ok(); - assert_eq!(None, none); - // too short - let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok(); - assert_eq!(None, none); - // too long - let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok(); - assert_eq!(None, none); - // triple colon - let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok(); - assert_eq!(None, none); - // two double colons - let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok(); - assert_eq!(None, none); - // `::` indicating zero groups of zeros - let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok(); - assert_eq!(None, none); -} - -#[test] -fn test_from_str_ipv4_in_ipv6() { - assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse()); - assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), "::FFFF:192.0.2.33".parse()); - assert_eq!( - Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)), - "64:ff9b::192.0.2.33".parse() - ); - assert_eq!( - Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)), - "2001:db8:122:c000:2:2100:192.0.2.33".parse() - ); - - // colon after v4 - let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok(); - assert_eq!(None, none); - // not enough groups - let none: Option<Ipv6Addr> = "1:2:3:4:5:127.0.0.1".parse().ok(); - assert_eq!(None, none); - // too many groups - let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:127.0.0.1".parse().ok(); - assert_eq!(None, none); -} - -#[test] -fn test_from_str_socket_addr() { - assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse()); - assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse()); - assert_eq!( - Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), - "[2a02:6b8:0:1::1]:53".parse() - ); - assert_eq!( - Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)), - "[2a02:6b8:0:1::1]:53".parse() - ); - assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), "[::127.0.0.1]:22".parse()); - assert_eq!( - Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)), - "[::127.0.0.1]:22".parse() - ); - - // without port - let none: Option<SocketAddr> = "127.0.0.1".parse().ok(); - assert_eq!(None, none); - // without port - let none: Option<SocketAddr> = "127.0.0.1:".parse().ok(); - assert_eq!(None, none); - // wrong brackets around v4 - let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok(); - assert_eq!(None, none); - // port out of range - let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok(); - assert_eq!(None, none); -} - -#[test] -fn ipv4_addr_to_string() { - assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1"); - // Short address - assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1"); - // Long address - assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127"); - - // Test padding - assert_eq!(format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 "); - assert_eq!(format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1"); -} - -#[test] -fn ipv6_addr_to_string() { - // ipv4-mapped address - let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280); - assert_eq!(a1.to_string(), "::ffff:192.0.2.128"); - - // ipv4-compatible address - let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280); - assert_eq!(a1.to_string(), "::192.0.2.128"); - - // v6 address with no zero segments - assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f"); - - // longest possible IPv6 length - assert_eq!( - Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888).to_string(), - "1111:2222:3333:4444:5555:6666:7777:8888" - ); - // padding - assert_eq!(format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8 "); - assert_eq!(format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), " 1:2:3:4:5:6:7:8"); - - // reduce a single run of zeros - assert_eq!( - "ae::ffff:102:304", - Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string() - ); - - // don't reduce just a single zero segment - assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string()); - - // 'any' address - assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string()); - - // loopback address - assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string()); - - // ends in zeros - assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string()); - - // two runs of zeros, second one is longer - assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string()); - - // two runs of zeros, equal length - assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string()); - - // don't prefix `0x` to each segment in `dbg!`. - assert_eq!("1::4:5:0:0:8", &format!("{:#?}", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8))); -} - -#[test] -fn ipv4_to_ipv6() { - assert_eq!( - Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678), - Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped() - ); - assert_eq!( - Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678), - Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible() - ); -} - -#[test] -fn ipv6_to_ipv4_mapped() { - assert_eq!( - Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(), - Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)) - ); - assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None); -} - -#[test] -fn ipv6_to_ipv4() { - assert_eq!( - Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(), - Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)) - ); - assert_eq!( - Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), - Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)) - ); - assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None); -} - -#[test] -fn ip_properties() { - macro_rules! ip { - ($s:expr) => { - IpAddr::from_str($s).unwrap() - }; - } - - macro_rules! check { - ($s:expr) => { - check!($s, 0); - }; - - ($s:expr, $mask:expr) => {{ - let unspec: u8 = 1 << 0; - let loopback: u8 = 1 << 1; - let global: u8 = 1 << 2; - let multicast: u8 = 1 << 3; - let doc: u8 = 1 << 4; - let benchmarking: u8 = 1 << 5; - - if ($mask & unspec) == unspec { - assert!(ip!($s).is_unspecified()); - } else { - assert!(!ip!($s).is_unspecified()); - } - - if ($mask & loopback) == loopback { - assert!(ip!($s).is_loopback()); - } else { - assert!(!ip!($s).is_loopback()); - } - - if ($mask & global) == global { - assert!(ip!($s).is_global()); - } else { - assert!(!ip!($s).is_global()); - } - - if ($mask & multicast) == multicast { - assert!(ip!($s).is_multicast()); - } else { - assert!(!ip!($s).is_multicast()); - } - - if ($mask & doc) == doc { - assert!(ip!($s).is_documentation()); - } else { - assert!(!ip!($s).is_documentation()); - } - - if ($mask & benchmarking) == benchmarking { - assert!(ip!($s).is_benchmarking()); - } else { - assert!(!ip!($s).is_benchmarking()); - } - }}; - } - - let unspec: u8 = 1 << 0; - let loopback: u8 = 1 << 1; - let global: u8 = 1 << 2; - let multicast: u8 = 1 << 3; - let doc: u8 = 1 << 4; - let benchmarking: u8 = 1 << 5; - - check!("0.0.0.0", unspec); - check!("0.0.0.1"); - check!("0.1.0.0"); - check!("10.9.8.7"); - check!("127.1.2.3", loopback); - check!("172.31.254.253"); - check!("169.254.253.242"); - check!("192.0.2.183", doc); - check!("192.1.2.183", global); - check!("192.168.254.253"); - check!("198.51.100.0", doc); - check!("203.0.113.0", doc); - check!("203.2.113.0", global); - check!("224.0.0.0", global | multicast); - check!("239.255.255.255", global | multicast); - check!("255.255.255.255"); - // make sure benchmarking addresses are not global - check!("198.18.0.0", benchmarking); - check!("198.18.54.2", benchmarking); - check!("198.19.255.255", benchmarking); - // make sure addresses reserved for protocol assignment are not global - check!("192.0.0.0"); - check!("192.0.0.255"); - check!("192.0.0.100"); - // make sure reserved addresses are not global - check!("240.0.0.0"); - check!("251.54.1.76"); - check!("254.255.255.255"); - // make sure shared addresses are not global - check!("100.64.0.0"); - check!("100.127.255.255"); - check!("100.100.100.0"); - - check!("::", unspec); - check!("::1", loopback); - check!("::0.0.0.2", global); - check!("1::", global); - check!("fc00::"); - check!("fdff:ffff::"); - check!("fe80:ffff::"); - check!("febf:ffff::"); - check!("fec0::", global); - check!("ff01::", global | multicast); - check!("ff02::", global | multicast); - check!("ff03::", global | multicast); - check!("ff04::", global | multicast); - check!("ff05::", global | multicast); - check!("ff08::", global | multicast); - check!("ff0e::", global | multicast); - check!("2001:db8:85a3::8a2e:370:7334", doc); - check!("2001:2::ac32:23ff:21", benchmarking); - check!("102:304:506:708:90a:b0c:d0e:f10", global); -} - -#[test] -fn ipv4_properties() { - macro_rules! ip { - ($s:expr) => { - Ipv4Addr::from_str($s).unwrap() - }; - } - - macro_rules! check { - ($s:expr) => { - check!($s, 0); - }; - - ($s:expr, $mask:expr) => {{ - let unspec: u16 = 1 << 0; - let loopback: u16 = 1 << 1; - let private: u16 = 1 << 2; - let link_local: u16 = 1 << 3; - let global: u16 = 1 << 4; - let multicast: u16 = 1 << 5; - let broadcast: u16 = 1 << 6; - let documentation: u16 = 1 << 7; - let benchmarking: u16 = 1 << 8; - let reserved: u16 = 1 << 10; - let shared: u16 = 1 << 11; - - if ($mask & unspec) == unspec { - assert!(ip!($s).is_unspecified()); - } else { - assert!(!ip!($s).is_unspecified()); - } - - if ($mask & loopback) == loopback { - assert!(ip!($s).is_loopback()); - } else { - assert!(!ip!($s).is_loopback()); - } - - if ($mask & private) == private { - assert!(ip!($s).is_private()); - } else { - assert!(!ip!($s).is_private()); - } - - if ($mask & link_local) == link_local { - assert!(ip!($s).is_link_local()); - } else { - assert!(!ip!($s).is_link_local()); - } - - if ($mask & global) == global { - assert!(ip!($s).is_global()); - } else { - assert!(!ip!($s).is_global()); - } - - if ($mask & multicast) == multicast { - assert!(ip!($s).is_multicast()); - } else { - assert!(!ip!($s).is_multicast()); - } - - if ($mask & broadcast) == broadcast { - assert!(ip!($s).is_broadcast()); - } else { - assert!(!ip!($s).is_broadcast()); - } - - if ($mask & documentation) == documentation { - assert!(ip!($s).is_documentation()); - } else { - assert!(!ip!($s).is_documentation()); - } - - if ($mask & benchmarking) == benchmarking { - assert!(ip!($s).is_benchmarking()); - } else { - assert!(!ip!($s).is_benchmarking()); - } - - if ($mask & reserved) == reserved { - assert!(ip!($s).is_reserved()); - } else { - assert!(!ip!($s).is_reserved()); - } - - if ($mask & shared) == shared { - assert!(ip!($s).is_shared()); - } else { - assert!(!ip!($s).is_shared()); - } - }}; - } - - let unspec: u16 = 1 << 0; - let loopback: u16 = 1 << 1; - let private: u16 = 1 << 2; - let link_local: u16 = 1 << 3; - let global: u16 = 1 << 4; - let multicast: u16 = 1 << 5; - let broadcast: u16 = 1 << 6; - let documentation: u16 = 1 << 7; - let benchmarking: u16 = 1 << 8; - let reserved: u16 = 1 << 10; - let shared: u16 = 1 << 11; - - check!("0.0.0.0", unspec); - check!("0.0.0.1"); - check!("0.1.0.0"); - check!("10.9.8.7", private); - check!("127.1.2.3", loopback); - check!("172.31.254.253", private); - check!("169.254.253.242", link_local); - check!("192.0.2.183", documentation); - check!("192.1.2.183", global); - check!("192.168.254.253", private); - check!("198.51.100.0", documentation); - check!("203.0.113.0", documentation); - check!("203.2.113.0", global); - check!("224.0.0.0", global | multicast); - check!("239.255.255.255", global | multicast); - check!("255.255.255.255", broadcast); - check!("198.18.0.0", benchmarking); - check!("198.18.54.2", benchmarking); - check!("198.19.255.255", benchmarking); - check!("192.0.0.0"); - check!("192.0.0.255"); - check!("192.0.0.100"); - check!("240.0.0.0", reserved); - check!("251.54.1.76", reserved); - check!("254.255.255.255", reserved); - check!("100.64.0.0", shared); - check!("100.127.255.255", shared); - check!("100.100.100.0", shared); -} - -#[test] -fn ipv6_properties() { - macro_rules! ip { - ($s:expr) => { - Ipv6Addr::from_str($s).unwrap() - }; - } - - macro_rules! check { - ($s:expr, &[$($octet:expr),*], $mask:expr) => { - assert_eq!($s, ip!($s).to_string()); - let octets = &[$($octet),*]; - assert_eq!(&ip!($s).octets(), octets); - assert_eq!(Ipv6Addr::from(*octets), ip!($s)); - - let unspecified: u32 = 1 << 0; - let loopback: u32 = 1 << 1; - let unique_local: u32 = 1 << 2; - let global: u32 = 1 << 3; - let unicast_link_local: u32 = 1 << 4; - let unicast_global: u32 = 1 << 7; - let documentation: u32 = 1 << 8; - let benchmarking: u32 = 1 << 16; - let multicast_interface_local: u32 = 1 << 9; - let multicast_link_local: u32 = 1 << 10; - let multicast_realm_local: u32 = 1 << 11; - let multicast_admin_local: u32 = 1 << 12; - let multicast_site_local: u32 = 1 << 13; - let multicast_organization_local: u32 = 1 << 14; - let multicast_global: u32 = 1 << 15; - let multicast: u32 = multicast_interface_local - | multicast_admin_local - | multicast_global - | multicast_link_local - | multicast_realm_local - | multicast_site_local - | multicast_organization_local; - - if ($mask & unspecified) == unspecified { - assert!(ip!($s).is_unspecified()); - } else { - assert!(!ip!($s).is_unspecified()); - } - if ($mask & loopback) == loopback { - assert!(ip!($s).is_loopback()); - } else { - assert!(!ip!($s).is_loopback()); - } - if ($mask & unique_local) == unique_local { - assert!(ip!($s).is_unique_local()); - } else { - assert!(!ip!($s).is_unique_local()); - } - if ($mask & global) == global { - assert!(ip!($s).is_global()); - } else { - assert!(!ip!($s).is_global()); - } - if ($mask & unicast_link_local) == unicast_link_local { - assert!(ip!($s).is_unicast_link_local()); - } else { - assert!(!ip!($s).is_unicast_link_local()); - } - if ($mask & unicast_global) == unicast_global { - assert!(ip!($s).is_unicast_global()); - } else { - assert!(!ip!($s).is_unicast_global()); - } - if ($mask & documentation) == documentation { - assert!(ip!($s).is_documentation()); - } else { - assert!(!ip!($s).is_documentation()); - } - if ($mask & benchmarking) == benchmarking { - assert!(ip!($s).is_benchmarking()); - } else { - assert!(!ip!($s).is_benchmarking()); - } - if ($mask & multicast) != 0 { - assert!(ip!($s).multicast_scope().is_some()); - assert!(ip!($s).is_multicast()); - } else { - assert!(ip!($s).multicast_scope().is_none()); - assert!(!ip!($s).is_multicast()); - } - if ($mask & multicast_interface_local) == multicast_interface_local { - assert_eq!(ip!($s).multicast_scope().unwrap(), - Ipv6MulticastScope::InterfaceLocal); - } - if ($mask & multicast_link_local) == multicast_link_local { - assert_eq!(ip!($s).multicast_scope().unwrap(), - Ipv6MulticastScope::LinkLocal); - } - if ($mask & multicast_realm_local) == multicast_realm_local { - assert_eq!(ip!($s).multicast_scope().unwrap(), - Ipv6MulticastScope::RealmLocal); - } - if ($mask & multicast_admin_local) == multicast_admin_local { - assert_eq!(ip!($s).multicast_scope().unwrap(), - Ipv6MulticastScope::AdminLocal); - } - if ($mask & multicast_site_local) == multicast_site_local { - assert_eq!(ip!($s).multicast_scope().unwrap(), - Ipv6MulticastScope::SiteLocal); - } - if ($mask & multicast_organization_local) == multicast_organization_local { - assert_eq!(ip!($s).multicast_scope().unwrap(), - Ipv6MulticastScope::OrganizationLocal); - } - if ($mask & multicast_global) == multicast_global { - assert_eq!(ip!($s).multicast_scope().unwrap(), - Ipv6MulticastScope::Global); - } - } - } - - let unspecified: u32 = 1 << 0; - let loopback: u32 = 1 << 1; - let unique_local: u32 = 1 << 2; - let global: u32 = 1 << 3; - let unicast_link_local: u32 = 1 << 4; - let unicast_global: u32 = 1 << 7; - let documentation: u32 = 1 << 8; - let benchmarking: u32 = 1 << 16; - let multicast_interface_local: u32 = 1 << 9; - let multicast_link_local: u32 = 1 << 10; - let multicast_realm_local: u32 = 1 << 11; - let multicast_admin_local: u32 = 1 << 12; - let multicast_site_local: u32 = 1 << 13; - let multicast_organization_local: u32 = 1 << 14; - let multicast_global: u32 = 1 << 15; - - check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified); - - check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback); - - check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global); - - check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global); - - check!( - "::ffff:127.0.0.1", - &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1], - unicast_global - ); - - check!( - "64:ff9b:1::", - &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_global - ); - - check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); - - check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); - - check!( - "2001:1::1", - &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], - global | unicast_global - ); - - check!( - "2001:1::2", - &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], - global | unicast_global - ); - - check!( - "2001:3::", - &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - global | unicast_global - ); - - check!( - "2001:4:112::", - &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - global | unicast_global - ); - - check!( - "2001:20::", - &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - global | unicast_global - ); - - check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); - - check!( - "2001:200::", - &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - global | unicast_global - ); - - check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local); - - check!( - "fdff:ffff::", - &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unique_local - ); - - check!( - "fe80:ffff::", - &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_link_local - ); - - check!("fe80::", &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local); - - check!( - "febf:ffff::", - &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_link_local - ); - - check!("febf::", &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local); - - check!( - "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - &[ - 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff - ], - unicast_link_local - ); - - check!( - "fe80::ffff:ffff:ffff:ffff", - &[ - 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff - ], - unicast_link_local - ); - - check!( - "fe80:0:0:1::", - &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_link_local - ); - - check!( - "fec0::", - &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_global | global - ); - - check!( - "ff01::", - &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_interface_local | global - ); - - check!( - "ff02::", - &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_link_local | global - ); - - check!( - "ff03::", - &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_realm_local | global - ); - - check!( - "ff04::", - &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_admin_local | global - ); - - check!( - "ff05::", - &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_site_local | global - ); - - check!( - "ff08::", - &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_organization_local | global - ); - - check!( - "ff0e::", - &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_global | global - ); - - check!( - "2001:db8:85a3::8a2e:370:7334", - &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], - documentation - ); - - check!( - "2001:2::ac32:23ff:21", - &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21], - benchmarking - ); - - check!( - "102:304:506:708:90a:b0c:d0e:f10", - &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], - global | unicast_global - ); -} +use crate::net::test::{sa4, tsa}; +use crate::net::Ipv4Addr; #[test] fn to_socket_addr_socketaddr() { let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345); assert_eq!(Ok(vec![a]), tsa(a)); } - -#[test] -fn test_ipv4_to_int() { - let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44); - assert_eq!(u32::from(a), 0x11223344); -} - -#[test] -fn test_int_to_ipv4() { - let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44); - assert_eq!(Ipv4Addr::from(0x11223344), a); -} - -#[test] -fn test_ipv6_to_int() { - let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11); - assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128); -} - -#[test] -fn test_int_to_ipv6() { - let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11); - assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a); -} - -#[test] -fn ipv4_from_constructors() { - assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1)); - assert!(Ipv4Addr::LOCALHOST.is_loopback()); - assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0)); - assert!(Ipv4Addr::UNSPECIFIED.is_unspecified()); - assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255)); - assert!(Ipv4Addr::BROADCAST.is_broadcast()); -} - -#[test] -fn ipv6_from_constructors() { - assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); - assert!(Ipv6Addr::LOCALHOST.is_loopback()); - assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); - assert!(Ipv6Addr::UNSPECIFIED.is_unspecified()); -} - -#[test] -fn ipv4_from_octets() { - assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1)) -} - -#[test] -fn ipv6_from_segments() { - let from_u16s = - Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]); - let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff); - assert_eq!(new, from_u16s); -} - -#[test] -fn ipv6_from_octets() { - let from_u16s = - Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]); - let from_u8s = Ipv6Addr::from([ - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, - 0xff, - ]); - assert_eq!(from_u16s, from_u8s); -} - -#[test] -fn cmp() { - let v41 = Ipv4Addr::new(100, 64, 3, 3); - let v42 = Ipv4Addr::new(192, 0, 2, 2); - let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap(); - let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap(); - assert!(v41 < v42); - assert!(v61 < v62); - - assert_eq!(v41, IpAddr::V4(v41)); - assert_eq!(v61, IpAddr::V6(v61)); - assert!(v41 != IpAddr::V4(v42)); - assert!(v61 != IpAddr::V6(v62)); - - assert!(v41 < IpAddr::V4(v42)); - assert!(v61 < IpAddr::V6(v62)); - assert!(IpAddr::V4(v41) < v42); - assert!(IpAddr::V6(v61) < v62); - - assert!(v41 < IpAddr::V6(v61)); - assert!(IpAddr::V4(v41) < v61); -} - -#[test] -fn is_v4() { - let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3)); - assert!(ip.is_ipv4()); - assert!(!ip.is_ipv6()); -} - -#[test] -fn is_v6() { - let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678)); - assert!(!ip.is_ipv4()); - assert!(ip.is_ipv6()); -} - -#[test] -fn ipv4_const() { - // test that the methods of `Ipv4Addr` are usable in a const context - - const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); - assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST); - - const OCTETS: [u8; 4] = IP_ADDRESS.octets(); - assert_eq!(OCTETS, [127, 0, 0, 1]); - - const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); - assert!(!IS_UNSPECIFIED); - - const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback(); - assert!(IS_LOOPBACK); - - const IS_PRIVATE: bool = IP_ADDRESS.is_private(); - assert!(!IS_PRIVATE); - - const IS_LINK_LOCAL: bool = IP_ADDRESS.is_link_local(); - assert!(!IS_LINK_LOCAL); - - const IS_GLOBAL: bool = IP_ADDRESS.is_global(); - assert!(!IS_GLOBAL); - - const IS_SHARED: bool = IP_ADDRESS.is_shared(); - assert!(!IS_SHARED); - - const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking(); - assert!(!IS_BENCHMARKING); - - const IS_RESERVED: bool = IP_ADDRESS.is_reserved(); - assert!(!IS_RESERVED); - - const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); - assert!(!IS_MULTICAST); - - const IS_BROADCAST: bool = IP_ADDRESS.is_broadcast(); - assert!(!IS_BROADCAST); - - const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation(); - assert!(!IS_DOCUMENTATION); - - const IP_V6_COMPATIBLE: Ipv6Addr = IP_ADDRESS.to_ipv6_compatible(); - assert_eq!( - IP_V6_COMPATIBLE, - Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1]) - ); - - const IP_V6_MAPPED: Ipv6Addr = IP_ADDRESS.to_ipv6_mapped(); - assert_eq!( - IP_V6_MAPPED, - Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1]) - ); -} - -#[test] -fn ipv6_const() { - // test that the methods of `Ipv6Addr` are usable in a const context - - const IP_ADDRESS: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); - assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST); - - const SEGMENTS: [u16; 8] = IP_ADDRESS.segments(); - assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]); - - const OCTETS: [u8; 16] = IP_ADDRESS.octets(); - assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); - - const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); - assert!(!IS_UNSPECIFIED); - - const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback(); - assert!(IS_LOOPBACK); - - const IS_GLOBAL: bool = IP_ADDRESS.is_global(); - assert!(!IS_GLOBAL); - - const IS_UNIQUE_LOCAL: bool = IP_ADDRESS.is_unique_local(); - assert!(!IS_UNIQUE_LOCAL); - - const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local(); - assert!(!IS_UNICAST_LINK_LOCAL); - - const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation(); - assert!(!IS_DOCUMENTATION); - - const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking(); - assert!(!IS_BENCHMARKING); - - const IS_UNICAST_GLOBAL: bool = IP_ADDRESS.is_unicast_global(); - assert!(!IS_UNICAST_GLOBAL); - - const MULTICAST_SCOPE: Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope(); - assert_eq!(MULTICAST_SCOPE, None); - - const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); - assert!(!IS_MULTICAST); - - const IP_V4: Option<Ipv4Addr> = IP_ADDRESS.to_ipv4(); - assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1)); -} - -#[test] -fn ip_const() { - // test that the methods of `IpAddr` are usable in a const context - - const IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); - - const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); - assert!(!IS_UNSPECIFIED); - - const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback(); - assert!(IS_LOOPBACK); - - const IS_GLOBAL: bool = IP_ADDRESS.is_global(); - assert!(!IS_GLOBAL); - - const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); - assert!(!IS_MULTICAST); - - const IS_IP_V4: bool = IP_ADDRESS.is_ipv4(); - assert!(IS_IP_V4); - - const IS_IP_V6: bool = IP_ADDRESS.is_ipv6(); - assert!(!IS_IP_V6); -} - -#[test] -fn structural_match() { - // test that all IP types can be structurally matched upon - - const IPV4: Ipv4Addr = Ipv4Addr::LOCALHOST; - match IPV4 { - Ipv4Addr::LOCALHOST => {} - _ => unreachable!(), - } - - const IPV6: Ipv6Addr = Ipv6Addr::LOCALHOST; - match IPV6 { - Ipv6Addr::LOCALHOST => {} - _ => unreachable!(), - } - - const IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); - match IP { - IpAddr::V4(Ipv4Addr::LOCALHOST) => {} - _ => unreachable!(), - } -} diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index 19d90e7ec38..bcab15db35b 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -26,8 +26,6 @@ use crate::io::{self, ErrorKind}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::parser::AddrParseError; -#[stable(feature = "rust1", since = "1.0.0")] pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; #[unstable(feature = "tcplistener_into_incoming", issue = "88339")] pub use self::tcp::IntoIncoming; @@ -35,10 +33,10 @@ pub use self::tcp::IntoIncoming; pub use self::tcp::{Incoming, TcpListener, TcpStream}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::udp::UdpSocket; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::net::AddrParseError; -mod display_buffer; mod ip_addr; -mod parser; mod socket_addr; mod tcp; #[cfg(test)] diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs index 1264bae809b..421fed9077c 100644 --- a/library/std/src/net/socket_addr.rs +++ b/library/std/src/net/socket_addr.rs @@ -1,9 +1,7 @@ +// Tests for this module #[cfg(all(test, not(target_os = "emscripten")))] mod tests; -use crate::cmp::Ordering; -use crate::fmt::{self, Write}; -use crate::hash; use crate::io; use crate::iter; use crate::mem; @@ -15,533 +13,23 @@ use crate::sys_common::net::LookupHost; use crate::sys_common::{FromInner, IntoInner}; use crate::vec; -use super::display_buffer::DisplayBuffer; - -/// 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)] -#[stable(feature = "rust1", since = "1.0.0")] -pub enum SocketAddr { - /// An IPv4 socket address. - #[stable(feature = "rust1", since = "1.0.0")] - V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4), - /// An IPv6 socket address. - #[stable(feature = "rust1", since = "1.0.0")] - V6(#[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)] -#[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)] #[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); - /// ``` - #[stable(feature = "ip_addr", since = "1.7.0")] - #[must_use] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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] - #[stable(feature = "ip_addr", since = "1.7.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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))); - /// ``` - #[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] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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); - /// ``` - #[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] - #[stable(feature = "sockaddr_checker", since = "1.16.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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] - #[stable(feature = "sockaddr_checker", since = "1.16.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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)); - /// ``` - #[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] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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); - /// ``` - #[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); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[must_use] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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)); - /// ``` - #[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] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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); - /// ``` - #[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] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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); - /// ``` - #[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] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")] - 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); - /// ``` - #[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; - } -} +pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; impl FromInner<c::sockaddr_in> for SocketAddrV4 { fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 { - SocketAddrV4 { ip: Ipv4Addr::from_inner(addr.sin_addr), port: u16::from_be(addr.sin_port) } + SocketAddrV4::new(Ipv4Addr::from_inner(addr.sin_addr), u16::from_be(addr.sin_port)) } } impl FromInner<c::sockaddr_in6> for SocketAddrV6 { fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 { - SocketAddrV6 { - ip: Ipv6Addr::from_inner(addr.sin6_addr), - port: u16::from_be(addr.sin6_port), - flowinfo: addr.sin6_flowinfo, - scope_id: addr.sin6_scope_id, - } + SocketAddrV6::new( + Ipv6Addr::from_inner(addr.sin6_addr), + u16::from_be(addr.sin6_port), + addr.sin6_flowinfo, + addr.sin6_scope_id, + ) } } @@ -549,8 +37,8 @@ impl IntoInner<c::sockaddr_in> for SocketAddrV4 { fn into_inner(self) -> c::sockaddr_in { c::sockaddr_in { sin_family: c::AF_INET as c::sa_family_t, - sin_port: self.port.to_be(), - sin_addr: self.ip.into_inner(), + sin_port: self.port().to_be(), + sin_addr: self.ip().into_inner(), ..unsafe { mem::zeroed() } } } @@ -560,162 +48,15 @@ impl IntoInner<c::sockaddr_in6> for SocketAddrV6 { fn into_inner(self) -> c::sockaddr_in6 { c::sockaddr_in6 { sin6_family: c::AF_INET6 as c::sa_family_t, - sin6_port: self.port.to_be(), - sin6_addr: self.ip.into_inner(), - sin6_flowinfo: self.flowinfo, - sin6_scope_id: self.scope_id, + sin6_port: self.port().to_be(), + sin6_addr: self.ip().into_inner(), + sin6_flowinfo: self.flowinfo(), + sin6_scope_id: self.scope_id(), ..unsafe { mem::zeroed() } } } } -#[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) - } -} - -#[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) - } -} - -#[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) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for SocketAddr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - SocketAddr::V4(ref a) => a.fmt(f), - SocketAddr::V6(ref a) => a.fmt(f), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for SocketAddr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, fmt) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for SocketAddrV4 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // If there are no alignment requirements, write the socket address directly to `f`. - // Otherwise, write it to a local buffer and then use `f.pad`. - if f.precision().is_none() && f.width().is_none() { - write!(f, "{}:{}", self.ip(), self.port()) - } else { - const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65536"; - - let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new(); - // Buffer is long enough for the longest possible IPv4 socket address, so this should never fail. - write!(buf, "{}:{}", self.ip(), self.port()).unwrap(); - - f.pad(buf.as_str()) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for SocketAddrV4 { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, fmt) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for SocketAddrV6 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // If there are no alignment requirements, write the socket address directly to `f`. - // Otherwise, write it to a local buffer and then use `f.pad`. - if f.precision().is_none() && f.width().is_none() { - match self.scope_id() { - 0 => write!(f, "[{}]:{}", self.ip(), self.port()), - scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()), - } - } else { - const LONGEST_IPV6_SOCKET_ADDR: &str = - "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967296]:65536"; - - let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new(); - match self.scope_id() { - 0 => write!(buf, "[{}]:{}", self.ip(), self.port()), - scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()), - } - // Buffer is long enough for the longest possible IPv6 socket address, so this should never fail. - .unwrap(); - - f.pad(buf.as_str()) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for SocketAddrV6 { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, fmt) - } -} - -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl PartialOrd for SocketAddrV4 { - fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl PartialOrd for SocketAddrV6 { - fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -#[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())) - } -} - -#[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())) - } -} - -#[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) - } -} -#[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) - } -} - /// A trait for objects which can be converted or resolved to one or more /// [`SocketAddr`] values. /// diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index ac09a805975..541e95d229b 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -6,7 +6,7 @@ mod tests; use crate::io::prelude::*; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::iter::FusedIterator; use crate::net::{Shutdown, SocketAddr, ToSocketAddrs}; use crate::sys_common::net as net_imp; @@ -619,6 +619,10 @@ impl Read for TcpStream { self.0.read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.0.read_vectored(bufs) } @@ -653,6 +657,10 @@ impl Read for &TcpStream { self.0.read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.0.read_vectored(bufs) } @@ -683,6 +691,7 @@ impl Write for &TcpStream { } impl AsInner<net_imp::TcpStream> for TcpStream { + #[inline] fn as_inner(&self) -> &net_imp::TcpStream { &self.0 } @@ -861,7 +870,7 @@ impl TcpListener { /// use std::net::{TcpListener, TcpStream}; /// /// fn listen_on(port: u16) -> impl Iterator<Item = TcpStream> { - /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); + /// let listener = TcpListener::bind(("127.0.0.1", port)).unwrap(); /// listener.into_incoming() /// .filter_map(Result::ok) /* Ignore failed connections */ /// } @@ -1025,6 +1034,7 @@ impl Iterator for IntoIncoming { impl FusedIterator for IntoIncoming {} impl AsInner<net_imp::TcpListener> for TcpListener { + #[inline] fn as_inner(&self) -> &net_imp::TcpListener { &self.0 } diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 8c0adcfb0eb..7a3c66e4504 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -1,6 +1,7 @@ use crate::fmt; use crate::io::prelude::*; -use crate::io::{ErrorKind, IoSlice, IoSliceMut}; +use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut}; +use crate::mem::MaybeUninit; use crate::net::test::{next_test_ip4, next_test_ip6}; use crate::net::*; use crate::sync::mpsc::channel; @@ -280,6 +281,31 @@ fn partial_read() { } #[test] +fn read_buf() { + each_ip(&mut |addr| { + let srv = t!(TcpListener::bind(&addr)); + let t = thread::spawn(move || { + let mut s = t!(TcpStream::connect(&addr)); + s.write_all(&[1, 2, 3, 4]).unwrap(); + }); + + let mut s = t!(srv.accept()).0; + let mut buf: [MaybeUninit<u8>; 128] = MaybeUninit::uninit_array(); + let mut buf = BorrowedBuf::from(buf.as_mut_slice()); + t!(s.read_buf(buf.unfilled())); + assert_eq!(buf.filled(), &[1, 2, 3, 4]); + + // FIXME: sgx uses default_read_buf that initializes the buffer. + if cfg!(not(target_env = "sgx")) { + // TcpStream::read_buf should omit buffer initialization. + assert_eq!(buf.init_len(), 4); + } + + t.join().ok().expect("thread panicked"); + }) +} + +#[test] fn read_vectored() { each_ip(&mut |addr| { let srv = t!(TcpListener::bind(&addr)); @@ -670,7 +696,10 @@ fn debug() { // FIXME: re-enabled openbsd tests once their socket timeout code // no longer has rounding errors. // VxWorks ignores SO_SNDTIMEO. -#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] +#[cfg_attr( + any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"), + ignore +)] #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 #[test] fn timeouts() { diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 864e1b0f345..9628bcc5108 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -788,6 +788,7 @@ impl UdpSocket { // `AsRawSocket`/`IntoRawSocket`/`FromRawSocket` on Windows. impl AsInner<net_imp::UdpSocket> for UdpSocket { + #[inline] fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 } diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index f82904ffbbf..892fe2ba8ba 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -180,7 +180,10 @@ fn debug() { // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code // no longer has rounding errors. // VxWorks ignores SO_SNDTIMEO. -#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] +#[cfg_attr( + any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"), + ignore +)] #[test] fn timeouts() { let addr = next_test_ip4(); diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs index 7cecd1bbfaa..fe40d6319c2 100644 --- a/library/std/src/os/android/net.rs +++ b/library/std/src/os/android/net.rs @@ -1,8 +1,8 @@ //! Android-specific networking functionality. -#![unstable(feature = "tcp_quickack", issue = "96256")] +#![stable(feature = "unix_socket_abstract", since = "1.70.0")] -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 439b8d52a2d..2180d2974d5 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -9,7 +9,7 @@ use crate::fs; use crate::io; use crate::marker::PhantomData; use crate::mem::forget; -#[cfg(not(any(target_arch = "wasm32", target_env = "sgx")))] +#[cfg(not(any(target_arch = "wasm32", target_env = "sgx", target_os = "hermit")))] use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -89,7 +89,7 @@ impl OwnedFd { impl BorrowedFd<'_> { /// Creates a new `OwnedFd` instance that shares the same underlying file /// description as the existing `BorrowedFd` instance. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(any(target_arch = "wasm32", target_os = "hermit")))] #[stable(feature = "io_safety", since = "1.63.0")] pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> { // We want to atomically duplicate this file descriptor and set the @@ -112,7 +112,7 @@ impl BorrowedFd<'_> { /// Creates a new `OwnedFd` instance that shares the same underlying file /// description as the existing `BorrowedFd` instance. - #[cfg(target_arch = "wasm32")] + #[cfg(any(target_arch = "wasm32", target_os = "hermit"))] #[stable(feature = "io_safety", since = "1.63.0")] pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> { Err(crate::io::const_io_error!( @@ -174,7 +174,10 @@ impl Drop for OwnedFd { // 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. + #[cfg(not(target_os = "hermit"))] let _ = libc::close(self.fd); + #[cfg(target_os = "hermit")] + let _ = hermit_abi::close(self.fd); } } } @@ -198,7 +201,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "1.70.0")] impl crate::io::IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { @@ -265,7 +268,7 @@ impl AsFd for OwnedFd { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { // Safety: `OwnedFd` and `BorrowedFd` have the same validity - // invariants, and the `BorrowdFd` is bounded by the lifetime + // invariants, and the `BorrowedFd` is bounded by the lifetime // of `&self`. unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } } @@ -396,7 +399,7 @@ impl<T: AsFd> AsFd for crate::sync::Arc<T> { } } -#[stable(feature = "asfd_rc", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "asfd_rc", since = "1.69.0")] impl<T: AsFd> AsFd for crate::rc::Rc<T> { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index c138162f1ab..592e072ad90 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -4,6 +4,9 @@ use crate::fs; use crate::io; +#[cfg(target_os = "hermit")] +use crate::os::hermit::io::OwnedFd; +#[cfg(not(target_os = "hermit"))] use crate::os::raw; #[cfg(all(doc, not(target_arch = "wasm32")))] use crate::os::unix::io::AsFd; @@ -12,11 +15,18 @@ use crate::os::unix::io::OwnedFd; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; use crate::sys_common::{AsInner, IntoInner}; +#[cfg(target_os = "hermit")] +use hermit_abi as libc; /// Raw file descriptors. #[rustc_allowed_through_unstable_modules] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(target_os = "hermit"))] pub type RawFd = raw::c_int; +#[rustc_allowed_through_unstable_modules] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(target_os = "hermit")] +pub type RawFd = i32; /// A trait to extract the raw file descriptor from an underlying object. /// @@ -244,7 +254,7 @@ impl<T: AsRawFd> AsRawFd for crate::sync::Arc<T> { } } -#[stable(feature = "asfd_rc", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "asfd_rc", since = "1.69.0")] impl<T: AsRawFd> AsRawFd for crate::rc::Rc<T> { #[inline] fn as_raw_fd(&self) -> RawFd { diff --git a/library/std/src/os/fuchsia/raw.rs b/library/std/src/os/fuchsia/raw.rs index ea6b94f2f13..cb570beb8a1 100644 --- a/library/std/src/os/fuchsia/raw.rs +++ b/library/std/src/os/fuchsia/raw.rs @@ -286,3 +286,9 @@ mod arch { pub __unused: [c_long; 3], } } + +#[cfg(target_arch = "riscv64")] +mod arch { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; +} diff --git a/library/std/src/os/hermit/io/mod.rs b/library/std/src/os/hermit/io/mod.rs new file mode 100644 index 00000000000..524dfae0d63 --- /dev/null +++ b/library/std/src/os/hermit/io/mod.rs @@ -0,0 +1,13 @@ +#![stable(feature = "os_fd", since = "1.66.0")] + +mod net; +#[path = "../../fd/owned.rs"] +mod owned; +#[path = "../../fd/raw.rs"] +mod raw; + +// Export the types and traits for the public API. +#[stable(feature = "os_fd", since = "1.66.0")] +pub use owned::*; +#[stable(feature = "os_fd", since = "1.66.0")] +pub use raw::*; diff --git a/library/std/src/os/hermit/io/net.rs b/library/std/src/os/hermit/io/net.rs new file mode 100644 index 00000000000..8f3802d7873 --- /dev/null +++ b/library/std/src/os/hermit/io/net.rs @@ -0,0 +1,46 @@ +use crate::os::hermit::io::OwnedFd; +use crate::os::hermit::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use crate::sys_common::{self, AsInner, FromInner, IntoInner}; +use crate::{net, sys}; + +macro_rules! impl_as_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for net::$t { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.as_inner().socket().as_raw_fd() + } + } + )*}; +} +impl_as_raw_fd! { TcpStream TcpListener UdpSocket } + +macro_rules! impl_from_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "from_raw_os", since = "1.1.0")] + impl FromRawFd for net::$t { + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> net::$t { + unsafe { + let socket = sys::net::Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))); + net::$t::from_inner(sys_common::net::$t::from_inner(socket)) + } + } + } + )*}; +} +impl_from_raw_fd! { TcpStream TcpListener UdpSocket } + +macro_rules! impl_into_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "into_raw_os", since = "1.4.0")] + impl IntoRawFd for net::$t { + #[inline] + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner().into_inner().into_raw_fd() + } + } + )*}; +} +impl_into_raw_fd! { TcpStream TcpListener UdpSocket } diff --git a/library/std/src/os/hermit/mod.rs b/library/std/src/os/hermit/mod.rs index 4657b545a1b..89b1b831912 100644 --- a/library/std/src/os/hermit/mod.rs +++ b/library/std/src/os/hermit/mod.rs @@ -1,6 +1,11 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[allow(unused_extern_crates)] +#[stable(feature = "rust1", since = "1.0.0")] +pub extern crate hermit_abi as abi; + pub mod ffi; +pub mod io; /// A prelude for conveniently writing platform-specific code. /// diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs index 94081c8dd31..c8e734d740b 100644 --- a/library/std/src/os/linux/net.rs +++ b/library/std/src/os/linux/net.rs @@ -1,8 +1,8 @@ //! Linux-specific networking functionality. -#![unstable(feature = "tcp_quickack", issue = "96256")] +#![stable(feature = "unix_socket_abstract", since = "1.70.0")] -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index 540363c0349..2b3ff76d7a4 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -52,6 +52,7 @@ pub struct PidFd { } impl AsInner<FileDesc> for PidFd { + #[inline] fn as_inner(&self) -> &FileDesc { &self.inner } @@ -70,6 +71,7 @@ impl IntoInner<FileDesc> for PidFd { } impl AsRawFd for PidFd { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().as_raw_fd() } diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs index f46028c3a96..c55ca8ba26e 100644 --- a/library/std/src/os/linux/raw.rs +++ b/library/std/src/os/linux/raw.rs @@ -231,6 +231,7 @@ mod arch { } #[cfg(any( + target_arch = "loongarch64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64", diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 42773805cdb..5b54cc5f2e4 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -60,16 +60,6 @@ pub mod windows {} all(target_vendor = "fortanix", target_env = "sgx") ) )))] -#[cfg(target_os = "hermit")] -#[path = "hermit/mod.rs"] -pub mod unix; -#[cfg(not(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -)))] #[cfg(all(not(target_os = "hermit"), any(unix, doc)))] pub mod unix; @@ -123,6 +113,8 @@ pub mod freebsd; pub mod fuchsia; #[cfg(target_os = "haiku")] pub mod haiku; +#[cfg(target_os = "hermit")] +pub mod hermit; #[cfg(target_os = "horizon")] pub mod horizon; #[cfg(target_os = "illumos")] @@ -135,6 +127,8 @@ pub mod l4re; pub mod macos; #[cfg(target_os = "netbsd")] pub mod netbsd; +#[cfg(target_os = "nto")] +pub mod nto; #[cfg(target_os = "openbsd")] pub mod openbsd; #[cfg(target_os = "redox")] @@ -143,6 +137,8 @@ pub mod redox; pub mod solaris; #[cfg(target_os = "solid_asp3")] pub mod solid; +#[cfg(target_os = "vita")] +pub mod vita; #[cfg(target_os = "vxworks")] pub mod vxworks; #[cfg(target_os = "watchos")] diff --git a/library/std/src/os/net/linux_ext/addr.rs b/library/std/src/os/net/linux_ext/addr.rs index 85065984fbb..aed772056e1 100644 --- a/library/std/src/os/net/linux_ext/addr.rs +++ b/library/std/src/os/net/linux_ext/addr.rs @@ -4,7 +4,7 @@ use crate::os::unix::net::SocketAddr; use crate::sealed::Sealed; /// Platform-specific extensions to [`SocketAddr`]. -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub trait SocketAddrExt: Sealed { /// Creates a Unix socket address in the abstract namespace. /// @@ -22,7 +22,6 @@ pub trait SocketAddrExt: Sealed { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixListener, SocketAddr}; /// use std::os::linux::net::SocketAddrExt; /// @@ -38,6 +37,7 @@ pub trait SocketAddrExt: Sealed { /// Ok(()) /// } /// ``` + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] fn from_abstract_name<N>(name: N) -> crate::io::Result<SocketAddr> where N: AsRef<[u8]>; @@ -47,7 +47,6 @@ pub trait SocketAddrExt: Sealed { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixListener, SocketAddr}; /// use std::os::linux::net::SocketAddrExt; /// @@ -60,5 +59,6 @@ pub trait SocketAddrExt: Sealed { /// Ok(()) /// } /// ``` + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] fn as_abstract_name(&self) -> Option<&[u8]>; } diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs index 318ebacfd7a..62e78cc50d4 100644 --- a/library/std/src/os/net/linux_ext/mod.rs +++ b/library/std/src/os/net/linux_ext/mod.rs @@ -2,7 +2,7 @@ #![doc(cfg(any(target_os = "linux", target_os = "android")))] -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub(crate) mod addr; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/nto/fs.rs b/library/std/src/os/nto/fs.rs new file mode 100644 index 00000000000..8f915b08c9e --- /dev/null +++ b/library/std/src/os/nto/fs.rs @@ -0,0 +1,92 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atim.tv_sec as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atim.tv_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtim.tv_sec as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtim.tv_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctim.tv_sec as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctim.tv_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/library/std/src/os/nto/mod.rs b/library/std/src/os/nto/mod.rs new file mode 100644 index 00000000000..3e591dace92 --- /dev/null +++ b/library/std/src/os/nto/mod.rs @@ -0,0 +1,4 @@ +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub(super) mod raw; diff --git a/library/std/src/os/nto/raw.rs b/library/std/src/os/nto/raw.rs new file mode 100644 index 00000000000..90e9ad54643 --- /dev/null +++ b/library/std/src/os/nto/raw.rs @@ -0,0 +1,40 @@ +#![stable(feature = "raw_ext", since = "1.1.0")] +#![deprecated( + since = "1.8.0", + note = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions" +)] +#![allow(deprecated)] + +use crate::os::raw::c_int; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = u32; + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = c_int; + +#[doc(inline)] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, time_t}; + +mod arch { + use crate::os::raw::c_long; + + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blkcnt_t = i64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blksize_t = i32; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type ino_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type nlink_t = u32; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type off_t = i64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type time_t = c_long; +} diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 3fc6cc44ce4..1e1c3693105 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -17,6 +17,10 @@ use crate::sealed::Sealed; #[allow(unused_imports)] use io::{Read, Write}; +// Tests for this module +#[cfg(test)] +mod tests; + /// Unix-specific extensions to [`fs::File`]. #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { @@ -54,6 +58,16 @@ pub trait FileExt { #[stable(feature = "file_offset", since = "1.15.0")] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>; + /// Like `read_at`, except that it reads into a slice of buffers. + /// + /// Data is copied to fill each buffer in order, with the final buffer + /// written to possibly being only partially filled. This method must behave + /// equivalently to a single call to read with concatenated buffers. + #[unstable(feature = "unix_file_vectored_at", issue = "89517")] + fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + io::default_read_vectored(|b| self.read_at(b, offset), bufs) + } + /// Reads the exact number of byte required to fill `buf` from the given offset. /// /// The offset is relative to the start of the file and thus independent @@ -155,6 +169,16 @@ pub trait FileExt { #[stable(feature = "file_offset", since = "1.15.0")] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>; + /// Like `write_at`, except that it writes from a slice of buffers. + /// + /// Data is copied from each buffer in order, with the final buffer read + /// from possibly being only partially consumed. This method must behave as + /// a call to `write_at` with the buffers concatenated would. + #[unstable(feature = "unix_file_vectored_at", issue = "89517")] + fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> { + io::default_write_vectored(|b| self.write_at(b, offset), bufs) + } + /// Attempts to write an entire buffer starting from a given offset. /// /// The offset is relative to the start of the file and thus independent @@ -218,9 +242,15 @@ impl FileExt for fs::File { fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { self.as_inner().read_at(buf, offset) } + fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + self.as_inner().read_vectored_at(bufs, offset) + } fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { self.as_inner().write_at(buf, offset) } + fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> { + self.as_inner().write_vectored_at(bufs, offset) + } } /// Unix-specific extensions to [`fs::Permissions`]. @@ -338,7 +368,7 @@ pub trait OpenOptionsExt { /// /// ```no_run /// # #![feature(rustc_private)] - /// extern crate libc; + /// use libc; /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; /// diff --git a/library/std/src/os/unix/fs/tests.rs b/library/std/src/os/unix/fs/tests.rs new file mode 100644 index 00000000000..67f607bd468 --- /dev/null +++ b/library/std/src/os/unix/fs/tests.rs @@ -0,0 +1,57 @@ +use super::*; + +#[test] +fn read_vectored_at() { + let msg = b"preadv is working!"; + let dir = crate::sys_common::io::test::tmpdir(); + + let filename = dir.join("preadv.txt"); + { + let mut file = fs::File::create(&filename).unwrap(); + file.write_all(msg).unwrap(); + } + { + let file = fs::File::open(&filename).unwrap(); + let mut buf0 = [0; 4]; + let mut buf1 = [0; 3]; + + let mut iovec = [io::IoSliceMut::new(&mut buf0), io::IoSliceMut::new(&mut buf1)]; + + let n = file.read_vectored_at(&mut iovec, 4).unwrap(); + + assert!(n == 4 || n == 7); + assert_eq!(&buf0, b"dv i"); + + if n == 7 { + assert_eq!(&buf1, b"s w"); + } + } +} + +#[test] +fn write_vectored_at() { + let msg = b"pwritev is not working!"; + let dir = crate::sys_common::io::test::tmpdir(); + + let filename = dir.join("preadv.txt"); + { + let mut file = fs::File::create(&filename).unwrap(); + file.write_all(msg).unwrap(); + } + let expected = { + let file = fs::File::options().write(true).open(&filename).unwrap(); + let buf0 = b" "; + let buf1 = b"great "; + + let iovec = [io::IoSlice::new(buf0), io::IoSlice::new(buf1)]; + + let n = file.write_vectored_at(&iovec, 11).unwrap(); + + assert!(n == 4 || n == 11); + + if n == 4 { b"pwritev is working!" } else { b"pwritev is great !" } + }; + + let content = fs::read(&filename).unwrap(); + assert_eq!(&content, expected); +} diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index f97fa0fb06f..6fe1111188a 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -65,12 +65,16 @@ mod platform { pub use crate::os::macos::*; #[cfg(target_os = "netbsd")] pub use crate::os::netbsd::*; + #[cfg(target_os = "nto")] + pub use crate::os::nto::*; #[cfg(target_os = "openbsd")] pub use crate::os::openbsd::*; #[cfg(target_os = "redox")] pub use crate::os::redox::*; #[cfg(target_os = "solaris")] pub use crate::os::solaris::*; + #[cfg(target_os = "vita")] + pub use crate::os::vita::*; #[cfg(target_os = "vxworks")] pub use crate::os::vxworks::*; #[cfg(target_os = "watchos")] @@ -95,7 +99,8 @@ pub mod thread; target_os = "watchos", target_os = "macos", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", + target_os = "nto", ))] pub mod ucred; diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index ece2b33bddf..6c99e8c3620 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -245,12 +245,12 @@ impl SocketAddr { } } -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] impl Sealed for SocketAddr {} #[doc(cfg(any(target_os = "android", target_os = "linux")))] #[cfg(any(doc, target_os = "android", target_os = "linux"))] -#[unstable(feature = "unix_socket_abstract", issue = "85410")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] impl linux_ext::addr::SocketAddrExt for SocketAddr { fn as_abstract_name(&self) -> Option<&[u8]> { if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 7cc901a7944..7565fbc0d09 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -86,7 +86,12 @@ fn add_to_ancillary_data<T>( cmsg_level: libc::c_int, cmsg_type: libc::c_int, ) -> bool { - let source_len = if let Some(source_len) = source.len().checked_mul(size_of::<T>()) { + #[cfg(not(target_os = "freebsd"))] + let cmsg_size = source.len().checked_mul(size_of::<T>()); + #[cfg(target_os = "freebsd")] + let cmsg_size = Some(unsafe { libc::SOCKCRED2SIZE(1) }); + + let source_len = if let Some(source_len) = cmsg_size { if let Ok(source_len) = u32::try_from(source_len) { source_len } else { @@ -178,7 +183,13 @@ impl<'a, T> Iterator for AncillaryDataIter<'a, T> { } } -#[cfg(all(doc, not(target_os = "android"), not(target_os = "linux"), not(target_os = "netbsd")))] +#[cfg(all( + doc, + not(target_os = "android"), + not(target_os = "linux"), + not(target_os = "netbsd"), + not(target_os = "freebsd") +))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] #[derive(Clone)] pub struct SocketCred(()); @@ -194,6 +205,11 @@ pub struct SocketCred(libc::ucred); #[derive(Clone)] pub struct SocketCred(libc::sockcred); +#[cfg(target_os = "freebsd")] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +#[derive(Clone)] +pub struct SocketCred(libc::sockcred2); + #[doc(cfg(any(target_os = "android", target_os = "linux")))] #[cfg(any(target_os = "android", target_os = "linux"))] impl SocketCred { @@ -246,6 +262,66 @@ impl SocketCred { } } +#[cfg(target_os = "freebsd")] +impl SocketCred { + /// Create a Unix credential struct. + /// + /// PID, UID and GID is set to 0. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + #[must_use] + pub fn new() -> SocketCred { + SocketCred(libc::sockcred2 { + sc_version: 0, + sc_pid: 0, + sc_uid: 0, + sc_euid: 0, + sc_gid: 0, + sc_egid: 0, + sc_ngroups: 0, + sc_groups: [0; 1], + }) + } + + /// Set the PID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_pid(&mut self, pid: libc::pid_t) { + self.0.sc_pid = pid; + } + + /// Get the current PID. + #[must_use] + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_pid(&self) -> libc::pid_t { + self.0.sc_pid + } + + /// Set the UID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_uid(&mut self, uid: libc::uid_t) { + self.0.sc_euid = uid; + } + + /// Get the current UID. + #[must_use] + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_uid(&self) -> libc::uid_t { + self.0.sc_euid + } + + /// Set the GID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_gid(&mut self, gid: libc::gid_t) { + self.0.sc_egid = gid; + } + + /// Get the current GID. + #[must_use] + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_gid(&self) -> libc::gid_t { + self.0.sc_egid + } +} + #[cfg(target_os = "netbsd")] impl SocketCred { /// Create a Unix credential struct. @@ -271,6 +347,7 @@ impl SocketCred { } /// Get the current PID. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_pid(&self) -> libc::pid_t { self.0.sc_pid @@ -283,6 +360,7 @@ impl SocketCred { } /// Get the current UID. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_uid(&self) -> libc::uid_t { self.0.sc_uid @@ -295,6 +373,7 @@ impl SocketCred { } /// Get the current GID. + #[must_use] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn get_gid(&self) -> libc::gid_t { self.0.sc_gid @@ -316,7 +395,13 @@ impl<'a> Iterator for ScmRights<'a> { } } -#[cfg(all(doc, not(target_os = "android"), not(target_os = "linux"), not(target_os = "netbsd")))] +#[cfg(all( + doc, + not(target_os = "android"), + not(target_os = "linux"), + not(target_os = "netbsd"), + not(target_os = "freebsd") +))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub struct ScmCredentials<'a>(AncillaryDataIter<'a, ()>); @@ -327,11 +412,21 @@ pub struct ScmCredentials<'a>(AncillaryDataIter<'a, ()>); #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>); +#[cfg(target_os = "freebsd")] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::sockcred2>); + #[cfg(target_os = "netbsd")] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::sockcred>); -#[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] +#[cfg(any( + doc, + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" +))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] impl<'a> Iterator for ScmCredentials<'a> { type Item = SocketCred; @@ -353,7 +448,13 @@ pub enum AncillaryError { #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub enum AncillaryData<'a> { ScmRights(ScmRights<'a>), - #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] + #[cfg(any( + doc, + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + ))] ScmCredentials(ScmCredentials<'a>), } @@ -376,7 +477,13 @@ impl<'a> AncillaryData<'a> { /// /// `data` must contain a valid control message and the control message must be type of /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDS`. - #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] + #[cfg(any( + doc, + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + ))] unsafe fn as_credentials(data: &'a [u8]) -> Self { let ancillary_data_iter = AncillaryDataIter::new(data); let scm_credentials = ScmCredentials(ancillary_data_iter); @@ -395,6 +502,8 @@ impl<'a> AncillaryData<'a> { libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)), #[cfg(any(target_os = "android", target_os = "linux",))] libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)), + #[cfg(target_os = "freebsd")] + libc::SCM_CREDS2 => Ok(AncillaryData::as_credentials(data)), #[cfg(target_os = "netbsd")] libc::SCM_CREDS => Ok(AncillaryData::as_credentials(data)), cmsg_type => { @@ -603,12 +712,18 @@ impl<'a> SocketAncillary<'a> { /// Add credentials to the ancillary data. /// - /// The function returns `true` if there was enough space in the buffer. - /// If there was not enough space then no credentials was appended. + /// The function returns `true` if there is enough space in the buffer. + /// If there is not enough space then no credentials will be appended. /// Technically, that means this operation adds a control message with the level `SOL_SOCKET` - /// and type `SCM_CREDENTIALS` or `SCM_CREDS`. - /// - #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] + /// and type `SCM_CREDENTIALS`, `SCM_CREDS`, or `SCM_CREDS2`. + /// + #[cfg(any( + doc, + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + ))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool { self.truncated = false; @@ -617,8 +732,10 @@ impl<'a> SocketAncillary<'a> { &mut self.length, creds, libc::SOL_SOCKET, - #[cfg(not(target_os = "netbsd"))] + #[cfg(not(any(target_os = "netbsd", target_os = "freebsd")))] libc::SCM_CREDENTIALS, + #[cfg(target_os = "freebsd")] + libc::SCM_CREDS2, #[cfg(target_os = "netbsd")] libc::SCM_CREDS, ) diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index f758f88d0a3..34db54235f1 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -19,7 +19,8 @@ use crate::{fmt, io}; target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "haiku" + target_os = "haiku", + target_os = "nto", ))] use libc::MSG_NOSIGNAL; #[cfg(not(any( @@ -29,7 +30,8 @@ use libc::MSG_NOSIGNAL; target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "haiku" + target_os = "haiku", + target_os = "nto", )))] const MSG_NOSIGNAL: libc::c_int = 0x0; @@ -100,7 +102,6 @@ impl UnixDatagram { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -117,7 +118,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixDatagram> { unsafe { let socket = UnixDatagram::unbound()?; @@ -215,7 +216,6 @@ impl UnixDatagram { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -233,7 +233,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> { unsafe { cvt(libc::connect( @@ -521,7 +521,6 @@ impl UnixDatagram { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixDatagram}; /// /// fn main() -> std::io::Result<()> { @@ -533,7 +532,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn send_to_addr(&self, buf: &[u8], socket_addr: &SocketAddr) -> io::Result<usize> { unsafe { let count = cvt(libc::sendto( @@ -809,8 +808,24 @@ impl UnixDatagram { /// /// # Examples /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] + #[cfg_attr( + any( + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd", + ), + doc = "```no_run" + )] + #[cfg_attr( + not(any( + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + )), + doc = "```ignore" + )] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::UnixDatagram; /// @@ -820,7 +835,13 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] + #[cfg(any( + doc, + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + ))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { self.0.set_passcred(passcred) @@ -832,7 +853,13 @@ impl UnixDatagram { /// Get the socket option `SO_PASSCRED`. /// /// [`set_passcred`]: UnixDatagram::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] + #[cfg(any( + doc, + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + ))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn passcred(&self) -> io::Result<bool> { self.0.passcred() diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 02090afc82f..5be8aebc70f 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -90,7 +90,6 @@ impl UnixListener { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixListener}; /// /// fn main() -> std::io::Result<()> { @@ -107,7 +106,7 @@ impl UnixListener { /// Ok(()) /// } /// ``` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixListener> { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index dff8f6e8567..bf2a51b5edb 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -106,7 +106,6 @@ impl UnixStream { /// # Examples /// /// ```no_run - /// #![feature(unix_socket_abstract)] /// use std::os::unix::net::{UnixListener, UnixStream}; /// /// fn main() -> std::io::Result<()> { @@ -123,7 +122,7 @@ impl UnixStream { /// Ok(()) /// } /// ```` - #[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result<UnixStream> { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; @@ -398,8 +397,24 @@ impl UnixStream { /// /// # Examples /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] + #[cfg_attr( + any( + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + ), + doc = "```no_run" + )] + #[cfg_attr( + not(any( + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + )), + doc = "```ignore" + )] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::UnixStream; /// @@ -409,7 +424,13 @@ impl UnixStream { /// Ok(()) /// } /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] + #[cfg(any( + doc, + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + ))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { self.0.set_passcred(passcred) @@ -421,7 +442,13 @@ impl UnixStream { /// Get the socket option `SO_PASSCRED`. /// /// [`set_passcred`]: UnixStream::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] + #[cfg(any( + doc, + target_os = "android", + target_os = "linux", + target_os = "netbsd", + target_os = "freebsd" + ))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn passcred(&self) -> io::Result<bool> { self.0.passcred() diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 37fcfa8446b..39f10c50dc4 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -167,6 +167,7 @@ fn long_path() { } #[test] +#[cfg(not(target_os = "nto"))] fn timeouts() { let dir = tmpdir(); let socket_path = dir.path().join("sock"); @@ -645,7 +646,7 @@ fn test_send_vectored_fds_unix_stream() { } } -#[cfg(any(target_os = "android", target_os = "linux",))] +#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] #[test] fn test_send_vectored_with_ancillary_to_unix_datagram() { fn getpid() -> libc::pid_t { diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 09b2bfe39f0..729c63d184f 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -12,15 +12,23 @@ use crate::sealed::Sealed; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))] -type UserId = u32; -#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))] -type GroupId = u32; - -#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] -type UserId = u16; -#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] -type GroupId = u16; +use cfg_if::cfg_if; + +cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] { + type UserId = u16; + type GroupId = u16; + } else if #[cfg(target_os = "nto")] { + // Both IDs are signed, see `sys/target_nto.h` of the QNX Neutrino SDP. + // Only positive values should be used, see e.g. + // https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/s/setuid.html + type UserId = i32; + type GroupId = i32; + } else { + type UserId = u32; + type GroupId = u32; + } +} /// Unix-specific extensions to the [`process::Command`] builder. /// diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/ucred.rs index ae4faf27b4d..95967eac295 100644 --- a/library/std/src/os/unix/ucred.rs +++ b/library/std/src/os/unix/ucred.rs @@ -79,7 +79,8 @@ pub mod impl_linux { target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", - target_os = "netbsd" + target_os = "netbsd", + target_os = "nto", ))] pub mod impl_bsd { use super::UCred; diff --git a/library/std/src/os/vita/fs.rs b/library/std/src/os/vita/fs.rs new file mode 100644 index 00000000000..a5a06764a4d --- /dev/null +++ b/library/std/src/os/vita/fs.rs @@ -0,0 +1,95 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: crate::fs::Metadata +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + fn st_atime_nsec(&self) -> i64 { + 0 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + fn st_mtime_nsec(&self) -> i64 { + 0 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + fn st_ctime_nsec(&self) -> i64 { + 0 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/library/std/src/os/vita/mod.rs b/library/std/src/os/vita/mod.rs new file mode 100644 index 00000000000..da9edd12f7b --- /dev/null +++ b/library/std/src/os/vita/mod.rs @@ -0,0 +1,6 @@ +//! Definitions for vita + +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub(crate) mod raw; diff --git a/library/std/src/os/vita/raw.rs b/library/std/src/os/vita/raw.rs new file mode 100644 index 00000000000..74cae4d4135 --- /dev/null +++ b/library/std/src/os/vita/raw.rs @@ -0,0 +1,70 @@ +//! vita raw type definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] +#![deprecated( + since = "1.8.0", + note = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions" +)] +#![allow(deprecated)] + +use crate::os::raw::c_long; +use crate::os::unix::raw::{gid_t, uid_t}; + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = libc::pthread_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blkcnt_t = libc::blkcnt_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blksize_t = libc::blksize_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = libc::dev_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type ino_t = libc::ino_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = libc::mode_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type nlink_t = libc::nlink_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type off_t = libc::off_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type time_t = libc::time_t; + +#[repr(C)] +#[derive(Clone)] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: ino_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: mode_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: nlink_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: uid_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: gid_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: off_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: blksize_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: blkcnt_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_spare4: [c_long; 2usize], +} diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 1dfecc57338..cbf8209a5ad 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -9,7 +9,7 @@ use crate::io; use crate::marker::PhantomData; use crate::mem::forget; use crate::ptr; -use crate::sys::c; +use crate::sys; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -190,14 +190,14 @@ impl BorrowedHandle<'_> { /// object as the existing `BorrowedHandle` instance. #[stable(feature = "io_safety", since = "1.63.0")] pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedHandle> { - self.duplicate(0, false, c::DUPLICATE_SAME_ACCESS) + self.duplicate(0, false, sys::c::DUPLICATE_SAME_ACCESS) } pub(crate) fn duplicate( &self, - access: c::DWORD, + access: u32, inherit: bool, - options: c::DWORD, + options: u32, ) -> io::Result<OwnedHandle> { let handle = self.as_raw_handle(); @@ -211,14 +211,14 @@ impl BorrowedHandle<'_> { let mut ret = ptr::null_mut(); cvt(unsafe { - let cur_proc = c::GetCurrentProcess(); - c::DuplicateHandle( + let cur_proc = sys::c::GetCurrentProcess(); + sys::c::DuplicateHandle( cur_proc, handle, cur_proc, &mut ret, access, - inherit as c::BOOL, + inherit as sys::c::BOOL, options, ) })?; @@ -233,7 +233,7 @@ impl TryFrom<HandleOrInvalid> for OwnedHandle { #[inline] fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> { let owned_handle = handle_or_invalid.0; - if owned_handle.handle == c::INVALID_HANDLE_VALUE { + if owned_handle.handle == sys::c::INVALID_HANDLE_VALUE { // Don't call `CloseHandle`; it'd be harmless, except that it could // overwrite the `GetLastError` error. forget(owned_handle); @@ -365,7 +365,7 @@ impl Drop for OwnedHandle { #[inline] fn drop(&mut self) { unsafe { - let _ = c::CloseHandle(self.handle); + let _ = sys::c::CloseHandle(self.handle); } } } @@ -389,7 +389,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "1.70.0")] impl crate::io::IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { @@ -437,6 +437,42 @@ impl<T: AsHandle> AsHandle for &mut T { } } +#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")] +/// This impl allows implementing traits that require `AsHandle` on Arc. +/// ``` +/// # #[cfg(windows)] mod group_cfg { +/// # use std::os::windows::io::AsHandle; +/// use std::fs::File; +/// use std::sync::Arc; +/// +/// trait MyTrait: AsHandle {} +/// impl MyTrait for Arc<File> {} +/// impl MyTrait for Box<File> {} +/// # } +/// ``` +impl<T: AsHandle> AsHandle for crate::sync::Arc<T> { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + (**self).as_handle() + } +} + +#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")] +impl<T: AsHandle> AsHandle for crate::rc::Rc<T> { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + (**self).as_handle() + } +} + +#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")] +impl<T: AsHandle> AsHandle for Box<T> { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + (**self).as_handle() + } +} + #[stable(feature = "io_safety", since = "1.63.0")] impl AsHandle for BorrowedHandle<'_> { #[inline] @@ -450,7 +486,7 @@ impl AsHandle for OwnedHandle { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity - // invariants, and the `BorrowdHandle` is bounded by the lifetime + // invariants, and the `BorrowedHandle` is bounded by the lifetime // of `&self`. unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 49e4f304f5d..1759e2e7f3f 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -11,7 +11,6 @@ use crate::os::windows::io::{OwnedHandle, OwnedSocket}; use crate::os::windows::raw; use crate::ptr; use crate::sys; -use crate::sys::c; use crate::sys_common::{self, AsInner, FromInner, IntoInner}; /// Raw HANDLEs. @@ -104,42 +103,42 @@ impl AsRawHandle for fs::File { #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawHandle for io::Stdin { fn as_raw_handle(&self) -> RawHandle { - stdio_handle(unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle }) + stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_INPUT_HANDLE) as RawHandle }) } } #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawHandle for io::Stdout { fn as_raw_handle(&self) -> RawHandle { - stdio_handle(unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle }) + stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_OUTPUT_HANDLE) as RawHandle }) } } #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawHandle for io::Stderr { fn as_raw_handle(&self) -> RawHandle { - stdio_handle(unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle }) + stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_ERROR_HANDLE) as RawHandle }) } } #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawHandle for io::StdinLock<'a> { fn as_raw_handle(&self) -> RawHandle { - stdio_handle(unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle }) + stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_INPUT_HANDLE) as RawHandle }) } } #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawHandle for io::StdoutLock<'a> { fn as_raw_handle(&self) -> RawHandle { - stdio_handle(unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle }) + stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_OUTPUT_HANDLE) as RawHandle }) } } #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawHandle for io::StderrLock<'a> { fn as_raw_handle(&self) -> RawHandle { - stdio_handle(unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle }) + stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_ERROR_HANDLE) as RawHandle }) } } @@ -152,14 +151,14 @@ fn stdio_handle(raw: RawHandle) -> RawHandle { // console. In that case, return null to the user, which is consistent // with what they'd get in the parent, and which avoids the problem that // `INVALID_HANDLE_VALUE` aliases the current process handle. - if raw == c::INVALID_HANDLE_VALUE { ptr::null_mut() } else { raw } + if raw == sys::c::INVALID_HANDLE_VALUE { ptr::null_mut() } else { raw } } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawHandle for fs::File { #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> fs::File { - let handle = handle as c::HANDLE; + let handle = handle as sys::c::HANDLE; fs::File::from_inner(sys::fs::File::from_inner(FromInner::from_inner( OwnedHandle::from_raw_handle(handle), ))) diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index 5c1634084a0..0c90d55c024 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -9,7 +9,6 @@ use crate::marker::PhantomData; use crate::mem; use crate::mem::forget; use crate::sys; -use crate::sys::c; #[cfg(not(target_vendor = "uwp"))] use crate::sys::cvt; @@ -76,7 +75,7 @@ impl BorrowedSocket<'_> { #[rustc_const_stable(feature = "io_safety", since = "1.63.0")] #[stable(feature = "io_safety", since = "1.63.0")] pub const unsafe fn borrow_raw(socket: RawSocket) -> Self { - assert!(socket != c::INVALID_SOCKET as RawSocket); + assert!(socket != sys::c::INVALID_SOCKET as RawSocket); Self { socket, _phantom: PhantomData } } } @@ -94,7 +93,11 @@ impl OwnedSocket { #[cfg(not(target_vendor = "uwp"))] pub(crate) fn set_no_inherit(&self) -> io::Result<()> { cvt(unsafe { - c::SetHandleInformation(self.as_raw_socket() as c::HANDLE, c::HANDLE_FLAG_INHERIT, 0) + sys::c::SetHandleInformation( + self.as_raw_socket() as sys::c::HANDLE, + sys::c::HANDLE_FLAG_INHERIT, + 0, + ) }) .map(drop) } @@ -110,43 +113,47 @@ impl BorrowedSocket<'_> { /// object as the existing `BorrowedSocket` instance. #[stable(feature = "io_safety", since = "1.63.0")] pub fn try_clone_to_owned(&self) -> io::Result<OwnedSocket> { - let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() }; + let mut info = unsafe { mem::zeroed::<sys::c::WSAPROTOCOL_INFOW>() }; let result = unsafe { - c::WSADuplicateSocketW(self.as_raw_socket(), c::GetCurrentProcessId(), &mut info) + sys::c::WSADuplicateSocketW( + self.as_raw_socket(), + sys::c::GetCurrentProcessId(), + &mut info, + ) }; sys::net::cvt(result)?; let socket = unsafe { - c::WSASocketW( + sys::c::WSASocketW( info.iAddressFamily, info.iSocketType, info.iProtocol, &mut info, 0, - c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT, + sys::c::WSA_FLAG_OVERLAPPED | sys::c::WSA_FLAG_NO_HANDLE_INHERIT, ) }; - if socket != c::INVALID_SOCKET { + if socket != sys::c::INVALID_SOCKET { unsafe { Ok(OwnedSocket::from_raw_socket(socket)) } } else { - let error = unsafe { c::WSAGetLastError() }; + let error = unsafe { sys::c::WSAGetLastError() }; - if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL { + if error != sys::c::WSAEPROTOTYPE && error != sys::c::WSAEINVAL { return Err(io::Error::from_raw_os_error(error)); } let socket = unsafe { - c::WSASocketW( + sys::c::WSASocketW( info.iAddressFamily, info.iSocketType, info.iProtocol, &mut info, 0, - c::WSA_FLAG_OVERLAPPED, + sys::c::WSA_FLAG_OVERLAPPED, ) }; - if socket == c::INVALID_SOCKET { + if socket == sys::c::INVALID_SOCKET { return Err(last_error()); } @@ -161,7 +168,7 @@ impl BorrowedSocket<'_> { /// Returns the last error from the Windows socket interface. fn last_error() -> io::Error { - io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() }) + io::Error::from_raw_os_error(unsafe { sys::c::WSAGetLastError() }) } #[stable(feature = "io_safety", since = "1.63.0")] @@ -194,7 +201,7 @@ impl IntoRawSocket for OwnedSocket { impl FromRawSocket for OwnedSocket { #[inline] unsafe fn from_raw_socket(socket: RawSocket) -> Self { - debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket); + debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket); Self { socket } } } @@ -204,7 +211,7 @@ impl Drop for OwnedSocket { #[inline] fn drop(&mut self) { unsafe { - let _ = c::closesocket(self.socket); + let _ = sys::c::closesocket(self.socket); } } } @@ -247,6 +254,42 @@ impl<T: AsSocket> AsSocket for &mut T { } } +#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")] +/// This impl allows implementing traits that require `AsSocket` on Arc. +/// ``` +/// # #[cfg(windows)] mod group_cfg { +/// # use std::os::windows::io::AsSocket; +/// use std::net::UdpSocket; +/// use std::sync::Arc; +/// +/// trait MyTrait: AsSocket {} +/// impl MyTrait for Arc<UdpSocket> {} +/// impl MyTrait for Box<UdpSocket> {} +/// # } +/// ``` +impl<T: AsSocket> AsSocket for crate::sync::Arc<T> { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + (**self).as_socket() + } +} + +#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")] +impl<T: AsSocket> AsSocket for crate::rc::Rc<T> { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + (**self).as_socket() + } +} + +#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")] +impl<T: AsSocket> AsSocket for Box<T> { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + (**self).as_socket() + } +} + #[stable(feature = "io_safety", since = "1.63.0")] impl AsSocket for BorrowedSocket<'_> { #[inline] @@ -260,7 +303,7 @@ 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 + // invariants, and the `BorrowedSocket` is bounded by the lifetime // of `&self`. unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } } diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 9fa8f5702a8..a2ffd8b1e7e 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -26,7 +26,9 @@ pub macro panic_2015 { $crate::rt::panic_display(&$arg) }), ($fmt:expr, $($arg:tt)+) => ({ - $crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) + // Semicolon to prevent temporaries inside the formatting machinery from + // being considered alive in the caller after the panic_fmt call. + $crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+)); }), } @@ -308,8 +310,7 @@ pub fn get_backtrace_style() -> Option<BacktraceStyle> { BacktraceStyle::Short } }) - .unwrap_or(if cfg!(target_os = "fuchsia") { - // Fuchsia components default to full backtrace. + .unwrap_or(if crate::sys::FULL_BACKTRACE_DEFAULT { BacktraceStyle::Full } else { BacktraceStyle::Off diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index b0db3112e22..6d59266b6f8 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -46,12 +46,10 @@ extern "C" { fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); } -#[allow(improper_ctypes)] extern "Rust" { - /// `payload` is passed through another layer of raw pointers as `&mut dyn Trait` is not - /// FFI-safe. `BoxMeUp` lazily performs allocation only when needed (this avoids allocations - /// when using the "abort" panic runtime). - fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32; + /// `BoxMeUp` lazily performs allocation only when needed (this avoids + /// allocations when using the "abort" panic runtime). + fn __rust_start_panic(payload: &mut dyn BoxMeUp) -> u32; } /// This function is called by the panic runtime if FFI code catches a Rust @@ -95,13 +93,16 @@ impl Default for Hook { static HOOK: RwLock<Hook> = RwLock::new(Hook::Default); -/// Registers a custom panic hook, replacing any that was previously registered. +/// Registers a custom panic hook, replacing the previously registered hook. /// /// The panic hook is invoked when a thread panics, but before the panic runtime /// is invoked. As such, the hook will run with both the aborting and unwinding -/// runtimes. The default hook prints a message to standard error and generates -/// a backtrace if requested, but this behavior can be customized with the -/// `set_hook` and [`take_hook`] functions. +/// runtimes. +/// +/// The default hook, which is registered at startup, prints a message to standard error and +/// generates a backtrace if requested. This behavior can be customized using the `set_hook` function. +/// The current hook can be retrieved while reinstating the default hook with the [`take_hook`] +/// function. /// /// [`take_hook`]: ./fn.take_hook.html /// @@ -143,13 +144,14 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) { drop(old); } -/// Unregisters the current panic hook, returning it. +/// Unregisters the current panic hook and returns it, registering the default hook +/// in its place. /// /// *See also the function [`set_hook`].* /// /// [`set_hook`]: ./fn.set_hook.html /// -/// If no custom hook is registered, the default hook will be returned. +/// If the default hook is registered it will be returned, but remain registered. /// /// # Panics /// @@ -496,6 +498,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> // This function cannot be marked as `unsafe` because `intrinsics::r#try` // expects normal function pointers. #[inline] + #[rustc_nounwind] // `intrinsic::r#try` requires catch fn to be nounwind fn do_catch<F: FnOnce() -> R, R>(data: *mut u8, payload: *mut u8) { // SAFETY: this is the responsibility of the caller, see above. // @@ -538,7 +541,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { // Lazily, the first time this gets called, run the actual string formatting. self.string.get_or_insert_with(|| { let mut s = String::new(); - drop(s.write_fmt(*inner)); + let _err = s.write_fmt(*inner); s }) } @@ -734,10 +737,7 @@ pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! { /// yer breakpoints. #[inline(never)] #[cfg_attr(not(test), rustc_std_internal_symbol)] -fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! { - let code = unsafe { - let obj = &mut msg as *mut &mut dyn BoxMeUp; - __rust_start_panic(obj) - }; +fn rust_panic(msg: &mut dyn BoxMeUp) -> ! { + let code = unsafe { __rust_start_panic(msg) }; rtabort!("failed to initiate panic, error {code}") } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index cd6b393a2ea..43203c5824d 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -78,7 +78,7 @@ use crate::fmt; use crate::fs; use crate::hash::{Hash, Hasher}; use crate::io; -use crate::iter::{self, FusedIterator}; +use crate::iter::FusedIterator; use crate::ops::{self, Deref}; use crate::rc::Rc; use crate::str::FromStr; @@ -117,7 +117,7 @@ use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR} /// use std::path::Prefix::*; /// use std::ffi::OsStr; /// -/// fn get_path_prefix(s: &str) -> Prefix { +/// fn get_path_prefix(s: &str) -> Prefix<'_> { /// let path = Path::new(s); /// match path.components().next().unwrap() { /// Component::Prefix(prefix_component) => prefix_component.kind(), @@ -450,26 +450,26 @@ impl<'a> PrefixComponent<'a> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> cmp::PartialEq for PrefixComponent<'a> { +impl<'a> PartialEq for PrefixComponent<'a> { #[inline] fn eq(&self, other: &PrefixComponent<'a>) -> bool { - cmp::PartialEq::eq(&self.parsed, &other.parsed) + self.parsed == other.parsed } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> cmp::PartialOrd for PrefixComponent<'a> { +impl<'a> PartialOrd for PrefixComponent<'a> { #[inline] fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> { - cmp::PartialOrd::partial_cmp(&self.parsed, &other.parsed) + PartialOrd::partial_cmp(&self.parsed, &other.parsed) } } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Ord for PrefixComponent<'_> { +impl Ord for PrefixComponent<'_> { #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { - cmp::Ord::cmp(&self.parsed, &other.parsed) + Ord::cmp(&self.parsed, &other.parsed) } } @@ -988,7 +988,7 @@ impl<'a> DoubleEndedIterator for Components<'a> { impl FusedIterator for Components<'_> {} #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> cmp::PartialEq for Components<'a> { +impl<'a> PartialEq for Components<'a> { #[inline] fn eq(&self, other: &Components<'a>) -> bool { let Components { path: _, front: _, back: _, has_physical_root: _, prefix: _ } = self; @@ -1015,10 +1015,10 @@ impl<'a> cmp::PartialEq for Components<'a> { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Eq for Components<'_> {} +impl Eq for Components<'_> {} #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> cmp::PartialOrd for Components<'a> { +impl<'a> PartialOrd for Components<'a> { #[inline] fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> { Some(compare_components(self.clone(), other.clone())) @@ -1026,7 +1026,7 @@ impl<'a> cmp::PartialOrd for Components<'a> { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Ord for Components<'_> { +impl Ord for Components<'_> { #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { compare_components(self.clone(), other.clone()) @@ -1395,11 +1395,16 @@ impl PathBuf { /// /// let mut buf = PathBuf::from("/"); /// assert!(buf.file_name() == None); - /// buf.set_file_name("bar"); - /// assert!(buf == PathBuf::from("/bar")); + /// + /// buf.set_file_name("foo.txt"); + /// assert!(buf == PathBuf::from("/foo.txt")); /// assert!(buf.file_name().is_some()); - /// buf.set_file_name("baz.txt"); - /// assert!(buf == PathBuf::from("/baz.txt")); + /// + /// buf.set_file_name("bar.txt"); + /// assert!(buf == PathBuf::from("/bar.txt")); + /// + /// buf.set_file_name("baz"); + /// assert!(buf == PathBuf::from("/baz")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) { @@ -1498,7 +1503,6 @@ impl PathBuf { /// # Examples /// /// ``` - /// #![feature(path_as_mut_os_str)] /// use std::path::{Path, PathBuf}; /// /// let mut path = PathBuf::from("/foo"); @@ -1510,7 +1514,7 @@ impl PathBuf { /// path.as_mut_os_string().push("baz"); /// assert_eq!(path, Path::new("/foo/barbaz")); /// ``` - #[unstable(feature = "path_as_mut_os_str", issue = "105021")] + #[stable(feature = "path_as_mut_os_str", since = "1.70.0")] #[must_use] #[inline] pub fn as_mut_os_string(&mut self) -> &mut OsString { @@ -1742,7 +1746,7 @@ impl FromStr for PathBuf { } #[stable(feature = "rust1", since = "1.0.0")] -impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf { +impl<P: AsRef<Path>> FromIterator<P> for PathBuf { fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf { let mut buf = PathBuf::new(); buf.extend(iter); @@ -1751,7 +1755,7 @@ impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf { } #[stable(feature = "rust1", since = "1.0.0")] -impl<P: AsRef<Path>> iter::Extend<P> for PathBuf { +impl<P: AsRef<Path>> Extend<P> for PathBuf { fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) { iter.into_iter().for_each(move |p| self.push(p.as_ref())); } @@ -1905,7 +1909,7 @@ impl ToOwned for Path { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::PartialEq for PathBuf { +impl PartialEq for PathBuf { #[inline] fn eq(&self, other: &PathBuf) -> bool { self.components() == other.components() @@ -1920,10 +1924,10 @@ impl Hash for PathBuf { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Eq for PathBuf {} +impl Eq for PathBuf {} #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::PartialOrd for PathBuf { +impl PartialOrd for PathBuf { #[inline] fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> { Some(compare_components(self.components(), other.components())) @@ -1931,7 +1935,7 @@ impl cmp::PartialOrd for PathBuf { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Ord for PathBuf { +impl Ord for PathBuf { #[inline] fn cmp(&self, other: &PathBuf) -> cmp::Ordering { compare_components(self.components(), other.components()) @@ -2066,7 +2070,6 @@ impl Path { /// # Examples /// /// ``` - /// #![feature(path_as_mut_os_str)] /// use std::path::{Path, PathBuf}; /// /// let mut path = PathBuf::from("Foo.TXT"); @@ -2076,7 +2079,7 @@ impl Path { /// path.as_mut_os_str().make_ascii_lowercase(); /// assert_eq!(path, Path::new("foo.txt")); /// ``` - #[unstable(feature = "path_as_mut_os_str", issue = "105021")] + #[stable(feature = "path_as_mut_os_str", since = "1.70.0")] #[must_use] #[inline] pub fn as_mut_os_str(&mut self) -> &mut OsStr { @@ -2564,7 +2567,8 @@ impl Path { /// ``` /// use std::path::{Path, PathBuf}; /// - /// let path = Path::new("/tmp/foo.txt"); + /// let path = Path::new("/tmp/foo.png"); + /// assert_eq!(path.with_file_name("bar"), PathBuf::from("/tmp/bar")); /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt")); /// /// let path = Path::new("/tmp"); @@ -2846,9 +2850,11 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `Ok(false)`. /// - /// As opposed to the [`exists()`] method, this one doesn't silently ignore errors - /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission - /// denied on some of the parent directories.) + /// [`Path::exists()`] only checks whether or not a path was both found and readable. By + /// contrast, `try_exists` will return `Ok(true)` or `Ok(false)`, respectively, if the path + /// was _verified_ to exist or not exist. If its existence can neither be confirmed nor + /// denied, it will propagate an `Err(_)` instead. This can be the case if e.g. listing + /// permission is denied on one of the parent directories. /// /// Note that while this avoids some pitfalls of the `exists()` method, it still can not /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios @@ -3027,7 +3033,7 @@ impl fmt::Display for Display<'_> { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::PartialEq for Path { +impl PartialEq for Path { #[inline] fn eq(&self, other: &Path) -> bool { self.components() == other.components() @@ -3086,10 +3092,10 @@ impl Hash for Path { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Eq for Path {} +impl Eq for Path {} #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::PartialOrd for Path { +impl PartialOrd for Path { #[inline] fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> { Some(compare_components(self.components(), other.components())) @@ -3097,7 +3103,7 @@ impl cmp::PartialOrd for Path { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Ord for Path { +impl Ord for Path { #[inline] fn cmp(&self, other: &Path) -> cmp::Ordering { compare_components(self.components(), other.components()) diff --git a/library/std/src/personality/dwarf/eh.rs b/library/std/src/personality/dwarf/eh.rs index 87585a8fcd0..79624703a4c 100644 --- a/library/std/src/personality/dwarf/eh.rs +++ b/library/std/src/personality/dwarf/eh.rs @@ -47,6 +47,7 @@ pub enum EHAction { None, Cleanup(usize), Catch(usize), + Filter(usize), Terminate, } @@ -142,9 +143,11 @@ unsafe fn interpret_cs_action( let ttype_index = action_reader.read_sleb128(); if ttype_index == 0 { EHAction::Cleanup(lpad) - } else { + } else if ttype_index > 0 { // Stop unwinding Rust panics at catch_unwind. EHAction::Catch(lpad) + } else { + EHAction::Filter(lpad) } } } diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs index 41c0fe725a5..82edb11cbd1 100644 --- a/library/std/src/personality/gcc.rs +++ b/library/std/src/personality/gcc.rs @@ -77,6 +77,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 +#[cfg(target_arch = "loongarch64")] +const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1 + // The following code is based on GCC's C and C++ personality routines. For reference, see: // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c @@ -132,7 +135,7 @@ cfg_if::cfg_if! { EHAction::None | EHAction::Cleanup(_) => { return continue_unwind(exception_object, context); } - EHAction::Catch(_) => { + EHAction::Catch(_) | EHAction::Filter(_) => { // EHABI requires the personality routine to update the // SP value in the barrier cache of the exception object. (*exception_object).private[5] = @@ -144,7 +147,8 @@ cfg_if::cfg_if! { } else { match eh_action { EHAction::None => return continue_unwind(exception_object, context), - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => { + EHAction::Filter(_) if state & uw::_US_FORCE_UNWIND as c_int != 0 => return continue_unwind(exception_object, context), + EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { uw::_Unwind_SetGR( context, UNWIND_DATA_REG.0, @@ -198,13 +202,15 @@ cfg_if::cfg_if! { if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { match eh_action { EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, - EHAction::Catch(_) => uw::_URC_HANDLER_FOUND, + EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND, EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR, } } else { match eh_action { EHAction::None => uw::_URC_CONTINUE_UNWIND, - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => { + // Forced unwinding hits a terminate action. + EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND, + EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { uw::_Unwind_SetGR( context, UNWIND_DATA_REG.0, diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index c314bbbb68e..1b29c887d21 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -34,7 +34,7 @@ //! marker traits that indicate fundamental properties of types. //! * <code>[std::ops]::{[Drop], [Fn], [FnMut], [FnOnce]}</code>, various //! operations for both destructors and overloading `()`. -//! * <code>[std::mem]::[drop][mem::drop]</code>, a convenience function for explicitly +//! * <code>[std::mem]::[drop]</code>, a convenience function for explicitly //! dropping a value. //! * <code>[std::boxed]::[Box]</code>, a way to allocate values on the heap. //! * <code>[std::borrow]::[ToOwned]</code>, the conversion trait that defines @@ -66,7 +66,6 @@ //! * <code>[std::convert]::{[TryFrom], [TryInto]}</code>, //! * <code>[std::iter]::[FromIterator]</code>. //! -//! [mem::drop]: crate::mem::drop //! [std::borrow]: crate::borrow //! [std::boxed]: crate::boxed //! [std::clone]: crate::clone @@ -86,9 +85,6 @@ //! [std::slice]: crate::slice //! [std::string]: crate::string //! [std::vec]: mod@crate::vec -//! [TryFrom]: crate::convert::TryFrom -//! [TryInto]: crate::convert::TryInto -//! [FromIterator]: crate::iter::FromIterator //! [`to_owned`]: crate::borrow::ToOwned::to_owned //! [book-closures]: ../../book/ch13-01-closures.html //! [book-dtor]: ../../book/ch15-03-drop.html diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 2aefd7c513d..7a7a7737635 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -91,10 +91,10 @@ pub use core::prelude::v1::cfg_eval; )] pub use core::prelude::v1::type_ascribe; -// The file so far is equivalent to src/libcore/prelude/v1.rs, -// and below to src/liballoc/prelude.rs. -// Those files are duplicated rather than using glob imports -// because we want docs to show these re-exports as pointing to within `std`. +// The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated +// rather than glob imported because we want docs to show these re-exports as +// pointing to within `std`. +// Below are the items from the alloc crate. #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index d6e9da187e8..8266e899011 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1,7 +1,7 @@ // `library/{std,core}/src/primitive_docs.rs` should have the same contents. // These are different files so that relative links work properly without // having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same. -#[doc(primitive = "bool")] +#[rustc_doc_primitive = "bool"] #[doc(alias = "true")] #[doc(alias = "false")] /// The boolean type. @@ -63,7 +63,7 @@ #[stable(feature = "rust1", since = "1.0.0")] mod prim_bool {} -#[doc(primitive = "never")] +#[rustc_doc_primitive = "never"] #[doc(alias = "!")] // /// The `!` type, also called "never". @@ -274,7 +274,7 @@ mod prim_bool {} #[unstable(feature = "never_type", issue = "35121")] mod prim_never {} -#[doc(primitive = "char")] +#[rustc_doc_primitive = "char"] #[allow(rustdoc::invalid_rust_codeblocks)] /// A character type. /// @@ -398,7 +398,7 @@ mod prim_never {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_char {} -#[doc(primitive = "unit")] +#[rustc_doc_primitive = "unit"] #[doc(alias = "(")] #[doc(alias = ")")] #[doc(alias = "()")] @@ -460,7 +460,7 @@ impl Copy for () { // empty } -#[doc(primitive = "pointer")] +#[rustc_doc_primitive = "pointer"] #[doc(alias = "ptr")] #[doc(alias = "*")] #[doc(alias = "*const")] @@ -550,6 +550,7 @@ impl Copy for () { /// /// ``` /// # #![feature(rustc_private)] +/// #[allow(unused_extern_crates)] /// extern crate libc; /// /// use std::mem; @@ -572,12 +573,11 @@ impl Copy for () { /// [`is_null`]: pointer::is_null /// [`offset`]: pointer::offset #[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))] -/// [`drop`]: mem::drop /// [`write`]: ptr::write #[stable(feature = "rust1", since = "1.0.0")] mod prim_pointer {} -#[doc(primitive = "array")] +#[rustc_doc_primitive = "array"] #[doc(alias = "[]")] #[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases #[doc(alias = "[T; N]")] @@ -587,8 +587,10 @@ mod prim_pointer {} /// There are two syntactic forms for creating an array: /// /// * A list with each element, i.e., `[x, y, z]`. -/// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`. -/// The type of `x` must be [`Copy`]. +/// * A repeat expression `[expr; N]` where `N` is how many times to repeat `expr` in the array. `expr` must either be: +/// +/// * A value of a type implementing the [`Copy`] trait +/// * A `const` value /// /// Note that `[expr; 0]` is allowed, and produces an empty array. /// This will still evaluate `expr`, however, and immediately drop the resulting value, so @@ -609,6 +611,9 @@ mod prim_pointer {} /// if the element type allows it. As a stopgap, trait implementations are /// statically generated up to size 32. /// +/// Arrays of sizes from 1 to 12 (inclusive) implement [`From<Tuple>`], where `Tuple` +/// is a homogenous [prim@tuple] of appropriate length. +/// /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on /// an array. Indeed, this provides most of the API for working with arrays. /// @@ -671,6 +676,13 @@ mod prim_pointer {} /// move_away(roa); /// ``` /// +/// Arrays can be created from homogenous tuples of appropriate length: +/// +/// ``` +/// let tuple: (u32, u32, u32) = (1, 2, 3); +/// let array: [u32; 3] = tuple.into(); +/// ``` +/// /// # Editions /// /// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call @@ -773,10 +785,11 @@ mod prim_pointer {} /// [`Borrow`]: borrow::Borrow /// [`BorrowMut`]: borrow::BorrowMut /// [slice pattern]: ../reference/patterns.html#slice-patterns +/// [`From<Tuple>`]: convert::From #[stable(feature = "rust1", since = "1.0.0")] mod prim_array {} -#[doc(primitive = "slice")] +#[rustc_doc_primitive = "slice"] #[doc(alias = "[")] #[doc(alias = "]")] #[doc(alias = "[]")] @@ -868,7 +881,7 @@ mod prim_array {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_slice {} -#[doc(primitive = "str")] +#[rustc_doc_primitive = "str"] /// String slices. /// /// *[See also the `std::str` module](crate::str).* @@ -935,7 +948,7 @@ mod prim_slice {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_str {} -#[doc(primitive = "tuple")] +#[rustc_doc_primitive = "tuple"] #[doc(alias = "(")] #[doc(alias = ")")] #[doc(alias = "()")] @@ -999,7 +1012,9 @@ mod prim_str {} /// * [`Debug`] /// * [`Default`] /// * [`Hash`] +/// * [`From<[T; N]>`][from] /// +/// [from]: convert::From /// [`Debug`]: fmt::Debug /// [`Hash`]: hash::Hash /// @@ -1015,7 +1030,6 @@ mod prim_str {} /// * [`UnwindSafe`] /// * [`RefUnwindSafe`] /// -/// [`Unpin`]: marker::Unpin /// [`UnwindSafe`]: panic::UnwindSafe /// [`RefUnwindSafe`]: panic::RefUnwindSafe /// @@ -1051,6 +1065,13 @@ mod prim_str {} /// assert_eq!(y, 5); /// ``` /// +/// Homogenous tuples can be created from arrays of appropriate length: +/// +/// ``` +/// let array: [u32; 3] = [1, 2, 3]; +/// let tuple: (u32, u32, u32) = array.into(); +/// ``` +/// #[stable(feature = "rust1", since = "1.0.0")] mod prim_tuple {} @@ -1079,7 +1100,7 @@ impl<T: Copy> Copy for (T,) { // empty } -#[doc(primitive = "f32")] +#[rustc_doc_primitive = "f32"] /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). /// /// This type can represent a wide range of decimal numbers, like `3.5`, `27`, @@ -1108,7 +1129,7 @@ impl<T: Copy> Copy for (T,) { /// - [NaN (not a number)](#associatedconstant.NAN): this value results from /// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected /// behavior: -/// - It is unequal to any float, including itself! This is the reason `f32` +/// - It is not equal to any float, including itself! This is the reason `f32` /// doesn't implement the `Eq` trait. /// - It is also neither smaller nor greater than any float, making it /// impossible to sort by the default comparison operation, which is the @@ -1145,7 +1166,7 @@ impl<T: Copy> Copy for (T,) { #[stable(feature = "rust1", since = "1.0.0")] mod prim_f32 {} -#[doc(primitive = "f64")] +#[rustc_doc_primitive = "f64"] /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008). /// /// This type is very similar to [`f32`], but has increased @@ -1160,67 +1181,67 @@ mod prim_f32 {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_f64 {} -#[doc(primitive = "i8")] +#[rustc_doc_primitive = "i8"] // /// The 8-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i8 {} -#[doc(primitive = "i16")] +#[rustc_doc_primitive = "i16"] // /// The 16-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i16 {} -#[doc(primitive = "i32")] +#[rustc_doc_primitive = "i32"] // /// The 32-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i32 {} -#[doc(primitive = "i64")] +#[rustc_doc_primitive = "i64"] // /// The 64-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i64 {} -#[doc(primitive = "i128")] +#[rustc_doc_primitive = "i128"] // /// The 128-bit signed integer type. #[stable(feature = "i128", since = "1.26.0")] mod prim_i128 {} -#[doc(primitive = "u8")] +#[rustc_doc_primitive = "u8"] // /// The 8-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u8 {} -#[doc(primitive = "u16")] +#[rustc_doc_primitive = "u16"] // /// The 16-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u16 {} -#[doc(primitive = "u32")] +#[rustc_doc_primitive = "u32"] // /// The 32-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u32 {} -#[doc(primitive = "u64")] +#[rustc_doc_primitive = "u64"] // /// The 64-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u64 {} -#[doc(primitive = "u128")] +#[rustc_doc_primitive = "u128"] // /// The 128-bit unsigned integer type. #[stable(feature = "i128", since = "1.26.0")] mod prim_u128 {} -#[doc(primitive = "isize")] +#[rustc_doc_primitive = "isize"] // /// The pointer-sized signed integer type. /// @@ -1230,7 +1251,7 @@ mod prim_u128 {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_isize {} -#[doc(primitive = "usize")] +#[rustc_doc_primitive = "usize"] // /// The pointer-sized unsigned integer type. /// @@ -1240,7 +1261,7 @@ mod prim_isize {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_usize {} -#[doc(primitive = "reference")] +#[rustc_doc_primitive = "reference"] #[doc(alias = "&")] #[doc(alias = "&mut")] // @@ -1336,6 +1357,7 @@ mod prim_usize {} /// * [`Hash`] /// * [`ToSocketAddrs`] /// * [`Send`] \(`&T` references also require <code>T: [Sync]</code>) +/// * [`Sync`] /// /// [`std::fmt`]: fmt /// [`Hash`]: hash::Hash @@ -1371,16 +1393,12 @@ mod prim_usize {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_ref {} -#[doc(primitive = "fn")] +#[rustc_doc_primitive = "fn"] // /// Function pointers, like `fn(usize) -> bool`. /// /// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].* /// -/// [`Fn`]: ops::Fn -/// [`FnMut`]: ops::FnMut -/// [`FnOnce`]: ops::FnOnce -/// /// Function pointers are pointers that point to *code*, not data. They can be called /// just like functions. Like references, function pointers are, among other things, assumed to /// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 62ce2cb33dc..9da74a5ddb5 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -110,7 +110,7 @@ use crate::convert::Infallible; use crate::ffi::OsStr; use crate::fmt; use crate::fs; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::num::NonZeroI32; use crate::path::Path; use crate::str; @@ -211,6 +211,7 @@ pub struct Child { impl crate::sealed::Sealed for Child {} impl AsInner<imp::Process> for Child { + #[inline] fn as_inner(&self) -> &imp::Process { &self.handle } @@ -304,6 +305,7 @@ impl Write for &ChildStdin { } impl AsInner<AnonPipe> for ChildStdin { + #[inline] fn as_inner(&self) -> &AnonPipe { &self.inner } @@ -354,6 +356,10 @@ impl Read for ChildStdout { self.inner.read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.inner.read_buf(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.inner.read_vectored(bufs) } @@ -369,6 +375,7 @@ impl Read for ChildStdout { } impl AsInner<AnonPipe> for ChildStdout { + #[inline] fn as_inner(&self) -> &AnonPipe { &self.inner } @@ -419,6 +426,10 @@ impl Read for ChildStderr { self.inner.read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.inner.read_buf(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.inner.read_vectored(bufs) } @@ -430,6 +441,7 @@ impl Read for ChildStderr { } impl AsInner<AnonPipe> for ChildStderr { + #[inline] fn as_inner(&self) -> &AnonPipe { &self.inner } @@ -644,10 +656,19 @@ impl Command { self } - /// Inserts or updates an environment variable mapping. + /// Inserts or updates an explicit environment variable mapping. /// - /// Note that environment variable names are case-insensitive (but case-preserving) on Windows, - /// and case-sensitive on all other platforms. + /// This method allows you to add an environment variable mapping to the spawned process or + /// overwrite a previously set value. You can use [`Command::envs`] to set multiple environment + /// variables simultaneously. + /// + /// Child processes will inherit environment variables from their parent process by default. + /// Environment variables explicitly set using [`Command::env`] take precedence over inherited + /// variables. You can disable environment variable inheritance entirely using + /// [`Command::env_clear`] or for a single key using [`Command::env_remove`]. + /// + /// Note that environment variable names are case-insensitive (but + /// case-preserving) on Windows and case-sensitive on all other platforms. /// /// # Examples /// @@ -671,7 +692,19 @@ impl Command { self } - /// Adds or updates multiple environment variable mappings. + /// Inserts or updates multiple explicit environment variable mappings. + /// + /// This method allows you to add multiple environment variable mappings to the spawned process + /// or overwrite previously set values. You can use [`Command::env`] to set a single environment + /// variable. + /// + /// Child processes will inherit environment variables from their parent process by default. + /// Environment variables explicitly set using [`Command::envs`] take precedence over inherited + /// variables. You can disable environment variable inheritance entirely using + /// [`Command::env_clear`] or for a single key using [`Command::env_remove`]. + /// + /// Note that environment variable names are case-insensitive (but case-preserving) on Windows + /// and case-sensitive on all other platforms. /// /// # Examples /// @@ -708,7 +741,18 @@ impl Command { self } - /// Removes an environment variable mapping. + /// Removes an explicitly set environment variable and prevents inheriting it from a parent + /// process. + /// + /// This method will remove the explicit value of an environment variable set via + /// [`Command::env`] or [`Command::envs`]. In addition, it will prevent the spawned child + /// process from inheriting that environment variable from its parent process. + /// + /// After calling [`Command::env_remove`], the value associated with its key from + /// [`Command::get_envs`] will be [`None`]. + /// + /// To clear all explicitly set environment variables and disable all environment variable + /// inheritance, you can use [`Command::env_clear`]. /// /// # Examples /// @@ -728,7 +772,17 @@ impl Command { self } - /// Clears the entire environment map for the child process. + /// Clears all explicitly set environment variables and prevents inheriting any parent process + /// environment variables. + /// + /// This method will remove all explicitly added environment variables set via [`Command::env`] + /// or [`Command::envs`]. In addition, it will prevent the spawned child process from inheriting + /// any environment variable from its parent process. + /// + /// After calling [`Command::env_remove`], the iterator from [`Command::get_envs`] will be + /// empty. + /// + /// You can use [`Command::env_remove`] to clear a single mapping. /// /// # Examples /// @@ -980,17 +1034,21 @@ impl Command { CommandArgs { inner: self.inner.get_args() } } - /// Returns an iterator of the environment variables that will be set when - /// the process is spawned. + /// Returns an iterator of the environment variables explicitly set for the child process. /// - /// Each element is a tuple `(&OsStr, Option<&OsStr>)`, where the first - /// value is the key, and the second is the value, which is [`None`] if - /// the environment variable is to be explicitly removed. + /// Environment variables explicitly set using [`Command::env`], [`Command::envs`], and + /// [`Command::env_remove`] can be retrieved with this method. /// - /// This only includes environment variables explicitly set with - /// [`Command::env`], [`Command::envs`], and [`Command::env_remove`]. It - /// does not include environment variables that will be inherited by the - /// child process. + /// Note that this output does not include environment variables inherited from the parent + /// process. + /// + /// Each element is a tuple key/value pair `(&OsStr, Option<&OsStr>)`. A [`None`] value + /// indicates its key was explicitly removed via [`Command::env_remove`]. The associated key for + /// the [`None`] value will no longer inherit from its parent process. + /// + /// An empty iterator can indicate that no explicit mappings were added or that + /// [`Command::env_clear`] was called. After calling [`Command::env_clear`], the child process + /// will not inherit any environment variables from its parent process. /// /// # Examples /// @@ -1053,12 +1111,14 @@ impl fmt::Debug for Command { } impl AsInner<imp::Command> for Command { + #[inline] fn as_inner(&self) -> &imp::Command { &self.inner } } impl AsInnerMut<imp::Command> for Command { + #[inline] fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner } @@ -1416,7 +1476,7 @@ impl From<fs::File> for Stdio { /// use std::fs::File; /// use std::process::Command; /// - /// // With the `foo.txt` file containing `Hello, world!" + /// // With the `foo.txt` file containing "Hello, world!" /// let file = File::open("foo.txt").unwrap(); /// /// let reverse = Command::new("rev") @@ -1551,6 +1611,7 @@ impl ExitStatus { } impl AsInner<imp::ExitStatus> for ExitStatus { + #[inline] fn as_inner(&self) -> &imp::ExitStatus { &self.0 } @@ -1781,7 +1842,7 @@ impl ExitCode { /// # use std::fmt; /// # enum UhOhError { GenericProblem, Specific, WithCode { exit_code: ExitCode, _x: () } } /// # impl fmt::Display for UhOhError { - /// # fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { unimplemented!() } + /// # fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { unimplemented!() } /// # } /// // there's no way to gracefully recover from an UhOhError, so we just /// // print a message and exit @@ -1830,6 +1891,7 @@ impl From<u8> for ExitCode { } impl AsInner<imp::ExitCode> for ExitCode { + #[inline] fn as_inner(&self) -> &imp::ExitCode { &self.0 } diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index b4f6cc2daba..d7f4d335de3 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -1,7 +1,8 @@ use crate::io::prelude::*; use super::{Command, Output, Stdio}; -use crate::io::ErrorKind; +use crate::io::{BorrowedBuf, ErrorKind}; +use crate::mem::MaybeUninit; use crate::str; fn known_command() -> Command { @@ -121,6 +122,37 @@ fn stdin_works() { #[test] #[cfg_attr(any(target_os = "vxworks"), ignore)] +fn child_stdout_read_buf() { + let mut cmd = if cfg!(target_os = "windows") { + let mut cmd = Command::new("cmd"); + cmd.arg("/C").arg("echo abc"); + cmd + } else { + let mut cmd = shell_cmd(); + cmd.arg("-c").arg("echo abc"); + cmd + }; + cmd.stdin(Stdio::null()); + cmd.stdout(Stdio::piped()); + let child = cmd.spawn().unwrap(); + + let mut stdout = child.stdout.unwrap(); + let mut buf: [MaybeUninit<u8>; 128] = MaybeUninit::uninit_array(); + let mut buf = BorrowedBuf::from(buf.as_mut_slice()); + stdout.read_buf(buf.unfilled()).unwrap(); + + // ChildStdout::read_buf should omit buffer initialization. + if cfg!(target_os = "windows") { + assert_eq!(buf.filled(), b"abc\r\n"); + assert_eq!(buf.init_len(), 5); + } else { + assert_eq!(buf.filled(), b"abc\n"); + assert_eq!(buf.init_len(), 4); + }; +} + +#[test] +#[cfg_attr(any(target_os = "vxworks"), ignore)] fn test_process_status() { let mut status = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap() diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 7e85d6a063a..a6bc468b092 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -1,9 +1,9 @@ use crate::cell::UnsafeCell; -use crate::fmt; use crate::mem::ManuallyDrop; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::Once; +use crate::{fmt, ptr}; use super::once::ExclusiveState; @@ -26,7 +26,7 @@ union Data<T, F> { /// # Examples /// /// ``` -/// #![feature(once_cell)] +/// #![feature(lazy_cell)] /// /// use std::collections::HashMap; /// @@ -54,7 +54,7 @@ union Data<T, F> { /// // Some("Hoyten") /// } /// ``` -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] pub struct LazyLock<T, F = fn() -> T> { once: Once, data: UnsafeCell<Data<T, F>>, @@ -64,11 +64,47 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// Creates a new lazy value with the given initializing /// function. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "lazy_cell", issue = "109736")] pub const fn new(f: F) -> LazyLock<T, F> { LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) } } + /// Consumes this `LazyLock` returning the stored value. + /// + /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(lazy_cell)] + /// #![feature(lazy_cell_consume)] + /// + /// use std::sync::LazyLock; + /// + /// let hello = "Hello, World!".to_string(); + /// + /// let lazy = LazyLock::new(|| hello.to_uppercase()); + /// + /// assert_eq!(&*lazy, "HELLO, WORLD!"); + /// assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string())); + /// ``` + #[unstable(feature = "lazy_cell_consume", issue = "109736")] + pub fn into_inner(mut this: Self) -> Result<T, F> { + let state = this.once.state(); + match state { + ExclusiveState::Poisoned => panic!("LazyLock instance has previously been poisoned"), + state => { + let this = ManuallyDrop::new(this); + let data = unsafe { ptr::read(&this.data) }.into_inner(); + match state { + ExclusiveState::Incomplete => Err(ManuallyDrop::into_inner(unsafe { data.f })), + ExclusiveState::Complete => Ok(ManuallyDrop::into_inner(unsafe { data.value })), + ExclusiveState::Poisoned => unreachable!(), + } + } + } + } + /// Forces the evaluation of this lazy value and /// returns a reference to result. This is equivalent /// to the `Deref` impl, but is explicit. @@ -76,7 +112,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(lazy_cell)] /// /// use std::sync::LazyLock; /// @@ -86,7 +122,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// assert_eq!(&*lazy, &92); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "lazy_cell", issue = "109736")] pub fn force(this: &LazyLock<T, F>) -> &T { this.once.call_once(|| { // SAFETY: `call_once` only runs this closure once, ever. @@ -122,7 +158,7 @@ impl<T, F> LazyLock<T, F> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T, F> Drop for LazyLock<T, F> { fn drop(&mut self) { match self.once.state() { @@ -135,7 +171,7 @@ impl<T, F> Drop for LazyLock<T, F> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> { type Target = T; @@ -145,7 +181,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T: Default> Default for LazyLock<T> { /// Creates a new lazy value using `Default` as the initializing function. #[inline] @@ -154,7 +190,7 @@ impl<T: Default> Default for LazyLock<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { @@ -166,13 +202,13 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> { // We never create a `&F` from a `&LazyLock<T, F>` so it is fine // to not impl `Sync` for `F` -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {} // auto-derived `Send` impl is OK. -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {} -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {} #[cfg(test)] diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 4edc956173b..f6a7c0a9f75 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -133,7 +133,9 @@ //! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at //! most one thread at a time is able to access some data. //! -//! - [`Once`]: Used for thread-safe, one-time initialization of a +//! - [`Once`]: Used for a thread-safe, one-time global initialization routine +//! +//! - [`OnceLock`]: Used for thread-safe, one-time initialization of a //! global variable. //! //! - [`RwLock`]: Provides a mutual exclusion mechanism which allows @@ -147,6 +149,7 @@ //! [`mpsc`]: crate::sync::mpsc //! [`Mutex`]: crate::sync::Mutex //! [`Once`]: crate::sync::Once +//! [`OnceLock`]: crate::sync::OnceLock //! [`RwLock`]: crate::sync::RwLock #![stable(feature = "rust1", since = "1.0.0")] @@ -172,9 +175,9 @@ pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] pub use self::lazy_lock::LazyLock; -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] pub use self::once_lock::OnceLock; pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard}; diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs index c6bb09b0417..492e21d9bdb 100644 --- a/library/std/src/sync/mpmc/array.rs +++ b/library/std/src/sync/mpmc/array.rs @@ -25,7 +25,8 @@ struct Slot<T> { /// The current stamp. stamp: AtomicUsize, - /// The message in this slot. + /// The message in this slot. Either read out in `read` or dropped through + /// `discard_all_messages`. msg: UnsafeCell<MaybeUninit<T>>, } @@ -439,14 +440,13 @@ impl<T> Channel<T> { Some(self.cap) } - /// Disconnects the channel and wakes up all blocked senders and receivers. + /// Disconnects senders and wakes up all blocked receivers. /// /// Returns `true` if this call disconnected the channel. - pub(crate) fn disconnect(&self) -> bool { + pub(crate) fn disconnect_senders(&self) -> bool { let tail = self.tail.fetch_or(self.mark_bit, Ordering::SeqCst); if tail & self.mark_bit == 0 { - self.senders.disconnect(); self.receivers.disconnect(); true } else { @@ -454,6 +454,85 @@ impl<T> Channel<T> { } } + /// Disconnects receivers and wakes up all blocked senders. + /// + /// Returns `true` if this call disconnected the channel. + /// + /// # Safety + /// May only be called once upon dropping the last receiver. The + /// destruction of all other receivers must have been observed with acquire + /// ordering or stronger. + pub(crate) unsafe fn disconnect_receivers(&self) -> bool { + let tail = self.tail.fetch_or(self.mark_bit, Ordering::SeqCst); + let disconnected = if tail & self.mark_bit == 0 { + self.senders.disconnect(); + true + } else { + false + }; + + self.discard_all_messages(tail); + disconnected + } + + /// Discards all messages. + /// + /// `tail` should be the current (and therefore last) value of `tail`. + /// + /// # Panicking + /// If a destructor panics, the remaining messages are leaked, matching the + /// behaviour of the unbounded channel. + /// + /// # Safety + /// This method must only be called when dropping the last receiver. The + /// destruction of all other receivers must have been observed with acquire + /// ordering or stronger. + unsafe fn discard_all_messages(&self, tail: usize) { + debug_assert!(self.is_disconnected()); + + // Only receivers modify `head`, so since we are the last one, + // this value will not change and will not be observed (since + // no new messages can be sent after disconnection). + let mut head = self.head.load(Ordering::Relaxed); + let tail = tail & !self.mark_bit; + + let backoff = Backoff::new(); + loop { + // Deconstruct the head. + let index = head & (self.mark_bit - 1); + let lap = head & !(self.one_lap - 1); + + // Inspect the corresponding slot. + debug_assert!(index < self.buffer.len()); + let slot = unsafe { self.buffer.get_unchecked(index) }; + let stamp = slot.stamp.load(Ordering::Acquire); + + // If the stamp is ahead of the head by 1, we may drop the message. + if head + 1 == stamp { + head = if index + 1 < self.cap { + // Same lap, incremented index. + // Set to `{ lap: lap, mark: 0, index: index + 1 }`. + head + 1 + } else { + // One lap forward, index wraps around to zero. + // Set to `{ lap: lap.wrapping_add(1), mark: 0, index: 0 }`. + lap.wrapping_add(self.one_lap) + }; + + unsafe { + (*slot.msg.get()).assume_init_drop(); + } + // If the tail equals the head, that means the channel is empty. + } else if tail == head { + return; + // Otherwise, a sender is about to write into the slot, so we need + // to wait for it to update the stamp. + } else { + backoff.spin_heavy(); + } + } + } + /// Returns `true` if the channel is disconnected. pub(crate) fn is_disconnected(&self) -> bool { self.tail.load(Ordering::SeqCst) & self.mark_bit != 0 @@ -483,23 +562,3 @@ impl<T> Channel<T> { head.wrapping_add(self.one_lap) == tail & !self.mark_bit } } - -impl<T> Drop for Channel<T> { - fn drop(&mut self) { - // Get the index of the head. - let hix = self.head.load(Ordering::Relaxed) & (self.mark_bit - 1); - - // Loop over all slots that hold a message and drop them. - for i in 0..self.len() { - // Compute the index of the next slot holding a message. - let index = if hix + i < self.cap { hix + i } else { hix + i - self.cap }; - - unsafe { - debug_assert!(index < self.buffer.len()); - let slot = self.buffer.get_unchecked_mut(index); - let msg = &mut *slot.msg.get(); - msg.as_mut_ptr().drop_in_place(); - } - } - } -} diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index ec6c0726ac7..406a331a309 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -549,6 +549,18 @@ impl<T> Channel<T> { let mut head = self.head.index.load(Ordering::Acquire); let mut block = self.head.block.load(Ordering::Acquire); + // If we're going to be dropping messages we need to synchronize with initialization + if head >> SHIFT != tail >> SHIFT { + // The block can be null here only if a sender is in the process of initializing the + // channel while another sender managed to send a message by inserting it into the + // semi-initialized channel and advanced the tail. + // In that case, just wait until it gets initialized. + while block.is_null() { + backoff.spin_heavy(); + block = self.head.block.load(Ordering::Acquire); + } + } + unsafe { // Drop all messages between head and tail and deallocate the heap-allocated blocks. while head >> SHIFT != tail >> SHIFT { diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index 7a602cecd3b..2068dda393a 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -227,7 +227,7 @@ impl<T> Drop for Sender<T> { fn drop(&mut self) { unsafe { match &self.flavor { - SenderFlavor::Array(chan) => chan.release(|c| c.disconnect()), + SenderFlavor::Array(chan) => chan.release(|c| c.disconnect_senders()), SenderFlavor::List(chan) => chan.release(|c| c.disconnect_senders()), SenderFlavor::Zero(chan) => chan.release(|c| c.disconnect()), } @@ -403,7 +403,7 @@ impl<T> Drop for Receiver<T> { fn drop(&mut self) { unsafe { match &self.flavor { - ReceiverFlavor::Array(chan) => chan.release(|c| c.disconnect()), + ReceiverFlavor::Array(chan) => chan.release(|c| c.disconnect_receivers()), ReceiverFlavor::List(chan) => chan.release(|c| c.disconnect_receivers()), ReceiverFlavor::Zero(chan) => chan.release(|c| c.disconnect()), } diff --git a/library/std/src/sync/mpsc/sync_tests.rs b/library/std/src/sync/mpsc/sync_tests.rs index 9d2f92ffc9b..632709fd98d 100644 --- a/library/std/src/sync/mpsc/sync_tests.rs +++ b/library/std/src/sync/mpsc/sync_tests.rs @@ -1,5 +1,6 @@ use super::*; use crate::env; +use crate::rc::Rc; use crate::sync::mpmc::SendTimeoutError; use crate::thread; use crate::time::Duration; @@ -656,3 +657,15 @@ fn issue_15761() { repro() } } + +#[test] +fn drop_unreceived() { + let (tx, rx) = sync_channel::<Rc<()>>(1); + let msg = Rc::new(()); + let weak = Rc::downgrade(&msg); + assert!(tx.send(msg).is_ok()); + drop(rx); + // Messages should be dropped immediately when the last receiver is destroyed. + assert!(weak.upgrade().is_none()); + drop(tx); +} diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index 065045f4420..b8fec6902a0 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -107,8 +107,8 @@ use crate::sys::locks as sys; /// *guard += 1; /// ``` /// -/// It is sometimes necessary to manually drop the mutex guard to unlock it -/// sooner than the end of the enclosing scope. +/// To unlock a mutex guard sooner than the end of the enclosing scope, +/// either create an inner scope or drop the guard manually. /// /// ``` /// use std::sync::{Arc, Mutex}; @@ -125,11 +125,18 @@ use crate::sys::locks as sys; /// let res_mutex_clone = Arc::clone(&res_mutex); /// /// threads.push(thread::spawn(move || { -/// let mut data = data_mutex_clone.lock().unwrap(); -/// // This is the result of some important and long-ish work. -/// let result = data.iter().fold(0, |acc, x| acc + x * 2); -/// data.push(result); -/// drop(data); +/// // Here we use a block to limit the lifetime of the lock guard. +/// let result = { +/// let mut data = data_mutex_clone.lock().unwrap(); +/// // This is the result of some important and long-ish work. +/// let result = data.iter().fold(0, |acc, x| acc + x * 2); +/// data.push(result); +/// result +/// // The mutex guard gets dropped here, together with any other values +/// // created in the critical section. +/// }; +/// // The guard created here is a temporary dropped at the end of the statement, i.e. +/// // the lock would not remain being held even if the thread did some additional work. /// *res_mutex_clone.lock().unwrap() += result; /// })); /// }); @@ -146,6 +153,8 @@ use crate::sys::locks as sys; /// // It's even more important here than in the threads because we `.join` the /// // threads after that. If we had not dropped the mutex guard, a thread could /// // be waiting forever for it, causing a deadlock. +/// // As in the threads, a block could have been used instead of calling the +/// // `drop` function. /// drop(data); /// // Here the mutex guard is not assigned to a variable and so, even if the /// // scope does not end after this line, the mutex is still released: there is @@ -160,6 +169,7 @@ use crate::sys::locks as sys; /// /// assert_eq!(*res_mutex.lock().unwrap(), 800); /// ``` +/// #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Mutex")] pub struct Mutex<T: ?Sized> { diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index ed339ca5df6..e83bc35ee98 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -14,8 +14,6 @@ use crate::sync::Once; /// # Examples /// /// ``` -/// #![feature(once_cell)] -/// /// use std::sync::OnceLock; /// /// static CELL: OnceLock<String> = OnceLock::new(); @@ -32,7 +30,7 @@ use crate::sync::Once; /// assert!(value.is_some()); /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); /// ``` -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] pub struct OnceLock<T> { once: Once, // Whether or not the value is initialized is tracked by `once.is_completed()`. @@ -40,8 +38,6 @@ pub struct OnceLock<T> { /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl. /// /// ```compile_fail,E0597 - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// struct A<'a>(&'a str); @@ -63,7 +59,8 @@ impl<T> OnceLock<T> { /// Creates a new empty cell. #[inline] #[must_use] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_const_stable(feature = "once_cell", since = "1.70.0")] pub const fn new() -> OnceLock<T> { OnceLock { once: Once::new(), @@ -77,7 +74,7 @@ impl<T> OnceLock<T> { /// Returns `None` if the cell is empty, or being initialized. This /// method never blocks. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get(&self) -> Option<&T> { if self.is_initialized() { // Safe b/c checked is_initialized @@ -91,7 +88,7 @@ impl<T> OnceLock<T> { /// /// Returns `None` if the cell is empty. This method never blocks. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_mut(&mut self) -> Option<&mut T> { if self.is_initialized() { // Safe b/c checked is_initialized and we have a unique access @@ -111,8 +108,6 @@ impl<T> OnceLock<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// static CELL: OnceLock<i32> = OnceLock::new(); @@ -129,7 +124,7 @@ impl<T> OnceLock<T> { /// } /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn set(&self, value: T) -> Result<(), T> { let mut value = Some(value); self.get_or_init(|| value.take().unwrap()); @@ -158,8 +153,6 @@ impl<T> OnceLock<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// let cell = OnceLock::new(); @@ -169,7 +162,7 @@ impl<T> OnceLock<T> { /// assert_eq!(value, &92); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_or_init<F>(&self, f: F) -> &T where F: FnOnce() -> T, @@ -195,7 +188,7 @@ impl<T> OnceLock<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(once_cell_try)] /// /// use std::sync::OnceLock; /// @@ -209,7 +202,7 @@ impl<T> OnceLock<T> { /// assert_eq!(cell.get(), Some(&92)) /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "once_cell_try", issue = "109737")] pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result<T, E>, @@ -236,8 +229,6 @@ impl<T> OnceLock<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// let cell: OnceLock<String> = OnceLock::new(); @@ -248,7 +239,7 @@ impl<T> OnceLock<T> { /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn into_inner(mut self) -> Option<T> { self.take() } @@ -262,8 +253,6 @@ impl<T> OnceLock<T> { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// let mut cell: OnceLock<String> = OnceLock::new(); @@ -275,7 +264,7 @@ impl<T> OnceLock<T> { /// assert_eq!(cell.get(), None); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn take(&mut self) -> Option<T> { if self.is_initialized() { self.once = Once::new(); @@ -344,26 +333,23 @@ impl<T> OnceLock<T> { // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] unsafe impl<T: Sync + Send> Sync for OnceLock<T> {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] unsafe impl<T: Send> Send for OnceLock<T> {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {} -#[unstable(feature = "once_cell", issue = "74465")] -#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] -impl<T> const Default for OnceLock<T> { +#[stable(feature = "once_cell", since = "1.70.0")] +impl<T> Default for OnceLock<T> { /// Creates a new empty cell. /// /// # Example /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// fn main() { @@ -376,7 +362,7 @@ impl<T> const Default for OnceLock<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: fmt::Debug> fmt::Debug for OnceLock<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { @@ -386,7 +372,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceLock<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: Clone> Clone for OnceLock<T> { #[inline] fn clone(&self) -> OnceLock<T> { @@ -401,15 +387,13 @@ impl<T: Clone> Clone for OnceLock<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T> From<T> for OnceLock<T> { /// Create a new cell with its contents set to `value`. /// /// # Example /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// # fn main() -> Result<(), i32> { @@ -430,7 +414,7 @@ impl<T> From<T> for OnceLock<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: PartialEq> PartialEq for OnceLock<T> { #[inline] fn eq(&self, other: &OnceLock<T>) -> bool { @@ -438,10 +422,10 @@ impl<T: PartialEq> PartialEq for OnceLock<T> { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: Eq> Eq for OnceLock<T> {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "1.70.0")] unsafe impl<#[may_dangle] T> Drop for OnceLock<T> { #[inline] fn drop(&mut self) { diff --git a/library/std/src/sync/once_lock/tests.rs b/library/std/src/sync/once_lock/tests.rs index 46695225b9f..d5d32e73d88 100644 --- a/library/std/src/sync/once_lock/tests.rs +++ b/library/std/src/sync/once_lock/tests.rs @@ -24,7 +24,7 @@ fn sync_once_cell() { assert_eq!(ONCE_CELL.get(), Some(&92)); }); - ONCE_CELL.get_or_init(|| panic!("Kabom!")); + ONCE_CELL.get_or_init(|| panic!("Kaboom!")); assert_eq!(ONCE_CELL.get(), Some(&92)); } diff --git a/library/std/src/sync/remutex.rs b/library/std/src/sync/remutex.rs index 4c054da6471..0ced48d10b7 100644 --- a/library/std/src/sync/remutex.rs +++ b/library/std/src/sync/remutex.rs @@ -7,7 +7,7 @@ use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; use crate::sys::locks as sys; -/// A re-entrant mutual exclusion +/// A reentrant mutual exclusion /// /// This mutex will block *other* threads waiting for the lock to become /// available. The thread which has already locked the mutex can lock it @@ -35,7 +35,7 @@ use crate::sys::locks as sys; /// `owner` can be checked by other threads that want to see if they already /// hold the lock, so needs to be atomic. If it compares equal, we're on the /// same thread that holds the mutex and memory access can use relaxed ordering -/// since we're not dealing with multiple threads. If it compares unequal, +/// since we're not dealing with multiple threads. If it's not equal, /// synchronization is left to the mutex, making relaxed memory ordering for /// the `owner` field fine in all cases. pub struct ReentrantMutex<T> { diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs index 403a5e627f1..a5fcbdf39c6 100644 --- a/library/std/src/sys/common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -22,6 +22,7 @@ pub const MIN_ALIGN: usize = 8; #[cfg(any( target_arch = "x86_64", target_arch = "aarch64", + target_arch = "loongarch64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64", diff --git a/library/std/src/sys/common/mod.rs b/library/std/src/sys/common/mod.rs index 29fc0835d76..2b8782ddf44 100644 --- a/library/std/src/sys/common/mod.rs +++ b/library/std/src/sys/common/mod.rs @@ -12,6 +12,7 @@ pub mod alloc; pub mod small_c_string; +pub mod thread_local; #[cfg(test)] mod tests; diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs new file mode 100644 index 00000000000..447044a798b --- /dev/null +++ b/library/std/src/sys/common/thread_local/fast_local.rs @@ -0,0 +1,247 @@ +use super::lazy::LazyKeyInner; +use crate::cell::Cell; +use crate::sys::thread_local_dtor::register_dtor; +use crate::{fmt, mem, panic}; + +#[doc(hidden)] +#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)] +#[allow_internal_unsafe] +#[unstable(feature = "thread_local_internals", issue = "none")] +#[rustc_macro_transparency = "semitransparent"] +pub macro thread_local_inner { + // used to generate the `LocalKey` value for const-initialized thread locals + (@key $t:ty, const $init:expr) => {{ + #[inline] + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn __getit( + _init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + const INIT_EXPR: $t = $init; + // If the platform has support for `#[thread_local]`, use it. + #[thread_local] + static mut VAL: $t = INIT_EXPR; + + // If a dtor isn't needed we can do something "very raw" and + // just get going. + if !$crate::mem::needs_drop::<$t>() { + unsafe { + return $crate::option::Option::Some(&VAL) + } + } + + // 0 == dtor not registered + // 1 == dtor registered, dtor not run + // 2 == dtor registered and is running or has run + #[thread_local] + static mut STATE: $crate::primitive::u8 = 0; + + unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) { + let ptr = ptr as *mut $t; + + unsafe { + $crate::debug_assert_eq!(STATE, 1); + STATE = 2; + $crate::ptr::drop_in_place(ptr); + } + } + + unsafe { + match STATE { + // 0 == we haven't registered a destructor, so do + // so now. + 0 => { + $crate::thread::local_impl::Key::<$t>::register_dtor( + $crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8, + destroy, + ); + STATE = 1; + $crate::option::Option::Some(&VAL) + } + // 1 == the destructor is registered and the value + // is valid, so return the pointer. + 1 => $crate::option::Option::Some(&VAL), + // otherwise the destructor has already run, so we + // can't give access. + _ => $crate::option::Option::None, + } + } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + }}, + + // used to generate the `LocalKey` value for `thread_local!` + (@key $t:ty, $init:expr) => { + { + #[inline] + fn __init() -> $t { $init } + + #[inline] + unsafe fn __getit( + init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + #[thread_local] + static __KEY: $crate::thread::local_impl::Key<$t> = + $crate::thread::local_impl::Key::<$t>::new(); + + // FIXME: remove the #[allow(...)] marker when macros don't + // raise warning for missing/extraneous unsafe blocks anymore. + // See https://github.com/rust-lang/rust/issues/74838. + #[allow(unused_unsafe)] + unsafe { + __KEY.get(move || { + if let $crate::option::Option::Some(init) = init { + if let $crate::option::Option::Some(value) = init.take() { + return value; + } else if $crate::cfg!(debug_assertions) { + $crate::unreachable!("missing default value"); + } + } + __init() + }) + } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + } + }, + ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { + $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = + $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); + }, +} + +#[derive(Copy, Clone)] +enum DtorState { + Unregistered, + Registered, + RunningOrHasRun, +} + +// This data structure has been carefully constructed so that the fast path +// only contains one branch on x86. That optimization is necessary to avoid +// duplicated tls lookups on OSX. +// +// LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 +pub struct Key<T> { + // If `LazyKeyInner::get` returns `None`, that indicates either: + // * The value has never been initialized + // * The value is being recursively initialized + // * The value has already been destroyed or is being destroyed + // To determine which kind of `None`, check `dtor_state`. + // + // This is very optimizer friendly for the fast path - initialized but + // not yet dropped. + inner: LazyKeyInner<T>, + + // Metadata to keep track of the state of the destructor. Remember that + // this variable is thread-local, not global. + dtor_state: Cell<DtorState>, +} + +impl<T> fmt::Debug for Key<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Key").finish_non_exhaustive() + } +} + +impl<T> Key<T> { + pub const fn new() -> Key<T> { + Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } + } + + // note that this is just a publicly-callable function only for the + // const-initialized form of thread locals, basically a way to call the + // free `register_dtor` function defined elsewhere in std. + pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { + unsafe { + register_dtor(a, dtor); + } + } + + pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { + // SAFETY: See the definitions of `LazyKeyInner::get` and + // `try_initialize` for more information. + // + // The caller must ensure no mutable references are ever active to + // the inner cell or the inner T when this is called. + // The `try_initialize` is dependant on the passed `init` function + // for this. + unsafe { + match self.inner.get() { + Some(val) => Some(val), + None => self.try_initialize(init), + } + } + } + + // `try_initialize` is only called once per fast thread local variable, + // except in corner cases where thread_local dtors reference other + // thread_local's, or it is being recursively initialized. + // + // Macos: Inlining this function can cause two `tlv_get_addr` calls to + // be performed for every call to `Key::get`. + // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 + #[inline(never)] + unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { + // SAFETY: See comment above (this function doc). + if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } { + // SAFETY: See comment above (this function doc). + Some(unsafe { self.inner.initialize(init) }) + } else { + None + } + } + + // `try_register_dtor` is only called once per fast thread local + // variable, except in corner cases where thread_local dtors reference + // other thread_local's, or it is being recursively initialized. + unsafe fn try_register_dtor(&self) -> bool { + match self.dtor_state.get() { + DtorState::Unregistered => { + // SAFETY: dtor registration happens before initialization. + // Passing `self` as a pointer while using `destroy_value<T>` + // is safe because the function will build a pointer to a + // Key<T>, which is the type of self and so find the correct + // size. + unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::<T>) }; + self.dtor_state.set(DtorState::Registered); + true + } + DtorState::Registered => { + // recursively initialized + true + } + DtorState::RunningOrHasRun => false, + } + } +} + +unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) { + let ptr = ptr as *mut Key<T>; + + // SAFETY: + // + // The pointer `ptr` has been built just above and comes from + // `try_register_dtor` where it is originally a Key<T> coming from `self`, + // making it non-NUL and of the correct type. + // + // Right before we run the user destructor be sure to set the + // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This + // causes future calls to `get` to run `try_initialize_drop` again, + // which will now fail, and return `None`. + // + // Wrap the call in a catch to ensure unwinding is caught in the event + // a panic takes place in a destructor. + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe { + let value = (*ptr).inner.take(); + (*ptr).dtor_state.set(DtorState::RunningOrHasRun); + drop(value); + })) { + rtabort!("thread local panicked on drop"); + } +} diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs new file mode 100644 index 00000000000..77f64588310 --- /dev/null +++ b/library/std/src/sys/common/thread_local/mod.rs @@ -0,0 +1,103 @@ +#![unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")] + +// There are three thread-local implementations: "static", "fast", "OS". +// The "OS" thread local key type is accessed via platform-specific API calls and is slow, while the +// "fast" key type is accessed via code generated via LLVM, where TLS keys are set up by the linker. +// "static" is for single-threaded platforms where a global static is sufficient. + +cfg_if::cfg_if! { + if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] { + #[doc(hidden)] + mod static_local; + #[doc(hidden)] + pub use static_local::{Key, thread_local_inner}; + } else if #[cfg(target_thread_local)] { + #[doc(hidden)] + mod fast_local; + #[doc(hidden)] + pub use fast_local::{Key, thread_local_inner}; + } else { + #[doc(hidden)] + mod os_local; + #[doc(hidden)] + pub use os_local::{Key, thread_local_inner}; + } +} + +mod lazy { + use crate::cell::UnsafeCell; + use crate::hint; + use crate::mem; + + pub struct LazyKeyInner<T> { + inner: UnsafeCell<Option<T>>, + } + + impl<T> LazyKeyInner<T> { + pub const fn new() -> LazyKeyInner<T> { + LazyKeyInner { inner: UnsafeCell::new(None) } + } + + pub unsafe fn get(&self) -> Option<&'static T> { + // SAFETY: The caller must ensure no reference is ever handed out to + // the inner cell nor mutable reference to the Option<T> inside said + // cell. This make it safe to hand a reference, though the lifetime + // of 'static is itself unsafe, making the get method unsafe. + unsafe { (*self.inner.get()).as_ref() } + } + + /// The caller must ensure that no reference is active: this method + /// needs unique access. + pub unsafe fn initialize<F: FnOnce() -> T>(&self, init: F) -> &'static T { + // Execute the initialization up front, *then* move it into our slot, + // just in case initialization fails. + let value = init(); + let ptr = self.inner.get(); + + // SAFETY: + // + // note that this can in theory just be `*ptr = Some(value)`, but due to + // the compiler will currently codegen that pattern with something like: + // + // ptr::drop_in_place(ptr) + // ptr::write(ptr, Some(value)) + // + // Due to this pattern it's possible for the destructor of the value in + // `ptr` (e.g., if this is being recursively initialized) to re-access + // TLS, in which case there will be a `&` and `&mut` pointer to the same + // value (an aliasing violation). To avoid setting the "I'm running a + // destructor" flag we just use `mem::replace` which should sequence the + // operations a little differently and make this safe to call. + // + // The precondition also ensures that we are the only one accessing + // `self` at the moment so replacing is fine. + unsafe { + let _ = mem::replace(&mut *ptr, Some(value)); + } + + // SAFETY: With the call to `mem::replace` it is guaranteed there is + // a `Some` behind `ptr`, not a `None` so `unreachable_unchecked` + // will never be reached. + unsafe { + // After storing `Some` we want to get a reference to the contents of + // what we just stored. While we could use `unwrap` here and it should + // always work it empirically doesn't seem to always get optimized away, + // which means that using something like `try_with` can pull in + // panicking code and cause a large size bloat. + match *ptr { + Some(ref x) => x, + None => hint::unreachable_unchecked(), + } + } + } + + /// The other methods hand out references while taking &self. + /// As such, callers of this method must ensure no `&` and `&mut` are + /// available and used at the same time. + #[allow(unused)] + pub unsafe fn take(&mut self) -> Option<T> { + // SAFETY: See doc comment for this method. + unsafe { (*self.inner.get()).take() } + } + } +} diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs new file mode 100644 index 00000000000..5d48ce1e03b --- /dev/null +++ b/library/std/src/sys/common/thread_local/os_local.rs @@ -0,0 +1,190 @@ +use super::lazy::LazyKeyInner; +use crate::cell::Cell; +use crate::sys_common::thread_local_key::StaticKey as OsStaticKey; +use crate::{fmt, marker, panic, ptr}; + +#[doc(hidden)] +#[allow_internal_unstable(thread_local_internals)] +#[allow_internal_unsafe] +#[unstable(feature = "thread_local_internals", issue = "none")] +#[rustc_macro_transparency = "semitransparent"] +pub macro thread_local_inner { + // used to generate the `LocalKey` value for const-initialized thread locals + (@key $t:ty, const $init:expr) => {{ + #[inline] + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn __getit( + _init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + const INIT_EXPR: $t = $init; + + // On platforms without `#[thread_local]` we fall back to the + // same implementation as below for os thread locals. + #[inline] + const fn __init() -> $t { INIT_EXPR } + static __KEY: $crate::thread::local_impl::Key<$t> = + $crate::thread::local_impl::Key::new(); + #[allow(unused_unsafe)] + unsafe { + __KEY.get(move || { + if let $crate::option::Option::Some(init) = _init { + if let $crate::option::Option::Some(value) = init.take() { + return value; + } else if $crate::cfg!(debug_assertions) { + $crate::unreachable!("missing initial value"); + } + } + __init() + }) + } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + }}, + + // used to generate the `LocalKey` value for `thread_local!` + (@key $t:ty, $init:expr) => { + { + #[inline] + fn __init() -> $t { $init } + + // `#[inline] does not work on windows-gnu due to linking errors around dllimports. + // See https://github.com/rust-lang/rust/issues/109797. + #[cfg_attr(not(windows), inline)] + unsafe fn __getit( + init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + static __KEY: $crate::thread::local_impl::Key<$t> = + $crate::thread::local_impl::Key::new(); + + // FIXME: remove the #[allow(...)] marker when macros don't + // raise warning for missing/extraneous unsafe blocks anymore. + // See https://github.com/rust-lang/rust/issues/74838. + #[allow(unused_unsafe)] + unsafe { + __KEY.get(move || { + if let $crate::option::Option::Some(init) = init { + if let $crate::option::Option::Some(value) = init.take() { + return value; + } else if $crate::cfg!(debug_assertions) { + $crate::unreachable!("missing default value"); + } + } + __init() + }) + } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + } + }, + ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { + $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = + $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); + }, +} + +/// Use a regular global static to store this key; the state provided will then be +/// thread-local. +pub struct Key<T> { + // OS-TLS key that we'll use to key off. + os: OsStaticKey, + marker: marker::PhantomData<Cell<T>>, +} + +impl<T> fmt::Debug for Key<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Key").finish_non_exhaustive() + } +} + +unsafe impl<T> Sync for Key<T> {} + +struct Value<T: 'static> { + inner: LazyKeyInner<T>, + key: &'static Key<T>, +} + +impl<T: 'static> Key<T> { + #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] + pub const fn new() -> Key<T> { + Key { os: OsStaticKey::new(Some(destroy_value::<T>)), marker: marker::PhantomData } + } + + /// It is a requirement for the caller to ensure that no mutable + /// reference is active when this method is called. + pub unsafe fn get(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> { + // SAFETY: See the documentation for this method. + let ptr = unsafe { self.os.get() as *mut Value<T> }; + if ptr.addr() > 1 { + // SAFETY: the check ensured the pointer is safe (its destructor + // is not running) + it is coming from a trusted source (self). + if let Some(ref value) = unsafe { (*ptr).inner.get() } { + return Some(value); + } + } + // SAFETY: At this point we are sure we have no value and so + // initializing (or trying to) is safe. + unsafe { self.try_initialize(init) } + } + + // `try_initialize` is only called once per os thread local variable, + // except in corner cases where thread_local dtors reference other + // thread_local's, or it is being recursively initialized. + unsafe fn try_initialize(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> { + // SAFETY: No mutable references are ever handed out meaning getting + // the value is ok. + let ptr = unsafe { self.os.get() as *mut Value<T> }; + if ptr.addr() == 1 { + // destructor is running + return None; + } + + let ptr = if ptr.is_null() { + // If the lookup returned null, we haven't initialized our own + // local copy, so do that now. + let ptr = Box::into_raw(Box::new(Value { inner: LazyKeyInner::new(), key: self })); + // SAFETY: At this point we are sure there is no value inside + // ptr so setting it will not affect anyone else. + unsafe { + self.os.set(ptr as *mut u8); + } + ptr + } else { + // recursive initialization + ptr + }; + + // SAFETY: ptr has been ensured as non-NUL just above an so can be + // dereferenced safely. + unsafe { Some((*ptr).inner.initialize(init)) } + } +} + +unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) { + // SAFETY: + // + // The OS TLS ensures that this key contains a null value when this + // destructor starts to run. We set it back to a sentinel value of 1 to + // ensure that any future calls to `get` for this thread will return + // `None`. + // + // Note that to prevent an infinite loop we reset it back to null right + // before we return from the destructor ourselves. + // + // Wrap the call in a catch to ensure unwinding is caught in the event + // a panic takes place in a destructor. + if let Err(_) = panic::catch_unwind(|| unsafe { + let ptr = Box::from_raw(ptr as *mut Value<T>); + let key = ptr.key; + key.os.set(ptr::invalid_mut(1)); + drop(ptr); + key.os.set(ptr::null_mut()); + }) { + rtabort!("thread local panicked on drop"); + } +} diff --git a/library/std/src/sys/common/thread_local/static_local.rs b/library/std/src/sys/common/thread_local/static_local.rs new file mode 100644 index 00000000000..80322a97864 --- /dev/null +++ b/library/std/src/sys/common/thread_local/static_local.rs @@ -0,0 +1,109 @@ +use super::lazy::LazyKeyInner; +use crate::fmt; + +#[doc(hidden)] +#[allow_internal_unstable(thread_local_internals)] +#[allow_internal_unsafe] +#[unstable(feature = "thread_local_internals", issue = "none")] +#[rustc_macro_transparency = "semitransparent"] +pub macro thread_local_inner { + // used to generate the `LocalKey` value for const-initialized thread locals + (@key $t:ty, const $init:expr) => {{ + #[inline] // see comments below + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn __getit( + _init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + const INIT_EXPR: $t = $init; + + // wasm without atomics maps directly to `static mut`, and dtors + // aren't implemented because thread dtors aren't really a thing + // on wasm right now + // + // FIXME(#84224) this should come after the `target_thread_local` + // block. + static mut VAL: $t = INIT_EXPR; + unsafe { $crate::option::Option::Some(&VAL) } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + }}, + + // used to generate the `LocalKey` value for `thread_local!` + (@key $t:ty, $init:expr) => { + { + #[inline] + fn __init() -> $t { $init } + #[inline] + unsafe fn __getit( + init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + static __KEY: $crate::thread::local_impl::Key<$t> = + $crate::thread::local_impl::Key::new(); + + // FIXME: remove the #[allow(...)] marker when macros don't + // raise warning for missing/extraneous unsafe blocks anymore. + // See https://github.com/rust-lang/rust/issues/74838. + #[allow(unused_unsafe)] + unsafe { + __KEY.get(move || { + if let $crate::option::Option::Some(init) = init { + if let $crate::option::Option::Some(value) = init.take() { + return value; + } else if $crate::cfg!(debug_assertions) { + $crate::unreachable!("missing default value"); + } + } + __init() + }) + } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + } + }, + ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { + $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = + $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); + }, +} + +/// On some targets like wasm there's no threads, so no need to generate +/// thread locals and we can instead just use plain statics! + +pub struct Key<T> { + inner: LazyKeyInner<T>, +} + +unsafe impl<T> Sync for Key<T> {} + +impl<T> fmt::Debug for Key<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Key").finish_non_exhaustive() + } +} + +impl<T> Key<T> { + pub const fn new() -> Key<T> { + Key { inner: LazyKeyInner::new() } + } + + pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> { + // SAFETY: The caller must ensure no reference is ever handed out to + // the inner cell nor mutable reference to the Option<T> inside said + // cell. This make it safe to hand a reference, though the lifetime + // of 'static is itself unsafe, making the get method unsafe. + let value = unsafe { + match self.inner.get() { + Some(ref value) => value, + None => self.inner.initialize(init), + } + }; + + Some(value) + } +} diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs index afcae6c90ee..220a76e4b12 100644 --- a/library/std/src/sys/hermit/args.rs +++ b/library/std/src/sys/hermit/args.rs @@ -1,6 +1,6 @@ use crate::ffi::{c_char, CStr, OsString}; use crate::fmt; -use crate::os::unix::ffi::OsStringExt; +use crate::os::hermit::ffi::OsStringExt; use crate::ptr; use crate::sync::atomic::{ AtomicIsize, AtomicPtr, diff --git a/library/std/src/sys/hermit/fd.rs b/library/std/src/sys/hermit/fd.rs index c400f5f2c2e..ccde05aa1d7 100644 --- a/library/std/src/sys/hermit/fd.rs +++ b/library/std/src/sys/hermit/fd.rs @@ -1,36 +1,23 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] use crate::io::{self, Read}; -use crate::mem; +use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd}; use crate::sys::cvt; use crate::sys::hermit::abi; use crate::sys::unsupported; -use crate::sys_common::AsInner; +use crate::sys_common::{AsInner, FromInner, IntoInner}; + +use crate::os::hermit::io::*; #[derive(Debug)] pub struct FileDesc { - fd: i32, + fd: OwnedFd, } impl FileDesc { - pub fn new(fd: i32) -> FileDesc { - FileDesc { fd } - } - - pub fn raw(&self) -> i32 { - self.fd - } - - /// Extracts the actual file descriptor without closing it. - pub fn into_raw(self) -> i32 { - let fd = self.fd; - mem::forget(self); - fd - } - pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - let result = unsafe { abi::read(self.fd, buf.as_mut_ptr(), buf.len()) }; - cvt(result as i32) + let result = cvt(unsafe { abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?; + Ok(result as usize) } pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { @@ -39,8 +26,8 @@ impl FileDesc { } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { - let result = unsafe { abi::write(self.fd, buf.as_ptr(), buf.len()) }; - cvt(result as i32) + let result = cvt(unsafe { abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?; + Ok(result as usize) } pub fn duplicate(&self) -> io::Result<FileDesc> { @@ -69,19 +56,46 @@ impl<'a> Read for &'a FileDesc { } } -impl AsInner<i32> for FileDesc { - fn as_inner(&self) -> &i32 { +impl IntoInner<OwnedFd> for FileDesc { + fn into_inner(self) -> OwnedFd { + self.fd + } +} + +impl FromInner<OwnedFd> for FileDesc { + fn from_inner(owned_fd: OwnedFd) -> Self { + Self { fd: owned_fd } + } +} + +impl FromRawFd for FileDesc { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self { fd: FromRawFd::from_raw_fd(raw_fd) } + } +} + +impl AsInner<OwnedFd> for FileDesc { + #[inline] + fn as_inner(&self) -> &OwnedFd { &self.fd } } -impl Drop for FileDesc { - fn drop(&mut self) { - // Note that 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. - let _ = unsafe { abi::close(self.fd) }; +impl AsFd for FileDesc { + fn as_fd(&self) -> BorrowedFd<'_> { + self.fd.as_fd() + } +} + +impl AsRawFd for FileDesc { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.fd.as_raw_fd() + } +} + +impl IntoRawFd for FileDesc { + fn into_raw_fd(self) -> RawFd { + self.fd.into_raw_fd() } } diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index 6fb92c037ee..4bb735668d2 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -3,14 +3,17 @@ use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::io::{self, Error, ErrorKind}; use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; +use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::path::{Path, PathBuf}; use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::cvt; -use crate::sys::hermit::abi; -use crate::sys::hermit::abi::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}; +use crate::sys::hermit::abi::{ + self, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, +}; use crate::sys::hermit::fd::FileDesc; use crate::sys::time::SystemTime; use crate::sys::unsupported; +use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; pub use crate::sys_common::fs::{copy, try_exists}; //pub use crate::sys_common::fs::remove_dir_all; @@ -199,7 +202,7 @@ impl OpenOptions { create: false, create_new: false, // system-specific - mode: 0x777, + mode: 0o777, } } @@ -283,7 +286,7 @@ impl File { } let fd = unsafe { cvt(abi::open(path.as_ptr(), flags, mode))? }; - Ok(File(FileDesc::new(fd as i32))) + Ok(File(unsafe { FileDesc::from_raw_fd(fd as i32) })) } pub fn file_attr(&self) -> io::Result<FileAttr> { @@ -363,6 +366,57 @@ impl DirBuilder { } } +impl AsInner<FileDesc> for File { + #[inline] + fn as_inner(&self) -> &FileDesc { + &self.0 + } +} + +impl AsInnerMut<FileDesc> for File { + #[inline] + fn as_inner_mut(&mut self) -> &mut FileDesc { + &mut self.0 + } +} + +impl IntoInner<FileDesc> for File { + fn into_inner(self) -> FileDesc { + self.0 + } +} + +impl FromInner<FileDesc> for File { + fn from_inner(file_desc: FileDesc) -> Self { + Self(file_desc) + } +} + +impl AsFd for File { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +impl AsRawFd for File { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +impl IntoRawFd for File { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} + +impl FromRawFd for File { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self(FromRawFd::from_raw_fd(raw_fd)) + } +} + pub fn readdir(_p: &Path) -> io::Result<ReadDir> { unsupported() } diff --git a/library/std/src/sys/hermit/futex.rs b/library/std/src/sys/hermit/futex.rs index b64c174b06c..427d8ff6f2e 100644 --- a/library/std/src/sys/hermit/futex.rs +++ b/library/std/src/sys/hermit/futex.rs @@ -16,7 +16,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - let r = unsafe { abi::futex_wait( - futex.as_mut_ptr(), + futex.as_ptr(), expected, timespec.as_ref().map_or(null(), |t| t as *const abi::timespec), abi::FUTEX_RELATIVE_TIMEOUT, @@ -28,12 +28,12 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - #[inline] pub fn futex_wake(futex: &AtomicU32) -> bool { - unsafe { abi::futex_wake(futex.as_mut_ptr(), 1) > 0 } + unsafe { abi::futex_wake(futex.as_ptr(), 1) > 0 } } #[inline] pub fn futex_wake_all(futex: &AtomicU32) { unsafe { - abi::futex_wake(futex.as_mut_ptr(), i32::MAX); + abi::futex_wake(futex.as_ptr(), i32::MAX); } } diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index 20fd3dd8f09..c7cb8466705 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -13,9 +13,8 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -#![allow(unsafe_op_in_unsafe_fn)] +#![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)] -use crate::intrinsics; use crate::os::raw::c_char; pub mod alloc; @@ -57,9 +56,7 @@ pub mod locks { } use crate::io::ErrorKind; - -#[allow(unused_extern_crates)] -pub extern crate hermit_abi as abi; +use crate::os::hermit::abi; pub fn unsupported<T>() -> crate::io::Result<T> { Err(unsupported_err()) @@ -78,9 +75,18 @@ pub fn abort_internal() -> ! { } } -// FIXME: just a workaround to test the system pub fn hashmap_random_keys() -> (u64, u64) { - (1, 2) + let mut buf = [0; 16]; + let mut slice = &mut buf[..]; + while !slice.is_empty() { + let res = cvt(unsafe { abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) }) + .expect("failed to generate random hashmap keys"); + slice = &mut slice[res as usize..]; + } + + let key1 = buf[..8].try_into().unwrap(); + let key2 = buf[8..].try_into().unwrap(); + (u64::from_ne_bytes(key1), u64::from_ne_bytes(key2)) } // This function is needed by the panic runtime. The symbol is named in @@ -126,25 +132,72 @@ pub unsafe extern "C" fn runtime_entry( pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno { - x if x == 13 as i32 => ErrorKind::PermissionDenied, - x if x == 98 as i32 => ErrorKind::AddrInUse, - x if x == 99 as i32 => ErrorKind::AddrNotAvailable, - x if x == 11 as i32 => ErrorKind::WouldBlock, - x if x == 103 as i32 => ErrorKind::ConnectionAborted, - x if x == 111 as i32 => ErrorKind::ConnectionRefused, - x if x == 104 as i32 => ErrorKind::ConnectionReset, - x if x == 17 as i32 => ErrorKind::AlreadyExists, - x if x == 4 as i32 => ErrorKind::Interrupted, - x if x == 22 as i32 => ErrorKind::InvalidInput, - x if x == 2 as i32 => ErrorKind::NotFound, - x if x == 107 as i32 => ErrorKind::NotConnected, - x if x == 1 as i32 => ErrorKind::PermissionDenied, - x if x == 32 as i32 => ErrorKind::BrokenPipe, - x if x == 110 as i32 => ErrorKind::TimedOut, + abi::errno::EACCES => ErrorKind::PermissionDenied, + abi::errno::EADDRINUSE => ErrorKind::AddrInUse, + abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + abi::errno::EAGAIN => ErrorKind::WouldBlock, + abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted, + abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused, + abi::errno::ECONNRESET => ErrorKind::ConnectionReset, + abi::errno::EEXIST => ErrorKind::AlreadyExists, + abi::errno::EINTR => ErrorKind::Interrupted, + abi::errno::EINVAL => ErrorKind::InvalidInput, + abi::errno::ENOENT => ErrorKind::NotFound, + abi::errno::ENOTCONN => ErrorKind::NotConnected, + abi::errno::EPERM => ErrorKind::PermissionDenied, + abi::errno::EPIPE => ErrorKind::BrokenPipe, + abi::errno::ETIMEDOUT => ErrorKind::TimedOut, _ => ErrorKind::Uncategorized, } } -pub fn cvt(result: i32) -> crate::io::Result<usize> { - if result < 0 { Err(crate::io::Error::from_raw_os_error(-result)) } else { Ok(result as usize) } +#[doc(hidden)] +pub trait IsNegative { + fn is_negative(&self) -> bool; + fn negate(&self) -> i32; +} + +macro_rules! impl_is_negative { + ($($t:ident)*) => ($(impl IsNegative for $t { + fn is_negative(&self) -> bool { + *self < 0 + } + + fn negate(&self) -> i32 { + i32::try_from(-(*self)).unwrap() + } + })*) +} + +impl IsNegative for i32 { + fn is_negative(&self) -> bool { + *self < 0 + } + + fn negate(&self) -> i32 { + -(*self) + } +} +impl_is_negative! { i8 i16 i64 isize } + +pub fn cvt<T: IsNegative>(t: T) -> crate::io::Result<T> { + if t.is_negative() { + let e = decode_error_kind(t.negate()); + Err(crate::io::Error::from(e)) + } else { + Ok(t) + } +} + +pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T> +where + T: IsNegative, + F: FnMut() -> T, +{ + loop { + match cvt(f()) { + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + other => return other, + } + } } diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index 8a13879d8cc..8c2d489d6a3 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -1,490 +1,372 @@ -use crate::fmt; -use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; -use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; -use crate::str; -use crate::sync::Arc; -use crate::sys::hermit::abi; -use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6}; -use crate::sys::unsupported; -use crate::sys_common::AsInner; +#![allow(dead_code)] + +use crate::cmp; +use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; +use crate::mem; +use crate::net::{Shutdown, SocketAddr}; +use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd}; +use crate::sys::hermit::fd::FileDesc; +use crate::sys::time::Instant; +use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; -/// Checks whether the HermitCore's socket interface has been started already, and -/// if not, starts it. -pub fn init() -> io::Result<()> { - if abi::network_init() < 0 { - return Err(io::const_io_error!( - ErrorKind::Uncategorized, - "Unable to initialize network interface", - )); - } +use core::ffi::c_int; - Ok(()) -} +#[allow(unused_extern_crates)] +pub extern crate hermit_abi as netc; -#[derive(Debug, Clone)] -pub struct Socket(abi::Handle); +pub use crate::sys::{cvt, cvt_r}; -impl AsInner<abi::Handle> for Socket { - fn as_inner(&self) -> &abi::Handle { - &self.0 +pub type wrlen_t = usize; + +pub fn cvt_gai(err: i32) -> io::Result<()> { + if err == 0 { + return Ok(()); } + + let detail = ""; + + Err(io::Error::new( + io::ErrorKind::Uncategorized, + &format!("failed to lookup address information: {detail}")[..], + )) } -impl Drop for Socket { - fn drop(&mut self) { - let _ = abi::tcpstream::close(self.0); +/// Checks whether the HermitCore's socket interface has been started already, and +/// if not, starts it. +pub fn init() { + if unsafe { netc::network_init() } < 0 { + panic!("Unable to initialize network interface"); } } -// Arc is used to count the number of used sockets. -// Only if all sockets are released, the drop -// method will close the socket. -#[derive(Clone)] -pub struct TcpStream(Arc<Socket>); - -impl TcpStream { - pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> { - let addr = addr?; - - match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { - Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), - _ => Err(io::const_io_error!( - ErrorKind::Uncategorized, - "Unable to initiate a connection on a socket", - )), - } - } +#[derive(Debug)] +pub struct Socket(FileDesc); - pub fn connect_timeout(saddr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> { - match abi::tcpstream::connect( - saddr.ip().to_string().as_bytes(), - saddr.port(), - Some(duration.as_millis() as u64), - ) { - Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), - _ => Err(io::const_io_error!( - ErrorKind::Uncategorized, - "Unable to initiate a connection on a socket", - )), - } +impl Socket { + pub fn new(addr: &SocketAddr, ty: i32) -> io::Result<Socket> { + let fam = match *addr { + SocketAddr::V4(..) => netc::AF_INET, + SocketAddr::V6(..) => netc::AF_INET6, + }; + Socket::new_raw(fam, ty) } - pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> { - abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64)) - .map_err(|_| { - io::const_io_error!(ErrorKind::Uncategorized, "Unable to set timeout value") - }) + pub fn new_raw(fam: i32, ty: i32) -> io::Result<Socket> { + let fd = cvt(unsafe { netc::socket(fam, ty, 0) })?; + Ok(Socket(unsafe { FileDesc::from_raw_fd(fd) })) } - pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> { - abi::tcpstream::set_write_timeout( - *self.0.as_inner(), - duration.map(|d| d.as_millis() as u64), - ) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "Unable to set timeout value")) + pub fn new_pair(_fam: i32, _ty: i32) -> io::Result<(Socket, Socket)> { + unimplemented!() } - pub fn read_timeout(&self) -> io::Result<Option<Duration>> { - let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| { - io::const_io_error!(ErrorKind::Uncategorized, "Unable to determine timeout value") - })?; - - Ok(duration.map(|d| Duration::from_millis(d))) - } + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { + self.set_nonblocking(true)?; + let r = unsafe { + let (addr, len) = addr.into_inner(); + cvt(netc::connect(self.as_raw_fd(), addr.as_ptr(), len)) + }; + self.set_nonblocking(false)?; - pub fn write_timeout(&self) -> io::Result<Option<Duration>> { - let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| { - io::const_io_error!(ErrorKind::Uncategorized, "Unable to determine timeout value") - })?; + match r { + Ok(_) => return Ok(()), + // there's no ErrorKind for EINPROGRESS :( + Err(ref e) if e.raw_os_error() == Some(netc::errno::EINPROGRESS) => {} + Err(e) => return Err(e), + } - Ok(duration.map(|d| Duration::from_millis(d))) - } + let mut pollfd = netc::pollfd { fd: self.as_raw_fd(), events: netc::POLLOUT, revents: 0 }; - pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { - abi::tcpstream::peek(*self.0.as_inner(), buf) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "peek failed")) - } + if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout", + )); + } - pub fn read(&self, buffer: &mut [u8]) -> io::Result<usize> { - self.read_vectored(&mut [IoSliceMut::new(buffer)]) - } + let start = Instant::now(); - pub fn read_vectored(&self, ioslice: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - let mut size: usize = 0; + loop { + let elapsed = start.elapsed(); + if elapsed >= timeout { + return Err(io::const_io_error!(io::ErrorKind::TimedOut, "connection timed out")); + } - for i in ioslice.iter_mut() { - let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]).map_err(|_| { - io::const_io_error!(ErrorKind::Uncategorized, "Unable to read on socket") - })?; + let timeout = timeout - elapsed; + let mut timeout = timeout + .as_secs() + .saturating_mul(1_000) + .saturating_add(timeout.subsec_nanos() as u64 / 1_000_000); + if timeout == 0 { + timeout = 1; + } - if ret != 0 { - size += ret; + let timeout = cmp::min(timeout, c_int::MAX as u64) as c_int; + + match unsafe { netc::poll(&mut pollfd, 1, timeout) } { + -1 => { + let err = io::Error::last_os_error(); + if err.kind() != io::ErrorKind::Interrupted { + return Err(err); + } + } + 0 => {} + _ => { + // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look + // for POLLHUP rather than read readiness + if pollfd.revents & netc::POLLHUP != 0 { + let e = self.take_error()?.unwrap_or_else(|| { + io::const_io_error!( + io::ErrorKind::Uncategorized, + "no error set after POLLHUP", + ) + }); + return Err(e); + } + + return Ok(()); + } } } - - Ok(size) } - #[inline] - pub fn is_read_vectored(&self) -> bool { - true + pub fn accept( + &self, + storage: *mut netc::sockaddr, + len: *mut netc::socklen_t, + ) -> io::Result<Socket> { + let fd = cvt(unsafe { netc::accept(self.0.as_raw_fd(), storage, len) })?; + Ok(Socket(unsafe { FileDesc::from_raw_fd(fd) })) } - pub fn write(&self, buffer: &[u8]) -> io::Result<usize> { - self.write_vectored(&[IoSlice::new(buffer)]) + pub fn duplicate(&self) -> io::Result<Socket> { + let fd = cvt(unsafe { netc::dup(self.0.as_raw_fd()) })?; + Ok(Socket(unsafe { FileDesc::from_raw_fd(fd) })) } - pub fn write_vectored(&self, ioslice: &[IoSlice<'_>]) -> io::Result<usize> { - let mut size: usize = 0; - - for i in ioslice.iter() { - size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| { - io::const_io_error!(ErrorKind::Uncategorized, "Unable to write on socket") - })?; + fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: i32) -> io::Result<()> { + let ret = cvt(unsafe { + netc::recv( + self.0.as_raw_fd(), + buf.as_mut().as_mut_ptr() as *mut u8, + buf.capacity(), + flags, + ) + })?; + unsafe { + buf.advance(ret as usize); } - - Ok(size) - } - - #[inline] - pub fn is_write_vectored(&self) -> bool { - true + Ok(()) } - pub fn peer_addr(&self) -> io::Result<SocketAddr> { - let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner()) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "peer_addr failed"))?; - - let saddr = match ipaddr { - Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), - Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), - _ => { - return Err(io::const_io_error!(ErrorKind::Uncategorized, "peer_addr failed")); - } - }; - - Ok(saddr) + pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { + let mut buf = BorrowedBuf::from(buf); + self.recv_with_flags(buf.unfilled(), 0)?; + Ok(buf.len()) } - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - unsupported() + pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { + let mut buf = BorrowedBuf::from(buf); + self.recv_with_flags(buf.unfilled(), netc::MSG_PEEK)?; + Ok(buf.len()) } - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - abi::tcpstream::shutdown(*self.0.as_inner(), how as i32) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to shutdown socket")) + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.recv_with_flags(buf, 0) } - pub fn duplicate(&self) -> io::Result<TcpStream> { - Ok(self.clone()) - } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { + let mut size: isize = 0; - pub fn set_linger(&self, _linger: Option<Duration>) -> io::Result<()> { - unsupported() - } + for i in bufs.iter_mut() { + let ret: isize = + cvt(unsafe { netc::read(self.0.as_raw_fd(), i.as_mut_ptr(), i.len()) })?; - pub fn linger(&self) -> io::Result<Option<Duration>> { - unsupported() - } + if ret != 0 { + size += ret; + } + } - pub fn set_nodelay(&self, mode: bool) -> io::Result<()> { - abi::tcpstream::set_nodelay(*self.0.as_inner(), mode) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "set_nodelay failed")) + Ok(size.try_into().unwrap()) } - pub fn nodelay(&self) -> io::Result<bool> { - abi::tcpstream::nodelay(*self.0.as_inner()) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "nodelay failed")) + #[inline] + pub fn is_read_vectored(&self) -> bool { + true } - pub fn set_ttl(&self, tll: u32) -> io::Result<()> { - abi::tcpstream::set_tll(*self.0.as_inner(), tll) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to set TTL")) - } + fn recv_from_with_flags(&self, buf: &mut [u8], flags: i32) -> io::Result<(usize, SocketAddr)> { + let mut storage: netc::sockaddr_storage = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as netc::socklen_t; - pub fn ttl(&self) -> io::Result<u32> { - abi::tcpstream::get_tll(*self.0.as_inner()) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to get TTL")) + let n = cvt(unsafe { + netc::recvfrom( + self.as_raw_fd(), + buf.as_mut_ptr(), + buf.len(), + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen, + ) + })?; + Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) } - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - unsupported() + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) } - pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { - abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode).map_err(|_| { - io::const_io_error!(ErrorKind::Uncategorized, "unable to set blocking mode") - }) + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, netc::MSG_PEEK) } -} -impl fmt::Debug for TcpStream { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - Ok(()) + pub fn write(&self, buf: &[u8]) -> io::Result<usize> { + let sz = cvt(unsafe { netc::write(self.0.as_raw_fd(), buf.as_ptr(), buf.len()) })?; + Ok(sz.try_into().unwrap()) } -} -#[derive(Clone)] -pub struct TcpListener(SocketAddr); + pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { + let mut size: isize = 0; -impl TcpListener { - pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> { - let addr = addr?; + for i in bufs.iter() { + size += cvt(unsafe { netc::write(self.0.as_raw_fd(), i.as_ptr(), i.len()) })?; + } - Ok(TcpListener(*addr)) + Ok(size.try_into().unwrap()) } - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - Ok(self.0) + pub fn is_write_vectored(&self) -> bool { + true } - pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port()) - .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "accept failed"))?; - let saddr = match ipaddr { - Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), - Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), - _ => { - return Err(io::const_io_error!(ErrorKind::Uncategorized, "accept failed")); + pub fn set_timeout(&self, dur: Option<Duration>, kind: i32) -> io::Result<()> { + let timeout = match dur { + Some(dur) => { + if dur.as_secs() == 0 && dur.subsec_nanos() == 0 { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout", + )); + } + + let secs = if dur.as_secs() > netc::time_t::MAX as u64 { + netc::time_t::MAX + } else { + dur.as_secs() as netc::time_t + }; + let mut timeout = netc::timeval { + tv_sec: secs, + tv_usec: dur.subsec_micros() as netc::suseconds_t, + }; + if timeout.tv_sec == 0 && timeout.tv_usec == 0 { + timeout.tv_usec = 1; + } + timeout } + None => netc::timeval { tv_sec: 0, tv_usec: 0 }, }; - Ok((TcpStream(Arc::new(Socket(handle))), saddr)) - } - - pub fn duplicate(&self) -> io::Result<TcpListener> { - Ok(self.clone()) - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - unsupported() - } - - pub fn ttl(&self) -> io::Result<u32> { - unsupported() - } - - pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - unsupported() - } - - pub fn only_v6(&self) -> io::Result<bool> { - unsupported() + setsockopt(self, netc::SOL_SOCKET, kind, timeout) } - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - unsupported() - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unsupported() + pub fn timeout(&self, kind: i32) -> io::Result<Option<Duration>> { + let raw: netc::timeval = getsockopt(self, netc::SOL_SOCKET, kind)?; + if raw.tv_sec == 0 && raw.tv_usec == 0 { + Ok(None) + } else { + let sec = raw.tv_sec as u64; + let nsec = (raw.tv_usec as u32) * 1000; + Ok(Some(Duration::new(sec, nsec))) + } } -} -impl fmt::Debug for TcpListener { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + let how = match how { + Shutdown::Write => netc::SHUT_WR, + Shutdown::Read => netc::SHUT_RD, + Shutdown::Both => netc::SHUT_RDWR, + }; + cvt(unsafe { netc::shutdown_socket(self.as_raw_fd(), how) })?; Ok(()) } -} - -pub struct UdpSocket(abi::Handle); - -impl UdpSocket { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { - unsupported() - } - - pub fn peer_addr(&self) -> io::Result<SocketAddr> { - unsupported() - } - - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - unsupported() - } - - pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unsupported() - } - - pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unsupported() - } - - pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> { - unsupported() - } - - pub fn duplicate(&self) -> io::Result<UdpSocket> { - unsupported() - } - - pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> { - unsupported() - } - - pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> { - unsupported() - } - - pub fn read_timeout(&self) -> io::Result<Option<Duration>> { - unsupported() - } - - pub fn write_timeout(&self) -> io::Result<Option<Duration>> { - unsupported() - } - - pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - unsupported() - } - - pub fn broadcast(&self) -> io::Result<bool> { - unsupported() - } - - pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - unsupported() - } - - pub fn multicast_loop_v4(&self) -> io::Result<bool> { - unsupported() - } - - pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - unsupported() - } - - pub fn multicast_ttl_v4(&self) -> io::Result<u32> { - unsupported() - } - - pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - unsupported() - } - pub fn multicast_loop_v6(&self) -> io::Result<bool> { - unsupported() - } - - pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - unsupported() - } + pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> { + let linger = netc::linger { + l_onoff: linger.is_some() as i32, + l_linger: linger.unwrap_or_default().as_secs() as libc::c_int, + }; - pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - unsupported() + setsockopt(self, netc::SOL_SOCKET, netc::SO_LINGER, linger) } - pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - unsupported() - } + pub fn linger(&self) -> io::Result<Option<Duration>> { + let val: netc::linger = getsockopt(self, netc::SOL_SOCKET, netc::SO_LINGER)?; - pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - unsupported() + Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64))) } - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - unsupported() + pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { + let value: i32 = if nodelay { 1 } else { 0 }; + setsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY, value) } - pub fn ttl(&self) -> io::Result<u32> { - unsupported() + pub fn nodelay(&self) -> io::Result<bool> { + let raw: i32 = getsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY)?; + Ok(raw != 0) + } + + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + let mut nonblocking: i32 = if nonblocking { 1 } else { 0 }; + cvt(unsafe { + netc::ioctl( + self.as_raw_fd(), + netc::FIONBIO, + &mut nonblocking as *mut _ as *mut core::ffi::c_void, + ) + }) + .map(drop) } pub fn take_error(&self) -> io::Result<Option<io::Error>> { - unsupported() - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unsupported() - } - - pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> { - unsupported() - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> { - unsupported() - } - - pub fn send(&self, _: &[u8]) -> io::Result<usize> { - unsupported() + unimplemented!() } - pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - unsupported() - } -} - -impl fmt::Debug for UdpSocket { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - Ok(()) + // This is used by sys_common code to abstract over Windows and Unix. + pub fn as_raw(&self) -> RawFd { + self.0.as_raw_fd() } } -pub struct LookupHost(!); - -impl LookupHost { - pub fn port(&self) -> u16 { - self.0 +impl AsInner<FileDesc> for Socket { + #[inline] + fn as_inner(&self) -> &FileDesc { + &self.0 } } -impl Iterator for LookupHost { - type Item = SocketAddr; - fn next(&mut self) -> Option<SocketAddr> { +impl IntoInner<FileDesc> for Socket { + fn into_inner(self) -> FileDesc { self.0 } } -impl TryFrom<&str> for LookupHost { - type Error = io::Error; - - fn try_from(_v: &str) -> io::Result<LookupHost> { - unsupported() +impl FromInner<FileDesc> for Socket { + fn from_inner(file_desc: FileDesc) -> Self { + Self(file_desc) } } -impl<'a> TryFrom<(&'a str, u16)> for LookupHost { - type Error = io::Error; - - fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> { - unsupported() +impl AsFd for Socket { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() } } -#[allow(nonstandard_style)] -pub mod netc { - pub const AF_INET: u8 = 0; - pub const AF_INET6: u8 = 1; - pub type sa_family_t = u8; - - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: u32, - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in { - pub sin_family: sa_family_t, - pub sin_port: u16, - pub sin_addr: in_addr, - } - - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u8; 16], - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - pub sin6_family: sa_family_t, - pub sin6_port: u16, - pub sin6_addr: in6_addr, - pub sin6_flowinfo: u32, - pub sin6_scope_id: u32, +impl AsRawFd for Socket { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() } - - #[derive(Copy, Clone)] - pub struct sockaddr {} } diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs index 8f927df85be..e53dbae6119 100644 --- a/library/std/src/sys/hermit/os.rs +++ b/library/std/src/sys/hermit/os.rs @@ -4,7 +4,7 @@ use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt; use crate::io; use crate::marker::PhantomData; -use crate::os::unix::ffi::OsStringExt; +use crate::os::hermit::ffi::OsStringExt; use crate::path::{self, PathBuf}; use crate::str; use crate::sync::Mutex; diff --git a/library/std/src/sys/hermit/time.rs b/library/std/src/sys/hermit/time.rs index c17e6c8af62..5440d85df4a 100644 --- a/library/std/src/sys/hermit/time.rs +++ b/library/std/src/sys/hermit/time.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use crate::cmp::Ordering; +use crate::ops::{Add, AddAssign, Sub, SubAssign}; use crate::sys::hermit::abi; use crate::sys::hermit::abi::timespec; use crate::sys::hermit::abi::{CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC}; @@ -39,11 +40,7 @@ impl Timespec { } fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { - let mut secs = other - .as_secs() - .try_into() // <- target type would be `libc::time_t` - .ok() - .and_then(|secs| self.t.tv_sec.checked_add(secs))?; + let mut secs = self.tv_sec.checked_add_unsigned(other.as_secs())?; // Nano calculations can't overflow because nanos are <1B which fit // in a u32. @@ -56,11 +53,7 @@ impl Timespec { } fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { - let mut secs = other - .as_secs() - .try_into() // <- target type would be `libc::time_t` - .ok() - .and_then(|secs| self.t.tv_sec.checked_sub(secs))?; + let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?; // Similar to above, nanos can't overflow. let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; @@ -102,55 +95,122 @@ impl Hash for Timespec { } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub struct Instant { - t: Timespec, -} +pub struct Instant(Timespec); impl Instant { pub fn now() -> Instant { let mut time: Timespec = Timespec::zero(); let _ = unsafe { abi::clock_gettime(CLOCK_MONOTONIC, &mut time.t as *mut timespec) }; - Instant { t: time } + Instant(time) + } + + #[stable(feature = "time2", since = "1.8.0")] + pub fn elapsed(&self) -> Duration { + Instant::now() - *self + } + + pub fn duration_since(&self, earlier: Instant) -> Duration { + self.checked_duration_since(earlier).unwrap_or_default() + } + + pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> { + self.checked_sub_instant(&earlier) } pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> { - self.t.sub_timespec(&other.t).ok() + self.0.sub_timespec(&other.0).ok() } pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> { - Some(Instant { t: self.t.checked_add_duration(other)? }) + Some(Instant(self.0.checked_add_duration(other)?)) } pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> { - Some(Instant { t: self.t.checked_sub_duration(other)? }) + Some(Instant(self.0.checked_sub_duration(other)?)) + } + + pub fn checked_add(&self, duration: Duration) -> Option<Instant> { + self.0.checked_add_duration(&duration).map(Instant) + } + + pub fn checked_sub(&self, duration: Duration) -> Option<Instant> { + self.0.checked_sub_duration(&duration).map(Instant) } } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct SystemTime { - t: Timespec, +impl Add<Duration> for Instant { + type Output = Instant; + + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`Instant::checked_add`] for a version without panic. + fn add(self, other: Duration) -> Instant { + self.checked_add(other).expect("overflow when adding duration to instant") + } } -pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() }; +impl AddAssign<Duration> for Instant { + fn add_assign(&mut self, other: Duration) { + *self = *self + other; + } +} + +impl Sub<Duration> for Instant { + type Output = Instant; + + fn sub(self, other: Duration) -> Instant { + self.checked_sub(other).expect("overflow when subtracting duration from instant") + } +} + +impl SubAssign<Duration> for Instant { + fn sub_assign(&mut self, other: Duration) { + *self = *self - other; + } +} + +impl Sub<Instant> for Instant { + type Output = Duration; + + /// Returns the amount of time elapsed from another instant to this one, + /// or zero duration if that instant is later than this one. + /// + /// # Panics + /// + /// Previous rust versions panicked when `other` was later than `self`. Currently this + /// method saturates. Future versions may reintroduce the panic in some circumstances. + /// See [Monotonicity]. + /// + /// [Monotonicity]: Instant#monotonicity + fn sub(self, other: Instant) -> Duration { + self.duration_since(other) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub struct SystemTime(Timespec); + +pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero()); impl SystemTime { pub fn now() -> SystemTime { let mut time: Timespec = Timespec::zero(); let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, &mut time.t as *mut timespec) }; - SystemTime { t: time } + SystemTime(time) } pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.t.sub_timespec(&other.t) + self.0.sub_timespec(&other.0) } pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { - Some(SystemTime { t: self.t.checked_add_duration(other)? }) + Some(SystemTime(self.0.checked_add_duration(other)?)) } pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { - Some(SystemTime { t: self.t.checked_sub_duration(other)? }) + Some(SystemTime(self.0.checked_sub_duration(other)?)) } } diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index 19350b83fab..ae0f718535b 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -247,7 +247,7 @@ impl Thread { // [FINISHED → JOINED] // To synchronize with the child task's memory accesses to // `inner` up to the point of the assignment of `FINISHED`, - // `Ordering::Acquire` must be used for the above `swap` call`. + // `Ordering::Acquire` must be used for the above `swap` call. } _ => unsafe { hint::unreachable_unchecked() }, } diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index c080c176a2a..c72be13804d 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -52,27 +52,11 @@ cfg_if::cfg_if! { } } -// Import essential modules from platforms used in `std::os` when documenting. -// -// Note that on some platforms those modules don't compile -// (missing things in `libc` which is empty), so they are not included in `std::os` and can be -// omitted here as well. - -#[cfg(doc)] -#[cfg(not(any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") -)))] cfg_if::cfg_if! { - if #[cfg(not(windows))] { - // On non-Windows platforms (aka linux/osx/etc) pull in a "minimal" - // amount of windows goop which ends up compiling - - #[macro_use] - #[path = "windows/compat.rs"] - pub mod compat; - - #[path = "windows/c.rs"] - pub mod c; + // Fuchsia components default to full backtrace. + if #[cfg(target_os = "fuchsia")] { + pub const FULL_BACKTRACE_DEFAULT: bool = true; + } else { + pub const FULL_BACKTRACE_DEFAULT: bool = false; } } diff --git a/library/std/src/sys/sgx/abi/entry.S b/library/std/src/sys/sgx/abi/entry.S index f61bcf06f08..8a063b65dac 100644 --- a/library/std/src/sys/sgx/abi/entry.S +++ b/library/std/src/sys/sgx/abi/entry.S @@ -26,7 +26,7 @@ IMAGE_BASE: .Lxsave_clear: .org .+24 .Lxsave_mxcsr: - .short 0x1f80 + .short 0x1fbf /* We can store a bunch of data in the gap between MXCSR and the XSAVE header */ @@ -58,7 +58,7 @@ IMAGE_BASE: globvar DEBUG 1 /* The base address (relative to enclave start) of the enclave text section */ globvar TEXT_BASE 8 - /* The size in bytes of enclacve text section */ + /* The size in bytes of enclave text section */ globvar TEXT_SIZE 8 /* The base address (relative to enclave start) of the enclave .eh_frame_hdr section */ globvar EH_FRM_HDR_OFFSET 8 @@ -66,7 +66,7 @@ IMAGE_BASE: globvar EH_FRM_HDR_LEN 8 /* The base address (relative to enclave start) of the enclave .eh_frame section */ globvar EH_FRM_OFFSET 8 - /* The size in bytes of enclacve .eh_frame section */ + /* The size in bytes of enclave .eh_frame section */ globvar EH_FRM_LEN 8 .org .Lxsave_clear+512 @@ -178,6 +178,7 @@ sgx_entry: mov $-1, %rax mov $-1, %rdx xrstor .Lxsave_clear(%rip) + lfence mov %r10, %rdx /* check if returning from usercall */ @@ -311,6 +312,9 @@ usercall: movq $0,%gs:tcsls_last_rsp /* restore callee-saved state, cf. "save" above */ mov %r11,%rsp + /* MCDT mitigation requires an lfence after ldmxcsr _before_ any of the affected */ + /* vector instructions is used. We omit the lfence here as one is required before */ + /* the jmp instruction anyway. */ ldmxcsr (%rsp) fldcw 4(%rsp) add $8, %rsp diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 0d934318c22..01505e94487 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -3,7 +3,6 @@ use crate::arch::asm; use crate::cell::UnsafeCell; use crate::cmp; -use crate::convert::TryInto; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut}; use crate::ptr::{self, NonNull}; diff --git a/library/std/src/sys/sgx/fd.rs b/library/std/src/sys/sgx/fd.rs index e5dc5b5adaa..b3686d0e283 100644 --- a/library/std/src/sys/sgx/fd.rs +++ b/library/std/src/sys/sgx/fd.rs @@ -1,7 +1,7 @@ use fortanix_sgx_abi::Fd; use super::abi::usercalls; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem; use crate::sys::{AsInner, FromInner, IntoInner}; @@ -30,6 +30,10 @@ impl FileDesc { usercalls::read(self.fd, &mut [IoSliceMut::new(buf)]) } + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { + crate::io::default_read_buf(|b| self.read(b), buf) + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { usercalls::read(self.fd, bufs) } @@ -58,6 +62,7 @@ impl FileDesc { } impl AsInner<Fd> for FileDesc { + #[inline] fn as_inner(&self) -> &Fd { &self.fd } diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs index 4c4cd7d1d1d..03620a08f2c 100644 --- a/library/std/src/sys/sgx/net.rs +++ b/library/std/src/sys/sgx/net.rs @@ -1,6 +1,6 @@ use crate::error; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; use crate::sync::Arc; use crate::sys::fd::FileDesc; @@ -24,6 +24,7 @@ impl Socket { } impl AsInner<FileDesc> for Socket { + #[inline] fn as_inner(&self) -> &FileDesc { &self.inner } @@ -144,6 +145,10 @@ impl TcpStream { self.inner.inner.read(buf) } + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.inner.inner.read_buf(buf) + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.inner.inner.read_vectored(bufs) } @@ -216,6 +221,7 @@ impl TcpStream { } impl AsInner<Socket> for TcpStream { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } @@ -300,6 +306,7 @@ impl TcpListener { } impl AsInner<Socket> for TcpListener { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } diff --git a/library/std/src/sys/sgx/waitqueue/mod.rs b/library/std/src/sys/sgx/waitqueue/mod.rs index 61bb11d9a6f..5e1d859ee99 100644 --- a/library/std/src/sys/sgx/waitqueue/mod.rs +++ b/library/std/src/sys/sgx/waitqueue/mod.rs @@ -202,12 +202,18 @@ impl WaitQueue { pub fn notify_one<T>( mut guard: SpinMutexGuard<'_, WaitVariable<T>>, ) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> { + // SAFETY: lifetime of the pop() return value is limited to the map + // closure (The closure return value is 'static). The underlying + // stack frame won't be freed until after the WaitGuard created below + // is dropped. unsafe { - if let Some(entry) = guard.queue.inner.pop() { + let tcs = guard.queue.inner.pop().map(|entry| -> Tcs { let mut entry_guard = entry.lock(); - let tcs = entry_guard.tcs; entry_guard.wake = true; - drop(entry); + entry_guard.tcs + }); + + if let Some(tcs) = tcs { Ok(WaitGuard { mutex_guard: Some(guard), notified_tcs: NotifiedTcs::Single(tcs) }) } else { Err(guard) @@ -223,6 +229,9 @@ impl WaitQueue { pub fn notify_all<T>( mut guard: SpinMutexGuard<'_, WaitVariable<T>>, ) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> { + // SAFETY: lifetime of the pop() return values are limited to the + // while loop body. The underlying stack frames won't be freed until + // after the WaitGuard created below is dropped. unsafe { let mut count = 0; while let Some(entry) = guard.queue.inner.pop() { @@ -230,6 +239,7 @@ impl WaitQueue { let mut entry_guard = entry.lock(); entry_guard.wake = true; } + if let Some(count) = NonZeroUsize::new(count) { Ok(WaitGuard { mutex_guard: Some(guard), notified_tcs: NotifiedTcs::All { count } }) } else { diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 1b98ef993b0..0bd2bc3b961 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -2,7 +2,7 @@ use super::abi; use crate::{ cmp, ffi::CStr, - io::{self, ErrorKind, IoSlice, IoSliceMut}, + io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}, mem, net::{Shutdown, SocketAddr}, ptr, str, @@ -112,6 +112,7 @@ impl FileDesc { } impl AsInner<c_int> for FileDesc { + #[inline] fn as_inner(&self) -> &c_int { &self.fd } @@ -294,19 +295,30 @@ impl Socket { self.0.duplicate().map(Socket) } - fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> { + fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> { let ret = cvt(unsafe { - netc::recv(self.0.raw(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags) + netc::recv(self.0.raw(), buf.as_mut().as_mut_ptr().cast(), buf.capacity(), flags) })?; - Ok(ret as usize) + unsafe { + buf.advance(ret as usize); + } + Ok(()) } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - self.recv_with_flags(buf, 0) + let mut buf = BorrowedBuf::from(buf); + self.recv_with_flags(buf.unfilled(), 0)?; + Ok(buf.len()) } pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { - self.recv_with_flags(buf, MSG_PEEK) + let mut buf = BorrowedBuf::from(buf); + self.recv_with_flags(buf.unfilled(), MSG_PEEK)?; + Ok(buf.len()) + } + + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.recv_with_flags(buf, 0) } pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { @@ -451,6 +463,7 @@ impl Socket { } impl AsInner<c_int> for Socket { + #[inline] fn as_inner(&self) -> &c_int { self.0.as_inner() } diff --git a/library/std/src/sys/solid/time.rs b/library/std/src/sys/solid/time.rs index ce31cb45a69..f83f1644fe8 100644 --- a/library/std/src/sys/solid/time.rs +++ b/library/std/src/sys/solid/time.rs @@ -47,10 +47,10 @@ impl SystemTime { } pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { - Some(SystemTime(self.0.checked_add(other.as_secs().try_into().ok()?)?)) + Some(SystemTime(self.0.checked_add_unsigned(other.as_secs())?)) } pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { - Some(SystemTime(self.0.checked_sub(other.as_secs().try_into().ok()?)?)) + Some(SystemTime(self.0.checked_sub_unsigned(other.as_secs())?)) } } diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs index 9d6567c9fb4..8604b53983d 100644 --- a/library/std/src/sys/unix/alloc.rs +++ b/library/std/src/sys/unix/alloc.rs @@ -59,7 +59,8 @@ cfg_if::cfg_if! { target_os = "redox", target_os = "solaris", target_os = "espidf", - target_os = "horizon" + target_os = "horizon", + target_os = "vita", ))] { #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index a5ce6d5120d..9ed4d9c1e0d 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -69,7 +69,8 @@ impl DoubleEndedIterator for Args { target_os = "fuchsia", target_os = "redox", target_os = "vxworks", - target_os = "horizon" + target_os = "horizon", + target_os = "nto", ))] mod imp { use super::Args; @@ -264,7 +265,7 @@ mod imp { } } -#[cfg(target_os = "espidf")] +#[cfg(any(target_os = "espidf", target_os = "vita"))] mod imp { use super::Args; diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs index c9ba661c829..8c3ef88d8f8 100644 --- a/library/std/src/sys/unix/env.rs +++ b/library/std/src/sys/unix/env.rs @@ -141,6 +141,17 @@ pub mod os { pub const EXE_EXTENSION: &str = "elf"; } +#[cfg(target_os = "vita")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "vita"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ".elf"; + pub const EXE_EXTENSION: &str = "elf"; +} + #[cfg(all(target_os = "emscripten", target_arch = "asmjs"))] pub mod os { pub const FAMILY: &str = "unix"; @@ -185,6 +196,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "nto")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "nto"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + #[cfg(target_os = "redox")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index ab57fba6c9f..cb630eede6d 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -53,7 +53,12 @@ const fn max_iov() -> usize { libc::IOV_MAX as usize } -#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))] +#[cfg(any( + target_os = "android", + target_os = "emscripten", + target_os = "linux", + target_os = "nto", +))] const fn max_iov() -> usize { libc::UIO_MAXIOV as usize } @@ -67,8 +72,10 @@ const fn max_iov() -> usize { target_os = "linux", target_os = "macos", target_os = "netbsd", + target_os = "nto", target_os = "openbsd", target_os = "horizon", + target_os = "vita", target_os = "watchos", )))] const fn max_iov() -> usize { @@ -87,26 +94,26 @@ impl FileDesc { Ok(ret as usize) } - #[cfg(not(any(target_os = "espidf", target_os = "horizon")))] + #[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))] pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { let ret = cvt(unsafe { libc::readv( self.as_raw_fd(), - bufs.as_ptr() as *const libc::iovec, + bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, cmp::min(bufs.len(), max_iov()) as libc::c_int, ) })?; Ok(ret as usize) } - #[cfg(any(target_os = "espidf", target_os = "horizon"))] + #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - return crate::io::default_read_vectored(|b| self.read(b), bufs); + io::default_read_vectored(|b| self.read(b), bufs) } #[inline] pub fn is_read_vectored(&self) -> bool { - cfg!(not(any(target_os = "espidf", target_os = "horizon"))) + cfg!(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))) } pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { @@ -147,6 +154,95 @@ impl FileDesc { Ok(()) } + #[cfg(any( + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "illumos", + target_os = "linux", + target_os = "netbsd", + ))] + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + let ret = cvt(unsafe { + libc::preadv( + self.as_raw_fd(), + bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + + #[cfg(not(any( + target_os = "android", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "illumos", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + )))] + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + io::default_read_vectored(|b| self.read_at(b, offset), bufs) + } + + // We support some old Android versions that do not have `preadv` in libc, + // so we use weak linkage and fallback to a direct syscall if not available. + // + // On 32-bit targets, we don't want to deal with weird ABI issues around + // passing 64-bits parameters to syscalls, so we fallback to the default + // implementation if `preadv` is not available. + #[cfg(all(target_os = "android", target_pointer_width = "64"))] + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + super::weak::syscall! { + fn preadv( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t + ) -> isize + } + + let ret = cvt(unsafe { + preadv( + self.as_raw_fd(), + bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + + // We support old MacOS and iOS versions that do not have `preadv`. There is + // no `syscall` possible in these platform. + #[cfg(any( + all(target_os = "android", target_pointer_width = "32"), + target_os = "ios", + target_os = "macos", + ))] + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + + match preadv64.get() { + Some(preadv) => { + let ret = cvt(unsafe { + preadv( + self.as_raw_fd(), + bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + None => io::default_read_vectored(|b| self.read_at(b, offset), bufs), + } + } + pub fn write(&self, buf: &[u8]) -> io::Result<usize> { let ret = cvt(unsafe { libc::write( @@ -158,7 +254,7 @@ impl FileDesc { Ok(ret as usize) } - #[cfg(not(any(target_os = "espidf", target_os = "horizon")))] + #[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))] pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { let ret = cvt(unsafe { libc::writev( @@ -170,14 +266,14 @@ impl FileDesc { Ok(ret as usize) } - #[cfg(any(target_os = "espidf", target_os = "horizon"))] + #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - return crate::io::default_write_vectored(|b| self.write(b), bufs); + io::default_write_vectored(|b| self.write(b), bufs) } #[inline] pub fn is_write_vectored(&self) -> bool { - cfg!(not(any(target_os = "espidf", target_os = "horizon"))) + cfg!(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))) } pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { @@ -197,9 +293,93 @@ impl FileDesc { } } - #[cfg(target_os = "linux")] - pub fn get_cloexec(&self) -> io::Result<bool> { - unsafe { Ok((cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) } + #[cfg(any( + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "illumos", + target_os = "linux", + target_os = "netbsd", + ))] + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { + let ret = cvt(unsafe { + libc::pwritev( + self.as_raw_fd(), + bufs.as_ptr() as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + + #[cfg(not(any( + target_os = "android", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "illumos", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + )))] + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { + io::default_write_vectored(|b| self.write_at(b, offset), bufs) + } + + // We support some old Android versions that do not have `pwritev` in libc, + // so we use weak linkage and fallback to a direct syscall if not available. + // + // On 32-bit targets, we don't want to deal with weird ABI issues around + // passing 64-bits parameters to syscalls, so we fallback to the default + // implementation if `pwritev` is not available. + #[cfg(all(target_os = "android", target_pointer_width = "64"))] + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { + super::weak::syscall! { + fn pwritev( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t + ) -> isize + } + + let ret = cvt(unsafe { + pwritev( + self.as_raw_fd(), + bufs.as_ptr() as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + + // We support old MacOS and iOS versions that do not have `pwritev`. There is + // no `syscall` possible in these platform. + #[cfg(any( + all(target_os = "android", target_pointer_width = "32"), + target_os = "ios", + target_os = "macos", + ))] + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { + super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + + match pwritev64.get() { + Some(pwritev) => { + let ret = cvt(unsafe { + pwritev( + self.as_raw_fd(), + bufs.as_ptr() as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + None => io::default_write_vectored(|b| self.write_at(b, offset), bufs), + } } #[cfg(not(any( @@ -212,7 +392,8 @@ impl FileDesc { target_os = "linux", target_os = "haiku", target_os = "redox", - target_os = "vxworks" + target_os = "vxworks", + target_os = "nto", )))] pub fn set_cloexec(&self) -> io::Result<()> { unsafe { @@ -230,7 +411,8 @@ impl FileDesc { target_os = "linux", target_os = "haiku", target_os = "redox", - target_os = "vxworks" + target_os = "vxworks", + target_os = "nto", ))] pub fn set_cloexec(&self) -> io::Result<()> { unsafe { @@ -288,9 +470,19 @@ impl<'a> Read for &'a FileDesc { fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { (**self).read_buf(cursor) } + + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { + (**self).read_vectored(bufs) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + (**self).is_read_vectored() + } } impl AsInner<OwnedFd> for FileDesc { + #[inline] fn as_inner(&self) -> &OwnedFd { &self.0 } @@ -315,6 +507,7 @@ impl AsFd for FileDesc { } impl AsRawFd for FileDesc { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 8e1f35d6cc9..09db5b11dbf 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -13,7 +13,8 @@ use crate::mem; target_os = "solaris", target_os = "fuchsia", target_os = "redox", - target_os = "illumos" + target_os = "illumos", + target_os = "nto", ))] use crate::mem::MaybeUninit; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; @@ -33,7 +34,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; target_os = "watchos", ))] use crate::sys::weak::syscall; -#[cfg(any(target_os = "android", target_os = "macos"))] +#[cfg(any(target_os = "android", target_os = "macos", target_os = "solaris"))] use crate::sys::weak::weak; use libc::{c_int, mode_t}; @@ -42,6 +43,7 @@ use libc::{c_int, mode_t}; target_os = "macos", target_os = "ios", target_os = "watchos", + target_os = "solaris", all(target_os = "linux", target_env = "gnu") ))] use libc::c_char; @@ -54,7 +56,8 @@ use libc::fstatat64; target_os = "solaris", target_os = "fuchsia", target_os = "redox", - target_os = "illumos" + target_os = "illumos", + target_os = "nto", ))] use libc::readdir as readdir64; #[cfg(target_os = "linux")] @@ -69,7 +72,8 @@ use libc::readdir64_r; target_os = "illumos", target_os = "l4re", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", )))] use libc::readdir_r as readdir64_r; #[cfg(target_os = "android")] @@ -277,7 +281,8 @@ unsafe impl Sync for Dir {} target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", ))] pub struct DirEntry { dir: Arc<InnerReadDir>, @@ -297,11 +302,12 @@ pub struct DirEntry { target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", ))] struct dirent64_min { d_ino: u64, - #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] + #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "nto")))] d_type: u8, } @@ -311,7 +317,8 @@ struct dirent64_min { target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", )))] pub struct DirEntry { dir: Arc<InnerReadDir>, @@ -438,9 +445,14 @@ impl FileAttr { } } -#[cfg(not(target_os = "netbsd"))] +#[cfg(not(any(target_os = "netbsd", target_os = "nto")))] impl FileAttr { - #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))] + #[cfg(not(any( + target_os = "vxworks", + target_os = "espidf", + target_os = "horizon", + target_os = "vita" + )))] pub fn modified(&self) -> io::Result<SystemTime> { #[cfg(target_pointer_width = "32")] cfg_has_statx! { @@ -452,7 +464,7 @@ impl FileAttr { Ok(SystemTime::new(self.stat.st_mtime as i64, self.stat.st_mtime_nsec as i64)) } - #[cfg(any(target_os = "vxworks", target_os = "espidf"))] + #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))] pub fn modified(&self) -> io::Result<SystemTime> { Ok(SystemTime::new(self.stat.st_mtime as i64, 0)) } @@ -462,7 +474,12 @@ impl FileAttr { Ok(SystemTime::from(self.stat.st_mtim)) } - #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))] + #[cfg(not(any( + target_os = "vxworks", + target_os = "espidf", + target_os = "horizon", + target_os = "vita" + )))] pub fn accessed(&self) -> io::Result<SystemTime> { #[cfg(target_pointer_width = "32")] cfg_has_statx! { @@ -474,7 +491,7 @@ impl FileAttr { Ok(SystemTime::new(self.stat.st_atime as i64, self.stat.st_atime_nsec as i64)) } - #[cfg(any(target_os = "vxworks", target_os = "espidf"))] + #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))] pub fn accessed(&self) -> io::Result<SystemTime> { Ok(SystemTime::new(self.stat.st_atime as i64, 0)) } @@ -524,7 +541,23 @@ impl FileAttr { } } +#[cfg(target_os = "nto")] +impl FileAttr { + pub fn modified(&self) -> io::Result<SystemTime> { + Ok(SystemTime::new(self.stat.st_mtim.tv_sec, self.stat.st_mtim.tv_nsec)) + } + + pub fn accessed(&self) -> io::Result<SystemTime> { + Ok(SystemTime::new(self.stat.st_atim.tv_sec, self.stat.st_atim.tv_nsec)) + } + + pub fn created(&self) -> io::Result<SystemTime> { + Ok(SystemTime::new(self.stat.st_ctim.tv_sec, self.stat.st_ctim.tv_nsec)) + } +} + impl AsInner<stat64> for FileAttr { + #[inline] fn as_inner(&self) -> &stat64 { &self.stat } @@ -603,7 +636,8 @@ impl Iterator for ReadDir { target_os = "solaris", target_os = "fuchsia", target_os = "redox", - target_os = "illumos" + target_os = "illumos", + target_os = "nto", ))] fn next(&mut self) -> Option<io::Result<DirEntry>> { if self.end_of_stream { @@ -686,7 +720,11 @@ impl Iterator for ReadDir { let entry = dirent64_min { d_ino: *offset_ptr!(entry_ptr, d_ino) as u64, - #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "nto", + )))] d_type: *offset_ptr!(entry_ptr, d_type) as u8, }; @@ -705,7 +743,8 @@ impl Iterator for ReadDir { target_os = "solaris", target_os = "fuchsia", target_os = "redox", - target_os = "illumos" + target_os = "illumos", + target_os = "nto", )))] fn next(&mut self) -> Option<io::Result<DirEntry>> { if self.end_of_stream { @@ -794,7 +833,8 @@ impl DirEntry { target_os = "solaris", target_os = "illumos", target_os = "haiku", - target_os = "vxworks" + target_os = "vxworks", + target_os = "nto", ))] pub fn file_type(&self) -> io::Result<FileType> { self.metadata().map(|m| m.file_type()) @@ -804,7 +844,8 @@ impl DirEntry { target_os = "solaris", target_os = "illumos", target_os = "haiku", - target_os = "vxworks" + target_os = "vxworks", + target_os = "nto", )))] pub fn file_type(&self) -> io::Result<FileType> { match self.entry.d_type { @@ -834,7 +875,9 @@ impl DirEntry { target_os = "redox", target_os = "vxworks", target_os = "espidf", - target_os = "horizon" + target_os = "horizon", + target_os = "vita", + target_os = "nto", ))] pub fn ino(&self) -> u64 { self.entry.d_ino as u64 @@ -887,7 +930,8 @@ impl DirEntry { target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", )))] fn name_cstr(&self) -> &CStr { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) } @@ -898,7 +942,8 @@ impl DirEntry { target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", ))] fn name_cstr(&self) -> &CStr { &self.name @@ -1051,7 +1096,8 @@ impl File { target_os = "linux", target_os = "android", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", + target_os = "nto", ))] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fdatasync(fd) @@ -1065,6 +1111,7 @@ impl File { target_os = "netbsd", target_os = "openbsd", target_os = "watchos", + target_os = "nto", )))] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fsync(fd) @@ -1098,6 +1145,10 @@ impl File { self.0.read_buf(cursor) } + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + self.0.read_vectored_at(bufs, offset) + } + pub fn write(&self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } @@ -1115,6 +1166,10 @@ impl File { self.0.write_at(buf, offset) } + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { + self.0.write_vectored_at(bufs, offset) + } + pub fn flush(&self) -> io::Result<()> { Ok(()) } @@ -1150,19 +1205,18 @@ impl File { None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), } }; - #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))] - let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; cfg_if::cfg_if! { if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] { // Redox doesn't appear to support `UTIME_OMIT`. // ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore // the same as for Redox. - drop(times); + let _ = times; Err(io::const_io_error!( io::ErrorKind::Unsupported, "setting file times not supported", )) } else if #[cfg(any(target_os = "android", target_os = "macos"))] { + let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; // futimens requires macOS 10.13, and Android API level 19 cvt(unsafe { weak!(fn futimens(c_int, *const libc::timespec) -> c_int); @@ -1189,6 +1243,22 @@ impl File { })?; Ok(()) } else { + #[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32", not(target_arch = "riscv32")))] + { + use crate::sys::{time::__timespec64, weak::weak}; + + // Added in glibc 2.34 + weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int); + + if let Some(futimens64) = __futimens64.get() { + let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64()) + .unwrap_or(__timespec64::new(0, libc::UTIME_OMIT as _)); + let times = [to_timespec(times.accessed), to_timespec(times.modified)]; + cvt(unsafe { futimens64(self.as_raw_fd(), times.as_ptr()) })?; + return Ok(()); + } + } + let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; cvt(unsafe { libc::futimens(self.as_raw_fd(), times.as_ptr()) })?; Ok(()) } @@ -1211,12 +1281,14 @@ impl DirBuilder { } impl AsInner<FileDesc> for File { + #[inline] fn as_inner(&self) -> &FileDesc { &self.0 } } impl AsInnerMut<FileDesc> for File { + #[inline] fn as_inner_mut(&mut self) -> &mut FileDesc { &mut self.0 } @@ -1241,6 +1313,7 @@ impl AsFd for File { } impl AsRawFd for File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } @@ -1455,8 +1528,8 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { // Android has `linkat` on newer versions, but we happen to know `link` // always has the correct behavior, so it's here as well. cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; - } else if #[cfg(target_os = "macos")] { - // On MacOS, older versions (<=10.9) lack support for linkat while newer + } else if #[cfg(any(target_os = "macos", target_os = "solaris"))] { + // MacOS (<=10.9) and Solaris 10 lack support for linkat while newer // versions have it. We want to use linkat if it is available, so we use weak! // to check. `linkat` is preferable to `link` because it gives us a flag to // specify how symlinks should be handled. We pass 0 as the flags argument, @@ -1750,13 +1823,25 @@ pub fn chroot(dir: &Path) -> io::Result<()> { pub use remove_dir_impl::remove_dir_all; // Fallback for REDOX, ESP-ID, Horizon, and Miri -#[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri))] +#[cfg(any( + target_os = "redox", + target_os = "espidf", + target_os = "horizon", + target_os = "nto", + miri +))] mod remove_dir_impl { pub use crate::sys_common::fs::remove_dir_all; } // Modern implementation using openat(), unlinkat() and fdopendir() -#[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri)))] +#[cfg(not(any( + target_os = "redox", + target_os = "espidf", + target_os = "horizon", + target_os = "nto", + miri +)))] mod remove_dir_impl { use super::{lstat, Dir, DirEntry, InnerReadDir, ReadDir}; use crate::ffi::CStr; @@ -1838,7 +1923,7 @@ mod remove_dir_impl { // file descriptor is automatically closed by libc::closedir() now, so give up ownership let new_parent_fd = dir_fd.into_raw_fd(); // a valid root is not needed because we do not call any functions involving the full path - // of the DirEntrys. + // of the `DirEntry`s. let dummy_root = PathBuf::new(); let inner = InnerReadDir { dirp, root: dummy_root }; Ok((ReadDir::new(inner), new_parent_fd)) diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs index 8d5b540212a..d310be6c7a1 100644 --- a/library/std/src/sys/unix/futex.rs +++ b/library/std/src/sys/unix/futex.rs @@ -273,8 +273,6 @@ pub mod zircon { #[cfg(target_os = "fuchsia")] pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { - use crate::convert::TryFrom; - // Sleep forever if the timeout is longer than fits in a i64. let deadline = timeout .and_then(|d| { diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 73b9bef7e2a..16c8e0c0ebf 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -17,11 +17,9 @@ //! Once it has obtained all necessary pieces and brought any wrapper types into a state where they //! can be safely bypassed it will attempt to use the `copy_file_range(2)`, //! `sendfile(2)` or `splice(2)` syscalls to move data directly between file descriptors. -//! Since those syscalls have requirements that cannot be fully checked in advance and -//! gathering additional information about file descriptors would require additional syscalls -//! anyway it simply attempts to use them one after another (guided by inaccurate hints) to -//! figure out which one works and falls back to the generic read-write copy loop if none of them -//! does. +//! Since those syscalls have requirements that cannot be fully checked in advance it attempts +//! to use them one after another (guided by hints) to figure out which one works and +//! falls back to the generic read-write copy loop if none of them does. //! Once a working syscall is found for a pair of file descriptors it will be called in a loop //! until the copy operation is completed. //! @@ -84,14 +82,10 @@ pub(crate) fn copy_spec<R: Read + ?Sized, W: Write + ?Sized>( /// The methods on this type only provide hints, due to `AsRawFd` and `FromRawFd` the inferred /// type may be wrong. enum FdMeta { - /// We obtained the FD from a type that can contain any type of `FileType` and queried the metadata - /// because it is cheaper than probing all possible syscalls (reader side) Metadata(Metadata), Socket, Pipe, - /// We don't have any metadata, e.g. because the original type was `File` which can represent - /// any `FileType` and we did not query the metadata either since it did not seem beneficial - /// (writer side) + /// We don't have any metadata because the stat syscall failed NoneObtained, } @@ -131,6 +125,39 @@ impl FdMeta { } } +/// Returns true either if changes made to the source after a sendfile/splice call won't become +/// visible in the sink or the source has explicitly opted into such behavior (e.g. by splicing +/// a file into a pipe, the pipe being the source in this case). +/// +/// This will prevent File -> Pipe and File -> Socket splicing/sendfile optimizations to uphold +/// the Read/Write API semantics of io::copy. +/// +/// Note: This is not 100% airtight, the caller can use the RawFd conversion methods to turn a +/// regular file into a TcpSocket which will be treated as a socket here without checking. +fn safe_kernel_copy(source: &FdMeta, sink: &FdMeta) -> bool { + match (source, sink) { + // Data arriving from a socket is safe because the sender can't modify the socket buffer. + // Data arriving from a pipe is safe(-ish) because either the sender *copied* + // the bytes into the pipe OR explicitly performed an operation that enables zero-copy, + // thus promising not to modify the data later. + (FdMeta::Socket, _) => true, + (FdMeta::Pipe, _) => true, + (FdMeta::Metadata(meta), _) + if meta.file_type().is_fifo() || meta.file_type().is_socket() => + { + true + } + // Data going into non-pipes/non-sockets is safe because the "later changes may become visible" issue + // only happens for pages sitting in send buffers or pipes. + (_, FdMeta::Metadata(meta)) + if !meta.file_type().is_fifo() && !meta.file_type().is_socket() => + { + true + } + _ => false, + } +} + struct CopyParams(FdMeta, Option<RawFd>); struct Copier<'a, 'b, R: Read + ?Sized, W: Write + ?Sized> { @@ -186,7 +213,8 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> { // So we just try and fallback if needed. // If current file offsets + write sizes overflow it may also fail, we do not try to fix that and instead // fall back to the generic copy loop. - if input_meta.potential_sendfile_source() { + if input_meta.potential_sendfile_source() && safe_kernel_copy(&input_meta, &output_meta) + { let result = sendfile_splice(SpliceMode::Sendfile, readfd, writefd, max_write); result.update_take(reader); @@ -197,7 +225,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> { } } - if input_meta.maybe_fifo() || output_meta.maybe_fifo() { + if (input_meta.maybe_fifo() || output_meta.maybe_fifo()) + && safe_kernel_copy(&input_meta, &output_meta) + { let result = sendfile_splice(SpliceMode::Splice, readfd, writefd, max_write); result.update_take(reader); @@ -298,13 +328,13 @@ impl CopyRead for &File { impl CopyWrite for File { fn properties(&self) -> CopyParams { - CopyParams(FdMeta::NoneObtained, Some(self.as_raw_fd())) + CopyParams(fd_to_meta(self), Some(self.as_raw_fd())) } } impl CopyWrite for &File { fn properties(&self) -> CopyParams { - CopyParams(FdMeta::NoneObtained, Some(self.as_raw_fd())) + CopyParams(fd_to_meta(*self), Some(self.as_raw_fd())) } } @@ -401,13 +431,13 @@ impl CopyRead for StdinLock<'_> { impl CopyWrite for StdoutLock<'_> { fn properties(&self) -> CopyParams { - CopyParams(FdMeta::NoneObtained, Some(self.as_raw_fd())) + CopyParams(fd_to_meta(self), Some(self.as_raw_fd())) } } impl CopyWrite for StderrLock<'_> { fn properties(&self) -> CopyParams { - CopyParams(FdMeta::NoneObtained, Some(self.as_raw_fd())) + CopyParams(fd_to_meta(self), Some(self.as_raw_fd())) } } diff --git a/library/std/src/sys/unix/kernel_copy/tests.rs b/library/std/src/sys/unix/kernel_copy/tests.rs index 3fe849e23e2..a524270e3fb 100644 --- a/library/std/src/sys/unix/kernel_copy/tests.rs +++ b/library/std/src/sys/unix/kernel_copy/tests.rs @@ -83,6 +83,48 @@ fn copies_append_mode_sink() -> Result<()> { Ok(()) } +#[test] +fn dont_splice_pipes_from_files() -> Result<()> { + // splicing to a pipe and then modifying the source could lead to changes + // becoming visible in an unexpected order. + + use crate::io::SeekFrom; + use crate::os::unix::fs::FileExt; + use crate::process::{ChildStdin, ChildStdout}; + use crate::sys_common::FromInner; + + let (read_end, write_end) = crate::sys::pipe::anon_pipe()?; + + let mut read_end = ChildStdout::from_inner(read_end); + let mut write_end = ChildStdin::from_inner(write_end); + + let tmp_path = tmpdir(); + let file = tmp_path.join("to_be_modified"); + let mut file = + crate::fs::OpenOptions::new().create_new(true).read(true).write(true).open(file)?; + + const SZ: usize = libc::PIPE_BUF as usize; + + // put data in page cache + let mut buf: [u8; SZ] = [0x01; SZ]; + file.write_all(&buf).unwrap(); + + // copy page into pipe + file.seek(SeekFrom::Start(0)).unwrap(); + assert!(io::copy(&mut file, &mut write_end).unwrap() == SZ as u64); + + // modify file + buf[0] = 0x02; + file.write_at(&buf, 0).unwrap(); + + // read from pipe + read_end.read_exact(buf.as_mut_slice()).unwrap(); + + assert_eq!(buf[0], 0x01, "data in pipe should reflect the original, not later modifications"); + + Ok(()) +} + #[bench] fn bench_file_to_file_copy(b: &mut test::Bencher) { const BYTES: usize = 128 * 1024; diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs index 9967588939a..ee016887e70 100644 --- a/library/std/src/sys/unix/l4re.rs +++ b/library/std/src/sys/unix/l4re.rs @@ -129,6 +129,7 @@ pub mod net { } impl AsInner<FileDesc> for Socket { + #[inline] fn as_inner(&self) -> &FileDesc { &self.0 } @@ -153,6 +154,7 @@ pub mod net { } impl AsRawFd for Socket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } @@ -183,6 +185,7 @@ pub mod net { unimpl!(); } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -305,6 +308,7 @@ pub mod net { unimpl!(); } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -371,6 +375,7 @@ pub mod net { unimpl!(); } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs index 6be1abc2b08..192fa216dfa 100644 --- a/library/std/src/sys/unix/locks/pthread_condvar.rs +++ b/library/std/src/sys/unix/locks/pthread_condvar.rs @@ -2,7 +2,10 @@ use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; use crate::sys::locks::{pthread_mutex, Mutex}; +#[cfg(not(target_os = "nto"))] use crate::sys::time::TIMESPEC_MAX; +#[cfg(target_os = "nto")] +use crate::sys::time::TIMESPEC_MAX_CAPPED; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use crate::time::Duration; @@ -132,10 +135,18 @@ impl Condvar { let mutex = pthread_mutex::raw(mutex); self.verify(mutex); + #[cfg(not(target_os = "nto"))] let timeout = Timespec::now(libc::CLOCK_MONOTONIC) .checked_add_duration(&dur) .and_then(|t| t.to_timespec()) .unwrap_or(TIMESPEC_MAX); + + #[cfg(target_os = "nto")] + let timeout = Timespec::now(libc::CLOCK_MONOTONIC) + .checked_add_duration(&dur) + .and_then(|t| t.to_timespec_capped()) + .unwrap_or(TIMESPEC_MAX_CAPPED); + let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout); assert!(r == libc::ETIMEDOUT || r == 0); r == 0 diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 30a96be1430..bb9e65e68e5 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -92,6 +92,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "redox", target_os = "l4re", target_os = "horizon", + target_os = "vita", )))] 'poll: { use crate::sys::os::errno; @@ -140,6 +141,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "vxworks", target_os = "l4re", target_os = "horizon", + target_os = "vita", )))] { use crate::sys::os::errno; @@ -162,7 +164,12 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { } unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) { - #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))] + #[cfg(not(any( + target_os = "emscripten", + target_os = "fuchsia", + target_os = "horizon", + target_os = "vita" + )))] { // We don't want to add this as a public type to std, nor do we // want to `include!` a file from the compiler (which would break @@ -199,7 +206,8 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "espidf", target_os = "emscripten", target_os = "fuchsia", - target_os = "horizon" + target_os = "horizon", + target_os = "vita" )))] static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool = crate::sync::atomic::AtomicBool::new(false); @@ -208,7 +216,8 @@ static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool = target_os = "espidf", target_os = "emscripten", target_os = "fuchsia", - target_os = "horizon" + target_os = "horizon", + target_os = "vita", )))] pub(crate) fn unix_sigpipe_attr_specified() -> bool { UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed) @@ -329,7 +338,7 @@ pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> { // do so. In 1003.1-2004 this was fixed. // // glibc's implementation did the flush, unsafely, before glibc commit -// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]' by Florian +// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]` by Florian // Weimer. According to glibc's NEWS: // // The abort function terminates the process immediately, without flushing @@ -402,7 +411,7 @@ cfg_if::cfg_if! { } } -#[cfg(any(target_os = "espidf", target_os = "horizon"))] +#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] mod unsupported { use crate::io; diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index c86f80972a6..39edb136c24 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -1,6 +1,6 @@ use crate::cmp; use crate::ffi::CStr; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem; use crate::net::{Shutdown, SocketAddr}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; @@ -78,6 +78,7 @@ impl Socket { target_os = "linux", target_os = "netbsd", target_os = "openbsd", + target_os = "nto", ))] { // On platforms that support it we pass the SOCK_CLOEXEC // flag to atomically create the socket and set it as @@ -115,6 +116,7 @@ impl Socket { target_os = "linux", target_os = "netbsd", target_os = "openbsd", + target_os = "nto", ))] { // Like above, set cloexec atomically cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?; @@ -240,19 +242,35 @@ impl Socket { self.0.duplicate().map(Socket) } - fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> { + fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> { let ret = cvt(unsafe { - libc::recv(self.as_raw_fd(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags) + libc::recv( + self.as_raw_fd(), + buf.as_mut().as_mut_ptr() as *mut c_void, + buf.capacity(), + flags, + ) })?; - Ok(ret as usize) + unsafe { + buf.advance(ret as usize); + } + Ok(()) } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - self.recv_with_flags(buf, 0) + let mut buf = BorrowedBuf::from(buf); + self.recv_with_flags(buf.unfilled(), 0)?; + Ok(buf.len()) } pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { - self.recv_with_flags(buf, MSG_PEEK) + let mut buf = BorrowedBuf::from(buf); + self.recv_with_flags(buf.unfilled(), MSG_PEEK)?; + Ok(buf.len()) + } + + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.recv_with_flags(buf, 0) } pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { @@ -425,6 +443,17 @@ impl Socket { Ok(passcred != 0) } + #[cfg(target_os = "freebsd")] + pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { + setsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT, passcred as libc::c_int) + } + + #[cfg(target_os = "freebsd")] + pub fn passcred(&self) -> io::Result<bool> { + let passcred: libc::c_int = getsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT)?; + Ok(passcred != 0) + } + #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as libc::c_int; @@ -461,6 +490,7 @@ impl Socket { } impl AsInner<FileDesc> for Socket { + #[inline] fn as_inner(&self) -> &FileDesc { &self.0 } @@ -485,6 +515,7 @@ impl AsFd for Socket { } impl AsRawFd for Socket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 2f2663db607..8edfd331304 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -7,7 +7,6 @@ mod tests; use crate::os::unix::prelude::*; -use crate::convert::TryFrom; use crate::error::Error as StdError; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; @@ -62,6 +61,7 @@ extern "C" { link_name = "__errno" )] #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] + #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")] #[cfg_attr( any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"), link_name = "__error" @@ -114,7 +114,10 @@ pub fn set_errno(e: i32) { /// Gets a detailed string description for the given error number. pub fn error_string(errno: i32) -> String { extern "C" { - #[cfg_attr(any(target_os = "linux", target_env = "newlib"), link_name = "__xpg_strerror_r")] + #[cfg_attr( + all(any(target_os = "linux", target_env = "newlib"), not(target_env = "ohos")), + link_name = "__xpg_strerror_r" + )] fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int; } @@ -361,6 +364,17 @@ pub fn current_exe() -> io::Result<PathBuf> { } } +#[cfg(target_os = "nto")] +pub fn current_exe() -> io::Result<PathBuf> { + let mut e = crate::fs::read("/proc/self/exefile")?; + // Current versions of QNX Neutrino provide a null-terminated path. + // Ensure the trailing null byte is not returned here. + if let Some(0) = e.last() { + e.pop(); + } + Ok(PathBuf::from(OsString::from_vec(e))) +} + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] pub fn current_exe() -> io::Result<PathBuf> { unsafe { @@ -446,7 +460,7 @@ pub fn current_exe() -> io::Result<PathBuf> { path.canonicalize() } -#[cfg(any(target_os = "espidf", target_os = "horizon"))] +#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] pub fn current_exe() -> io::Result<PathBuf> { super::unsupported::unsupported() } @@ -600,7 +614,8 @@ pub fn home_dir() -> Option<PathBuf> { target_os = "redox", target_os = "vxworks", target_os = "espidf", - target_os = "horizon" + target_os = "horizon", + target_os = "vita", ))] unsafe fn fallback() -> Option<OsString> { None @@ -613,7 +628,8 @@ pub fn home_dir() -> Option<PathBuf> { target_os = "redox", target_os = "vxworks", target_os = "espidf", - target_os = "horizon" + target_os = "horizon", + target_os = "vita", )))] unsafe fn fallback() -> Option<OsString> { let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs index 017e2af29d4..488217f3941 100644 --- a/library/std/src/sys/unix/os_str.rs +++ b/library/std/src/sys/unix/os_str.rs @@ -89,6 +89,7 @@ impl IntoInner<Vec<u8>> for Buf { } impl AsInner<[u8]> for Buf { + #[inline] fn as_inner(&self) -> &[u8] { &self.inner } diff --git a/library/std/src/sys/unix/pipe.rs b/library/std/src/sys/unix/pipe.rs index a744d0ab640..938a46bfdd8 100644 --- a/library/std/src/sys/unix/pipe.rs +++ b/library/std/src/sys/unix/pipe.rs @@ -1,4 +1,4 @@ -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::sys::fd::FileDesc; @@ -49,6 +49,10 @@ impl AnonPipe { self.0.read(buf) } + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.0.read_vectored(bufs) } @@ -131,6 +135,7 @@ pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> } impl AsRawFd for AnonPipe { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/unix/process/mod.rs b/library/std/src/sys/unix/process/mod.rs index 3701510f3a4..0cf163d9fb8 100644 --- a/library/std/src/sys/unix/process/mod.rs +++ b/library/std/src/sys/unix/process/mod.rs @@ -14,7 +14,7 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "vxworks")] { #[path = "process_vxworks.rs"] mod process_inner; - } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] { + } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] { #[path = "process_unsupported.rs"] mod process_inner; } else { diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index d4c7e58b34d..e45c380a0bb 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -166,7 +166,6 @@ impl Process { } pub fn wait(&mut self) -> io::Result<ExitStatus> { - use crate::default::Default; use crate::sys::process::zircon::*; let mut proc_info: zx_info_process_t = Default::default(); @@ -199,7 +198,6 @@ impl Process { } pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> { - use crate::default::Default; use crate::sys::process::zircon::*; let mut proc_info: zx_info_process_t = Default::default(); diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 3bc17b7754d..612d43fe204 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -18,6 +18,7 @@ use crate::sys::weak::raw_syscall; target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), + target_os = "nto", ))] use crate::sys::weak::weak; @@ -30,6 +31,15 @@ use libc::{c_int, pid_t}; #[cfg(not(any(target_os = "vxworks", target_os = "l4re")))] use libc::{gid_t, uid_t}; +cfg_if::cfg_if! { + if #[cfg(all(target_os = "nto", target_env = "nto71"))] { + use crate::thread; + use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t}; + // arbitrary number of tries: + const MAX_FORKSPAWN_TRIES: u32 = 4; + } +} + //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// @@ -140,11 +150,31 @@ impl Command { // Attempts to fork the process. If successful, returns Ok((0, -1)) // in the child, and Ok((child_pid, -1)) in the parent. - #[cfg(not(target_os = "linux"))] + #[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))] unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> { cvt(libc::fork()).map(|res| (res, -1)) } + // On QNX Neutrino, fork can fail with EBADF in case "another thread might have opened + // or closed a file descriptor while the fork() was occurring". + // Documentation says "... or try calling fork() again". This is what we do here. + // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html + #[cfg(all(target_os = "nto", target_env = "nto71"))] + unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> { + use crate::sys::os::errno; + + let mut tries_left = MAX_FORKSPAWN_TRIES; + loop { + let r = libc::fork(); + if r == -1 as libc::pid_t && tries_left > 0 && errno() as libc::c_int == libc::EBADF { + thread::yield_now(); + tries_left -= 1; + } else { + return cvt(r).map(|res| (res, -1)); + } + } + } + // Attempts to fork the process. If successful, returns Ok((0, -1)) // in the child, and Ok((child_pid, child_pidfd)) in the parent. #[cfg(target_os = "linux")] @@ -389,6 +419,7 @@ impl Command { target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), + target_os = "nto", )))] fn posix_spawn( &mut self, @@ -405,6 +436,7 @@ impl Command { target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), + target_os = "nto", ))] fn posix_spawn( &mut self, @@ -436,6 +468,34 @@ impl Command { } } + // On QNX Neutrino, posix_spawnp can fail with EBADF in case "another thread might have opened + // or closed a file descriptor while the posix_spawn() was occurring". + // Documentation says "... or try calling posix_spawn() again". This is what we do here. + // See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html + #[cfg(all(target_os = "nto", target_env = "nto71"))] + unsafe fn retrying_libc_posix_spawnp( + pid: *mut pid_t, + file: *const c_char, + file_actions: *const posix_spawn_file_actions_t, + attrp: *const posix_spawnattr_t, + argv: *const *mut c_char, + envp: *const *mut c_char, + ) -> i32 { + let mut tries_left = MAX_FORKSPAWN_TRIES; + loop { + match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) { + libc::EBADF if tries_left > 0 => { + thread::yield_now(); + tries_left -= 1; + continue; + } + r => { + return r; + } + } + } + } + // Solaris, glibc 2.29+, and musl 1.24+ can set a new working directory, // and maybe others will gain this non-POSIX function too. We'll check // for this weak symbol as soon as it's needed, so we can return early @@ -555,7 +615,12 @@ impl Command { // Make sure we synchronize access to the global `environ` resource let _env_lock = sys::os::env_read_lock(); let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _); - cvt_nz(libc::posix_spawnp( + + #[cfg(not(target_os = "nto"))] + let spawn_fn = libc::posix_spawnp; + #[cfg(target_os = "nto")] + let spawn_fn = retrying_libc_posix_spawnp; + cvt_nz(spawn_fn( &mut p.pid, self.get_program_cstr().as_ptr(), file_actions.0.as_ptr(), @@ -670,7 +735,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero_c_int::try_from(self.0) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), @@ -760,7 +825,7 @@ fn signal_string(signal: i32) -> &'static str { ) ))] libc::SIGSTKFLT => " (SIGSTKFLT)", - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "nto"))] libc::SIGPWR => " (SIGPWR)", #[cfg(any( target_os = "macos", @@ -769,7 +834,8 @@ fn signal_string(signal: i32) -> &'static str { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", - target_os = "dragonfly" + target_os = "dragonfly", + target_os = "nto", ))] libc::SIGEMT => " (SIGEMT)", #[cfg(any( diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs index 569a4b14912..c40e7ada03c 100644 --- a/library/std/src/sys/unix/process/process_vxworks.rs +++ b/library/std/src/sys/unix/process/process_vxworks.rs @@ -199,7 +199,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero_c_int::try_from(self.0) { Ok(failure) => Err(ExitStatusError(failure)), Err(_) => Ok(()), diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs index a6fe07873d7..d8b63546b9e 100644 --- a/library/std/src/sys/unix/rand.rs +++ b/library/std/src/sys/unix/rand.rs @@ -20,7 +20,9 @@ pub fn hashmap_random_keys() -> (u64, u64) { not(target_os = "netbsd"), not(target_os = "fuchsia"), not(target_os = "redox"), - not(target_os = "vxworks") + not(target_os = "vxworks"), + not(target_os = "emscripten"), + not(target_os = "vita"), ))] mod imp { use crate::fs::File; @@ -174,7 +176,7 @@ mod imp { } } -#[cfg(target_os = "openbsd")] +#[cfg(any(target_os = "openbsd", target_os = "emscripten", target_os = "vita"))] mod imp { use crate::sys::os::errno; diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs index b3626c564e8..a26f20795a1 100644 --- a/library/std/src/sys/unix/stdio.rs +++ b/library/std/src/sys/unix/stdio.rs @@ -1,4 +1,4 @@ -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; use crate::os::unix::io::FromRawFd; use crate::sys::fd::FileDesc; @@ -18,6 +18,10 @@ impl io::Read for Stdin { unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDIN_FILENO)).read(buf) } } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDIN_FILENO)).read_buf(buf) } + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDIN_FILENO)).read_vectored(bufs) } } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index cc0e5929569..7307d9b2c86 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -9,7 +9,7 @@ use crate::time::Duration; #[cfg(all(target_os = "linux", target_env = "gnu"))] use crate::sys::weak::dlsym; -#[cfg(any(target_os = "solaris", target_os = "illumos"))] +#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))] use crate::sys::weak::weak; #[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; @@ -173,7 +173,7 @@ impl Thread { } } - #[cfg(any(target_os = "solaris", target_os = "illumos"))] + #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))] pub fn set_name(name: &CStr) { weak! { fn pthread_setname_np( @@ -326,6 +326,25 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> { } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] { use crate::ptr; + #[cfg(target_os = "freebsd")] + { + let mut set: libc::cpuset_t = unsafe { mem::zeroed() }; + unsafe { + if libc::cpuset_getaffinity( + libc::CPU_LEVEL_WHICH, + libc::CPU_WHICH_PID, + -1, + mem::size_of::<libc::cpuset_t>(), + &mut set, + ) == 0 { + let count = libc::CPU_COUNT(&set) as usize; + if count > 0 { + return Ok(NonZeroUsize::new_unchecked(count)); + } + } + } + } + let mut cpus: libc::c_uint = 0; let mut cpus_size = crate::mem::size_of_val(&cpus); @@ -381,6 +400,17 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> { } Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else if #[cfg(target_os = "nto")] { + unsafe { + use libc::_syspage_ptr; + if _syspage_ptr.is_null() { + Err(io::const_io_error!(io::ErrorKind::NotFound, "No syspage available")) + } else { + let cpus = (*_syspage_ptr).num_cpu; + NonZeroUsize::new(cpus as usize) + .ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")) + } + } } else if #[cfg(target_os = "haiku")] { // system_info cpu_count field gets the static data set at boot time with `smp_set_num_cpus` // `get_system_info` calls then `smp_get_num_cpus` diff --git a/library/std/src/sys/unix/thread_parking/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs index 082d25e68f5..43046ed07b8 100644 --- a/library/std/src/sys/unix/thread_parking/pthread.rs +++ b/library/std/src/sys/unix/thread_parking/pthread.rs @@ -6,7 +6,10 @@ use crate::pin::Pin; use crate::ptr::addr_of_mut; use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::SeqCst; +#[cfg(not(target_os = "nto"))] use crate::sys::time::TIMESPEC_MAX; +#[cfg(target_os = "nto")] +use crate::sys::time::TIMESPEC_MAX_CAPPED; use crate::time::Duration; const EMPTY: usize = 0; @@ -80,8 +83,14 @@ unsafe fn wait_timeout( (Timespec::now(libc::CLOCK_MONOTONIC), dur) }; + #[cfg(not(target_os = "nto"))] let timeout = now.checked_add_duration(&dur).and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX); + #[cfg(target_os = "nto")] + let timeout = now + .checked_add_duration(&dur) + .and_then(|t| t.to_timespec_capped()) + .unwrap_or(TIMESPEC_MAX_CAPPED); let r = libc::pthread_cond_timedwait(cond, lock, &timeout); debug_assert!(r == libc::ETIMEDOUT || r == 0); } diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 2daad981b73..a9fbc7ab108 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -9,6 +9,14 @@ pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() }; pub const TIMESPEC_MAX: libc::timespec = libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 }; +// This additional constant is only used when calling +// `libc::pthread_cond_timedwait`. +#[cfg(target_os = "nto")] +pub(super) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec { + tv_sec: (u64::MAX / NSEC_PER_SEC) as i64, + tv_nsec: (u64::MAX % NSEC_PER_SEC) as i64, +}; + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(0)] @@ -105,11 +113,7 @@ impl Timespec { } pub fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { - let mut secs = other - .as_secs() - .try_into() // <- target type would be `i64` - .ok() - .and_then(|secs| self.tv_sec.checked_add(secs))?; + let mut secs = self.tv_sec.checked_add_unsigned(other.as_secs())?; // Nano calculations can't overflow because nanos are <1B which fit // in a u32. @@ -118,15 +122,11 @@ impl Timespec { nsec -= NSEC_PER_SEC as u32; secs = secs.checked_add(1)?; } - Some(Timespec::new(secs, nsec as i64)) + Some(Timespec::new(secs, nsec.into())) } pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { - let mut secs = other - .as_secs() - .try_into() // <- target type would be `i64` - .ok() - .and_then(|secs| self.tv_sec.checked_sub(secs))?; + let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?; // Similar to above, nanos can't overflow. let mut nsec = self.tv_nsec.0 as i32 - other.subsec_nanos() as i32; @@ -134,7 +134,7 @@ impl Timespec { nsec += NSEC_PER_SEC as i32; secs = secs.checked_sub(1)?; } - Some(Timespec::new(secs, nsec as i64)) + Some(Timespec::new(secs, nsec.into())) } #[allow(dead_code)] @@ -144,6 +144,30 @@ impl Timespec { tv_nsec: self.tv_nsec.0.try_into().ok()?, }) } + + // On QNX Neutrino, the maximum timespec for e.g. pthread_cond_timedwait + // is 2^64 nanoseconds + #[cfg(target_os = "nto")] + pub(super) fn to_timespec_capped(&self) -> Option<libc::timespec> { + // Check if timeout in nanoseconds would fit into an u64 + if (self.tv_nsec.0 as u64) + .checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?) + .is_none() + { + return None; + } + self.to_timespec() + } + + #[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") + ))] + pub fn to_timespec64(&self) -> __timespec64 { + __timespec64::new(self.tv_sec, self.tv_nsec.0 as _) + } } impl From<libc::timespec> for Timespec { @@ -152,6 +176,46 @@ impl From<libc::timespec> for Timespec { } } +#[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") +))] +#[repr(C)] +pub(in crate::sys::unix) struct __timespec64 { + pub(in crate::sys::unix) tv_sec: i64, + #[cfg(target_endian = "big")] + _padding: i32, + pub(in crate::sys::unix) tv_nsec: i32, + #[cfg(target_endian = "little")] + _padding: i32, +} + +#[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") +))] +impl __timespec64 { + pub(in crate::sys::unix) fn new(tv_sec: i64, tv_nsec: i32) -> Self { + Self { tv_sec, tv_nsec, _padding: 0 } + } +} + +#[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") +))] +impl From<__timespec64> for Timespec { + fn from(t: __timespec64) -> Timespec { + Timespec::new(t.tv_sec, t.tv_nsec.into()) + } +} + #[cfg(any( all(target_os = "macos", any(not(target_arch = "aarch64"))), target_os = "ios", @@ -330,29 +394,23 @@ mod inner { impl Timespec { pub fn now(clock: libc::clockid_t) -> Timespec { // Try to use 64-bit time in preparation for Y2038. - #[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32"))] + #[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") + ))] { use crate::sys::weak::weak; // __clock_gettime64 was added to 32-bit arches in glibc 2.34, // and it handles both vDSO calls and ENOSYS fallbacks itself. - weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int); - - #[repr(C)] - struct __timespec64 { - tv_sec: i64, - #[cfg(target_endian = "big")] - _padding: i32, - tv_nsec: i32, - #[cfg(target_endian = "little")] - _padding: i32, - } + weak!(fn __clock_gettime64(libc::clockid_t, *mut super::__timespec64) -> libc::c_int); if let Some(clock_gettime64) = __clock_gettime64.get() { let mut t = MaybeUninit::uninit(); cvt(unsafe { clock_gettime64(clock, t.as_mut_ptr()) }).unwrap(); - let t = unsafe { t.assume_init() }; - return Timespec::new(t.tv_sec, t.tv_nsec as i64); + return Timespec::from(unsafe { t.assume_init() }); } } diff --git a/library/std/src/sys/unsupported/io.rs b/library/std/src/sys/unsupported/io.rs index 82610ffab7e..6372fca74e0 100644 --- a/library/std/src/sys/unsupported/io.rs +++ b/library/std/src/sys/unsupported/io.rs @@ -30,7 +30,7 @@ impl<'a> IoSliceMut<'a> { #[inline] pub fn advance(&mut self, n: usize) { - let slice = mem::replace(&mut self.0, &mut []); + let slice = mem::take(&mut self.0); let (_, remaining) = slice.split_at_mut(n); self.0 = remaining; } diff --git a/library/std/src/sys/unsupported/mod.rs b/library/std/src/sys/unsupported/mod.rs index 15b22c620d5..e1a38de6471 100644 --- a/library/std/src/sys/unsupported/mod.rs +++ b/library/std/src/sys/unsupported/mod.rs @@ -22,6 +22,7 @@ pub mod thread; #[cfg(target_thread_local)] pub mod thread_local_dtor; pub mod thread_local_key; +pub mod thread_parking; pub mod time; mod common; diff --git a/library/std/src/sys/unsupported/net.rs b/library/std/src/sys/unsupported/net.rs index a5204a08453..bbc52703f96 100644 --- a/library/std/src/sys/unsupported/net.rs +++ b/library/std/src/sys/unsupported/net.rs @@ -1,5 +1,5 @@ use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::sys::unsupported; use crate::time::Duration; @@ -39,6 +39,10 @@ impl TcpStream { self.0 } + pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> { + self.0 + } + pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.0 } diff --git a/library/std/src/sys/unsupported/pipe.rs b/library/std/src/sys/unsupported/pipe.rs index 0bba673b458..d7d8f297ae5 100644 --- a/library/std/src/sys/unsupported/pipe.rs +++ b/library/std/src/sys/unsupported/pipe.rs @@ -1,4 +1,4 @@ -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; pub struct AnonPipe(!); @@ -7,6 +7,10 @@ impl AnonPipe { self.0 } + pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> { + self.0 + } + pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.0 } diff --git a/library/std/src/sys/unsupported/thread_parking.rs b/library/std/src/sys/unsupported/thread_parking.rs new file mode 100644 index 00000000000..197078bb186 --- /dev/null +++ b/library/std/src/sys/unsupported/thread_parking.rs @@ -0,0 +1,11 @@ +use crate::pin::Pin; +use crate::time::Duration; + +pub struct Parker {} + +impl Parker { + pub unsafe fn new_in_place(_parker: *mut Parker) {} + pub unsafe fn park(self: Pin<&Self>) {} + pub unsafe fn park_timeout(self: Pin<&Self>, _dur: Duration) {} + pub fn unpark(self: Pin<&Self>) {} +} diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs index 0b9c8e61db8..9a8b2a0be5b 100644 --- a/library/std/src/sys/wasi/fd.rs +++ b/library/std/src/sys/wasi/fd.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] use super::err2io; -use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; @@ -46,6 +46,22 @@ impl WasiFd { unsafe { wasi::fd_read(self.as_raw_fd() as wasi::Fd, iovec(bufs)).map_err(err2io) } } + pub fn read_buf(&self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { + unsafe { + let bufs = [wasi::Iovec { + buf: buf.as_mut().as_mut_ptr() as *mut u8, + buf_len: buf.capacity(), + }]; + match wasi::fd_read(self.as_raw_fd() as wasi::Fd, &bufs) { + Ok(n) => { + buf.advance(n); + Ok(()) + } + Err(e) => Err(err2io(e)), + } + } + } + pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { unsafe { wasi::fd_write(self.as_raw_fd() as wasi::Fd, ciovec(bufs)).map_err(err2io) } } @@ -259,12 +275,14 @@ impl WasiFd { } impl AsInner<OwnedFd> for WasiFd { + #[inline] fn as_inner(&self) -> &OwnedFd { &self.fd } } impl AsInnerMut<OwnedFd> for WasiFd { + #[inline] fn as_inner_mut(&mut self) -> &mut OwnedFd { &mut self.fd } @@ -289,6 +307,7 @@ impl AsFd for WasiFd { } impl AsRawFd for WasiFd { + #[inline] fn as_raw_fd(&self) -> RawFd { self.fd.as_raw_fd() } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index d4866bbc32b..8d1dbf59155 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -441,7 +441,7 @@ impl File { } pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { - crate::io::default_read_buf(|buf| self.read(buf), cursor) + self.fd.read_buf(cursor) } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { @@ -498,6 +498,7 @@ impl File { } impl AsInner<WasiFd> for File { + #[inline] fn as_inner(&self) -> &WasiFd { &self.fd } @@ -522,6 +523,7 @@ impl AsFd for File { } impl AsRawFd for File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.fd.as_raw_fd() } diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 1dc3f2b2026..a2223708024 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -32,8 +32,6 @@ pub mod io; #[path = "../unsupported/locks/mod.rs"] pub mod locks; pub mod net; -#[path = "../unsupported/once.rs"] -pub mod once; pub mod os; #[path = "../unix/os_str.rs"] pub mod os_str; @@ -49,8 +47,17 @@ pub mod thread; pub mod thread_local_dtor; #[path = "../unsupported/thread_local_key.rs"] pub mod thread_local_key; +#[path = "../unsupported/thread_parking.rs"] +pub mod thread_parking; pub mod time; +cfg_if::cfg_if! { + if #[cfg(not(target_feature = "atomics"))] { + #[path = "../unsupported/once.rs"] + pub mod once; + } +} + #[path = "../unsupported/common.rs"] #[deny(unsafe_op_in_unsafe_fn)] #[allow(unused)] diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index cf4ebba1a39..2239880ffbe 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -3,7 +3,7 @@ use super::err2io; use super::fd::WasiFd; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::sys::unsupported; @@ -17,6 +17,7 @@ pub struct TcpStream { } impl AsInner<WasiFd> for Socket { + #[inline] fn as_inner(&self) -> &WasiFd { &self.0 } @@ -41,6 +42,7 @@ impl AsFd for Socket { } impl AsRawFd for Socket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } @@ -91,6 +93,10 @@ impl TcpStream { self.read_vectored(&mut [IoSliceMut::new(buf)]) } + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.socket().as_inner().read_buf(buf) + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.socket().as_inner().read(bufs) } @@ -180,6 +186,7 @@ impl TcpStream { } } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -270,6 +277,7 @@ impl TcpListener { } } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -280,6 +288,7 @@ impl TcpListener { } impl AsInner<Socket> for TcpListener { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } @@ -432,6 +441,7 @@ impl UdpSocket { unsupported() } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -442,6 +452,7 @@ impl UdpSocket { } impl AsInner<Socket> for UdpSocket { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs index 77ebe3c4ac6..6c05b56e1bf 100644 --- a/library/std/src/sys/wasm/mod.rs +++ b/library/std/src/sys/wasm/mod.rs @@ -70,6 +70,8 @@ cfg_if::cfg_if! { pub mod once; #[path = "../unsupported/thread.rs"] pub mod thread; + #[path = "../unsupported/thread_parking.rs"] + pub mod thread_parking; } } diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs index 6741ae46d32..5bfd8b52ed0 100644 --- a/library/std/src/sys/windows/args.rs +++ b/library/std/src/sys/windows/args.rs @@ -11,10 +11,11 @@ use crate::fmt; use crate::io; use crate::num::NonZeroU16; use crate::os::windows::prelude::*; -use crate::path::PathBuf; -use crate::sys::c; +use crate::path::{Path, PathBuf}; +use crate::sys::path::get_long_path; use crate::sys::process::ensure_no_nuls; use crate::sys::windows::os::current_exe; +use crate::sys::{c, to_u16s}; use crate::sys_common::wstr::WStrUnits; use crate::vec; @@ -270,7 +271,7 @@ pub(crate) fn make_bat_command_line( // It is necessary to surround the command in an extra pair of quotes, // hence the trailing quote here. It will be closed after all arguments // have been added. - let mut cmd: Vec<u16> = "cmd.exe /c \"".encode_utf16().collect(); + let mut cmd: Vec<u16> = "cmd.exe /d /c \"".encode_utf16().collect(); // Push the script name surrounded by its quote pair. cmd.push(b'"' as u16); @@ -290,6 +291,15 @@ pub(crate) fn make_bat_command_line( // reconstructed by the batch script by default. for arg in args { cmd.push(' ' as u16); + // Make sure to always quote special command prompt characters, including: + // * Characters `cmd /?` says require quotes. + // * `%` for environment variables, as in `%TMP%`. + // * `|<>` pipe/redirect characters. + const SPECIAL: &[u8] = b"\t &()[]{}^=;!'+,`~%|<>"; + let force_quotes = match arg { + Arg::Regular(arg) if !force_quotes => arg.bytes().iter().any(|c| SPECIAL.contains(c)), + _ => force_quotes, + }; append_arg(&mut cmd, arg, force_quotes)?; } @@ -302,7 +312,10 @@ pub(crate) fn make_bat_command_line( /// Takes a path and tries to return a non-verbatim path. /// /// This is necessary because cmd.exe does not support verbatim paths. -pub(crate) fn to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> { +pub(crate) fn to_user_path(path: &Path) -> io::Result<Vec<u16>> { + from_wide_to_user_path(to_u16s(path)?) +} +pub(crate) fn from_wide_to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> { use crate::ptr; use crate::sys::windows::fill_utf16_buf; @@ -328,7 +341,13 @@ pub(crate) fn to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> { fill_utf16_buf( |buffer, size| c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut()), |full_path: &[u16]| { - if full_path == &path[4..path.len() - 1] { full_path.into() } else { path } + if full_path == &path[4..path.len() - 1] { + let mut path: Vec<u16> = full_path.into(); + path.push(0); + path + } else { + path + } }, ) }, @@ -341,7 +360,9 @@ pub(crate) fn to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> { |buffer, size| c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut()), |full_path: &[u16]| { if full_path == &path[6..path.len() - 1] { - full_path.into() + let mut path: Vec<u16> = full_path.into(); + path.push(0); + path } else { // Restore the 'C' in "UNC". path[6] = b'C' as u16; @@ -351,6 +372,6 @@ pub(crate) fn to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> { ) }, // For everything else, leave the path unchanged. - _ => Ok(path), + _ => get_long_path(path, false), } } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index f58dcf1287b..2bc40c4748a 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -6,31 +6,18 @@ use crate::ffi::CStr; use crate::mem; -use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort}; -use crate::os::windows::io::{BorrowedHandle, HandleOrInvalid, HandleOrNull}; +pub use crate::os::raw::c_int; +use crate::os::raw::{c_char, c_long, c_longlong, c_uint, c_ulong, c_ushort, c_void}; +use crate::os::windows::io::{AsRawHandle, BorrowedHandle}; use crate::ptr; use core::ffi::NonZero_c_ulong; -use libc::{c_void, size_t, wchar_t}; +#[path = "c/windows_sys.rs"] // c.rs is included from two places so we need to specify this +mod windows_sys; +pub use windows_sys::*; -#[path = "c/errors.rs"] // c.rs is included from two places so we need to specify this -mod errors; -pub use errors::*; - -pub use self::EXCEPTION_DISPOSITION::*; -pub use self::FILE_INFO_BY_HANDLE_CLASS::*; - -pub type DWORD_PTR = ULONG_PTR; pub type DWORD = c_ulong; pub type NonZeroDWORD = NonZero_c_ulong; -pub type HANDLE = LPVOID; -pub type HINSTANCE = HANDLE; -pub type HMODULE = HINSTANCE; -pub type HRESULT = LONG; -pub type BOOL = c_int; -pub type BYTE = u8; -pub type BOOLEAN = BYTE; -pub type GROUP = c_uint; pub type LARGE_INTEGER = c_longlong; pub type LONG = c_long; pub type UINT = c_uint; @@ -39,211 +26,40 @@ pub type USHORT = c_ushort; pub type SIZE_T = usize; pub type WORD = u16; pub type CHAR = c_char; -pub type CCHAR = c_char; -pub type ULONG_PTR = usize; pub type ULONG = c_ulong; -pub type NTSTATUS = LONG; pub type ACCESS_MASK = DWORD; -pub type LPBOOL = *mut BOOL; -pub type LPBYTE = *mut BYTE; -pub type LPCSTR = *const CHAR; -pub type LPCWSTR = *const WCHAR; -pub type LPDWORD = *mut DWORD; +pub type LPCVOID = *const c_void; pub type LPHANDLE = *mut HANDLE; pub type LPOVERLAPPED = *mut OVERLAPPED; -pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION; pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES; -pub type LPSTARTUPINFO = *mut STARTUPINFO; pub type LPVOID = *mut c_void; -pub type LPCVOID = *const c_void; pub type LPWCH = *mut WCHAR; -pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW; -pub type LPWSADATA = *mut WSADATA; -pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; pub type LPWSTR = *mut WCHAR; -pub type LPFILETIME = *mut FILETIME; -pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; -pub type LPWSABUF = *mut WSABUF; -pub type LPWSAOVERLAPPED = *mut c_void; -pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void; -pub type BCRYPT_ALG_HANDLE = LPVOID; -pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE; pub type PLARGE_INTEGER = *mut c_longlong; pub type PSRWLOCK = *mut SRWLOCK; -pub type LPINIT_ONCE = *mut INIT_ONCE; -pub type SOCKET = crate::os::windows::raw::SOCKET; pub type socklen_t = c_int; pub type ADDRESS_FAMILY = USHORT; +pub use FD_SET as fd_set; +pub use LINGER as linger; +pub use TIMEVAL as timeval; -pub const TRUE: BOOL = 1; -pub const FALSE: BOOL = 0; - -pub const CSTR_LESS_THAN: c_int = 1; -pub const CSTR_EQUAL: c_int = 2; -pub const CSTR_GREATER_THAN: c_int = 3; - -pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1; -pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10; -pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400; -pub const INVALID_FILE_ATTRIBUTES: DWORD = DWORD::MAX; - -pub const FILE_SHARE_DELETE: DWORD = 0x4; -pub const FILE_SHARE_READ: DWORD = 0x1; -pub const FILE_SHARE_WRITE: DWORD = 0x2; - -pub const FILE_OPEN: ULONG = 0x00000001; -pub const FILE_OPEN_REPARSE_POINT: ULONG = 0x200000; -pub const OBJ_DONT_REPARSE: ULONG = 0x1000; +pub type CONDITION_VARIABLE = RTL_CONDITION_VARIABLE; +pub type SRWLOCK = RTL_SRWLOCK; +pub type INIT_ONCE = RTL_RUN_ONCE; -pub const CREATE_ALWAYS: DWORD = 2; -pub const CREATE_NEW: DWORD = 1; -pub const OPEN_ALWAYS: DWORD = 4; -pub const OPEN_EXISTING: DWORD = 3; -pub const TRUNCATE_EXISTING: DWORD = 5; +pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() }; +pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() }; +pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() }; -pub const FILE_LIST_DIRECTORY: DWORD = 0x1; -pub const FILE_WRITE_DATA: DWORD = 0x00000002; -pub const FILE_APPEND_DATA: DWORD = 0x00000004; -pub const FILE_WRITE_EA: DWORD = 0x00000010; -pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100; -pub const DELETE: DWORD = 0x10000; -pub const READ_CONTROL: DWORD = 0x00020000; -pub const SYNCHRONIZE: DWORD = 0x00100000; -pub const GENERIC_READ: DWORD = 0x80000000; -pub const GENERIC_WRITE: DWORD = 0x40000000; -pub const STANDARD_RIGHTS_WRITE: DWORD = READ_CONTROL; -pub const FILE_GENERIC_WRITE: DWORD = STANDARD_RIGHTS_WRITE - | FILE_WRITE_DATA - | FILE_WRITE_ATTRIBUTES - | FILE_WRITE_EA - | FILE_APPEND_DATA - | SYNCHRONIZE; - -pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000; -pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000; -pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000; - -pub const FIONBIO: c_ulong = 0x8004667e; - -pub const MAX_PATH: usize = 260; - -pub const FILE_TYPE_PIPE: u32 = 3; - -#[repr(C)] -#[derive(Copy)] -pub struct WIN32_FIND_DATAW { - pub dwFileAttributes: DWORD, - pub ftCreationTime: FILETIME, - pub ftLastAccessTime: FILETIME, - pub ftLastWriteTime: FILETIME, - pub nFileSizeHigh: DWORD, - pub nFileSizeLow: DWORD, - pub dwReserved0: DWORD, - pub dwReserved1: DWORD, - pub cFileName: [wchar_t; 260], // #define MAX_PATH 260 - pub cAlternateFileName: [wchar_t; 14], -} -impl Clone for WIN32_FIND_DATAW { - fn clone(&self) -> Self { - *self - } -} - -pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01; -pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80; - -pub const WSADESCRIPTION_LEN: usize = 256; -pub const WSASYS_STATUS_LEN: usize = 128; -pub const WSAPROTOCOL_LEN: DWORD = 255; -pub const INVALID_SOCKET: SOCKET = !0; - -pub const MAX_PROTOCOL_CHAIN: DWORD = 7; - -pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; -pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8; -pub const IO_REPARSE_TAG_SYMLINK: DWORD = 0xa000000c; -pub const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003; -pub const SYMLINK_FLAG_RELATIVE: DWORD = 0x00000001; -pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4; - -pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; -pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; - -// Note that these are not actually HANDLEs, just values to pass to GetStdHandle -pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD; -pub const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; -pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; - -pub const PROGRESS_CONTINUE: DWORD = 0; - -pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT; - -pub const INVALID_HANDLE_VALUE: HANDLE = ptr::invalid_mut(!0); - -pub const FACILITY_NT_BIT: DWORD = 0x1000_0000; - -pub const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000; -pub const FORMAT_MESSAGE_FROM_HMODULE: DWORD = 0x00000800; -pub const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200; - -pub const TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF; - -pub const DLL_THREAD_DETACH: DWORD = 3; -pub const DLL_PROCESS_DETACH: DWORD = 0; - -pub const INFINITE: DWORD = !0; - -pub const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002; - -pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { ptr: ptr::null_mut() }; -pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: ptr::null_mut() }; -pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { ptr: ptr::null_mut() }; - -pub const INIT_ONCE_INIT_FAILED: DWORD = 0x00000004; - -pub const DETACHED_PROCESS: DWORD = 0x00000008; -pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200; -pub const CREATE_UNICODE_ENVIRONMENT: DWORD = 0x00000400; -pub const STARTF_USESTDHANDLES: DWORD = 0x00000100; - -pub const AF_INET: c_int = 2; -pub const AF_INET6: c_int = 23; -pub const SD_BOTH: c_int = 2; -pub const SD_RECEIVE: c_int = 0; -pub const SD_SEND: c_int = 1; -pub const SOCK_DGRAM: c_int = 2; -pub const SOCK_STREAM: c_int = 1; -pub const SOCKET_ERROR: c_int = -1; -pub const SOL_SOCKET: c_int = 0xffff; -pub const SO_LINGER: c_int = 0x0080; -pub const SO_RCVTIMEO: c_int = 0x1006; -pub const SO_SNDTIMEO: c_int = 0x1005; -pub const IPPROTO_IP: c_int = 0; -pub const IPPROTO_TCP: c_int = 6; -pub const IPPROTO_IPV6: c_int = 41; -pub const TCP_NODELAY: c_int = 0x0001; -pub const IP_TTL: c_int = 4; -pub const IPV6_V6ONLY: c_int = 27; -pub const SO_ERROR: c_int = 0x1007; -pub const SO_BROADCAST: c_int = 0x0020; -pub const IP_MULTICAST_LOOP: c_int = 11; -pub const IPV6_MULTICAST_LOOP: c_int = 11; -pub const IP_MULTICAST_TTL: c_int = 10; -pub const IP_ADD_MEMBERSHIP: c_int = 12; -pub const IP_DROP_MEMBERSHIP: c_int = 13; -pub const IPV6_ADD_MEMBERSHIP: c_int = 12; -pub const IPV6_DROP_MEMBERSHIP: c_int = 13; -pub const MSG_PEEK: c_int = 0x2; - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct linger { - pub l_onoff: c_ushort, - pub l_linger: c_ushort, -} +// Some windows_sys types have different signs than the types we use. +pub const OBJ_DONT_REPARSE: u32 = windows_sys::OBJ_DONT_REPARSE as u32; +pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: u32 = + windows_sys::FRS_ERR_SYSVOL_POPULATE_TIMEOUT as u32; +pub const AF_INET: c_int = windows_sys::AF_INET as c_int; +pub const AF_INET6: c_int = windows_sys::AF_INET6 as c_int; #[repr(C)] pub struct ip_mreq { @@ -257,67 +73,19 @@ pub struct ipv6_mreq { pub ipv6mr_interface: c_uint, } -pub const VOLUME_NAME_DOS: DWORD = 0x0; -pub const MOVEFILE_REPLACE_EXISTING: DWORD = 1; - -pub const FILE_BEGIN: DWORD = 0; -pub const FILE_CURRENT: DWORD = 1; -pub const FILE_END: DWORD = 2; - -pub const WAIT_OBJECT_0: DWORD = 0x00000000; -pub const WAIT_TIMEOUT: DWORD = 258; -pub const WAIT_FAILED: DWORD = 0xFFFFFFFF; - -pub const PIPE_ACCESS_INBOUND: DWORD = 0x00000001; -pub const PIPE_ACCESS_OUTBOUND: DWORD = 0x00000002; -pub const FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD = 0x00080000; -pub const FILE_FLAG_OVERLAPPED: DWORD = 0x40000000; -pub const PIPE_WAIT: DWORD = 0x00000000; -pub const PIPE_TYPE_BYTE: DWORD = 0x00000000; -pub const PIPE_REJECT_REMOTE_CLIENTS: DWORD = 0x00000008; -pub const PIPE_READMODE_BYTE: DWORD = 0x00000000; - -pub const FD_SETSIZE: usize = 64; - -pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000; - -pub const STATUS_SUCCESS: NTSTATUS = 0x00000000; -pub const STATUS_DELETE_PENDING: NTSTATUS = 0xc0000056_u32 as _; -pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; - -pub const STATUS_PENDING: NTSTATUS = 0x103 as _; -pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _; -pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _; - // Equivalent to the `NT_SUCCESS` C preprocessor macro. // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values pub fn nt_success(status: NTSTATUS) -> bool { status >= 0 } -pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; - -#[repr(C)] -pub struct UNICODE_STRING { - pub Length: u16, - pub MaximumLength: u16, - pub Buffer: *mut u16, -} impl UNICODE_STRING { pub fn from_ref(slice: &[u16]) -> Self { let len = slice.len() * mem::size_of::<u16>(); Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ } } } -#[repr(C)] -pub struct OBJECT_ATTRIBUTES { - pub Length: ULONG, - pub RootDirectory: HANDLE, - pub ObjectName: *const UNICODE_STRING, - pub Attributes: ULONG, - pub SecurityDescriptor: *mut c_void, - pub SecurityQualityOfService: *mut c_void, -} + impl Default for OBJECT_ATTRIBUTES { fn default() -> Self { Self { @@ -330,193 +98,20 @@ impl Default for OBJECT_ATTRIBUTES { } } } -#[repr(C)] -union IO_STATUS_BLOCK_union { - Status: NTSTATUS, - Pointer: *mut c_void, -} -impl Default for IO_STATUS_BLOCK_union { - fn default() -> Self { - let mut this = Self { Pointer: ptr::null_mut() }; - this.Status = STATUS_PENDING; - this - } -} -#[repr(C)] -#[derive(Default)] -pub struct IO_STATUS_BLOCK { - u: IO_STATUS_BLOCK_union, - pub Information: usize, -} + impl IO_STATUS_BLOCK { + pub const PENDING: Self = + IO_STATUS_BLOCK { Anonymous: IO_STATUS_BLOCK_0 { Status: STATUS_PENDING }, Information: 0 }; pub fn status(&self) -> NTSTATUS { - // SAFETY: If `self.u.Status` was set then this is obviously safe. - // If `self.u.Pointer` was set then this is the equivalent to converting + // SAFETY: If `self.Anonymous.Status` was set then this is obviously safe. + // If `self.Anonymous.Pointer` was set then this is the equivalent to converting // the pointer to an integer, which is also safe. // Currently the only safe way to construct `IO_STATUS_BLOCK` outside of // this module is to call the `default` method, which sets the `Status`. - unsafe { self.u.Status } + unsafe { self.Anonymous.Status } } } -pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn( - dwErrorCode: DWORD, - dwNumberOfBytesTransferred: DWORD, - lpOverlapped: *mut OVERLAPPED, -); - -type IO_APC_ROUTINE = unsafe extern "system" fn( - ApcContext: *mut c_void, - IoStatusBlock: *mut IO_STATUS_BLOCK, - Reserved: ULONG, -); - -#[repr(C)] -#[cfg(not(target_pointer_width = "64"))] -pub struct WSADATA { - pub wVersion: WORD, - pub wHighVersion: WORD, - pub szDescription: [u8; WSADESCRIPTION_LEN + 1], - pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], - pub iMaxSockets: u16, - pub iMaxUdpDg: u16, - pub lpVendorInfo: *mut u8, -} -#[repr(C)] -#[cfg(target_pointer_width = "64")] -pub struct WSADATA { - pub wVersion: WORD, - pub wHighVersion: WORD, - pub iMaxSockets: u16, - pub iMaxUdpDg: u16, - pub lpVendorInfo: *mut u8, - pub szDescription: [u8; WSADESCRIPTION_LEN + 1], - pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct WSABUF { - pub len: ULONG, - pub buf: *mut CHAR, -} - -#[repr(C)] -pub struct WSAPROTOCOL_INFO { - pub dwServiceFlags1: DWORD, - pub dwServiceFlags2: DWORD, - pub dwServiceFlags3: DWORD, - pub dwServiceFlags4: DWORD, - pub dwProviderFlags: DWORD, - pub ProviderId: GUID, - pub dwCatalogEntryId: DWORD, - pub ProtocolChain: WSAPROTOCOLCHAIN, - pub iVersion: c_int, - pub iAddressFamily: c_int, - pub iMaxSockAddr: c_int, - pub iMinSockAddr: c_int, - pub iSocketType: c_int, - pub iProtocol: c_int, - pub iProtocolMaxOffset: c_int, - pub iNetworkByteOrder: c_int, - pub iSecurityScheme: c_int, - pub dwMessageSize: DWORD, - pub dwProviderReserved: DWORD, - pub szProtocol: [u16; (WSAPROTOCOL_LEN as usize) + 1], -} - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct WIN32_FILE_ATTRIBUTE_DATA { - pub dwFileAttributes: DWORD, - pub ftCreationTime: FILETIME, - pub ftLastAccessTime: FILETIME, - pub ftLastWriteTime: FILETIME, - pub nFileSizeHigh: DWORD, - pub nFileSizeLow: DWORD, -} - -#[repr(C)] -#[allow(dead_code)] // we only use some variants -pub enum FILE_INFO_BY_HANDLE_CLASS { - FileBasicInfo = 0, - FileStandardInfo = 1, - FileNameInfo = 2, - FileRenameInfo = 3, - FileDispositionInfo = 4, - FileAllocationInfo = 5, - FileEndOfFileInfo = 6, - FileStreamInfo = 7, - FileCompressionInfo = 8, - FileAttributeTagInfo = 9, - FileIdBothDirectoryInfo = 10, // 0xA - FileIdBothDirectoryRestartInfo = 11, // 0xB - FileIoPriorityHintInfo = 12, // 0xC - FileRemoteProtocolInfo = 13, // 0xD - FileFullDirectoryInfo = 14, // 0xE - FileFullDirectoryRestartInfo = 15, // 0xF - FileStorageInfo = 16, // 0x10 - FileAlignmentInfo = 17, // 0x11 - FileIdInfo = 18, // 0x12 - FileIdExtdDirectoryInfo = 19, // 0x13 - FileIdExtdDirectoryRestartInfo = 20, // 0x14 - FileDispositionInfoEx = 21, // 0x15, Windows 10 version 1607 - MaximumFileInfoByHandlesClass, -} - -#[repr(C)] -pub struct FILE_ATTRIBUTE_TAG_INFO { - pub FileAttributes: DWORD, - pub ReparseTag: DWORD, -} - -#[repr(C)] -pub struct FILE_DISPOSITION_INFO { - pub DeleteFile: BOOLEAN, -} - -pub const FILE_DISPOSITION_DELETE: DWORD = 0x1; -pub const FILE_DISPOSITION_POSIX_SEMANTICS: DWORD = 0x2; -pub const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: DWORD = 0x10; - -#[repr(C)] -pub struct FILE_DISPOSITION_INFO_EX { - pub Flags: DWORD, -} - -#[repr(C)] -#[derive(Default)] -pub struct FILE_ID_BOTH_DIR_INFO { - pub NextEntryOffset: DWORD, - pub FileIndex: DWORD, - pub CreationTime: LARGE_INTEGER, - pub LastAccessTime: LARGE_INTEGER, - pub LastWriteTime: LARGE_INTEGER, - pub ChangeTime: LARGE_INTEGER, - pub EndOfFile: LARGE_INTEGER, - pub AllocationSize: LARGE_INTEGER, - pub FileAttributes: DWORD, - pub FileNameLength: DWORD, - pub EaSize: DWORD, - pub ShortNameLength: CCHAR, - pub ShortName: [WCHAR; 12], - pub FileId: LARGE_INTEGER, - pub FileName: [WCHAR; 1], -} -#[repr(C)] -pub struct FILE_BASIC_INFO { - pub CreationTime: LARGE_INTEGER, - pub LastAccessTime: LARGE_INTEGER, - pub LastWriteTime: LARGE_INTEGER, - pub ChangeTime: LARGE_INTEGER, - pub FileAttributes: DWORD, -} - -#[repr(C)] -pub struct FILE_END_OF_FILE_INFO { - pub EndOfFile: LARGE_INTEGER, -} - /// NB: Use carefully! In general using this as a reference is likely to get the /// provenance wrong for the `rest` field! #[repr(C)] @@ -539,14 +134,6 @@ pub struct SYMBOLIC_LINK_REPARSE_BUFFER { pub PathBuffer: WCHAR, } -/// NB: Use carefully! In general using this as a reference is likely to get the -/// provenance wrong for the `PathBuffer` field! -#[repr(C)] -pub struct FILE_NAME_INFO { - pub FileNameLength: DWORD, - pub FileName: [WCHAR; 1], -} - #[repr(C)] pub struct MOUNT_POINT_REPARSE_BUFFER { pub SubstituteNameOffset: c_ushort, @@ -555,34 +142,6 @@ pub struct MOUNT_POINT_REPARSE_BUFFER { pub PrintNameLength: c_ushort, pub PathBuffer: WCHAR, } - -pub type LPPROGRESS_ROUTINE = crate::option::Option< - unsafe extern "system" fn( - TotalFileSize: LARGE_INTEGER, - TotalBytesTransferred: LARGE_INTEGER, - StreamSize: LARGE_INTEGER, - StreamBytesTransferred: LARGE_INTEGER, - dwStreamNumber: DWORD, - dwCallbackReason: DWORD, - hSourceFile: HANDLE, - hDestinationFile: HANDLE, - lpData: LPVOID, - ) -> DWORD, ->; - -#[repr(C)] -pub struct CONDITION_VARIABLE { - pub ptr: LPVOID, -} -#[repr(C)] -pub struct SRWLOCK { - pub ptr: LPVOID, -} -#[repr(C)] -pub struct INIT_ONCE { - pub ptr: LPVOID, -} - #[repr(C)] pub struct REPARSE_MOUNTPOINT_DATA_BUFFER { pub ReparseTag: DWORD, @@ -595,103 +154,6 @@ pub struct REPARSE_MOUNTPOINT_DATA_BUFFER { } #[repr(C)] -pub struct GUID { - pub Data1: DWORD, - pub Data2: WORD, - pub Data3: WORD, - pub Data4: [BYTE; 8], -} - -#[repr(C)] -pub struct WSAPROTOCOLCHAIN { - pub ChainLen: c_int, - pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize], -} - -#[repr(C)] -pub struct SECURITY_ATTRIBUTES { - pub nLength: DWORD, - pub lpSecurityDescriptor: LPVOID, - pub bInheritHandle: BOOL, -} - -#[repr(C)] -pub struct PROCESS_INFORMATION { - pub hProcess: HANDLE, - pub hThread: HANDLE, - pub dwProcessId: DWORD, - pub dwThreadId: DWORD, -} - -#[repr(C)] -pub struct STARTUPINFO { - pub cb: DWORD, - pub lpReserved: LPWSTR, - pub lpDesktop: LPWSTR, - pub lpTitle: LPWSTR, - pub dwX: DWORD, - pub dwY: DWORD, - pub dwXSize: DWORD, - pub dwYSize: DWORD, - pub dwXCountChars: DWORD, - pub dwYCountCharts: DWORD, - pub dwFillAttribute: DWORD, - pub dwFlags: DWORD, - pub wShowWindow: WORD, - pub cbReserved2: WORD, - pub lpReserved2: LPBYTE, - pub hStdInput: HANDLE, - pub hStdOutput: HANDLE, - pub hStdError: HANDLE, -} - -#[repr(C)] -pub struct SOCKADDR { - pub sa_family: ADDRESS_FAMILY, - pub sa_data: [CHAR; 14], -} - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default)] -pub struct FILETIME { - pub dwLowDateTime: DWORD, - pub dwHighDateTime: DWORD, -} - -#[repr(C)] -pub struct SYSTEM_INFO { - pub wProcessorArchitecture: WORD, - pub wReserved: WORD, - pub dwPageSize: DWORD, - pub lpMinimumApplicationAddress: LPVOID, - pub lpMaximumApplicationAddress: LPVOID, - pub dwActiveProcessorMask: DWORD_PTR, - pub dwNumberOfProcessors: DWORD, - pub dwProcessorType: DWORD, - pub dwAllocationGranularity: DWORD, - pub wProcessorLevel: WORD, - pub wProcessorRevision: WORD, -} - -#[repr(C)] -pub struct OVERLAPPED { - pub Internal: *mut c_ulong, - pub InternalHigh: *mut c_ulong, - pub Offset: DWORD, - pub OffsetHigh: DWORD, - pub hEvent: HANDLE, -} - -#[repr(C)] -#[allow(dead_code)] // we only use some variants -pub enum ADDRESS_MODE { - AddrMode1616, - AddrMode1632, - AddrModeReal, - AddrModeFlat, -} - -#[repr(C)] pub struct SOCKADDR_STORAGE_LH { pub ss_family: ADDRESS_FAMILY, pub __ss_pad1: [CHAR; 6], @@ -700,18 +162,6 @@ pub struct SOCKADDR_STORAGE_LH { } #[repr(C)] -pub struct ADDRINFOA { - pub ai_flags: c_int, - pub ai_family: c_int, - pub ai_socktype: c_int, - pub ai_protocol: c_int, - pub ai_addrlen: size_t, - pub ai_canonname: *mut c_char, - pub ai_addr: *mut SOCKADDR, - pub ai_next: *mut ADDRINFOA, -} - -#[repr(C)] #[derive(Copy, Clone)] pub struct sockaddr_in { pub sin_family: ADDRESS_FAMILY, @@ -742,524 +192,126 @@ pub struct in6_addr { pub s6_addr: [u8; 16], } -#[repr(C)] -#[derive(Copy, Clone)] -#[allow(dead_code)] // we only use some variants -pub enum EXCEPTION_DISPOSITION { - ExceptionContinueExecution, - ExceptionContinueSearch, - ExceptionNestedException, - ExceptionCollidedUnwind, -} - -#[repr(C)] -#[derive(Copy)] -pub struct fd_set { - pub fd_count: c_uint, - pub fd_array: [SOCKET; FD_SETSIZE], -} - -impl Clone for fd_set { - fn clone(&self) -> fd_set { - *self - } -} - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct timeval { - pub tv_sec: c_long, - pub tv_usec: c_long, -} - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CONSOLE_READCONSOLE_CONTROL { - pub nLength: ULONG, - pub nInitialChars: ULONG, - pub dwCtrlWakeupMask: ULONG, - pub dwControlKeyState: ULONG, -} -pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL; - // Desktop specific functions & types cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { - pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0; - pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; - pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; - - #[repr(C)] - pub struct EXCEPTION_RECORD { - pub ExceptionCode: DWORD, - pub ExceptionFlags: DWORD, - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ExceptionAddress: LPVOID, - pub NumberParameters: DWORD, - pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS], - } - - pub enum CONTEXT {} - - #[repr(C)] - pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ContextRecord: *mut CONTEXT, - } - - pub type PVECTORED_EXCEPTION_HANDLER = - extern "system" fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG; - - #[repr(C)] - pub struct BY_HANDLE_FILE_INFORMATION { - pub dwFileAttributes: DWORD, - pub ftCreationTime: FILETIME, - pub ftLastAccessTime: FILETIME, - pub ftLastWriteTime: FILETIME, - pub dwVolumeSerialNumber: DWORD, - pub nFileSizeHigh: DWORD, - pub nFileSizeLow: DWORD, - pub nNumberOfLinks: DWORD, - pub nFileIndexHigh: DWORD, - pub nFileIndexLow: DWORD, - } - - pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; - - pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; - - pub const TOKEN_READ: DWORD = 0x20008; - - #[link(name = "advapi32")] - extern "system" { - // Forbidden when targeting UWP - #[link_name = "SystemFunction036"] - pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; - - // Allowed but unused by UWP - pub fn OpenProcessToken( - ProcessHandle: HANDLE, - DesiredAccess: DWORD, - TokenHandle: *mut HANDLE, - ) -> BOOL; - } - - #[link(name = "userenv")] - extern "system" { - // Allowed but unused by UWP - pub fn GetUserProfileDirectoryW( - hToken: HANDLE, - lpProfileDir: LPWSTR, - lpcchSize: *mut DWORD, - ) -> BOOL; - } - - #[link(name = "kernel32")] - extern "system" { - // Allowed but unused by UWP - pub fn GetFileInformationByHandle( - hFile: HANDLE, - lpFileInformation: LPBY_HANDLE_FILE_INFORMATION, - ) -> BOOL; - pub fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL; - pub fn AddVectoredExceptionHandler( - FirstHandler: ULONG, - VectoredHandler: PVECTORED_EXCEPTION_HANDLER, - ) -> LPVOID; - pub fn CreateHardLinkW( - lpSymlinkFileName: LPCWSTR, - lpTargetFileName: LPCWSTR, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES, - ) -> BOOL; - pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL; - pub fn GetWindowsDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; - } -} -} - -// UWP specific functions & types -cfg_if::cfg_if! { -if #[cfg(target_vendor = "uwp")] { - #[repr(C)] - pub struct FILE_STANDARD_INFO { - pub AllocationSize: LARGE_INTEGER, - pub EndOfFile: LARGE_INTEGER, - pub NumberOfLinks: DWORD, - pub DeletePending: BOOLEAN, - pub Directory: BOOLEAN, - } -} -} - -// Shared between Desktop & UWP - -#[link(name = "kernel32")] -extern "system" { - pub fn GetCurrentProcessId() -> DWORD; - - pub fn ReadConsoleW( - hConsoleInput: HANDLE, - lpBuffer: LPVOID, - nNumberOfCharsToRead: DWORD, - lpNumberOfCharsRead: LPDWORD, - pInputControl: PCONSOLE_READCONSOLE_CONTROL, - ) -> BOOL; - pub fn WriteConsoleW( - hConsoleOutput: HANDLE, - lpBuffer: LPCVOID, - nNumberOfCharsToWrite: DWORD, - lpNumberOfCharsWritten: LPDWORD, - lpReserved: LPVOID, - ) -> BOOL; - pub fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; - - pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; - pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; - pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; - pub fn SetFileTime( - hFile: BorrowedHandle<'_>, - lpCreationTime: Option<&FILETIME>, - lpLastAccessTime: Option<&FILETIME>, - lpLastWriteTime: Option<&FILETIME>, - ) -> BOOL; - pub fn SetLastError(dwErrCode: DWORD); - pub fn GetCommandLineW() -> LPWSTR; - pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD; - pub fn GetCurrentProcess() -> HANDLE; - pub fn GetCurrentThread() -> HANDLE; - pub fn GetStdHandle(which: DWORD) -> HANDLE; - pub fn ExitProcess(uExitCode: c_uint) -> !; - pub fn DeviceIoControl( - hDevice: HANDLE, - dwIoControlCode: DWORD, - lpInBuffer: LPVOID, - nInBufferSize: DWORD, - lpOutBuffer: LPVOID, - nOutBufferSize: DWORD, - lpBytesReturned: LPDWORD, - lpOverlapped: LPOVERLAPPED, - ) -> BOOL; - pub fn CreateThread( - lpThreadAttributes: LPSECURITY_ATTRIBUTES, - dwStackSize: SIZE_T, - lpStartAddress: extern "system" fn(*mut c_void) -> DWORD, - lpParameter: LPVOID, - dwCreationFlags: DWORD, - lpThreadId: LPDWORD, - ) -> HandleOrNull; - pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; - pub fn SwitchToThread() -> BOOL; - pub fn Sleep(dwMilliseconds: DWORD); - pub fn SleepEx(dwMilliseconds: DWORD, bAlertable: BOOL) -> DWORD; - pub fn GetProcessId(handle: HANDLE) -> DWORD; - pub fn CopyFileExW( - lpExistingFileName: LPCWSTR, - lpNewFileName: LPCWSTR, - lpProgressRoutine: LPPROGRESS_ROUTINE, - lpData: LPVOID, - pbCancel: LPBOOL, - dwCopyFlags: DWORD, - ) -> BOOL; - pub fn FormatMessageW( - flags: DWORD, - lpSrc: LPVOID, - msgId: DWORD, - langId: DWORD, - buf: LPWSTR, - nsize: DWORD, - args: *const c_void, - ) -> DWORD; - pub fn TlsAlloc() -> DWORD; - pub fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID; - pub fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL; - pub fn TlsFree(dwTlsIndex: DWORD) -> BOOL; - pub fn GetLastError() -> DWORD; - pub fn QueryPerformanceFrequency(lpFrequency: *mut LARGE_INTEGER) -> BOOL; - pub fn QueryPerformanceCounter(lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL; - pub fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL; - pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL; - pub fn CreateProcessW( - lpApplicationName: LPCWSTR, - lpCommandLine: LPWSTR, - lpProcessAttributes: LPSECURITY_ATTRIBUTES, - lpThreadAttributes: LPSECURITY_ATTRIBUTES, - bInheritHandles: BOOL, - dwCreationFlags: DWORD, - lpEnvironment: LPVOID, - lpCurrentDirectory: LPCWSTR, - lpStartupInfo: LPSTARTUPINFO, - lpProcessInformation: LPPROCESS_INFORMATION, - ) -> BOOL; - pub fn GetEnvironmentVariableW(n: LPCWSTR, v: LPWSTR, nsize: DWORD) -> DWORD; - pub fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR) -> BOOL; - pub fn GetEnvironmentStringsW() -> LPWCH; - pub fn FreeEnvironmentStringsW(env_ptr: LPWCH) -> BOOL; - pub fn GetModuleFileNameW(hModule: HMODULE, lpFilename: LPWSTR, nSize: DWORD) -> DWORD; - pub fn CreateDirectoryW( - lpPathName: LPCWSTR, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES, - ) -> BOOL; - pub fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL; - pub fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD; - pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL; - pub fn DuplicateHandle( - hSourceProcessHandle: HANDLE, - hSourceHandle: HANDLE, - hTargetProcessHandle: HANDLE, - lpTargetHandle: LPHANDLE, - dwDesiredAccess: DWORD, - bInheritHandle: BOOL, - dwOptions: DWORD, - ) -> BOOL; - pub fn ReadFile( - hFile: BorrowedHandle<'_>, - lpBuffer: LPVOID, - nNumberOfBytesToRead: DWORD, - lpNumberOfBytesRead: LPDWORD, - lpOverlapped: LPOVERLAPPED, - ) -> BOOL; - pub fn ReadFileEx( - hFile: BorrowedHandle<'_>, - lpBuffer: LPVOID, - nNumberOfBytesToRead: DWORD, - lpOverlapped: LPOVERLAPPED, - lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, - ) -> BOOL; - pub fn WriteFileEx( - hFile: BorrowedHandle<'_>, - lpBuffer: LPVOID, - nNumberOfBytesToWrite: DWORD, - lpOverlapped: LPOVERLAPPED, - lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, - ) -> BOOL; - pub fn CloseHandle(hObject: HANDLE) -> BOOL; - pub fn MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: DWORD) - -> BOOL; - pub fn SetFilePointerEx( - hFile: HANDLE, - liDistanceToMove: LARGE_INTEGER, - lpNewFilePointer: PLARGE_INTEGER, - dwMoveMethod: DWORD, - ) -> BOOL; - pub fn FlushFileBuffers(hFile: HANDLE) -> BOOL; - pub fn CreateFileW( - lpFileName: LPCWSTR, - dwDesiredAccess: DWORD, - dwShareMode: DWORD, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES, - dwCreationDisposition: DWORD, - dwFlagsAndAttributes: DWORD, - hTemplateFile: HANDLE, - ) -> HandleOrInvalid; - - pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW) -> HANDLE; - pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL; - pub fn FindClose(findFile: HANDLE) -> BOOL; - - pub fn GetProcAddress(handle: HMODULE, name: LPCSTR) -> *mut c_void; - pub fn GetModuleHandleA(lpModuleName: LPCSTR) -> HMODULE; - pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; - - pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); - pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO); - - pub fn CreateEventW( - lpEventAttributes: LPSECURITY_ATTRIBUTES, - bManualReset: BOOL, - bInitialState: BOOL, - lpName: LPCWSTR, - ) -> HANDLE; - pub fn WaitForMultipleObjects( - nCount: DWORD, - lpHandles: *const HANDLE, - bWaitAll: BOOL, - dwMilliseconds: DWORD, - ) -> DWORD; - pub fn CreateNamedPipeW( - lpName: LPCWSTR, - dwOpenMode: DWORD, - dwPipeMode: DWORD, - nMaxInstances: DWORD, - nOutBufferSize: DWORD, - nInBufferSize: DWORD, - nDefaultTimeOut: DWORD, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES, - ) -> HANDLE; - pub fn CancelIo(handle: HANDLE) -> BOOL; - pub fn GetOverlappedResult( - hFile: HANDLE, - lpOverlapped: LPOVERLAPPED, - lpNumberOfBytesTransferred: LPDWORD, - bWait: BOOL, - ) -> BOOL; - pub fn CreateSymbolicLinkW( - lpSymlinkFileName: LPCWSTR, - lpTargetFileName: LPCWSTR, - dwFlags: DWORD, - ) -> BOOLEAN; - pub fn GetFinalPathNameByHandleW( - hFile: HANDLE, - lpszFilePath: LPCWSTR, - cchFilePath: DWORD, - dwFlags: DWORD, - ) -> DWORD; - pub fn GetFileInformationByHandleEx( - hFile: HANDLE, - fileInfoClass: FILE_INFO_BY_HANDLE_CLASS, - lpFileInformation: LPVOID, - dwBufferSize: DWORD, - ) -> BOOL; - pub fn SetFileInformationByHandle( - hFile: HANDLE, - FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, - lpFileInformation: LPVOID, - dwBufferSize: DWORD, - ) -> BOOL; - pub fn GetFileType(hfile: HANDLE) -> DWORD; - pub fn SleepConditionVariableSRW( - ConditionVariable: PCONDITION_VARIABLE, - SRWLock: PSRWLOCK, - dwMilliseconds: DWORD, - Flags: ULONG, - ) -> BOOL; - - pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE); - pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE); - - pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK); - pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK); - pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK); - pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK); - pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN; - pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN; - - pub fn InitOnceBeginInitialize( - lpInitOnce: LPINIT_ONCE, - dwFlags: DWORD, - fPending: LPBOOL, - lpContext: *mut LPVOID, - ) -> BOOL; - pub fn InitOnceComplete(lpInitOnce: LPINIT_ONCE, dwFlags: DWORD, lpContext: LPVOID) -> BOOL; - - pub fn CompareStringOrdinal( - lpString1: LPCWSTR, - cchCount1: c_int, - lpString2: LPCWSTR, - cchCount2: c_int, - bIgnoreCase: BOOL, - ) -> c_int; - pub fn GetFullPathNameW( - lpFileName: LPCWSTR, - nBufferLength: DWORD, - lpBuffer: LPWSTR, - lpFilePart: *mut LPWSTR, - ) -> DWORD; - pub fn GetFileAttributesW(lpFileName: LPCWSTR) -> DWORD; + pub const EXCEPTION_CONTINUE_SEARCH: i32 = 0; } - -#[link(name = "ws2_32")] -extern "system" { - pub fn WSAStartup(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int; - pub fn WSACleanup() -> c_int; - pub fn WSAGetLastError() -> c_int; - pub fn WSADuplicateSocketW( - s: SOCKET, - dwProcessId: DWORD, - lpProtocolInfo: LPWSAPROTOCOL_INFO, - ) -> c_int; - pub fn WSASend( - s: SOCKET, - lpBuffers: LPWSABUF, - dwBufferCount: DWORD, - lpNumberOfBytesSent: LPDWORD, - dwFlags: DWORD, - lpOverlapped: LPWSAOVERLAPPED, - lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, - ) -> c_int; - pub fn WSARecv( - s: SOCKET, - lpBuffers: LPWSABUF, - dwBufferCount: DWORD, - lpNumberOfBytesRecvd: LPDWORD, - lpFlags: LPDWORD, - lpOverlapped: LPWSAOVERLAPPED, - lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, - ) -> c_int; - pub fn WSASocketW( - af: c_int, - kind: c_int, - protocol: c_int, - lpProtocolInfo: LPWSAPROTOCOL_INFO, - g: GROUP, - dwFlags: DWORD, - ) -> SOCKET; - pub fn ioctlsocket(s: SOCKET, cmd: c_long, argp: *mut c_ulong) -> c_int; - pub fn closesocket(socket: SOCKET) -> c_int; - pub fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int; - pub fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int; - pub fn recvfrom( - socket: SOCKET, - buf: *mut c_void, - len: c_int, - flags: c_int, - addr: *mut SOCKADDR, - addrlen: *mut c_int, - ) -> c_int; - pub fn sendto( - socket: SOCKET, - buf: *const c_void, - len: c_int, - flags: c_int, - addr: *const SOCKADDR, - addrlen: c_int, - ) -> c_int; - pub fn shutdown(socket: SOCKET, how: c_int) -> c_int; - pub fn accept(socket: SOCKET, address: *mut SOCKADDR, address_len: *mut c_int) -> SOCKET; - pub fn getsockopt( - s: SOCKET, - level: c_int, - optname: c_int, - optval: *mut c_char, - optlen: *mut c_int, - ) -> c_int; - pub fn setsockopt( - s: SOCKET, - level: c_int, - optname: c_int, - optval: *const c_void, - optlen: c_int, - ) -> c_int; - pub fn getsockname(socket: SOCKET, address: *mut SOCKADDR, address_len: *mut c_int) -> c_int; - pub fn getpeername(socket: SOCKET, address: *mut SOCKADDR, address_len: *mut c_int) -> c_int; - pub fn bind(socket: SOCKET, address: *const SOCKADDR, address_len: socklen_t) -> c_int; - pub fn listen(socket: SOCKET, backlog: c_int) -> c_int; - pub fn connect(socket: SOCKET, address: *const SOCKADDR, len: c_int) -> c_int; - pub fn getaddrinfo( - node: *const c_char, - service: *const c_char, - hints: *const ADDRINFOA, - res: *mut *mut ADDRINFOA, - ) -> c_int; - pub fn freeaddrinfo(res: *mut ADDRINFOA); - pub fn select( - nfds: c_int, - readfds: *mut fd_set, - writefds: *mut fd_set, - exceptfds: *mut fd_set, - timeout: *const timeval, - ) -> c_int; } -#[link(name = "bcrypt")] -extern "system" { - // >= Vista / Server 2008 - // https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom - pub fn BCryptGenRandom( - hAlgorithm: BCRYPT_ALG_HANDLE, - pBuffer: *mut u8, - cbBuffer: ULONG, - dwFlags: ULONG, - ) -> NTSTATUS; +pub unsafe extern "system" fn WriteFileEx( + hFile: BorrowedHandle<'_>, + lpBuffer: *mut ::core::ffi::c_void, + nNumberOfBytesToWrite: u32, + lpOverlapped: *mut OVERLAPPED, + lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, +) -> BOOL { + windows_sys::WriteFileEx( + hFile.as_raw_handle(), + lpBuffer.cast::<u8>(), + nNumberOfBytesToWrite, + lpOverlapped, + lpCompletionRoutine, + ) +} + +pub unsafe extern "system" fn ReadFileEx( + hFile: BorrowedHandle<'_>, + lpBuffer: *mut ::core::ffi::c_void, + nNumberOfBytesToRead: u32, + lpOverlapped: *mut OVERLAPPED, + lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, +) -> BOOL { + windows_sys::ReadFileEx( + hFile.as_raw_handle(), + lpBuffer, + nNumberOfBytesToRead, + lpOverlapped, + lpCompletionRoutine, + ) +} + +// POSIX compatibility shims. +pub unsafe fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int { + windows_sys::recv(socket, buf.cast::<u8>(), len, flags) +} +pub unsafe fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int { + windows_sys::send(socket, buf.cast::<u8>(), len, flags) +} +pub unsafe fn recvfrom( + socket: SOCKET, + buf: *mut c_void, + len: c_int, + flags: c_int, + addr: *mut SOCKADDR, + addrlen: *mut c_int, +) -> c_int { + windows_sys::recvfrom(socket, buf.cast::<u8>(), len, flags, addr, addrlen) +} +pub unsafe fn sendto( + socket: SOCKET, + buf: *const c_void, + len: c_int, + flags: c_int, + addr: *const SOCKADDR, + addrlen: c_int, +) -> c_int { + windows_sys::sendto(socket, buf.cast::<u8>(), len, flags, addr, addrlen) +} +pub unsafe fn getaddrinfo( + node: *const c_char, + service: *const c_char, + hints: *const ADDRINFOA, + res: *mut *mut ADDRINFOA, +) -> c_int { + windows_sys::getaddrinfo(node.cast::<u8>(), service.cast::<u8>(), hints, res) +} + +pub unsafe fn NtReadFile( + filehandle: BorrowedHandle<'_>, + event: HANDLE, + apcroutine: PIO_APC_ROUTINE, + apccontext: *mut c_void, + iostatusblock: &mut IO_STATUS_BLOCK, + buffer: *mut crate::mem::MaybeUninit<u8>, + length: ULONG, + byteoffset: Option<&LARGE_INTEGER>, + key: Option<&ULONG>, +) -> NTSTATUS { + windows_sys::NtReadFile( + filehandle.as_raw_handle(), + event, + apcroutine, + apccontext, + iostatusblock, + buffer.cast::<c_void>(), + length, + byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()), + key.map(|k| k as *const u32).unwrap_or(ptr::null()), + ) +} +pub unsafe fn NtWriteFile( + filehandle: BorrowedHandle<'_>, + event: HANDLE, + apcroutine: PIO_APC_ROUTINE, + apccontext: *mut c_void, + iostatusblock: &mut IO_STATUS_BLOCK, + buffer: *const u8, + length: ULONG, + byteoffset: Option<&LARGE_INTEGER>, + key: Option<&ULONG>, +) -> NTSTATUS { + windows_sys::NtWriteFile( + filehandle.as_raw_handle(), + event, + apcroutine, + apccontext, + iostatusblock, + buffer.cast::<c_void>(), + length, + byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()), + key.map(|k| k as *const u32).unwrap_or(ptr::null()), + ) } // Functions that aren't available on every version of Windows that we support, @@ -1269,85 +321,37 @@ compat_fn_with_fallback! { // >= Win10 1607 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription - pub fn SetThreadDescription(hThread: HANDLE, - lpThreadDescription: LPCWSTR) -> HRESULT { + pub fn SetThreadDescription(hthread: HANDLE, lpthreaddescription: PCWSTR) -> HRESULT { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL } // >= Win8 / Server 2012 // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime - pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME) - -> () { - GetSystemTimeAsFileTime(lpSystemTimeAsFileTime) + pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> () { + GetSystemTimeAsFileTime(lpsystemtimeasfiletime) } // >= Win11 / Server 2022 // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a - pub fn GetTempPath2W(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD { - GetTempPathW(nBufferLength, lpBuffer) + pub fn GetTempPath2W(bufferlength: u32, buffer: PWSTR) -> u32 { + GetTempPathW(bufferlength, buffer) } } compat_fn_optional! { crate::sys::compat::load_synch_functions(); pub fn WaitOnAddress( - Address: LPVOID, - CompareAddress: LPVOID, - AddressSize: SIZE_T, - dwMilliseconds: DWORD - ); - pub fn WakeByAddressSingle(Address: LPVOID); + address: *const ::core::ffi::c_void, + compareaddress: *const ::core::ffi::c_void, + addresssize: usize, + dwmilliseconds: u32 + ) -> BOOL; + pub fn WakeByAddressSingle(address: *const ::core::ffi::c_void); } compat_fn_with_fallback! { pub static NTDLL: &CStr = ansi_str!("ntdll"); - pub fn NtCreateFile( - FileHandle: *mut HANDLE, - DesiredAccess: ACCESS_MASK, - ObjectAttributes: *const OBJECT_ATTRIBUTES, - IoStatusBlock: *mut IO_STATUS_BLOCK, - AllocationSize: *mut i64, - FileAttributes: ULONG, - ShareAccess: ULONG, - CreateDisposition: ULONG, - CreateOptions: ULONG, - EaBuffer: *mut c_void, - EaLength: ULONG - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - pub fn NtReadFile( - FileHandle: BorrowedHandle<'_>, - Event: HANDLE, - ApcRoutine: Option<IO_APC_ROUTINE>, - ApcContext: *mut c_void, - IoStatusBlock: &mut IO_STATUS_BLOCK, - Buffer: *mut crate::mem::MaybeUninit<u8>, - Length: ULONG, - ByteOffset: Option<&LARGE_INTEGER>, - Key: Option<&ULONG> - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - pub fn NtWriteFile( - FileHandle: BorrowedHandle<'_>, - Event: HANDLE, - ApcRoutine: Option<IO_APC_ROUTINE>, - ApcContext: *mut c_void, - IoStatusBlock: &mut IO_STATUS_BLOCK, - Buffer: *const u8, - Length: ULONG, - ByteOffset: Option<&LARGE_INTEGER>, - Key: Option<&ULONG> - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - pub fn RtlNtStatusToDosError( - Status: NTSTATUS - ) -> ULONG { - Status as ULONG - } pub fn NtCreateKeyedEvent( KeyedEventHandle: LPHANDLE, DesiredAccess: ACCESS_MASK, diff --git a/library/std/src/sys/windows/c/errors.rs b/library/std/src/sys/windows/c/errors.rs deleted file mode 100644 index 23dcc119db9..00000000000 --- a/library/std/src/sys/windows/c/errors.rs +++ /dev/null @@ -1,1883 +0,0 @@ -// List of Windows system error codes with descriptions: -// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes - -#![allow(dead_code)] - -use super::{c_int, DWORD}; - -pub const ERROR_DIRECTORY_NOT_SUPPORTED: DWORD = 336; -pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594; -pub const ERROR_DISK_QUOTA_EXCEEDED: DWORD = 1295; -pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910; -pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014; -pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705; - -// The followiung list was obtained from -// `/usr/x86_64-w64-mingw32/include/winerror.h` -// in the Debian package -// mingw-w64_6.0.0-3_all.deb -// -// The header of that file says: -// * This file has no copyright assigned and is placed in the Public Domain. -// * This file is part of the mingw-w64 runtime package. -// * No warranty is given; refer to the file DISCLAIMER.PD within this package. -// -// The text here is the result of the following rune: -// grep -P '#define ERROR' /usr/x86_64-w64-mingw32/include/winerror.h >>library/std/src/sys/windows/c/errors.rs -// grep -P '#define WSA' /usr/x86_64-w64-mingw32/include/winerror.h >>library/std/src/sys/windows/c/errors.rs -// and then using some manually-invented but rather obvious editor search-and-replace -// invocations, plus some straightforward manual fixups, to turn it into Rust syntax -// and remove all the duplicates from the manual table above. - -pub const ERROR_SUCCESS: DWORD = 0; -pub const ERROR_INVALID_FUNCTION: DWORD = 1; -pub const ERROR_FILE_NOT_FOUND: DWORD = 2; -pub const ERROR_PATH_NOT_FOUND: DWORD = 3; -pub const ERROR_TOO_MANY_OPEN_FILES: DWORD = 4; -pub const ERROR_ACCESS_DENIED: DWORD = 5; -pub const ERROR_INVALID_HANDLE: DWORD = 6; -pub const ERROR_ARENA_TRASHED: DWORD = 7; -pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8; -pub const ERROR_INVALID_BLOCK: DWORD = 9; -pub const ERROR_BAD_ENVIRONMENT: DWORD = 10; -pub const ERROR_BAD_FORMAT: DWORD = 11; -pub const ERROR_INVALID_ACCESS: DWORD = 12; -pub const ERROR_INVALID_DATA: DWORD = 13; -pub const ERROR_OUTOFMEMORY: DWORD = 14; -pub const ERROR_INVALID_DRIVE: DWORD = 15; -pub const ERROR_CURRENT_DIRECTORY: DWORD = 16; -pub const ERROR_NOT_SAME_DEVICE: DWORD = 17; -pub const ERROR_NO_MORE_FILES: DWORD = 18; -pub const ERROR_WRITE_PROTECT: DWORD = 19; -pub const ERROR_BAD_UNIT: DWORD = 20; -pub const ERROR_NOT_READY: DWORD = 21; -pub const ERROR_BAD_COMMAND: DWORD = 22; -pub const ERROR_CRC: DWORD = 23; -pub const ERROR_BAD_LENGTH: DWORD = 24; -pub const ERROR_SEEK: DWORD = 25; -pub const ERROR_NOT_DOS_DISK: DWORD = 26; -pub const ERROR_SECTOR_NOT_FOUND: DWORD = 27; -pub const ERROR_OUT_OF_PAPER: DWORD = 28; -pub const ERROR_WRITE_FAULT: DWORD = 29; -pub const ERROR_READ_FAULT: DWORD = 30; -pub const ERROR_GEN_FAILURE: DWORD = 31; -pub const ERROR_SHARING_VIOLATION: DWORD = 32; -pub const ERROR_LOCK_VIOLATION: DWORD = 33; -pub const ERROR_WRONG_DISK: DWORD = 34; -pub const ERROR_SHARING_BUFFER_EXCEEDED: DWORD = 36; -pub const ERROR_HANDLE_EOF: DWORD = 38; -pub const ERROR_HANDLE_DISK_FULL: DWORD = 39; -pub const ERROR_NOT_SUPPORTED: DWORD = 50; -pub const ERROR_REM_NOT_LIST: DWORD = 51; -pub const ERROR_DUP_NAME: DWORD = 52; -pub const ERROR_BAD_NETPATH: DWORD = 53; -pub const ERROR_NETWORK_BUSY: DWORD = 54; -pub const ERROR_DEV_NOT_EXIST: DWORD = 55; -pub const ERROR_TOO_MANY_CMDS: DWORD = 56; -pub const ERROR_ADAP_HDW_ERR: DWORD = 57; -pub const ERROR_BAD_NET_RESP: DWORD = 58; -pub const ERROR_UNEXP_NET_ERR: DWORD = 59; -pub const ERROR_BAD_REM_ADAP: DWORD = 60; -pub const ERROR_PRINTQ_FULL: DWORD = 61; -pub const ERROR_NO_SPOOL_SPACE: DWORD = 62; -pub const ERROR_PRINT_CANCELLED: DWORD = 63; -pub const ERROR_NETNAME_DELETED: DWORD = 64; -pub const ERROR_NETWORK_ACCESS_DENIED: DWORD = 65; -pub const ERROR_BAD_DEV_TYPE: DWORD = 66; -pub const ERROR_BAD_NET_NAME: DWORD = 67; -pub const ERROR_TOO_MANY_NAMES: DWORD = 68; -pub const ERROR_TOO_MANY_SESS: DWORD = 69; -pub const ERROR_SHARING_PAUSED: DWORD = 70; -pub const ERROR_REQ_NOT_ACCEP: DWORD = 71; -pub const ERROR_REDIR_PAUSED: DWORD = 72; -pub const ERROR_FILE_EXISTS: DWORD = 80; -pub const ERROR_CANNOT_MAKE: DWORD = 82; -pub const ERROR_FAIL_I24: DWORD = 83; -pub const ERROR_OUT_OF_STRUCTURES: DWORD = 84; -pub const ERROR_ALREADY_ASSIGNED: DWORD = 85; -pub const ERROR_INVALID_PASSWORD: DWORD = 86; -pub const ERROR_INVALID_PARAMETER: DWORD = 87; -pub const ERROR_NET_WRITE_FAULT: DWORD = 88; -pub const ERROR_NO_PROC_SLOTS: DWORD = 89; -pub const ERROR_TOO_MANY_SEMAPHORES: DWORD = 100; -pub const ERROR_EXCL_SEM_ALREADY_OWNED: DWORD = 101; -pub const ERROR_SEM_IS_SET: DWORD = 102; -pub const ERROR_TOO_MANY_SEM_REQUESTS: DWORD = 103; -pub const ERROR_INVALID_AT_INTERRUPT_TIME: DWORD = 104; -pub const ERROR_SEM_OWNER_DIED: DWORD = 105; -pub const ERROR_SEM_USER_LIMIT: DWORD = 106; -pub const ERROR_DISK_CHANGE: DWORD = 107; -pub const ERROR_DRIVE_LOCKED: DWORD = 108; -pub const ERROR_BROKEN_PIPE: DWORD = 109; -pub const ERROR_OPEN_FAILED: DWORD = 110; -pub const ERROR_BUFFER_OVERFLOW: DWORD = 111; -pub const ERROR_DISK_FULL: DWORD = 112; -pub const ERROR_NO_MORE_SEARCH_HANDLES: DWORD = 113; -pub const ERROR_INVALID_TARGET_HANDLE: DWORD = 114; -pub const ERROR_INVALID_CATEGORY: DWORD = 117; -pub const ERROR_INVALID_VERIFY_SWITCH: DWORD = 118; -pub const ERROR_BAD_DRIVER_LEVEL: DWORD = 119; -pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; -pub const ERROR_SEM_TIMEOUT: DWORD = 121; -pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; -pub const ERROR_INVALID_NAME: DWORD = 123; -pub const ERROR_INVALID_LEVEL: DWORD = 124; -pub const ERROR_NO_VOLUME_LABEL: DWORD = 125; -pub const ERROR_MOD_NOT_FOUND: DWORD = 126; -pub const ERROR_PROC_NOT_FOUND: DWORD = 127; -pub const ERROR_WAIT_NO_CHILDREN: DWORD = 128; -pub const ERROR_CHILD_NOT_COMPLETE: DWORD = 129; -pub const ERROR_DIRECT_ACCESS_HANDLE: DWORD = 130; -pub const ERROR_NEGATIVE_SEEK: DWORD = 131; -pub const ERROR_SEEK_ON_DEVICE: DWORD = 132; -pub const ERROR_IS_JOIN_TARGET: DWORD = 133; -pub const ERROR_IS_JOINED: DWORD = 134; -pub const ERROR_IS_SUBSTED: DWORD = 135; -pub const ERROR_NOT_JOINED: DWORD = 136; -pub const ERROR_NOT_SUBSTED: DWORD = 137; -pub const ERROR_JOIN_TO_JOIN: DWORD = 138; -pub const ERROR_SUBST_TO_SUBST: DWORD = 139; -pub const ERROR_JOIN_TO_SUBST: DWORD = 140; -pub const ERROR_SUBST_TO_JOIN: DWORD = 141; -pub const ERROR_BUSY_DRIVE: DWORD = 142; -pub const ERROR_SAME_DRIVE: DWORD = 143; -pub const ERROR_DIR_NOT_ROOT: DWORD = 144; -pub const ERROR_DIR_NOT_EMPTY: DWORD = 145; -pub const ERROR_IS_SUBST_PATH: DWORD = 146; -pub const ERROR_IS_JOIN_PATH: DWORD = 147; -pub const ERROR_PATH_BUSY: DWORD = 148; -pub const ERROR_IS_SUBST_TARGET: DWORD = 149; -pub const ERROR_SYSTEM_TRACE: DWORD = 150; -pub const ERROR_INVALID_EVENT_COUNT: DWORD = 151; -pub const ERROR_TOO_MANY_MUXWAITERS: DWORD = 152; -pub const ERROR_INVALID_LIST_FORMAT: DWORD = 153; -pub const ERROR_LABEL_TOO_LONG: DWORD = 154; -pub const ERROR_TOO_MANY_TCBS: DWORD = 155; -pub const ERROR_SIGNAL_REFUSED: DWORD = 156; -pub const ERROR_DISCARDED: DWORD = 157; -pub const ERROR_NOT_LOCKED: DWORD = 158; -pub const ERROR_BAD_THREADID_ADDR: DWORD = 159; -pub const ERROR_BAD_ARGUMENTS: DWORD = 160; -pub const ERROR_BAD_PATHNAME: DWORD = 161; -pub const ERROR_SIGNAL_PENDING: DWORD = 162; -pub const ERROR_MAX_THRDS_REACHED: DWORD = 164; -pub const ERROR_LOCK_FAILED: DWORD = 167; -pub const ERROR_BUSY: DWORD = 170; -pub const ERROR_CANCEL_VIOLATION: DWORD = 173; -pub const ERROR_ATOMIC_LOCKS_NOT_SUPPORTED: DWORD = 174; -pub const ERROR_INVALID_SEGMENT_NUMBER: DWORD = 180; -pub const ERROR_INVALID_ORDINAL: DWORD = 182; -pub const ERROR_ALREADY_EXISTS: DWORD = 183; -pub const ERROR_INVALID_FLAG_NUMBER: DWORD = 186; -pub const ERROR_SEM_NOT_FOUND: DWORD = 187; -pub const ERROR_INVALID_STARTING_CODESEG: DWORD = 188; -pub const ERROR_INVALID_STACKSEG: DWORD = 189; -pub const ERROR_INVALID_MODULETYPE: DWORD = 190; -pub const ERROR_INVALID_EXE_SIGNATURE: DWORD = 191; -pub const ERROR_EXE_MARKED_INVALID: DWORD = 192; -pub const ERROR_BAD_EXE_FORMAT: DWORD = 193; -pub const ERROR_ITERATED_DATA_EXCEEDS_64k: DWORD = 194; -pub const ERROR_INVALID_MINALLOCSIZE: DWORD = 195; -pub const ERROR_DYNLINK_FROM_INVALID_RING: DWORD = 196; -pub const ERROR_IOPL_NOT_ENABLED: DWORD = 197; -pub const ERROR_INVALID_SEGDPL: DWORD = 198; -pub const ERROR_AUTODATASEG_EXCEEDS_64k: DWORD = 199; -pub const ERROR_RING2SEG_MUST_BE_MOVABLE: DWORD = 200; -pub const ERROR_RELOC_CHAIN_XEEDS_SEGLIM: DWORD = 201; -pub const ERROR_INFLOOP_IN_RELOC_CHAIN: DWORD = 202; -pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; -pub const ERROR_NO_SIGNAL_SENT: DWORD = 205; -pub const ERROR_FILENAME_EXCED_RANGE: DWORD = 206; -pub const ERROR_RING2_STACK_IN_USE: DWORD = 207; -pub const ERROR_META_EXPANSION_TOO_LONG: DWORD = 208; -pub const ERROR_INVALID_SIGNAL_NUMBER: DWORD = 209; -pub const ERROR_THREAD_1_INACTIVE: DWORD = 210; -pub const ERROR_LOCKED: DWORD = 212; -pub const ERROR_TOO_MANY_MODULES: DWORD = 214; -pub const ERROR_NESTING_NOT_ALLOWED: DWORD = 215; -pub const ERROR_EXE_MACHINE_TYPE_MISMATCH: DWORD = 216; -pub const ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY: DWORD = 217; -pub const ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY: DWORD = 218; -pub const ERROR_FILE_CHECKED_OUT: DWORD = 220; -pub const ERROR_CHECKOUT_REQUIRED: DWORD = 221; -pub const ERROR_BAD_FILE_TYPE: DWORD = 222; -pub const ERROR_FILE_TOO_LARGE: DWORD = 223; -pub const ERROR_FORMS_AUTH_REQUIRED: DWORD = 224; -pub const ERROR_PIPE_LOCAL: DWORD = 229; -pub const ERROR_BAD_PIPE: DWORD = 230; -pub const ERROR_PIPE_BUSY: DWORD = 231; -pub const ERROR_NO_DATA: DWORD = 232; -pub const ERROR_PIPE_NOT_CONNECTED: DWORD = 233; -pub const ERROR_MORE_DATA: DWORD = 234; -pub const ERROR_VC_DISCONNECTED: DWORD = 240; -pub const ERROR_INVALID_EA_NAME: DWORD = 254; -pub const ERROR_EA_LIST_INCONSISTENT: DWORD = 255; -pub const ERROR_NO_MORE_ITEMS: DWORD = 259; -pub const ERROR_CANNOT_COPY: DWORD = 266; -pub const ERROR_DIRECTORY: DWORD = 267; -pub const ERROR_EAS_DIDNT_FIT: DWORD = 275; -pub const ERROR_EA_FILE_CORRUPT: DWORD = 276; -pub const ERROR_EA_TABLE_FULL: DWORD = 277; -pub const ERROR_INVALID_EA_HANDLE: DWORD = 278; -pub const ERROR_EAS_NOT_SUPPORTED: DWORD = 282; -pub const ERROR_NOT_OWNER: DWORD = 288; -pub const ERROR_TOO_MANY_POSTS: DWORD = 298; -pub const ERROR_PARTIAL_COPY: DWORD = 299; -pub const ERROR_OPLOCK_NOT_GRANTED: DWORD = 300; -pub const ERROR_INVALID_OPLOCK_PROTOCOL: DWORD = 301; -pub const ERROR_DISK_TOO_FRAGMENTED: DWORD = 302; -pub const ERROR_DELETE_PENDING: DWORD = 303; -pub const ERROR_INVALID_TOKEN: DWORD = 315; -pub const ERROR_MR_MID_NOT_FOUND: DWORD = 317; -pub const ERROR_SCOPE_NOT_FOUND: DWORD = 318; -pub const ERROR_INVALID_ADDRESS: DWORD = 487; -pub const ERROR_ARITHMETIC_OVERFLOW: DWORD = 534; -pub const ERROR_PIPE_CONNECTED: DWORD = 535; -pub const ERROR_PIPE_LISTENING: DWORD = 536; -pub const ERROR_WAKE_SYSTEM: DWORD = 730; -pub const ERROR_WAIT_1: DWORD = 731; -pub const ERROR_WAIT_2: DWORD = 732; -pub const ERROR_WAIT_3: DWORD = 733; -pub const ERROR_WAIT_63: DWORD = 734; -pub const ERROR_ABANDONED_WAIT_0: DWORD = 735; -pub const ERROR_ABANDONED_WAIT_63: DWORD = 736; -pub const ERROR_USER_APC: DWORD = 737; -pub const ERROR_KERNEL_APC: DWORD = 738; -pub const ERROR_ALERTED: DWORD = 739; -pub const ERROR_EA_ACCESS_DENIED: DWORD = 994; -pub const ERROR_OPERATION_ABORTED: DWORD = 995; -pub const ERROR_IO_INCOMPLETE: DWORD = 996; -pub const ERROR_IO_PENDING: DWORD = 997; -pub const ERROR_NOACCESS: DWORD = 998; -pub const ERROR_SWAPERROR: DWORD = 999; -pub const ERROR_STACK_OVERFLOW: DWORD = 1001; -pub const ERROR_INVALID_MESSAGE: DWORD = 1002; -pub const ERROR_CAN_NOT_COMPLETE: DWORD = 1003; -pub const ERROR_INVALID_FLAGS: DWORD = 1004; -pub const ERROR_UNRECOGNIZED_VOLUME: DWORD = 1005; -pub const ERROR_FILE_INVALID: DWORD = 1006; -pub const ERROR_FULLSCREEN_MODE: DWORD = 1007; -pub const ERROR_NO_TOKEN: DWORD = 1008; -pub const ERROR_BADDB: DWORD = 1009; -pub const ERROR_BADKEY: DWORD = 1010; -pub const ERROR_CANTOPEN: DWORD = 1011; -pub const ERROR_CANTREAD: DWORD = 1012; -pub const ERROR_CANTWRITE: DWORD = 1013; -pub const ERROR_REGISTRY_RECOVERED: DWORD = 1014; -pub const ERROR_REGISTRY_CORRUPT: DWORD = 1015; -pub const ERROR_REGISTRY_IO_FAILED: DWORD = 1016; -pub const ERROR_NOT_REGISTRY_FILE: DWORD = 1017; -pub const ERROR_KEY_DELETED: DWORD = 1018; -pub const ERROR_NO_LOG_SPACE: DWORD = 1019; -pub const ERROR_KEY_HAS_CHILDREN: DWORD = 1020; -pub const ERROR_CHILD_MUST_BE_VOLATILE: DWORD = 1021; -pub const ERROR_NOTIFY_ENUM_DIR: DWORD = 1022; -pub const ERROR_DEPENDENT_SERVICES_RUNNING: DWORD = 1051; -pub const ERROR_INVALID_SERVICE_CONTROL: DWORD = 1052; -pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053; -pub const ERROR_SERVICE_NO_THREAD: DWORD = 1054; -pub const ERROR_SERVICE_DATABASE_LOCKED: DWORD = 1055; -pub const ERROR_SERVICE_ALREADY_RUNNING: DWORD = 1056; -pub const ERROR_INVALID_SERVICE_ACCOUNT: DWORD = 1057; -pub const ERROR_SERVICE_DISABLED: DWORD = 1058; -pub const ERROR_CIRCULAR_DEPENDENCY: DWORD = 1059; -pub const ERROR_SERVICE_DOES_NOT_EXIST: DWORD = 1060; -pub const ERROR_SERVICE_CANNOT_ACCEPT_CTRL: DWORD = 1061; -pub const ERROR_SERVICE_NOT_ACTIVE: DWORD = 1062; -pub const ERROR_FAILED_SERVICE_CONTROLLER_CONNECT: DWORD = 1063; -pub const ERROR_EXCEPTION_IN_SERVICE: DWORD = 1064; -pub const ERROR_DATABASE_DOES_NOT_EXIST: DWORD = 1065; -pub const ERROR_SERVICE_SPECIFIC_ERROR: DWORD = 1066; -pub const ERROR_PROCESS_ABORTED: DWORD = 1067; -pub const ERROR_SERVICE_DEPENDENCY_FAIL: DWORD = 1068; -pub const ERROR_SERVICE_LOGON_FAILED: DWORD = 1069; -pub const ERROR_SERVICE_START_HANG: DWORD = 1070; -pub const ERROR_INVALID_SERVICE_LOCK: DWORD = 1071; -pub const ERROR_SERVICE_MARKED_FOR_DELETE: DWORD = 1072; -pub const ERROR_SERVICE_EXISTS: DWORD = 1073; -pub const ERROR_ALREADY_RUNNING_LKG: DWORD = 1074; -pub const ERROR_SERVICE_DEPENDENCY_DELETED: DWORD = 1075; -pub const ERROR_BOOT_ALREADY_ACCEPTED: DWORD = 1076; -pub const ERROR_SERVICE_NEVER_STARTED: DWORD = 1077; -pub const ERROR_DUPLICATE_SERVICE_NAME: DWORD = 1078; -pub const ERROR_DIFFERENT_SERVICE_ACCOUNT: DWORD = 1079; -pub const ERROR_CANNOT_DETECT_DRIVER_FAILURE: DWORD = 1080; -pub const ERROR_CANNOT_DETECT_PROCESS_ABORT: DWORD = 1081; -pub const ERROR_NO_RECOVERY_PROGRAM: DWORD = 1082; -pub const ERROR_SERVICE_NOT_IN_EXE: DWORD = 1083; -pub const ERROR_NOT_SAFEBOOT_SERVICE: DWORD = 1084; -pub const ERROR_END_OF_MEDIA: DWORD = 1100; -pub const ERROR_FILEMARK_DETECTED: DWORD = 1101; -pub const ERROR_BEGINNING_OF_MEDIA: DWORD = 1102; -pub const ERROR_SETMARK_DETECTED: DWORD = 1103; -pub const ERROR_NO_DATA_DETECTED: DWORD = 1104; -pub const ERROR_PARTITION_FAILURE: DWORD = 1105; -pub const ERROR_INVALID_BLOCK_LENGTH: DWORD = 1106; -pub const ERROR_DEVICE_NOT_PARTITIONED: DWORD = 1107; -pub const ERROR_UNABLE_TO_LOCK_MEDIA: DWORD = 1108; -pub const ERROR_UNABLE_TO_UNLOAD_MEDIA: DWORD = 1109; -pub const ERROR_MEDIA_CHANGED: DWORD = 1110; -pub const ERROR_BUS_RESET: DWORD = 1111; -pub const ERROR_NO_MEDIA_IN_DRIVE: DWORD = 1112; -pub const ERROR_NO_UNICODE_TRANSLATION: DWORD = 1113; -pub const ERROR_DLL_INIT_FAILED: DWORD = 1114; -pub const ERROR_SHUTDOWN_IN_PROGRESS: DWORD = 1115; -pub const ERROR_NO_SHUTDOWN_IN_PROGRESS: DWORD = 1116; -pub const ERROR_IO_DEVICE: DWORD = 1117; -pub const ERROR_SERIAL_NO_DEVICE: DWORD = 1118; -pub const ERROR_IRQ_BUSY: DWORD = 1119; -pub const ERROR_MORE_WRITES: DWORD = 1120; -pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121; -pub const ERROR_FLOPPY_ID_MARK_NOT_FOUND: DWORD = 1122; -pub const ERROR_FLOPPY_WRONG_CYLINDER: DWORD = 1123; -pub const ERROR_FLOPPY_UNKNOWN_ERROR: DWORD = 1124; -pub const ERROR_FLOPPY_BAD_REGISTERS: DWORD = 1125; -pub const ERROR_DISK_RECALIBRATE_FAILED: DWORD = 1126; -pub const ERROR_DISK_OPERATION_FAILED: DWORD = 1127; -pub const ERROR_DISK_RESET_FAILED: DWORD = 1128; -pub const ERROR_EOM_OVERFLOW: DWORD = 1129; -pub const ERROR_NOT_ENOUGH_SERVER_MEMORY: DWORD = 1130; -pub const ERROR_POSSIBLE_DEADLOCK: DWORD = 1131; -pub const ERROR_MAPPED_ALIGNMENT: DWORD = 1132; -pub const ERROR_SET_POWER_STATE_VETOED: DWORD = 1140; -pub const ERROR_SET_POWER_STATE_FAILED: DWORD = 1141; -pub const ERROR_TOO_MANY_LINKS: DWORD = 1142; -pub const ERROR_OLD_WIN_VERSION: DWORD = 1150; -pub const ERROR_APP_WRONG_OS: DWORD = 1151; -pub const ERROR_SINGLE_INSTANCE_APP: DWORD = 1152; -pub const ERROR_RMODE_APP: DWORD = 1153; -pub const ERROR_INVALID_DLL: DWORD = 1154; -pub const ERROR_NO_ASSOCIATION: DWORD = 1155; -pub const ERROR_DDE_FAIL: DWORD = 1156; -pub const ERROR_DLL_NOT_FOUND: DWORD = 1157; -pub const ERROR_NO_MORE_USER_HANDLES: DWORD = 1158; -pub const ERROR_MESSAGE_SYNC_ONLY: DWORD = 1159; -pub const ERROR_SOURCE_ELEMENT_EMPTY: DWORD = 1160; -pub const ERROR_DESTINATION_ELEMENT_FULL: DWORD = 1161; -pub const ERROR_ILLEGAL_ELEMENT_ADDRESS: DWORD = 1162; -pub const ERROR_MAGAZINE_NOT_PRESENT: DWORD = 1163; -pub const ERROR_DEVICE_REINITIALIZATION_NEEDED: DWORD = 1164; -pub const ERROR_DEVICE_REQUIRES_CLEANING: DWORD = 1165; -pub const ERROR_DEVICE_DOOR_OPEN: DWORD = 1166; -pub const ERROR_DEVICE_NOT_CONNECTED: DWORD = 1167; -pub const ERROR_NOT_FOUND: DWORD = 1168; -pub const ERROR_NO_MATCH: DWORD = 1169; -pub const ERROR_SET_NOT_FOUND: DWORD = 1170; -pub const ERROR_POINT_NOT_FOUND: DWORD = 1171; -pub const ERROR_NO_TRACKING_SERVICE: DWORD = 1172; -pub const ERROR_NO_VOLUME_ID: DWORD = 1173; -pub const ERROR_UNABLE_TO_REMOVE_REPLACED: DWORD = 1175; -pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT: DWORD = 1176; -pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT_2: DWORD = 1177; -pub const ERROR_JOURNAL_DELETE_IN_PROGRESS: DWORD = 1178; -pub const ERROR_JOURNAL_NOT_ACTIVE: DWORD = 1179; -pub const ERROR_POTENTIAL_FILE_FOUND: DWORD = 1180; -pub const ERROR_JOURNAL_ENTRY_DELETED: DWORD = 1181; -pub const ERROR_BAD_DEVICE: DWORD = 1200; -pub const ERROR_CONNECTION_UNAVAIL: DWORD = 1201; -pub const ERROR_DEVICE_ALREADY_REMEMBERED: DWORD = 1202; -pub const ERROR_NO_NET_OR_BAD_PATH: DWORD = 1203; -pub const ERROR_BAD_PROVIDER: DWORD = 1204; -pub const ERROR_CANNOT_OPEN_PROFILE: DWORD = 1205; -pub const ERROR_BAD_PROFILE: DWORD = 1206; -pub const ERROR_NOT_CONTAINER: DWORD = 1207; -pub const ERROR_EXTENDED_ERROR: DWORD = 1208; -pub const ERROR_INVALID_GROUPNAME: DWORD = 1209; -pub const ERROR_INVALID_COMPUTERNAME: DWORD = 1210; -pub const ERROR_INVALID_EVENTNAME: DWORD = 1211; -pub const ERROR_INVALID_DOMAINNAME: DWORD = 1212; -pub const ERROR_INVALID_SERVICENAME: DWORD = 1213; -pub const ERROR_INVALID_NETNAME: DWORD = 1214; -pub const ERROR_INVALID_SHARENAME: DWORD = 1215; -pub const ERROR_INVALID_PASSWORDNAME: DWORD = 1216; -pub const ERROR_INVALID_MESSAGENAME: DWORD = 1217; -pub const ERROR_INVALID_MESSAGEDEST: DWORD = 1218; -pub const ERROR_SESSION_CREDENTIAL_CONFLICT: DWORD = 1219; -pub const ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: DWORD = 1220; -pub const ERROR_DUP_DOMAINNAME: DWORD = 1221; -pub const ERROR_NO_NETWORK: DWORD = 1222; -pub const ERROR_CANCELLED: DWORD = 1223; -pub const ERROR_USER_MAPPED_FILE: DWORD = 1224; -pub const ERROR_CONNECTION_REFUSED: DWORD = 1225; -pub const ERROR_GRACEFUL_DISCONNECT: DWORD = 1226; -pub const ERROR_ADDRESS_ALREADY_ASSOCIATED: DWORD = 1227; -pub const ERROR_ADDRESS_NOT_ASSOCIATED: DWORD = 1228; -pub const ERROR_CONNECTION_INVALID: DWORD = 1229; -pub const ERROR_CONNECTION_ACTIVE: DWORD = 1230; -pub const ERROR_NETWORK_UNREACHABLE: DWORD = 1231; -pub const ERROR_HOST_UNREACHABLE: DWORD = 1232; -pub const ERROR_PROTOCOL_UNREACHABLE: DWORD = 1233; -pub const ERROR_PORT_UNREACHABLE: DWORD = 1234; -pub const ERROR_REQUEST_ABORTED: DWORD = 1235; -pub const ERROR_CONNECTION_ABORTED: DWORD = 1236; -pub const ERROR_RETRY: DWORD = 1237; -pub const ERROR_CONNECTION_COUNT_LIMIT: DWORD = 1238; -pub const ERROR_LOGIN_TIME_RESTRICTION: DWORD = 1239; -pub const ERROR_LOGIN_WKSTA_RESTRICTION: DWORD = 1240; -pub const ERROR_INCORRECT_ADDRESS: DWORD = 1241; -pub const ERROR_ALREADY_REGISTERED: DWORD = 1242; -pub const ERROR_SERVICE_NOT_FOUND: DWORD = 1243; -pub const ERROR_NOT_AUTHENTICATED: DWORD = 1244; -pub const ERROR_NOT_LOGGED_ON: DWORD = 1245; -pub const ERROR_CONTINUE: DWORD = 1246; -pub const ERROR_ALREADY_INITIALIZED: DWORD = 1247; -pub const ERROR_NO_MORE_DEVICES: DWORD = 1248; -pub const ERROR_NO_SUCH_SITE: DWORD = 1249; -pub const ERROR_DOMAIN_CONTROLLER_EXISTS: DWORD = 1250; -pub const ERROR_ONLY_IF_CONNECTED: DWORD = 1251; -pub const ERROR_OVERRIDE_NOCHANGES: DWORD = 1252; -pub const ERROR_BAD_USER_PROFILE: DWORD = 1253; -pub const ERROR_NOT_SUPPORTED_ON_SBS: DWORD = 1254; -pub const ERROR_SERVER_SHUTDOWN_IN_PROGRESS: DWORD = 1255; -pub const ERROR_HOST_DOWN: DWORD = 1256; -pub const ERROR_NON_ACCOUNT_SID: DWORD = 1257; -pub const ERROR_NON_DOMAIN_SID: DWORD = 1258; -pub const ERROR_APPHELP_BLOCK: DWORD = 1259; -pub const ERROR_ACCESS_DISABLED_BY_POLICY: DWORD = 1260; -pub const ERROR_REG_NAT_CONSUMPTION: DWORD = 1261; -pub const ERROR_CSCSHARE_OFFLINE: DWORD = 1262; -pub const ERROR_PKINIT_FAILURE: DWORD = 1263; -pub const ERROR_SMARTCARD_SUBSYSTEM_FAILURE: DWORD = 1264; -pub const ERROR_DOWNGRADE_DETECTED: DWORD = 1265; -pub const ERROR_MACHINE_LOCKED: DWORD = 1271; -pub const ERROR_CALLBACK_SUPPLIED_INVALID_DATA: DWORD = 1273; -pub const ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED: DWORD = 1274; -pub const ERROR_DRIVER_BLOCKED: DWORD = 1275; -pub const ERROR_INVALID_IMPORT_OF_NON_DLL: DWORD = 1276; -pub const ERROR_ACCESS_DISABLED_WEBBLADE: DWORD = 1277; -pub const ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER: DWORD = 1278; -pub const ERROR_RECOVERY_FAILURE: DWORD = 1279; -pub const ERROR_ALREADY_FIBER: DWORD = 1280; -pub const ERROR_ALREADY_THREAD: DWORD = 1281; -pub const ERROR_STACK_BUFFER_OVERRUN: DWORD = 1282; -pub const ERROR_PARAMETER_QUOTA_EXCEEDED: DWORD = 1283; -pub const ERROR_DEBUGGER_INACTIVE: DWORD = 1284; -pub const ERROR_DELAY_LOAD_FAILED: DWORD = 1285; -pub const ERROR_VDM_DISALLOWED: DWORD = 1286; -pub const ERROR_UNIDENTIFIED_ERROR: DWORD = 1287; -pub const ERROR_NOT_ALL_ASSIGNED: DWORD = 1300; -pub const ERROR_SOME_NOT_MAPPED: DWORD = 1301; -pub const ERROR_NO_QUOTAS_FOR_ACCOUNT: DWORD = 1302; -pub const ERROR_LOCAL_USER_SESSION_KEY: DWORD = 1303; -pub const ERROR_NULL_LM_PASSWORD: DWORD = 1304; -pub const ERROR_UNKNOWN_REVISION: DWORD = 1305; -pub const ERROR_REVISION_MISMATCH: DWORD = 1306; -pub const ERROR_INVALID_OWNER: DWORD = 1307; -pub const ERROR_INVALID_PRIMARY_GROUP: DWORD = 1308; -pub const ERROR_NO_IMPERSONATION_TOKEN: DWORD = 1309; -pub const ERROR_CANT_DISABLE_MANDATORY: DWORD = 1310; -pub const ERROR_NO_LOGON_SERVERS: DWORD = 1311; -pub const ERROR_NO_SUCH_LOGON_SESSION: DWORD = 1312; -pub const ERROR_NO_SUCH_PRIVILEGE: DWORD = 1313; -pub const ERROR_PRIVILEGE_NOT_HELD: DWORD = 1314; -pub const ERROR_INVALID_ACCOUNT_NAME: DWORD = 1315; -pub const ERROR_USER_EXISTS: DWORD = 1316; -pub const ERROR_NO_SUCH_USER: DWORD = 1317; -pub const ERROR_GROUP_EXISTS: DWORD = 1318; -pub const ERROR_NO_SUCH_GROUP: DWORD = 1319; -pub const ERROR_MEMBER_IN_GROUP: DWORD = 1320; -pub const ERROR_MEMBER_NOT_IN_GROUP: DWORD = 1321; -pub const ERROR_LAST_ADMIN: DWORD = 1322; -pub const ERROR_WRONG_PASSWORD: DWORD = 1323; -pub const ERROR_ILL_FORMED_PASSWORD: DWORD = 1324; -pub const ERROR_PASSWORD_RESTRICTION: DWORD = 1325; -pub const ERROR_LOGON_FAILURE: DWORD = 1326; -pub const ERROR_ACCOUNT_RESTRICTION: DWORD = 1327; -pub const ERROR_INVALID_LOGON_HOURS: DWORD = 1328; -pub const ERROR_INVALID_WORKSTATION: DWORD = 1329; -pub const ERROR_PASSWORD_EXPIRED: DWORD = 1330; -pub const ERROR_ACCOUNT_DISABLED: DWORD = 1331; -pub const ERROR_NONE_MAPPED: DWORD = 1332; -pub const ERROR_TOO_MANY_LUIDS_REQUESTED: DWORD = 1333; -pub const ERROR_LUIDS_EXHAUSTED: DWORD = 1334; -pub const ERROR_INVALID_SUB_AUTHORITY: DWORD = 1335; -pub const ERROR_INVALID_ACL: DWORD = 1336; -pub const ERROR_INVALID_SID: DWORD = 1337; -pub const ERROR_INVALID_SECURITY_DESCR: DWORD = 1338; -pub const ERROR_BAD_INHERITANCE_ACL: DWORD = 1340; -pub const ERROR_SERVER_DISABLED: DWORD = 1341; -pub const ERROR_SERVER_NOT_DISABLED: DWORD = 1342; -pub const ERROR_INVALID_ID_AUTHORITY: DWORD = 1343; -pub const ERROR_ALLOTTED_SPACE_EXCEEDED: DWORD = 1344; -pub const ERROR_INVALID_GROUP_ATTRIBUTES: DWORD = 1345; -pub const ERROR_BAD_IMPERSONATION_LEVEL: DWORD = 1346; -pub const ERROR_CANT_OPEN_ANONYMOUS: DWORD = 1347; -pub const ERROR_BAD_VALIDATION_CLASS: DWORD = 1348; -pub const ERROR_BAD_TOKEN_TYPE: DWORD = 1349; -pub const ERROR_NO_SECURITY_ON_OBJECT: DWORD = 1350; -pub const ERROR_CANT_ACCESS_DOMAIN_INFO: DWORD = 1351; -pub const ERROR_INVALID_SERVER_STATE: DWORD = 1352; -pub const ERROR_INVALID_DOMAIN_STATE: DWORD = 1353; -pub const ERROR_INVALID_DOMAIN_ROLE: DWORD = 1354; -pub const ERROR_NO_SUCH_DOMAIN: DWORD = 1355; -pub const ERROR_DOMAIN_EXISTS: DWORD = 1356; -pub const ERROR_DOMAIN_LIMIT_EXCEEDED: DWORD = 1357; -pub const ERROR_INTERNAL_DB_CORRUPTION: DWORD = 1358; -pub const ERROR_INTERNAL_ERROR: DWORD = 1359; -pub const ERROR_GENERIC_NOT_MAPPED: DWORD = 1360; -pub const ERROR_BAD_DESCRIPTOR_FORMAT: DWORD = 1361; -pub const ERROR_NOT_LOGON_PROCESS: DWORD = 1362; -pub const ERROR_LOGON_SESSION_EXISTS: DWORD = 1363; -pub const ERROR_NO_SUCH_PACKAGE: DWORD = 1364; -pub const ERROR_BAD_LOGON_SESSION_STATE: DWORD = 1365; -pub const ERROR_LOGON_SESSION_COLLISION: DWORD = 1366; -pub const ERROR_INVALID_LOGON_TYPE: DWORD = 1367; -pub const ERROR_CANNOT_IMPERSONATE: DWORD = 1368; -pub const ERROR_RXACT_INVALID_STATE: DWORD = 1369; -pub const ERROR_RXACT_COMMIT_FAILURE: DWORD = 1370; -pub const ERROR_SPECIAL_ACCOUNT: DWORD = 1371; -pub const ERROR_SPECIAL_GROUP: DWORD = 1372; -pub const ERROR_SPECIAL_USER: DWORD = 1373; -pub const ERROR_MEMBERS_PRIMARY_GROUP: DWORD = 1374; -pub const ERROR_TOKEN_ALREADY_IN_USE: DWORD = 1375; -pub const ERROR_NO_SUCH_ALIAS: DWORD = 1376; -pub const ERROR_MEMBER_NOT_IN_ALIAS: DWORD = 1377; -pub const ERROR_MEMBER_IN_ALIAS: DWORD = 1378; -pub const ERROR_ALIAS_EXISTS: DWORD = 1379; -pub const ERROR_LOGON_NOT_GRANTED: DWORD = 1380; -pub const ERROR_TOO_MANY_SECRETS: DWORD = 1381; -pub const ERROR_SECRET_TOO_LONG: DWORD = 1382; -pub const ERROR_INTERNAL_DB_ERROR: DWORD = 1383; -pub const ERROR_TOO_MANY_CONTEXT_IDS: DWORD = 1384; -pub const ERROR_LOGON_TYPE_NOT_GRANTED: DWORD = 1385; -pub const ERROR_NT_CROSS_ENCRYPTION_REQUIRED: DWORD = 1386; -pub const ERROR_NO_SUCH_MEMBER: DWORD = 1387; -pub const ERROR_INVALID_MEMBER: DWORD = 1388; -pub const ERROR_TOO_MANY_SIDS: DWORD = 1389; -pub const ERROR_LM_CROSS_ENCRYPTION_REQUIRED: DWORD = 1390; -pub const ERROR_NO_INHERITANCE: DWORD = 1391; -pub const ERROR_FILE_CORRUPT: DWORD = 1392; -pub const ERROR_DISK_CORRUPT: DWORD = 1393; -pub const ERROR_NO_USER_SESSION_KEY: DWORD = 1394; -pub const ERROR_LICENSE_QUOTA_EXCEEDED: DWORD = 1395; -pub const ERROR_WRONG_TARGET_NAME: DWORD = 1396; -pub const ERROR_MUTUAL_AUTH_FAILED: DWORD = 1397; -pub const ERROR_TIME_SKEW: DWORD = 1398; -pub const ERROR_CURRENT_DOMAIN_NOT_ALLOWED: DWORD = 1399; -pub const ERROR_INVALID_WINDOW_HANDLE: DWORD = 1400; -pub const ERROR_INVALID_MENU_HANDLE: DWORD = 1401; -pub const ERROR_INVALID_CURSOR_HANDLE: DWORD = 1402; -pub const ERROR_INVALID_ACCEL_HANDLE: DWORD = 1403; -pub const ERROR_INVALID_HOOK_HANDLE: DWORD = 1404; -pub const ERROR_INVALID_DWP_HANDLE: DWORD = 1405; -pub const ERROR_TLW_WITH_WSCHILD: DWORD = 1406; -pub const ERROR_CANNOT_FIND_WND_CLASS: DWORD = 1407; -pub const ERROR_WINDOW_OF_OTHER_THREAD: DWORD = 1408; -pub const ERROR_HOTKEY_ALREADY_REGISTERED: DWORD = 1409; -pub const ERROR_CLASS_ALREADY_EXISTS: DWORD = 1410; -pub const ERROR_CLASS_DOES_NOT_EXIST: DWORD = 1411; -pub const ERROR_CLASS_HAS_WINDOWS: DWORD = 1412; -pub const ERROR_INVALID_INDEX: DWORD = 1413; -pub const ERROR_INVALID_ICON_HANDLE: DWORD = 1414; -pub const ERROR_PRIVATE_DIALOG_INDEX: DWORD = 1415; -pub const ERROR_LISTBOX_ID_NOT_FOUND: DWORD = 1416; -pub const ERROR_NO_WILDCARD_CHARACTERS: DWORD = 1417; -pub const ERROR_CLIPBOARD_NOT_OPEN: DWORD = 1418; -pub const ERROR_HOTKEY_NOT_REGISTERED: DWORD = 1419; -pub const ERROR_WINDOW_NOT_DIALOG: DWORD = 1420; -pub const ERROR_CONTROL_ID_NOT_FOUND: DWORD = 1421; -pub const ERROR_INVALID_COMBOBOX_MESSAGE: DWORD = 1422; -pub const ERROR_WINDOW_NOT_COMBOBOX: DWORD = 1423; -pub const ERROR_INVALID_EDIT_HEIGHT: DWORD = 1424; -pub const ERROR_DC_NOT_FOUND: DWORD = 1425; -pub const ERROR_INVALID_HOOK_FILTER: DWORD = 1426; -pub const ERROR_INVALID_FILTER_PROC: DWORD = 1427; -pub const ERROR_HOOK_NEEDS_HMOD: DWORD = 1428; -pub const ERROR_GLOBAL_ONLY_HOOK: DWORD = 1429; -pub const ERROR_JOURNAL_HOOK_SET: DWORD = 1430; -pub const ERROR_HOOK_NOT_INSTALLED: DWORD = 1431; -pub const ERROR_INVALID_LB_MESSAGE: DWORD = 1432; -pub const ERROR_SETCOUNT_ON_BAD_LB: DWORD = 1433; -pub const ERROR_LB_WITHOUT_TABSTOPS: DWORD = 1434; -pub const ERROR_DESTROY_OBJECT_OF_OTHER_THREAD: DWORD = 1435; -pub const ERROR_CHILD_WINDOW_MENU: DWORD = 1436; -pub const ERROR_NO_SYSTEM_MENU: DWORD = 1437; -pub const ERROR_INVALID_MSGBOX_STYLE: DWORD = 1438; -pub const ERROR_INVALID_SPI_VALUE: DWORD = 1439; -pub const ERROR_SCREEN_ALREADY_LOCKED: DWORD = 1440; -pub const ERROR_HWNDS_HAVE_DIFF_PARENT: DWORD = 1441; -pub const ERROR_NOT_CHILD_WINDOW: DWORD = 1442; -pub const ERROR_INVALID_GW_COMMAND: DWORD = 1443; -pub const ERROR_INVALID_THREAD_ID: DWORD = 1444; -pub const ERROR_NON_MDICHILD_WINDOW: DWORD = 1445; -pub const ERROR_POPUP_ALREADY_ACTIVE: DWORD = 1446; -pub const ERROR_NO_SCROLLBARS: DWORD = 1447; -pub const ERROR_INVALID_SCROLLBAR_RANGE: DWORD = 1448; -pub const ERROR_INVALID_SHOWWIN_COMMAND: DWORD = 1449; -pub const ERROR_NO_SYSTEM_RESOURCES: DWORD = 1450; -pub const ERROR_NONPAGED_SYSTEM_RESOURCES: DWORD = 1451; -pub const ERROR_PAGED_SYSTEM_RESOURCES: DWORD = 1452; -pub const ERROR_WORKING_SET_QUOTA: DWORD = 1453; -pub const ERROR_PAGEFILE_QUOTA: DWORD = 1454; -pub const ERROR_COMMITMENT_LIMIT: DWORD = 1455; -pub const ERROR_MENU_ITEM_NOT_FOUND: DWORD = 1456; -pub const ERROR_INVALID_KEYBOARD_HANDLE: DWORD = 1457; -pub const ERROR_HOOK_TYPE_NOT_ALLOWED: DWORD = 1458; -pub const ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION: DWORD = 1459; -pub const ERROR_TIMEOUT: DWORD = 1460; -pub const ERROR_INVALID_MONITOR_HANDLE: DWORD = 1461; -pub const ERROR_INCORRECT_SIZE: DWORD = 1462; -pub const ERROR_SYMLINK_CLASS_DISABLED: DWORD = 1463; -pub const ERROR_SYMLINK_NOT_SUPPORTED: DWORD = 1464; -pub const ERROR_XML_PARSE_ERROR: DWORD = 1465; -pub const ERROR_XMLDSIG_ERROR: DWORD = 1466; -pub const ERROR_RESTART_APPLICATION: DWORD = 1467; -pub const ERROR_WRONG_COMPARTMENT: DWORD = 1468; -pub const ERROR_AUTHIP_FAILURE: DWORD = 1469; -pub const ERROR_NO_NVRAM_RESOURCES: DWORD = 1470; -pub const ERROR_NOT_GUI_PROCESS: DWORD = 1471; -pub const ERROR_EVENTLOG_FILE_CORRUPT: DWORD = 1500; -pub const ERROR_EVENTLOG_CANT_START: DWORD = 1501; -pub const ERROR_LOG_FILE_FULL: DWORD = 1502; -pub const ERROR_EVENTLOG_FILE_CHANGED: DWORD = 1503; -pub const ERROR_INSTALL_SERVICE_FAILURE: DWORD = 1601; -pub const ERROR_INSTALL_USEREXIT: DWORD = 1602; -pub const ERROR_INSTALL_FAILURE: DWORD = 1603; -pub const ERROR_INSTALL_SUSPEND: DWORD = 1604; -pub const ERROR_UNKNOWN_PRODUCT: DWORD = 1605; -pub const ERROR_UNKNOWN_FEATURE: DWORD = 1606; -pub const ERROR_UNKNOWN_COMPONENT: DWORD = 1607; -pub const ERROR_UNKNOWN_PROPERTY: DWORD = 1608; -pub const ERROR_INVALID_HANDLE_STATE: DWORD = 1609; -pub const ERROR_BAD_CONFIGURATION: DWORD = 1610; -pub const ERROR_INDEX_ABSENT: DWORD = 1611; -pub const ERROR_INSTALL_SOURCE_ABSENT: DWORD = 1612; -pub const ERROR_INSTALL_PACKAGE_VERSION: DWORD = 1613; -pub const ERROR_PRODUCT_UNINSTALLED: DWORD = 1614; -pub const ERROR_BAD_QUERY_SYNTAX: DWORD = 1615; -pub const ERROR_INVALID_FIELD: DWORD = 1616; -pub const ERROR_DEVICE_REMOVED: DWORD = 1617; -pub const ERROR_INSTALL_ALREADY_RUNNING: DWORD = 1618; -pub const ERROR_INSTALL_PACKAGE_OPEN_FAILED: DWORD = 1619; -pub const ERROR_INSTALL_PACKAGE_INVALID: DWORD = 1620; -pub const ERROR_INSTALL_UI_FAILURE: DWORD = 1621; -pub const ERROR_INSTALL_LOG_FAILURE: DWORD = 1622; -pub const ERROR_INSTALL_LANGUAGE_UNSUPPORTED: DWORD = 1623; -pub const ERROR_INSTALL_TRANSFORM_FAILURE: DWORD = 1624; -pub const ERROR_INSTALL_PACKAGE_REJECTED: DWORD = 1625; -pub const ERROR_FUNCTION_NOT_CALLED: DWORD = 1626; -pub const ERROR_FUNCTION_FAILED: DWORD = 1627; -pub const ERROR_INVALID_TABLE: DWORD = 1628; -pub const ERROR_DATATYPE_MISMATCH: DWORD = 1629; -pub const ERROR_UNSUPPORTED_TYPE: DWORD = 1630; -pub const ERROR_CREATE_FAILED: DWORD = 1631; -pub const ERROR_INSTALL_TEMP_UNWRITABLE: DWORD = 1632; -pub const ERROR_INSTALL_PLATFORM_UNSUPPORTED: DWORD = 1633; -pub const ERROR_INSTALL_NOTUSED: DWORD = 1634; -pub const ERROR_PATCH_PACKAGE_OPEN_FAILED: DWORD = 1635; -pub const ERROR_PATCH_PACKAGE_INVALID: DWORD = 1636; -pub const ERROR_PATCH_PACKAGE_UNSUPPORTED: DWORD = 1637; -pub const ERROR_PRODUCT_VERSION: DWORD = 1638; -pub const ERROR_INVALID_COMMAND_LINE: DWORD = 1639; -pub const ERROR_INSTALL_REMOTE_DISALLOWED: DWORD = 1640; -pub const ERROR_SUCCESS_REBOOT_INITIATED: DWORD = 1641; -pub const ERROR_PATCH_TARGET_NOT_FOUND: DWORD = 1642; -pub const ERROR_PATCH_PACKAGE_REJECTED: DWORD = 1643; -pub const ERROR_INSTALL_TRANSFORM_REJECTED: DWORD = 1644; -pub const ERROR_INSTALL_REMOTE_PROHIBITED: DWORD = 1645; -pub const ERROR_INVALID_USER_BUFFER: DWORD = 1784; -pub const ERROR_UNRECOGNIZED_MEDIA: DWORD = 1785; -pub const ERROR_NO_TRUST_LSA_SECRET: DWORD = 1786; -pub const ERROR_NO_TRUST_SAM_ACCOUNT: DWORD = 1787; -pub const ERROR_TRUSTED_DOMAIN_FAILURE: DWORD = 1788; -pub const ERROR_TRUSTED_RELATIONSHIP_FAILURE: DWORD = 1789; -pub const ERROR_TRUST_FAILURE: DWORD = 1790; -pub const ERROR_NETLOGON_NOT_STARTED: DWORD = 1792; -pub const ERROR_ACCOUNT_EXPIRED: DWORD = 1793; -pub const ERROR_REDIRECTOR_HAS_OPEN_HANDLES: DWORD = 1794; -pub const ERROR_PRINTER_DRIVER_ALREADY_INSTALLED: DWORD = 1795; -pub const ERROR_UNKNOWN_PORT: DWORD = 1796; -pub const ERROR_UNKNOWN_PRINTER_DRIVER: DWORD = 1797; -pub const ERROR_UNKNOWN_PRINTPROCESSOR: DWORD = 1798; -pub const ERROR_INVALID_SEPARATOR_FILE: DWORD = 1799; -pub const ERROR_INVALID_PRIORITY: DWORD = 1800; -pub const ERROR_INVALID_PRINTER_NAME: DWORD = 1801; -pub const ERROR_PRINTER_ALREADY_EXISTS: DWORD = 1802; -pub const ERROR_INVALID_PRINTER_COMMAND: DWORD = 1803; -pub const ERROR_INVALID_DATATYPE: DWORD = 1804; -pub const ERROR_INVALID_ENVIRONMENT: DWORD = 1805; -pub const ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT: DWORD = 1807; -pub const ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT: DWORD = 1808; -pub const ERROR_NOLOGON_SERVER_TRUST_ACCOUNT: DWORD = 1809; -pub const ERROR_DOMAIN_TRUST_INCONSISTENT: DWORD = 1810; -pub const ERROR_SERVER_HAS_OPEN_HANDLES: DWORD = 1811; -pub const ERROR_RESOURCE_DATA_NOT_FOUND: DWORD = 1812; -pub const ERROR_RESOURCE_TYPE_NOT_FOUND: DWORD = 1813; -pub const ERROR_RESOURCE_NAME_NOT_FOUND: DWORD = 1814; -pub const ERROR_RESOURCE_LANG_NOT_FOUND: DWORD = 1815; -pub const ERROR_NOT_ENOUGH_QUOTA: DWORD = 1816; -pub const ERROR_INVALID_TIME: DWORD = 1901; -pub const ERROR_INVALID_FORM_NAME: DWORD = 1902; -pub const ERROR_INVALID_FORM_SIZE: DWORD = 1903; -pub const ERROR_ALREADY_WAITING: DWORD = 1904; -pub const ERROR_PRINTER_DELETED: DWORD = 1905; -pub const ERROR_INVALID_PRINTER_STATE: DWORD = 1906; -pub const ERROR_PASSWORD_MUST_CHANGE: DWORD = 1907; -pub const ERROR_DOMAIN_CONTROLLER_NOT_FOUND: DWORD = 1908; -pub const ERROR_ACCOUNT_LOCKED_OUT: DWORD = 1909; -pub const ERROR_NO_SITENAME: DWORD = 1919; -pub const ERROR_CANT_ACCESS_FILE: DWORD = 1920; -pub const ERROR_CANT_RESOLVE_FILENAME: DWORD = 1921; -pub const ERROR_KM_DRIVER_BLOCKED: DWORD = 1930; -pub const ERROR_CONTEXT_EXPIRED: DWORD = 1931; -pub const ERROR_PER_USER_TRUST_QUOTA_EXCEEDED: DWORD = 1932; -pub const ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED: DWORD = 1933; -pub const ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED: DWORD = 1934; -pub const ERROR_AUTHENTICATION_FIREWALL_FAILED: DWORD = 1935; -pub const ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED: DWORD = 1936; -pub const ERROR_INVALID_PIXEL_FORMAT: DWORD = 2000; -pub const ERROR_BAD_DRIVER: DWORD = 2001; -pub const ERROR_INVALID_WINDOW_STYLE: DWORD = 2002; -pub const ERROR_METAFILE_NOT_SUPPORTED: DWORD = 2003; -pub const ERROR_TRANSFORM_NOT_SUPPORTED: DWORD = 2004; -pub const ERROR_CLIPPING_NOT_SUPPORTED: DWORD = 2005; -pub const ERROR_INVALID_CMM: DWORD = 2010; -pub const ERROR_INVALID_PROFILE: DWORD = 2011; -pub const ERROR_TAG_NOT_FOUND: DWORD = 2012; -pub const ERROR_TAG_NOT_PRESENT: DWORD = 2013; -pub const ERROR_DUPLICATE_TAG: DWORD = 2014; -pub const ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE: DWORD = 2015; -pub const ERROR_PROFILE_NOT_FOUND: DWORD = 2016; -pub const ERROR_INVALID_COLORSPACE: DWORD = 2017; -pub const ERROR_ICM_NOT_ENABLED: DWORD = 2018; -pub const ERROR_DELETING_ICM_XFORM: DWORD = 2019; -pub const ERROR_INVALID_TRANSFORM: DWORD = 2020; -pub const ERROR_COLORSPACE_MISMATCH: DWORD = 2021; -pub const ERROR_INVALID_COLORINDEX: DWORD = 2022; -pub const ERROR_CONNECTED_OTHER_PASSWORD: DWORD = 2108; -pub const ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT: DWORD = 2109; -pub const ERROR_BAD_USERNAME: DWORD = 2202; -pub const ERROR_NOT_CONNECTED: DWORD = 2250; -pub const ERROR_OPEN_FILES: DWORD = 2401; -pub const ERROR_ACTIVE_CONNECTIONS: DWORD = 2402; -pub const ERROR_DEVICE_IN_USE: DWORD = 2404; -pub const ERROR_UNKNOWN_PRINT_MONITOR: DWORD = 3000; -pub const ERROR_PRINTER_DRIVER_IN_USE: DWORD = 3001; -pub const ERROR_SPOOL_FILE_NOT_FOUND: DWORD = 3002; -pub const ERROR_SPL_NO_STARTDOC: DWORD = 3003; -pub const ERROR_SPL_NO_ADDJOB: DWORD = 3004; -pub const ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED: DWORD = 3005; -pub const ERROR_PRINT_MONITOR_ALREADY_INSTALLED: DWORD = 3006; -pub const ERROR_INVALID_PRINT_MONITOR: DWORD = 3007; -pub const ERROR_PRINT_MONITOR_IN_USE: DWORD = 3008; -pub const ERROR_PRINTER_HAS_JOBS_QUEUED: DWORD = 3009; -pub const ERROR_SUCCESS_REBOOT_REQUIRED: DWORD = 3010; -pub const ERROR_SUCCESS_RESTART_REQUIRED: DWORD = 3011; -pub const ERROR_PRINTER_NOT_FOUND: DWORD = 3012; -pub const ERROR_PRINTER_DRIVER_WARNED: DWORD = 3013; -pub const ERROR_PRINTER_DRIVER_BLOCKED: DWORD = 3014; -pub const ERROR_WINS_INTERNAL: DWORD = 4000; -pub const ERROR_CAN_NOT_DEL_LOCAL_WINS: DWORD = 4001; -pub const ERROR_STATIC_INIT: DWORD = 4002; -pub const ERROR_INC_BACKUP: DWORD = 4003; -pub const ERROR_FULL_BACKUP: DWORD = 4004; -pub const ERROR_REC_NON_EXISTENT: DWORD = 4005; -pub const ERROR_RPL_NOT_ALLOWED: DWORD = 4006; -pub const ERROR_DHCP_ADDRESS_CONFLICT: DWORD = 4100; -pub const ERROR_WMI_GUID_NOT_FOUND: DWORD = 4200; -pub const ERROR_WMI_INSTANCE_NOT_FOUND: DWORD = 4201; -pub const ERROR_WMI_ITEMID_NOT_FOUND: DWORD = 4202; -pub const ERROR_WMI_TRY_AGAIN: DWORD = 4203; -pub const ERROR_WMI_DP_NOT_FOUND: DWORD = 4204; -pub const ERROR_WMI_UNRESOLVED_INSTANCE_REF: DWORD = 4205; -pub const ERROR_WMI_ALREADY_ENABLED: DWORD = 4206; -pub const ERROR_WMI_GUID_DISCONNECTED: DWORD = 4207; -pub const ERROR_WMI_SERVER_UNAVAILABLE: DWORD = 4208; -pub const ERROR_WMI_DP_FAILED: DWORD = 4209; -pub const ERROR_WMI_INVALID_MOF: DWORD = 4210; -pub const ERROR_WMI_INVALID_REGINFO: DWORD = 4211; -pub const ERROR_WMI_ALREADY_DISABLED: DWORD = 4212; -pub const ERROR_WMI_READ_ONLY: DWORD = 4213; -pub const ERROR_WMI_SET_FAILURE: DWORD = 4214; -pub const ERROR_INVALID_MEDIA: DWORD = 4300; -pub const ERROR_INVALID_LIBRARY: DWORD = 4301; -pub const ERROR_INVALID_MEDIA_POOL: DWORD = 4302; -pub const ERROR_DRIVE_MEDIA_MISMATCH: DWORD = 4303; -pub const ERROR_MEDIA_OFFLINE: DWORD = 4304; -pub const ERROR_LIBRARY_OFFLINE: DWORD = 4305; -pub const ERROR_EMPTY: DWORD = 4306; -pub const ERROR_NOT_EMPTY: DWORD = 4307; -pub const ERROR_MEDIA_UNAVAILABLE: DWORD = 4308; -pub const ERROR_RESOURCE_DISABLED: DWORD = 4309; -pub const ERROR_INVALID_CLEANER: DWORD = 4310; -pub const ERROR_UNABLE_TO_CLEAN: DWORD = 4311; -pub const ERROR_OBJECT_NOT_FOUND: DWORD = 4312; -pub const ERROR_DATABASE_FAILURE: DWORD = 4313; -pub const ERROR_DATABASE_FULL: DWORD = 4314; -pub const ERROR_MEDIA_INCOMPATIBLE: DWORD = 4315; -pub const ERROR_RESOURCE_NOT_PRESENT: DWORD = 4316; -pub const ERROR_INVALID_OPERATION: DWORD = 4317; -pub const ERROR_MEDIA_NOT_AVAILABLE: DWORD = 4318; -pub const ERROR_DEVICE_NOT_AVAILABLE: DWORD = 4319; -pub const ERROR_REQUEST_REFUSED: DWORD = 4320; -pub const ERROR_INVALID_DRIVE_OBJECT: DWORD = 4321; -pub const ERROR_LIBRARY_FULL: DWORD = 4322; -pub const ERROR_MEDIUM_NOT_ACCESSIBLE: DWORD = 4323; -pub const ERROR_UNABLE_TO_LOAD_MEDIUM: DWORD = 4324; -pub const ERROR_UNABLE_TO_INVENTORY_DRIVE: DWORD = 4325; -pub const ERROR_UNABLE_TO_INVENTORY_SLOT: DWORD = 4326; -pub const ERROR_UNABLE_TO_INVENTORY_TRANSPORT: DWORD = 4327; -pub const ERROR_TRANSPORT_FULL: DWORD = 4328; -pub const ERROR_CONTROLLING_IEPORT: DWORD = 4329; -pub const ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA: DWORD = 4330; -pub const ERROR_CLEANER_SLOT_SET: DWORD = 4331; -pub const ERROR_CLEANER_SLOT_NOT_SET: DWORD = 4332; -pub const ERROR_CLEANER_CARTRIDGE_SPENT: DWORD = 4333; -pub const ERROR_UNEXPECTED_OMID: DWORD = 4334; -pub const ERROR_CANT_DELETE_LAST_ITEM: DWORD = 4335; -pub const ERROR_MESSAGE_EXCEEDS_MAX_SIZE: DWORD = 4336; -pub const ERROR_VOLUME_CONTAINS_SYS_FILES: DWORD = 4337; -pub const ERROR_INDIGENOUS_TYPE: DWORD = 4338; -pub const ERROR_NO_SUPPORTING_DRIVES: DWORD = 4339; -pub const ERROR_CLEANER_CARTRIDGE_INSTALLED: DWORD = 4340; -pub const ERROR_IEPORT_FULL: DWORD = 4341; -pub const ERROR_FILE_OFFLINE: DWORD = 4350; -pub const ERROR_REMOTE_STORAGE_NOT_ACTIVE: DWORD = 4351; -pub const ERROR_REMOTE_STORAGE_MEDIA_ERROR: DWORD = 4352; -pub const ERROR_NOT_A_REPARSE_POINT: DWORD = 4390; -pub const ERROR_REPARSE_ATTRIBUTE_CONFLICT: DWORD = 4391; -pub const ERROR_INVALID_REPARSE_DATA: DWORD = 4392; -pub const ERROR_REPARSE_TAG_INVALID: DWORD = 4393; -pub const ERROR_REPARSE_TAG_MISMATCH: DWORD = 4394; -pub const ERROR_VOLUME_NOT_SIS_ENABLED: DWORD = 4500; -pub const ERROR_DEPENDENT_RESOURCE_EXISTS: DWORD = 5001; -pub const ERROR_DEPENDENCY_NOT_FOUND: DWORD = 5002; -pub const ERROR_DEPENDENCY_ALREADY_EXISTS: DWORD = 5003; -pub const ERROR_RESOURCE_NOT_ONLINE: DWORD = 5004; -pub const ERROR_HOST_NODE_NOT_AVAILABLE: DWORD = 5005; -pub const ERROR_RESOURCE_NOT_AVAILABLE: DWORD = 5006; -pub const ERROR_RESOURCE_NOT_FOUND: DWORD = 5007; -pub const ERROR_SHUTDOWN_CLUSTER: DWORD = 5008; -pub const ERROR_CANT_EVICT_ACTIVE_NODE: DWORD = 5009; -pub const ERROR_OBJECT_ALREADY_EXISTS: DWORD = 5010; -pub const ERROR_OBJECT_IN_LIST: DWORD = 5011; -pub const ERROR_GROUP_NOT_AVAILABLE: DWORD = 5012; -pub const ERROR_GROUP_NOT_FOUND: DWORD = 5013; -pub const ERROR_GROUP_NOT_ONLINE: DWORD = 5014; -pub const ERROR_HOST_NODE_NOT_RESOURCE_OWNER: DWORD = 5015; -pub const ERROR_HOST_NODE_NOT_GROUP_OWNER: DWORD = 5016; -pub const ERROR_RESMON_CREATE_FAILED: DWORD = 5017; -pub const ERROR_RESMON_ONLINE_FAILED: DWORD = 5018; -pub const ERROR_RESOURCE_ONLINE: DWORD = 5019; -pub const ERROR_QUORUM_RESOURCE: DWORD = 5020; -pub const ERROR_NOT_QUORUM_CAPABLE: DWORD = 5021; -pub const ERROR_CLUSTER_SHUTTING_DOWN: DWORD = 5022; -pub const ERROR_INVALID_STATE: DWORD = 5023; -pub const ERROR_RESOURCE_PROPERTIES_STORED: DWORD = 5024; -pub const ERROR_NOT_QUORUM_CLASS: DWORD = 5025; -pub const ERROR_CORE_RESOURCE: DWORD = 5026; -pub const ERROR_QUORUM_RESOURCE_ONLINE_FAILED: DWORD = 5027; -pub const ERROR_QUORUMLOG_OPEN_FAILED: DWORD = 5028; -pub const ERROR_CLUSTERLOG_CORRUPT: DWORD = 5029; -pub const ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE: DWORD = 5030; -pub const ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE: DWORD = 5031; -pub const ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND: DWORD = 5032; -pub const ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE: DWORD = 5033; -pub const ERROR_QUORUM_OWNER_ALIVE: DWORD = 5034; -pub const ERROR_NETWORK_NOT_AVAILABLE: DWORD = 5035; -pub const ERROR_NODE_NOT_AVAILABLE: DWORD = 5036; -pub const ERROR_ALL_NODES_NOT_AVAILABLE: DWORD = 5037; -pub const ERROR_RESOURCE_FAILED: DWORD = 5038; -pub const ERROR_CLUSTER_INVALID_NODE: DWORD = 5039; -pub const ERROR_CLUSTER_NODE_EXISTS: DWORD = 5040; -pub const ERROR_CLUSTER_JOIN_IN_PROGRESS: DWORD = 5041; -pub const ERROR_CLUSTER_NODE_NOT_FOUND: DWORD = 5042; -pub const ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND: DWORD = 5043; -pub const ERROR_CLUSTER_NETWORK_EXISTS: DWORD = 5044; -pub const ERROR_CLUSTER_NETWORK_NOT_FOUND: DWORD = 5045; -pub const ERROR_CLUSTER_NETINTERFACE_EXISTS: DWORD = 5046; -pub const ERROR_CLUSTER_NETINTERFACE_NOT_FOUND: DWORD = 5047; -pub const ERROR_CLUSTER_INVALID_REQUEST: DWORD = 5048; -pub const ERROR_CLUSTER_INVALID_NETWORK_PROVIDER: DWORD = 5049; -pub const ERROR_CLUSTER_NODE_DOWN: DWORD = 5050; -pub const ERROR_CLUSTER_NODE_UNREACHABLE: DWORD = 5051; -pub const ERROR_CLUSTER_NODE_NOT_MEMBER: DWORD = 5052; -pub const ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS: DWORD = 5053; -pub const ERROR_CLUSTER_INVALID_NETWORK: DWORD = 5054; -pub const ERROR_CLUSTER_NODE_UP: DWORD = 5056; -pub const ERROR_CLUSTER_IPADDR_IN_USE: DWORD = 5057; -pub const ERROR_CLUSTER_NODE_NOT_PAUSED: DWORD = 5058; -pub const ERROR_CLUSTER_NO_SECURITY_CONTEXT: DWORD = 5059; -pub const ERROR_CLUSTER_NETWORK_NOT_INTERNAL: DWORD = 5060; -pub const ERROR_CLUSTER_NODE_ALREADY_UP: DWORD = 5061; -pub const ERROR_CLUSTER_NODE_ALREADY_DOWN: DWORD = 5062; -pub const ERROR_CLUSTER_NETWORK_ALREADY_ONLINE: DWORD = 5063; -pub const ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE: DWORD = 5064; -pub const ERROR_CLUSTER_NODE_ALREADY_MEMBER: DWORD = 5065; -pub const ERROR_CLUSTER_LAST_INTERNAL_NETWORK: DWORD = 5066; -pub const ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS: DWORD = 5067; -pub const ERROR_INVALID_OPERATION_ON_QUORUM: DWORD = 5068; -pub const ERROR_DEPENDENCY_NOT_ALLOWED: DWORD = 5069; -pub const ERROR_CLUSTER_NODE_PAUSED: DWORD = 5070; -pub const ERROR_NODE_CANT_HOST_RESOURCE: DWORD = 5071; -pub const ERROR_CLUSTER_NODE_NOT_READY: DWORD = 5072; -pub const ERROR_CLUSTER_NODE_SHUTTING_DOWN: DWORD = 5073; -pub const ERROR_CLUSTER_JOIN_ABORTED: DWORD = 5074; -pub const ERROR_CLUSTER_INCOMPATIBLE_VERSIONS: DWORD = 5075; -pub const ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED: DWORD = 5076; -pub const ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED: DWORD = 5077; -pub const ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND: DWORD = 5078; -pub const ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED: DWORD = 5079; -pub const ERROR_CLUSTER_RESNAME_NOT_FOUND: DWORD = 5080; -pub const ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED: DWORD = 5081; -pub const ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST: DWORD = 5082; -pub const ERROR_CLUSTER_DATABASE_SEQMISMATCH: DWORD = 5083; -pub const ERROR_RESMON_INVALID_STATE: DWORD = 5084; -pub const ERROR_CLUSTER_GUM_NOT_LOCKER: DWORD = 5085; -pub const ERROR_QUORUM_DISK_NOT_FOUND: DWORD = 5086; -pub const ERROR_DATABASE_BACKUP_CORRUPT: DWORD = 5087; -pub const ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT: DWORD = 5088; -pub const ERROR_RESOURCE_PROPERTY_UNCHANGEABLE: DWORD = 5089; -pub const ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE: DWORD = 5890; -pub const ERROR_CLUSTER_QUORUMLOG_NOT_FOUND: DWORD = 5891; -pub const ERROR_CLUSTER_MEMBERSHIP_HALT: DWORD = 5892; -pub const ERROR_CLUSTER_INSTANCE_ID_MISMATCH: DWORD = 5893; -pub const ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP: DWORD = 5894; -pub const ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH: DWORD = 5895; -pub const ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP: DWORD = 5896; -pub const ERROR_CLUSTER_PARAMETER_MISMATCH: DWORD = 5897; -pub const ERROR_NODE_CANNOT_BE_CLUSTERED: DWORD = 5898; -pub const ERROR_CLUSTER_WRONG_OS_VERSION: DWORD = 5899; -pub const ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME: DWORD = 5900; -pub const ERROR_CLUSCFG_ALREADY_COMMITTED: DWORD = 5901; -pub const ERROR_CLUSCFG_ROLLBACK_FAILED: DWORD = 5902; -pub const ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT: DWORD = 5903; -pub const ERROR_CLUSTER_OLD_VERSION: DWORD = 5904; -pub const ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME: DWORD = 5905; -pub const ERROR_ENCRYPTION_FAILED: DWORD = 6000; -pub const ERROR_DECRYPTION_FAILED: DWORD = 6001; -pub const ERROR_FILE_ENCRYPTED: DWORD = 6002; -pub const ERROR_NO_RECOVERY_POLICY: DWORD = 6003; -pub const ERROR_NO_EFS: DWORD = 6004; -pub const ERROR_WRONG_EFS: DWORD = 6005; -pub const ERROR_NO_USER_KEYS: DWORD = 6006; -pub const ERROR_FILE_NOT_ENCRYPTED: DWORD = 6007; -pub const ERROR_NOT_EXPORT_FORMAT: DWORD = 6008; -pub const ERROR_FILE_READ_ONLY: DWORD = 6009; -pub const ERROR_DIR_EFS_DISALLOWED: DWORD = 6010; -pub const ERROR_EFS_SERVER_NOT_TRUSTED: DWORD = 6011; -pub const ERROR_BAD_RECOVERY_POLICY: DWORD = 6012; -pub const ERROR_EFS_ALG_BLOB_TOO_BIG: DWORD = 6013; -pub const ERROR_VOLUME_NOT_SUPPORT_EFS: DWORD = 6014; -pub const ERROR_EFS_DISABLED: DWORD = 6015; -pub const ERROR_EFS_VERSION_NOT_SUPPORT: DWORD = 6016; -pub const ERROR_NO_BROWSER_SERVERS_FOUND: DWORD = 6118; -pub const ERROR_CTX_WINSTATION_NAME_INVALID: DWORD = 7001; -pub const ERROR_CTX_INVALID_PD: DWORD = 7002; -pub const ERROR_CTX_PD_NOT_FOUND: DWORD = 7003; -pub const ERROR_CTX_WD_NOT_FOUND: DWORD = 7004; -pub const ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY: DWORD = 7005; -pub const ERROR_CTX_SERVICE_NAME_COLLISION: DWORD = 7006; -pub const ERROR_CTX_CLOSE_PENDING: DWORD = 7007; -pub const ERROR_CTX_NO_OUTBUF: DWORD = 7008; -pub const ERROR_CTX_MODEM_INF_NOT_FOUND: DWORD = 7009; -pub const ERROR_CTX_INVALID_MODEMNAME: DWORD = 7010; -pub const ERROR_CTX_MODEM_RESPONSE_ERROR: DWORD = 7011; -pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012; -pub const ERROR_CTX_MODEM_RESPONSE_NO_CARRIER: DWORD = 7013; -pub const ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE: DWORD = 7014; -pub const ERROR_CTX_MODEM_RESPONSE_BUSY: DWORD = 7015; -pub const ERROR_CTX_MODEM_RESPONSE_VOICE: DWORD = 7016; -pub const ERROR_CTX_TD_ERROR: DWORD = 7017; -pub const ERROR_CTX_WINSTATION_NOT_FOUND: DWORD = 7022; -pub const ERROR_CTX_WINSTATION_ALREADY_EXISTS: DWORD = 7023; -pub const ERROR_CTX_WINSTATION_BUSY: DWORD = 7024; -pub const ERROR_CTX_BAD_VIDEO_MODE: DWORD = 7025; -pub const ERROR_CTX_GRAPHICS_INVALID: DWORD = 7035; -pub const ERROR_CTX_LOGON_DISABLED: DWORD = 7037; -pub const ERROR_CTX_NOT_CONSOLE: DWORD = 7038; -pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040; -pub const ERROR_CTX_CONSOLE_DISCONNECT: DWORD = 7041; -pub const ERROR_CTX_CONSOLE_CONNECT: DWORD = 7042; -pub const ERROR_CTX_SHADOW_DENIED: DWORD = 7044; -pub const ERROR_CTX_WINSTATION_ACCESS_DENIED: DWORD = 7045; -pub const ERROR_CTX_INVALID_WD: DWORD = 7049; -pub const ERROR_CTX_SHADOW_INVALID: DWORD = 7050; -pub const ERROR_CTX_SHADOW_DISABLED: DWORD = 7051; -pub const ERROR_CTX_CLIENT_LICENSE_IN_USE: DWORD = 7052; -pub const ERROR_CTX_CLIENT_LICENSE_NOT_SET: DWORD = 7053; -pub const ERROR_CTX_LICENSE_NOT_AVAILABLE: DWORD = 7054; -pub const ERROR_CTX_LICENSE_CLIENT_INVALID: DWORD = 7055; -pub const ERROR_CTX_LICENSE_EXPIRED: DWORD = 7056; -pub const ERROR_CTX_SHADOW_NOT_RUNNING: DWORD = 7057; -pub const ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE: DWORD = 7058; -pub const ERROR_ACTIVATION_COUNT_EXCEEDED: DWORD = 7059; -pub const ERROR_DS_NOT_INSTALLED: DWORD = 8200; -pub const ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY: DWORD = 8201; -pub const ERROR_DS_NO_ATTRIBUTE_OR_VALUE: DWORD = 8202; -pub const ERROR_DS_INVALID_ATTRIBUTE_SYNTAX: DWORD = 8203; -pub const ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED: DWORD = 8204; -pub const ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS: DWORD = 8205; -pub const ERROR_DS_BUSY: DWORD = 8206; -pub const ERROR_DS_UNAVAILABLE: DWORD = 8207; -pub const ERROR_DS_NO_RIDS_ALLOCATED: DWORD = 8208; -pub const ERROR_DS_NO_MORE_RIDS: DWORD = 8209; -pub const ERROR_DS_INCORRECT_ROLE_OWNER: DWORD = 8210; -pub const ERROR_DS_RIDMGR_INIT_ERROR: DWORD = 8211; -pub const ERROR_DS_OBJ_CLASS_VIOLATION: DWORD = 8212; -pub const ERROR_DS_CANT_ON_NON_LEAF: DWORD = 8213; -pub const ERROR_DS_CANT_ON_RDN: DWORD = 8214; -pub const ERROR_DS_CANT_MOD_OBJ_CLASS: DWORD = 8215; -pub const ERROR_DS_CROSS_DOM_MOVE_ERROR: DWORD = 8216; -pub const ERROR_DS_GC_NOT_AVAILABLE: DWORD = 8217; -pub const ERROR_SHARED_POLICY: DWORD = 8218; -pub const ERROR_POLICY_OBJECT_NOT_FOUND: DWORD = 8219; -pub const ERROR_POLICY_ONLY_IN_DS: DWORD = 8220; -pub const ERROR_PROMOTION_ACTIVE: DWORD = 8221; -pub const ERROR_NO_PROMOTION_ACTIVE: DWORD = 8222; -pub const ERROR_DS_OPERATIONS_ERROR: DWORD = 8224; -pub const ERROR_DS_PROTOCOL_ERROR: DWORD = 8225; -pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226; -pub const ERROR_DS_SIZELIMIT_EXCEEDED: DWORD = 8227; -pub const ERROR_DS_ADMIN_LIMIT_EXCEEDED: DWORD = 8228; -pub const ERROR_DS_COMPARE_FALSE: DWORD = 8229; -pub const ERROR_DS_COMPARE_TRUE: DWORD = 8230; -pub const ERROR_DS_AUTH_METHOD_NOT_SUPPORTED: DWORD = 8231; -pub const ERROR_DS_STRONG_AUTH_REQUIRED: DWORD = 8232; -pub const ERROR_DS_INAPPROPRIATE_AUTH: DWORD = 8233; -pub const ERROR_DS_AUTH_UNKNOWN: DWORD = 8234; -pub const ERROR_DS_REFERRAL: DWORD = 8235; -pub const ERROR_DS_UNAVAILABLE_CRIT_EXTENSION: DWORD = 8236; -pub const ERROR_DS_CONFIDENTIALITY_REQUIRED: DWORD = 8237; -pub const ERROR_DS_INAPPROPRIATE_MATCHING: DWORD = 8238; -pub const ERROR_DS_CONSTRAINT_VIOLATION: DWORD = 8239; -pub const ERROR_DS_NO_SUCH_OBJECT: DWORD = 8240; -pub const ERROR_DS_ALIAS_PROBLEM: DWORD = 8241; -pub const ERROR_DS_INVALID_DN_SYNTAX: DWORD = 8242; -pub const ERROR_DS_IS_LEAF: DWORD = 8243; -pub const ERROR_DS_ALIAS_DEREF_PROBLEM: DWORD = 8244; -pub const ERROR_DS_UNWILLING_TO_PERFORM: DWORD = 8245; -pub const ERROR_DS_LOOP_DETECT: DWORD = 8246; -pub const ERROR_DS_NAMING_VIOLATION: DWORD = 8247; -pub const ERROR_DS_OBJECT_RESULTS_TOO_LARGE: DWORD = 8248; -pub const ERROR_DS_AFFECTS_MULTIPLE_DSAS: DWORD = 8249; -pub const ERROR_DS_SERVER_DOWN: DWORD = 8250; -pub const ERROR_DS_LOCAL_ERROR: DWORD = 8251; -pub const ERROR_DS_ENCODING_ERROR: DWORD = 8252; -pub const ERROR_DS_DECODING_ERROR: DWORD = 8253; -pub const ERROR_DS_FILTER_UNKNOWN: DWORD = 8254; -pub const ERROR_DS_PARAM_ERROR: DWORD = 8255; -pub const ERROR_DS_NOT_SUPPORTED: DWORD = 8256; -pub const ERROR_DS_NO_RESULTS_RETURNED: DWORD = 8257; -pub const ERROR_DS_CONTROL_NOT_FOUND: DWORD = 8258; -pub const ERROR_DS_CLIENT_LOOP: DWORD = 8259; -pub const ERROR_DS_REFERRAL_LIMIT_EXCEEDED: DWORD = 8260; -pub const ERROR_DS_SORT_CONTROL_MISSING: DWORD = 8261; -pub const ERROR_DS_OFFSET_RANGE_ERROR: DWORD = 8262; -pub const ERROR_DS_ROOT_MUST_BE_NC: DWORD = 8301; -pub const ERROR_DS_ADD_REPLICA_INHIBITED: DWORD = 8302; -pub const ERROR_DS_ATT_NOT_DEF_IN_SCHEMA: DWORD = 8303; -pub const ERROR_DS_MAX_OBJ_SIZE_EXCEEDED: DWORD = 8304; -pub const ERROR_DS_OBJ_STRING_NAME_EXISTS: DWORD = 8305; -pub const ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA: DWORD = 8306; -pub const ERROR_DS_RDN_DOESNT_MATCH_SCHEMA: DWORD = 8307; -pub const ERROR_DS_NO_REQUESTED_ATTS_FOUND: DWORD = 8308; -pub const ERROR_DS_USER_BUFFER_TO_SMALL: DWORD = 8309; -pub const ERROR_DS_ATT_IS_NOT_ON_OBJ: DWORD = 8310; -pub const ERROR_DS_ILLEGAL_MOD_OPERATION: DWORD = 8311; -pub const ERROR_DS_OBJ_TOO_LARGE: DWORD = 8312; -pub const ERROR_DS_BAD_INSTANCE_TYPE: DWORD = 8313; -pub const ERROR_DS_MASTERDSA_REQUIRED: DWORD = 8314; -pub const ERROR_DS_OBJECT_CLASS_REQUIRED: DWORD = 8315; -pub const ERROR_DS_MISSING_REQUIRED_ATT: DWORD = 8316; -pub const ERROR_DS_ATT_NOT_DEF_FOR_CLASS: DWORD = 8317; -pub const ERROR_DS_ATT_ALREADY_EXISTS: DWORD = 8318; -pub const ERROR_DS_CANT_ADD_ATT_VALUES: DWORD = 8320; -pub const ERROR_DS_SINGLE_VALUE_CONSTRAINT: DWORD = 8321; -pub const ERROR_DS_RANGE_CONSTRAINT: DWORD = 8322; -pub const ERROR_DS_ATT_VAL_ALREADY_EXISTS: DWORD = 8323; -pub const ERROR_DS_CANT_REM_MISSING_ATT: DWORD = 8324; -pub const ERROR_DS_CANT_REM_MISSING_ATT_VAL: DWORD = 8325; -pub const ERROR_DS_ROOT_CANT_BE_SUBREF: DWORD = 8326; -pub const ERROR_DS_NO_CHAINING: DWORD = 8327; -pub const ERROR_DS_NO_CHAINED_EVAL: DWORD = 8328; -pub const ERROR_DS_NO_PARENT_OBJECT: DWORD = 8329; -pub const ERROR_DS_PARENT_IS_AN_ALIAS: DWORD = 8330; -pub const ERROR_DS_CANT_MIX_MASTER_AND_REPS: DWORD = 8331; -pub const ERROR_DS_CHILDREN_EXIST: DWORD = 8332; -pub const ERROR_DS_OBJ_NOT_FOUND: DWORD = 8333; -pub const ERROR_DS_ALIASED_OBJ_MISSING: DWORD = 8334; -pub const ERROR_DS_BAD_NAME_SYNTAX: DWORD = 8335; -pub const ERROR_DS_ALIAS_POINTS_TO_ALIAS: DWORD = 8336; -pub const ERROR_DS_CANT_DEREF_ALIAS: DWORD = 8337; -pub const ERROR_DS_OUT_OF_SCOPE: DWORD = 8338; -pub const ERROR_DS_OBJECT_BEING_REMOVED: DWORD = 8339; -pub const ERROR_DS_CANT_DELETE_DSA_OBJ: DWORD = 8340; -pub const ERROR_DS_GENERIC_ERROR: DWORD = 8341; -pub const ERROR_DS_DSA_MUST_BE_INT_MASTER: DWORD = 8342; -pub const ERROR_DS_CLASS_NOT_DSA: DWORD = 8343; -pub const ERROR_DS_INSUFF_ACCESS_RIGHTS: DWORD = 8344; -pub const ERROR_DS_ILLEGAL_SUPERIOR: DWORD = 8345; -pub const ERROR_DS_ATTRIBUTE_OWNED_BY_SAM: DWORD = 8346; -pub const ERROR_DS_NAME_TOO_MANY_PARTS: DWORD = 8347; -pub const ERROR_DS_NAME_TOO_LONG: DWORD = 8348; -pub const ERROR_DS_NAME_VALUE_TOO_LONG: DWORD = 8349; -pub const ERROR_DS_NAME_UNPARSEABLE: DWORD = 8350; -pub const ERROR_DS_NAME_TYPE_UNKNOWN: DWORD = 8351; -pub const ERROR_DS_NOT_AN_OBJECT: DWORD = 8352; -pub const ERROR_DS_SEC_DESC_TOO_SHORT: DWORD = 8353; -pub const ERROR_DS_SEC_DESC_INVALID: DWORD = 8354; -pub const ERROR_DS_NO_DELETED_NAME: DWORD = 8355; -pub const ERROR_DS_SUBREF_MUST_HAVE_PARENT: DWORD = 8356; -pub const ERROR_DS_NCNAME_MUST_BE_NC: DWORD = 8357; -pub const ERROR_DS_CANT_ADD_SYSTEM_ONLY: DWORD = 8358; -pub const ERROR_DS_CLASS_MUST_BE_CONCRETE: DWORD = 8359; -pub const ERROR_DS_INVALID_DMD: DWORD = 8360; -pub const ERROR_DS_OBJ_GUID_EXISTS: DWORD = 8361; -pub const ERROR_DS_NOT_ON_BACKLINK: DWORD = 8362; -pub const ERROR_DS_NO_CROSSREF_FOR_NC: DWORD = 8363; -pub const ERROR_DS_SHUTTING_DOWN: DWORD = 8364; -pub const ERROR_DS_UNKNOWN_OPERATION: DWORD = 8365; -pub const ERROR_DS_INVALID_ROLE_OWNER: DWORD = 8366; -pub const ERROR_DS_COULDNT_CONTACT_FSMO: DWORD = 8367; -pub const ERROR_DS_CROSS_NC_DN_RENAME: DWORD = 8368; -pub const ERROR_DS_CANT_MOD_SYSTEM_ONLY: DWORD = 8369; -pub const ERROR_DS_REPLICATOR_ONLY: DWORD = 8370; -pub const ERROR_DS_OBJ_CLASS_NOT_DEFINED: DWORD = 8371; -pub const ERROR_DS_OBJ_CLASS_NOT_SUBCLASS: DWORD = 8372; -pub const ERROR_DS_NAME_REFERENCE_INVALID: DWORD = 8373; -pub const ERROR_DS_CROSS_REF_EXISTS: DWORD = 8374; -pub const ERROR_DS_CANT_DEL_MASTER_CROSSREF: DWORD = 8375; -pub const ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD: DWORD = 8376; -pub const ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX: DWORD = 8377; -pub const ERROR_DS_DUP_RDN: DWORD = 8378; -pub const ERROR_DS_DUP_OID: DWORD = 8379; -pub const ERROR_DS_DUP_MAPI_ID: DWORD = 8380; -pub const ERROR_DS_DUP_SCHEMA_ID_GUID: DWORD = 8381; -pub const ERROR_DS_DUP_LDAP_DISPLAY_NAME: DWORD = 8382; -pub const ERROR_DS_SEMANTIC_ATT_TEST: DWORD = 8383; -pub const ERROR_DS_SYNTAX_MISMATCH: DWORD = 8384; -pub const ERROR_DS_EXISTS_IN_MUST_HAVE: DWORD = 8385; -pub const ERROR_DS_EXISTS_IN_MAY_HAVE: DWORD = 8386; -pub const ERROR_DS_NONEXISTENT_MAY_HAVE: DWORD = 8387; -pub const ERROR_DS_NONEXISTENT_MUST_HAVE: DWORD = 8388; -pub const ERROR_DS_AUX_CLS_TEST_FAIL: DWORD = 8389; -pub const ERROR_DS_NONEXISTENT_POSS_SUP: DWORD = 8390; -pub const ERROR_DS_SUB_CLS_TEST_FAIL: DWORD = 8391; -pub const ERROR_DS_BAD_RDN_ATT_ID_SYNTAX: DWORD = 8392; -pub const ERROR_DS_EXISTS_IN_AUX_CLS: DWORD = 8393; -pub const ERROR_DS_EXISTS_IN_SUB_CLS: DWORD = 8394; -pub const ERROR_DS_EXISTS_IN_POSS_SUP: DWORD = 8395; -pub const ERROR_DS_RECALCSCHEMA_FAILED: DWORD = 8396; -pub const ERROR_DS_TREE_DELETE_NOT_FINISHED: DWORD = 8397; -pub const ERROR_DS_CANT_DELETE: DWORD = 8398; -pub const ERROR_DS_ATT_SCHEMA_REQ_ID: DWORD = 8399; -pub const ERROR_DS_BAD_ATT_SCHEMA_SYNTAX: DWORD = 8400; -pub const ERROR_DS_CANT_CACHE_ATT: DWORD = 8401; -pub const ERROR_DS_CANT_CACHE_CLASS: DWORD = 8402; -pub const ERROR_DS_CANT_REMOVE_ATT_CACHE: DWORD = 8403; -pub const ERROR_DS_CANT_REMOVE_CLASS_CACHE: DWORD = 8404; -pub const ERROR_DS_CANT_RETRIEVE_DN: DWORD = 8405; -pub const ERROR_DS_MISSING_SUPREF: DWORD = 8406; -pub const ERROR_DS_CANT_RETRIEVE_INSTANCE: DWORD = 8407; -pub const ERROR_DS_CODE_INCONSISTENCY: DWORD = 8408; -pub const ERROR_DS_DATABASE_ERROR: DWORD = 8409; -pub const ERROR_DS_GOVERNSID_MISSING: DWORD = 8410; -pub const ERROR_DS_MISSING_EXPECTED_ATT: DWORD = 8411; -pub const ERROR_DS_NCNAME_MISSING_CR_REF: DWORD = 8412; -pub const ERROR_DS_SECURITY_CHECKING_ERROR: DWORD = 8413; -pub const ERROR_DS_SCHEMA_NOT_LOADED: DWORD = 8414; -pub const ERROR_DS_SCHEMA_ALLOC_FAILED: DWORD = 8415; -pub const ERROR_DS_ATT_SCHEMA_REQ_SYNTAX: DWORD = 8416; -pub const ERROR_DS_GCVERIFY_ERROR: DWORD = 8417; -pub const ERROR_DS_DRA_SCHEMA_MISMATCH: DWORD = 8418; -pub const ERROR_DS_CANT_FIND_DSA_OBJ: DWORD = 8419; -pub const ERROR_DS_CANT_FIND_EXPECTED_NC: DWORD = 8420; -pub const ERROR_DS_CANT_FIND_NC_IN_CACHE: DWORD = 8421; -pub const ERROR_DS_CANT_RETRIEVE_CHILD: DWORD = 8422; -pub const ERROR_DS_SECURITY_ILLEGAL_MODIFY: DWORD = 8423; -pub const ERROR_DS_CANT_REPLACE_HIDDEN_REC: DWORD = 8424; -pub const ERROR_DS_BAD_HIERARCHY_FILE: DWORD = 8425; -pub const ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED: DWORD = 8426; -pub const ERROR_DS_CONFIG_PARAM_MISSING: DWORD = 8427; -pub const ERROR_DS_COUNTING_AB_INDICES_FAILED: DWORD = 8428; -pub const ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED: DWORD = 8429; -pub const ERROR_DS_INTERNAL_FAILURE: DWORD = 8430; -pub const ERROR_DS_UNKNOWN_ERROR: DWORD = 8431; -pub const ERROR_DS_ROOT_REQUIRES_CLASS_TOP: DWORD = 8432; -pub const ERROR_DS_REFUSING_FSMO_ROLES: DWORD = 8433; -pub const ERROR_DS_MISSING_FSMO_SETTINGS: DWORD = 8434; -pub const ERROR_DS_UNABLE_TO_SURRENDER_ROLES: DWORD = 8435; -pub const ERROR_DS_DRA_GENERIC: DWORD = 8436; -pub const ERROR_DS_DRA_INVALID_PARAMETER: DWORD = 8437; -pub const ERROR_DS_DRA_BUSY: DWORD = 8438; -pub const ERROR_DS_DRA_BAD_DN: DWORD = 8439; -pub const ERROR_DS_DRA_BAD_NC: DWORD = 8440; -pub const ERROR_DS_DRA_DN_EXISTS: DWORD = 8441; -pub const ERROR_DS_DRA_INTERNAL_ERROR: DWORD = 8442; -pub const ERROR_DS_DRA_INCONSISTENT_DIT: DWORD = 8443; -pub const ERROR_DS_DRA_CONNECTION_FAILED: DWORD = 8444; -pub const ERROR_DS_DRA_BAD_INSTANCE_TYPE: DWORD = 8445; -pub const ERROR_DS_DRA_OUT_OF_MEM: DWORD = 8446; -pub const ERROR_DS_DRA_MAIL_PROBLEM: DWORD = 8447; -pub const ERROR_DS_DRA_REF_ALREADY_EXISTS: DWORD = 8448; -pub const ERROR_DS_DRA_REF_NOT_FOUND: DWORD = 8449; -pub const ERROR_DS_DRA_OBJ_IS_REP_SOURCE: DWORD = 8450; -pub const ERROR_DS_DRA_DB_ERROR: DWORD = 8451; -pub const ERROR_DS_DRA_NO_REPLICA: DWORD = 8452; -pub const ERROR_DS_DRA_ACCESS_DENIED: DWORD = 8453; -pub const ERROR_DS_DRA_NOT_SUPPORTED: DWORD = 8454; -pub const ERROR_DS_DRA_RPC_CANCELLED: DWORD = 8455; -pub const ERROR_DS_DRA_SOURCE_DISABLED: DWORD = 8456; -pub const ERROR_DS_DRA_SINK_DISABLED: DWORD = 8457; -pub const ERROR_DS_DRA_NAME_COLLISION: DWORD = 8458; -pub const ERROR_DS_DRA_SOURCE_REINSTALLED: DWORD = 8459; -pub const ERROR_DS_DRA_MISSING_PARENT: DWORD = 8460; -pub const ERROR_DS_DRA_PREEMPTED: DWORD = 8461; -pub const ERROR_DS_DRA_ABANDON_SYNC: DWORD = 8462; -pub const ERROR_DS_DRA_SHUTDOWN: DWORD = 8463; -pub const ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET: DWORD = 8464; -pub const ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA: DWORD = 8465; -pub const ERROR_DS_DRA_EXTN_CONNECTION_FAILED: DWORD = 8466; -pub const ERROR_DS_INSTALL_SCHEMA_MISMATCH: DWORD = 8467; -pub const ERROR_DS_DUP_LINK_ID: DWORD = 8468; -pub const ERROR_DS_NAME_ERROR_RESOLVING: DWORD = 8469; -pub const ERROR_DS_NAME_ERROR_NOT_FOUND: DWORD = 8470; -pub const ERROR_DS_NAME_ERROR_NOT_UNIQUE: DWORD = 8471; -pub const ERROR_DS_NAME_ERROR_NO_MAPPING: DWORD = 8472; -pub const ERROR_DS_NAME_ERROR_DOMAIN_ONLY: DWORD = 8473; -pub const ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING: DWORD = 8474; -pub const ERROR_DS_CONSTRUCTED_ATT_MOD: DWORD = 8475; -pub const ERROR_DS_WRONG_OM_OBJ_CLASS: DWORD = 8476; -pub const ERROR_DS_DRA_REPL_PENDING: DWORD = 8477; -pub const ERROR_DS_DS_REQUIRED: DWORD = 8478; -pub const ERROR_DS_INVALID_LDAP_DISPLAY_NAME: DWORD = 8479; -pub const ERROR_DS_NON_BASE_SEARCH: DWORD = 8480; -pub const ERROR_DS_CANT_RETRIEVE_ATTS: DWORD = 8481; -pub const ERROR_DS_BACKLINK_WITHOUT_LINK: DWORD = 8482; -pub const ERROR_DS_EPOCH_MISMATCH: DWORD = 8483; -pub const ERROR_DS_SRC_NAME_MISMATCH: DWORD = 8484; -pub const ERROR_DS_SRC_AND_DST_NC_IDENTICAL: DWORD = 8485; -pub const ERROR_DS_DST_NC_MISMATCH: DWORD = 8486; -pub const ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC: DWORD = 8487; -pub const ERROR_DS_SRC_GUID_MISMATCH: DWORD = 8488; -pub const ERROR_DS_CANT_MOVE_DELETED_OBJECT: DWORD = 8489; -pub const ERROR_DS_PDC_OPERATION_IN_PROGRESS: DWORD = 8490; -pub const ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD: DWORD = 8491; -pub const ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION: DWORD = 8492; -pub const ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS: DWORD = 8493; -pub const ERROR_DS_NC_MUST_HAVE_NC_PARENT: DWORD = 8494; -pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE: DWORD = 8495; -pub const ERROR_DS_DST_DOMAIN_NOT_NATIVE: DWORD = 8496; -pub const ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER: DWORD = 8497; -pub const ERROR_DS_CANT_MOVE_ACCOUNT_GROUP: DWORD = 8498; -pub const ERROR_DS_CANT_MOVE_RESOURCE_GROUP: DWORD = 8499; -pub const ERROR_DS_INVALID_SEARCH_FLAG: DWORD = 8500; -pub const ERROR_DS_NO_TREE_DELETE_ABOVE_NC: DWORD = 8501; -pub const ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE: DWORD = 8502; -pub const ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE: DWORD = 8503; -pub const ERROR_DS_SAM_INIT_FAILURE: DWORD = 8504; -pub const ERROR_DS_SENSITIVE_GROUP_VIOLATION: DWORD = 8505; -pub const ERROR_DS_CANT_MOD_PRIMARYGROUPID: DWORD = 8506; -pub const ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD: DWORD = 8507; -pub const ERROR_DS_NONSAFE_SCHEMA_CHANGE: DWORD = 8508; -pub const ERROR_DS_SCHEMA_UPDATE_DISALLOWED: DWORD = 8509; -pub const ERROR_DS_CANT_CREATE_UNDER_SCHEMA: DWORD = 8510; -pub const ERROR_DS_INSTALL_NO_SRC_SCH_VERSION: DWORD = 8511; -pub const ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE: DWORD = 8512; -pub const ERROR_DS_INVALID_GROUP_TYPE: DWORD = 8513; -pub const ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN: DWORD = 8514; -pub const ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN: DWORD = 8515; -pub const ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER: DWORD = 8516; -pub const ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER: DWORD = 8517; -pub const ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER: DWORD = 8518; -pub const ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER: DWORD = 8519; -pub const ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER: DWORD = 8520; -pub const ERROR_DS_HAVE_PRIMARY_MEMBERS: DWORD = 8521; -pub const ERROR_DS_STRING_SD_CONVERSION_FAILED: DWORD = 8522; -pub const ERROR_DS_NAMING_MASTER_GC: DWORD = 8523; -pub const ERROR_DS_DNS_LOOKUP_FAILURE: DWORD = 8524; -pub const ERROR_DS_COULDNT_UPDATE_SPNS: DWORD = 8525; -pub const ERROR_DS_CANT_RETRIEVE_SD: DWORD = 8526; -pub const ERROR_DS_KEY_NOT_UNIQUE: DWORD = 8527; -pub const ERROR_DS_WRONG_LINKED_ATT_SYNTAX: DWORD = 8528; -pub const ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD: DWORD = 8529; -pub const ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY: DWORD = 8530; -pub const ERROR_DS_CANT_START: DWORD = 8531; -pub const ERROR_DS_INIT_FAILURE: DWORD = 8532; -pub const ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION: DWORD = 8533; -pub const ERROR_DS_SOURCE_DOMAIN_IN_FOREST: DWORD = 8534; -pub const ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST: DWORD = 8535; -pub const ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED: DWORD = 8536; -pub const ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN: DWORD = 8537; -pub const ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER: DWORD = 8538; -pub const ERROR_DS_SRC_SID_EXISTS_IN_FOREST: DWORD = 8539; -pub const ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH: DWORD = 8540; -pub const ERROR_SAM_INIT_FAILURE: DWORD = 8541; -pub const ERROR_DS_DRA_SCHEMA_INFO_SHIP: DWORD = 8542; -pub const ERROR_DS_DRA_SCHEMA_CONFLICT: DWORD = 8543; -pub const ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT: DWORD = 8544; -pub const ERROR_DS_DRA_OBJ_NC_MISMATCH: DWORD = 8545; -pub const ERROR_DS_NC_STILL_HAS_DSAS: DWORD = 8546; -pub const ERROR_DS_GC_REQUIRED: DWORD = 8547; -pub const ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY: DWORD = 8548; -pub const ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS: DWORD = 8549; -pub const ERROR_DS_CANT_ADD_TO_GC: DWORD = 8550; -pub const ERROR_DS_NO_CHECKPOINT_WITH_PDC: DWORD = 8551; -pub const ERROR_DS_SOURCE_AUDITING_NOT_ENABLED: DWORD = 8552; -pub const ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC: DWORD = 8553; -pub const ERROR_DS_INVALID_NAME_FOR_SPN: DWORD = 8554; -pub const ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS: DWORD = 8555; -pub const ERROR_DS_UNICODEPWD_NOT_IN_QUOTES: DWORD = 8556; -pub const ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED: DWORD = 8557; -pub const ERROR_DS_MUST_BE_RUN_ON_DST_DC: DWORD = 8558; -pub const ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER: DWORD = 8559; -pub const ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ: DWORD = 8560; -pub const ERROR_DS_INIT_FAILURE_CONSOLE: DWORD = 8561; -pub const ERROR_DS_SAM_INIT_FAILURE_CONSOLE: DWORD = 8562; -pub const ERROR_DS_FOREST_VERSION_TOO_HIGH: DWORD = 8563; -pub const ERROR_DS_DOMAIN_VERSION_TOO_HIGH: DWORD = 8564; -pub const ERROR_DS_FOREST_VERSION_TOO_LOW: DWORD = 8565; -pub const ERROR_DS_DOMAIN_VERSION_TOO_LOW: DWORD = 8566; -pub const ERROR_DS_INCOMPATIBLE_VERSION: DWORD = 8567; -pub const ERROR_DS_LOW_DSA_VERSION: DWORD = 8568; -pub const ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN: DWORD = 8569; -pub const ERROR_DS_NOT_SUPPORTED_SORT_ORDER: DWORD = 8570; -pub const ERROR_DS_NAME_NOT_UNIQUE: DWORD = 8571; -pub const ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4: DWORD = 8572; -pub const ERROR_DS_OUT_OF_VERSION_STORE: DWORD = 8573; -pub const ERROR_DS_INCOMPATIBLE_CONTROLS_USED: DWORD = 8574; -pub const ERROR_DS_NO_REF_DOMAIN: DWORD = 8575; -pub const ERROR_DS_RESERVED_LINK_ID: DWORD = 8576; -pub const ERROR_DS_LINK_ID_NOT_AVAILABLE: DWORD = 8577; -pub const ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER: DWORD = 8578; -pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE: DWORD = 8579; -pub const ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC: DWORD = 8580; -pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG: DWORD = 8581; -pub const ERROR_DS_MODIFYDN_WRONG_GRANDPARENT: DWORD = 8582; -pub const ERROR_DS_NAME_ERROR_TRUST_REFERRAL: DWORD = 8583; -pub const ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER: DWORD = 8584; -pub const ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD: DWORD = 8585; -pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2: DWORD = 8586; -pub const ERROR_DS_THREAD_LIMIT_EXCEEDED: DWORD = 8587; -pub const ERROR_DS_NOT_CLOSEST: DWORD = 8588; -pub const ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF: DWORD = 8589; -pub const ERROR_DS_SINGLE_USER_MODE_FAILED: DWORD = 8590; -pub const ERROR_DS_NTDSCRIPT_SYNTAX_ERROR: DWORD = 8591; -pub const ERROR_DS_NTDSCRIPT_PROCESS_ERROR: DWORD = 8592; -pub const ERROR_DS_DIFFERENT_REPL_EPOCHS: DWORD = 8593; -pub const ERROR_DS_DRS_EXTENSIONS_CHANGED: DWORD = 8594; -pub const ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR: DWORD = 8595; -pub const ERROR_DS_NO_MSDS_INTID: DWORD = 8596; -pub const ERROR_DS_DUP_MSDS_INTID: DWORD = 8597; -pub const ERROR_DS_EXISTS_IN_RDNATTID: DWORD = 8598; -pub const ERROR_DS_AUTHORIZATION_FAILED: DWORD = 8599; -pub const ERROR_DS_INVALID_SCRIPT: DWORD = 8600; -pub const ERROR_DS_REMOTE_CROSSREF_OP_FAILED: DWORD = 8601; -pub const ERROR_DS_CROSS_REF_BUSY: DWORD = 8602; -pub const ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN: DWORD = 8603; -pub const ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC: DWORD = 8604; -pub const ERROR_DS_DUPLICATE_ID_FOUND: DWORD = 8605; -pub const ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT: DWORD = 8606; -pub const ERROR_DS_GROUP_CONVERSION_ERROR: DWORD = 8607; -pub const ERROR_DS_CANT_MOVE_APP_BASIC_GROUP: DWORD = 8608; -pub const ERROR_DS_CANT_MOVE_APP_QUERY_GROUP: DWORD = 8609; -pub const ERROR_DS_ROLE_NOT_VERIFIED: DWORD = 8610; -pub const ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL: DWORD = 8611; -pub const ERROR_DS_DOMAIN_RENAME_IN_PROGRESS: DWORD = 8612; -pub const ERROR_DS_EXISTING_AD_CHILD_NC: DWORD = 8613; -pub const ERROR_DS_REPL_LIFETIME_EXCEEDED: DWORD = 8614; -pub const ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER: DWORD = 8615; -pub const ERROR_DS_LDAP_SEND_QUEUE_FULL: DWORD = 8616; -pub const ERROR_DS_DRA_OUT_SCHEDULE_WINDOW: DWORD = 8617; -pub const ERROR_SXS_SECTION_NOT_FOUND: DWORD = 14000; -pub const ERROR_SXS_CANT_GEN_ACTCTX: DWORD = 14001; -pub const ERROR_SXS_INVALID_ACTCTXDATA_FORMAT: DWORD = 14002; -pub const ERROR_SXS_ASSEMBLY_NOT_FOUND: DWORD = 14003; -pub const ERROR_SXS_MANIFEST_FORMAT_ERROR: DWORD = 14004; -pub const ERROR_SXS_MANIFEST_PARSE_ERROR: DWORD = 14005; -pub const ERROR_SXS_ACTIVATION_CONTEXT_DISABLED: DWORD = 14006; -pub const ERROR_SXS_KEY_NOT_FOUND: DWORD = 14007; -pub const ERROR_SXS_VERSION_CONFLICT: DWORD = 14008; -pub const ERROR_SXS_WRONG_SECTION_TYPE: DWORD = 14009; -pub const ERROR_SXS_THREAD_QUERIES_DISABLED: DWORD = 14010; -pub const ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET: DWORD = 14011; -pub const ERROR_SXS_UNKNOWN_ENCODING_GROUP: DWORD = 14012; -pub const ERROR_SXS_UNKNOWN_ENCODING: DWORD = 14013; -pub const ERROR_SXS_INVALID_XML_NAMESPACE_URI: DWORD = 14014; -pub const ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED: DWORD = 14015; -pub const ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED: DWORD = 14016; -pub const ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE: DWORD = 14017; -pub const ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE: DWORD = 14018; -pub const ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE: DWORD = 14019; -pub const ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT: DWORD = 14020; -pub const ERROR_SXS_DUPLICATE_DLL_NAME: DWORD = 14021; -pub const ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME: DWORD = 14022; -pub const ERROR_SXS_DUPLICATE_CLSID: DWORD = 14023; -pub const ERROR_SXS_DUPLICATE_IID: DWORD = 14024; -pub const ERROR_SXS_DUPLICATE_TLBID: DWORD = 14025; -pub const ERROR_SXS_DUPLICATE_PROGID: DWORD = 14026; -pub const ERROR_SXS_DUPLICATE_ASSEMBLY_NAME: DWORD = 14027; -pub const ERROR_SXS_FILE_HASH_MISMATCH: DWORD = 14028; -pub const ERROR_SXS_POLICY_PARSE_ERROR: DWORD = 14029; -pub const ERROR_SXS_XML_E_MISSINGQUOTE: DWORD = 14030; -pub const ERROR_SXS_XML_E_COMMENTSYNTAX: DWORD = 14031; -pub const ERROR_SXS_XML_E_BADSTARTNAMECHAR: DWORD = 14032; -pub const ERROR_SXS_XML_E_BADNAMECHAR: DWORD = 14033; -pub const ERROR_SXS_XML_E_BADCHARINSTRING: DWORD = 14034; -pub const ERROR_SXS_XML_E_XMLDECLSYNTAX: DWORD = 14035; -pub const ERROR_SXS_XML_E_BADCHARDATA: DWORD = 14036; -pub const ERROR_SXS_XML_E_MISSINGWHITESPACE: DWORD = 14037; -pub const ERROR_SXS_XML_E_EXPECTINGTAGEND: DWORD = 14038; -pub const ERROR_SXS_XML_E_MISSINGSEMICOLON: DWORD = 14039; -pub const ERROR_SXS_XML_E_UNBALANCEDPAREN: DWORD = 14040; -pub const ERROR_SXS_XML_E_INTERNALERROR: DWORD = 14041; -pub const ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE: DWORD = 14042; -pub const ERROR_SXS_XML_E_INCOMPLETE_ENCODING: DWORD = 14043; -pub const ERROR_SXS_XML_E_MISSING_PAREN: DWORD = 14044; -pub const ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE: DWORD = 14045; -pub const ERROR_SXS_XML_E_MULTIPLE_COLONS: DWORD = 14046; -pub const ERROR_SXS_XML_E_INVALID_DECIMAL: DWORD = 14047; -pub const ERROR_SXS_XML_E_INVALID_HEXIDECIMAL: DWORD = 14048; -pub const ERROR_SXS_XML_E_INVALID_UNICODE: DWORD = 14049; -pub const ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK: DWORD = 14050; -pub const ERROR_SXS_XML_E_UNEXPECTEDENDTAG: DWORD = 14051; -pub const ERROR_SXS_XML_E_UNCLOSEDTAG: DWORD = 14052; -pub const ERROR_SXS_XML_E_DUPLICATEATTRIBUTE: DWORD = 14053; -pub const ERROR_SXS_XML_E_MULTIPLEROOTS: DWORD = 14054; -pub const ERROR_SXS_XML_E_INVALIDATROOTLEVEL: DWORD = 14055; -pub const ERROR_SXS_XML_E_BADXMLDECL: DWORD = 14056; -pub const ERROR_SXS_XML_E_MISSINGROOT: DWORD = 14057; -pub const ERROR_SXS_XML_E_UNEXPECTEDEOF: DWORD = 14058; -pub const ERROR_SXS_XML_E_BADPEREFINSUBSET: DWORD = 14059; -pub const ERROR_SXS_XML_E_UNCLOSEDSTARTTAG: DWORD = 14060; -pub const ERROR_SXS_XML_E_UNCLOSEDENDTAG: DWORD = 14061; -pub const ERROR_SXS_XML_E_UNCLOSEDSTRING: DWORD = 14062; -pub const ERROR_SXS_XML_E_UNCLOSEDCOMMENT: DWORD = 14063; -pub const ERROR_SXS_XML_E_UNCLOSEDDECL: DWORD = 14064; -pub const ERROR_SXS_XML_E_UNCLOSEDCDATA: DWORD = 14065; -pub const ERROR_SXS_XML_E_RESERVEDNAMESPACE: DWORD = 14066; -pub const ERROR_SXS_XML_E_INVALIDENCODING: DWORD = 14067; -pub const ERROR_SXS_XML_E_INVALIDSWITCH: DWORD = 14068; -pub const ERROR_SXS_XML_E_BADXMLCASE: DWORD = 14069; -pub const ERROR_SXS_XML_E_INVALID_STANDALONE: DWORD = 14070; -pub const ERROR_SXS_XML_E_UNEXPECTED_STANDALONE: DWORD = 14071; -pub const ERROR_SXS_XML_E_INVALID_VERSION: DWORD = 14072; -pub const ERROR_SXS_XML_E_MISSINGEQUALS: DWORD = 14073; -pub const ERROR_SXS_PROTECTION_RECOVERY_FAILED: DWORD = 14074; -pub const ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT: DWORD = 14075; -pub const ERROR_SXS_PROTECTION_CATALOG_NOT_VALID: DWORD = 14076; -pub const ERROR_SXS_UNTRANSLATABLE_HRESULT: DWORD = 14077; -pub const ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING: DWORD = 14078; -pub const ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE: DWORD = 14079; -pub const ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME: DWORD = 14080; -pub const ERROR_SXS_ASSEMBLY_MISSING: DWORD = 14081; -pub const ERROR_SXS_CORRUPT_ACTIVATION_STACK: DWORD = 14082; -pub const ERROR_SXS_CORRUPTION: DWORD = 14083; -pub const ERROR_SXS_EARLY_DEACTIVATION: DWORD = 14084; -pub const ERROR_SXS_INVALID_DEACTIVATION: DWORD = 14085; -pub const ERROR_SXS_MULTIPLE_DEACTIVATION: DWORD = 14086; -pub const ERROR_SXS_PROCESS_TERMINATION_REQUESTED: DWORD = 14087; -pub const ERROR_SXS_RELEASE_ACTIVATION_CONTEXT: DWORD = 14088; -pub const ERROR_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY: DWORD = 14089; -pub const ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE: DWORD = 14090; -pub const ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME: DWORD = 14091; -pub const ERROR_SXS_IDENTITY_DUPLICATE_ATTRIBUTE: DWORD = 14092; -pub const ERROR_SXS_IDENTITY_PARSE_ERROR: DWORD = 14093; -pub const ERROR_MALFORMED_SUBSTITUTION_STRING: DWORD = 14094; -pub const ERROR_SXS_INCORRECT_PUBLIC_KEY_TOKEN: DWORD = 14095; -pub const ERROR_UNMAPPED_SUBSTITUTION_STRING: DWORD = 14096; -pub const ERROR_SXS_ASSEMBLY_NOT_LOCKED: DWORD = 14097; -pub const ERROR_SXS_COMPONENT_STORE_CORRUPT: DWORD = 14098; -pub const ERROR_ADVANCED_INSTALLER_FAILED: DWORD = 14099; -pub const ERROR_XML_ENCODING_MISMATCH: DWORD = 14100; -pub const ERROR_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT: DWORD = 14101; -pub const ERROR_SXS_IDENTITIES_DIFFERENT: DWORD = 14102; -pub const ERROR_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT: DWORD = 14103; -pub const ERROR_SXS_FILE_NOT_PART_OF_ASSEMBLY: DWORD = 14104; -pub const ERROR_SXS_MANIFEST_TOO_BIG: DWORD = 14105; -pub const ERROR_SXS_SETTING_NOT_REGISTERED: DWORD = 14106; -pub const ERROR_SXS_TRANSACTION_CLOSURE_INCOMPLETE: DWORD = 14107; -pub const ERROR_SMI_PRIMITIVE_INSTALLER_FAILED: DWORD = 14108; -pub const ERROR_GENERIC_COMMAND_FAILED: DWORD = 14109; -pub const ERROR_SXS_FILE_HASH_MISSING: DWORD = 14110; -pub const ERROR_IPSEC_QM_POLICY_EXISTS: DWORD = 13000; -pub const ERROR_IPSEC_QM_POLICY_NOT_FOUND: DWORD = 13001; -pub const ERROR_IPSEC_QM_POLICY_IN_USE: DWORD = 13002; -pub const ERROR_IPSEC_MM_POLICY_EXISTS: DWORD = 13003; -pub const ERROR_IPSEC_MM_POLICY_NOT_FOUND: DWORD = 13004; -pub const ERROR_IPSEC_MM_POLICY_IN_USE: DWORD = 13005; -pub const ERROR_IPSEC_MM_FILTER_EXISTS: DWORD = 13006; -pub const ERROR_IPSEC_MM_FILTER_NOT_FOUND: DWORD = 13007; -pub const ERROR_IPSEC_TRANSPORT_FILTER_EXISTS: DWORD = 13008; -pub const ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND: DWORD = 13009; -pub const ERROR_IPSEC_MM_AUTH_EXISTS: DWORD = 13010; -pub const ERROR_IPSEC_MM_AUTH_NOT_FOUND: DWORD = 13011; -pub const ERROR_IPSEC_MM_AUTH_IN_USE: DWORD = 13012; -pub const ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND: DWORD = 13013; -pub const ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND: DWORD = 13014; -pub const ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND: DWORD = 13015; -pub const ERROR_IPSEC_TUNNEL_FILTER_EXISTS: DWORD = 13016; -pub const ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND: DWORD = 13017; -pub const ERROR_IPSEC_MM_FILTER_PENDING_DELETION: DWORD = 13018; -pub const ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION: DWORD = 13019; -pub const ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION: DWORD = 13020; -pub const ERROR_IPSEC_MM_POLICY_PENDING_DELETION: DWORD = 13021; -pub const ERROR_IPSEC_MM_AUTH_PENDING_DELETION: DWORD = 13022; -pub const ERROR_IPSEC_QM_POLICY_PENDING_DELETION: DWORD = 13023; -pub const ERROR_IPSEC_IKE_NEG_STATUS_BEGIN: DWORD = 13800; -pub const ERROR_IPSEC_IKE_AUTH_FAIL: DWORD = 13801; -pub const ERROR_IPSEC_IKE_ATTRIB_FAIL: DWORD = 13802; -pub const ERROR_IPSEC_IKE_NEGOTIATION_PENDING: DWORD = 13803; -pub const ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR: DWORD = 13804; -pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805; -pub const ERROR_IPSEC_IKE_NO_CERT: DWORD = 13806; -pub const ERROR_IPSEC_IKE_SA_DELETED: DWORD = 13807; -pub const ERROR_IPSEC_IKE_SA_REAPED: DWORD = 13808; -pub const ERROR_IPSEC_IKE_MM_ACQUIRE_DROP: DWORD = 13809; -pub const ERROR_IPSEC_IKE_QM_ACQUIRE_DROP: DWORD = 13810; -pub const ERROR_IPSEC_IKE_QUEUE_DROP_MM: DWORD = 13811; -pub const ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM: DWORD = 13812; -pub const ERROR_IPSEC_IKE_DROP_NO_RESPONSE: DWORD = 13813; -pub const ERROR_IPSEC_IKE_MM_DELAY_DROP: DWORD = 13814; -pub const ERROR_IPSEC_IKE_QM_DELAY_DROP: DWORD = 13815; -pub const ERROR_IPSEC_IKE_ERROR: DWORD = 13816; -pub const ERROR_IPSEC_IKE_CRL_FAILED: DWORD = 13817; -pub const ERROR_IPSEC_IKE_INVALID_KEY_USAGE: DWORD = 13818; -pub const ERROR_IPSEC_IKE_INVALID_CERT_TYPE: DWORD = 13819; -pub const ERROR_IPSEC_IKE_NO_PRIVATE_KEY: DWORD = 13820; -pub const ERROR_IPSEC_IKE_DH_FAIL: DWORD = 13822; -pub const ERROR_IPSEC_IKE_INVALID_HEADER: DWORD = 13824; -pub const ERROR_IPSEC_IKE_NO_POLICY: DWORD = 13825; -pub const ERROR_IPSEC_IKE_INVALID_SIGNATURE: DWORD = 13826; -pub const ERROR_IPSEC_IKE_KERBEROS_ERROR: DWORD = 13827; -pub const ERROR_IPSEC_IKE_NO_PUBLIC_KEY: DWORD = 13828; -pub const ERROR_IPSEC_IKE_PROCESS_ERR: DWORD = 13829; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_SA: DWORD = 13830; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_PROP: DWORD = 13831; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_TRANS: DWORD = 13832; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_KE: DWORD = 13833; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_ID: DWORD = 13834; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_CERT: DWORD = 13835; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ: DWORD = 13836; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_HASH: DWORD = 13837; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_SIG: DWORD = 13838; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_NONCE: DWORD = 13839; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY: DWORD = 13840; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_DELETE: DWORD = 13841; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR: DWORD = 13842; -pub const ERROR_IPSEC_IKE_INVALID_PAYLOAD: DWORD = 13843; -pub const ERROR_IPSEC_IKE_LOAD_SOFT_SA: DWORD = 13844; -pub const ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN: DWORD = 13845; -pub const ERROR_IPSEC_IKE_INVALID_COOKIE: DWORD = 13846; -pub const ERROR_IPSEC_IKE_NO_PEER_CERT: DWORD = 13847; -pub const ERROR_IPSEC_IKE_PEER_CRL_FAILED: DWORD = 13848; -pub const ERROR_IPSEC_IKE_POLICY_CHANGE: DWORD = 13849; -pub const ERROR_IPSEC_IKE_NO_MM_POLICY: DWORD = 13850; -pub const ERROR_IPSEC_IKE_NOTCBPRIV: DWORD = 13851; -pub const ERROR_IPSEC_IKE_SECLOADFAIL: DWORD = 13852; -pub const ERROR_IPSEC_IKE_FAILSSPINIT: DWORD = 13853; -pub const ERROR_IPSEC_IKE_FAILQUERYSSP: DWORD = 13854; -pub const ERROR_IPSEC_IKE_SRVACQFAIL: DWORD = 13855; -pub const ERROR_IPSEC_IKE_SRVQUERYCRED: DWORD = 13856; -pub const ERROR_IPSEC_IKE_GETSPIFAIL: DWORD = 13857; -pub const ERROR_IPSEC_IKE_INVALID_FILTER: DWORD = 13858; -pub const ERROR_IPSEC_IKE_OUT_OF_MEMORY: DWORD = 13859; -pub const ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED: DWORD = 13860; -pub const ERROR_IPSEC_IKE_INVALID_POLICY: DWORD = 13861; -pub const ERROR_IPSEC_IKE_UNKNOWN_DOI: DWORD = 13862; -pub const ERROR_IPSEC_IKE_INVALID_SITUATION: DWORD = 13863; -pub const ERROR_IPSEC_IKE_DH_FAILURE: DWORD = 13864; -pub const ERROR_IPSEC_IKE_INVALID_GROUP: DWORD = 13865; -pub const ERROR_IPSEC_IKE_ENCRYPT: DWORD = 13866; -pub const ERROR_IPSEC_IKE_DECRYPT: DWORD = 13867; -pub const ERROR_IPSEC_IKE_POLICY_MATCH: DWORD = 13868; -pub const ERROR_IPSEC_IKE_UNSUPPORTED_ID: DWORD = 13869; -pub const ERROR_IPSEC_IKE_INVALID_HASH: DWORD = 13870; -pub const ERROR_IPSEC_IKE_INVALID_HASH_ALG: DWORD = 13871; -pub const ERROR_IPSEC_IKE_INVALID_HASH_SIZE: DWORD = 13872; -pub const ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG: DWORD = 13873; -pub const ERROR_IPSEC_IKE_INVALID_AUTH_ALG: DWORD = 13874; -pub const ERROR_IPSEC_IKE_INVALID_SIG: DWORD = 13875; -pub const ERROR_IPSEC_IKE_LOAD_FAILED: DWORD = 13876; -pub const ERROR_IPSEC_IKE_RPC_DELETE: DWORD = 13877; -pub const ERROR_IPSEC_IKE_BENIGN_REINIT: DWORD = 13878; -pub const ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY: DWORD = 13879; -pub const ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN: DWORD = 13881; -pub const ERROR_IPSEC_IKE_MM_LIMIT: DWORD = 13882; -pub const ERROR_IPSEC_IKE_NEGOTIATION_DISABLED: DWORD = 13883; -/*pub const ERROR_IPSEC_IKE_NEG_STATUS_END: DWORD = 13884)*/ -pub const ERROR_IPSEC_IKE_QM_LIMIT: DWORD = 13884; -pub const ERROR_IPSEC_IKE_MM_EXPIRED: DWORD = 13885; -pub const ERROR_IPSEC_IKE_PEER_MM_ASSUMED_INVALID: DWORD = 13886; -pub const ERROR_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH: DWORD = 13887; -pub const ERROR_IPSEC_IKE_UNEXPECTED_MESSAGE_ID: DWORD = 13888; -pub const ERROR_IPSEC_IKE_INVALID_AUTH_PAYLOAD: DWORD = 13889; -pub const ERROR_IPSEC_IKE_DOS_COOKIE_SENT: DWORD = 13890; -pub const ERROR_IPSEC_IKE_SHUTTING_DOWN: DWORD = 13891; -pub const ERROR_IPSEC_IKE_CGA_AUTH_FAILED: DWORD = 13892; -pub const ERROR_IPSEC_IKE_PROCESS_ERR_NATOA: DWORD = 13893; -pub const ERROR_IPSEC_IKE_INVALID_MM_FOR_QM: DWORD = 13894; -pub const ERROR_IPSEC_IKE_QM_EXPIRED: DWORD = 13895; -pub const ERROR_IPSEC_IKE_TOO_MANY_FILTERS: DWORD = 13896; -pub const ERROR_IPSEC_IKE_NEG_STATUS_END: DWORD = 13897; -pub const ERROR_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL: DWORD = 13898; -pub const ERROR_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE: DWORD = 13899; -pub const ERROR_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING: DWORD = 13900; -pub const ERROR_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING: DWORD = 13901; -pub const ERROR_IPSEC_IKE_COEXISTENCE_SUPPRESS: DWORD = 13902; -pub const ERROR_IPSEC_IKE_RATELIMIT_DROP: DWORD = 13903; -pub const ERROR_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE: DWORD = 13904; -pub const ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE: DWORD = 13905; -pub const ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE: DWORD = 13906; -pub const ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY: DWORD = 13907; -pub const ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE: DWORD = 13908; -pub const ERROR_IPSEC_IKE_NEG_STATUS_EXTENDED_END: DWORD = 13909; -pub const ERROR_IPSEC_BAD_SPI: DWORD = 13910; -pub const ERROR_IPSEC_SA_LIFETIME_EXPIRED: DWORD = 13911; -pub const ERROR_IPSEC_WRONG_SA: DWORD = 13912; -pub const ERROR_IPSEC_REPLAY_CHECK_FAILED: DWORD = 13913; -pub const ERROR_IPSEC_INVALID_PACKET: DWORD = 13914; -pub const ERROR_IPSEC_INTEGRITY_CHECK_FAILED: DWORD = 13915; -pub const ERROR_IPSEC_CLEAR_TEXT_DROP: DWORD = 13916; -pub const ERROR_IPSEC_AUTH_FIREWALL_DROP: DWORD = 13917; -pub const ERROR_IPSEC_THROTTLE_DROP: DWORD = 13918; -pub const ERROR_IPSEC_DOSP_BLOCK: DWORD = 13925; -pub const ERROR_IPSEC_DOSP_RECEIVED_MULTICAST: DWORD = 13926; -pub const ERROR_IPSEC_DOSP_INVALID_PACKET: DWORD = 13927; -pub const ERROR_IPSEC_DOSP_STATE_LOOKUP_FAILED: DWORD = 13928; -pub const ERROR_IPSEC_DOSP_MAX_ENTRIES: DWORD = 13929; -pub const ERROR_IPSEC_DOSP_KEYMOD_NOT_ALLOWED: DWORD = 13930; -pub const ERROR_IPSEC_DOSP_NOT_INSTALLED: DWORD = 13931; -pub const ERROR_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES: DWORD = 13932; -pub const ERROR_EVT_INVALID_CHANNEL_PATH: DWORD = 15000; -pub const ERROR_EVT_INVALID_QUERY: DWORD = 15001; -pub const ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND: DWORD = 15002; -pub const ERROR_EVT_EVENT_TEMPLATE_NOT_FOUND: DWORD = 15003; -pub const ERROR_EVT_INVALID_PUBLISHER_NAME: DWORD = 15004; -pub const ERROR_EVT_INVALID_EVENT_DATA: DWORD = 15005; -pub const ERROR_EVT_CHANNEL_NOT_FOUND: DWORD = 15007; -pub const ERROR_EVT_MALFORMED_XML_TEXT: DWORD = 15008; -pub const ERROR_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL: DWORD = 15009; -pub const ERROR_EVT_CONFIGURATION_ERROR: DWORD = 15010; -pub const ERROR_EVT_QUERY_RESULT_STALE: DWORD = 15011; -pub const ERROR_EVT_QUERY_RESULT_INVALID_POSITION: DWORD = 15012; -pub const ERROR_EVT_NON_VALIDATING_MSXML: DWORD = 15013; -pub const ERROR_EVT_FILTER_ALREADYSCOPED: DWORD = 15014; -pub const ERROR_EVT_FILTER_NOTELTSET: DWORD = 15015; -pub const ERROR_EVT_FILTER_INVARG: DWORD = 15016; -pub const ERROR_EVT_FILTER_INVTEST: DWORD = 15017; -pub const ERROR_EVT_FILTER_INVTYPE: DWORD = 15018; -pub const ERROR_EVT_FILTER_PARSEERR: DWORD = 15019; -pub const ERROR_EVT_FILTER_UNSUPPORTEDOP: DWORD = 15020; -pub const ERROR_EVT_FILTER_UNEXPECTEDTOKEN: DWORD = 15021; -pub const ERROR_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL: DWORD = 15022; -pub const ERROR_EVT_INVALID_CHANNEL_PROPERTY_VALUE: DWORD = 15023; -pub const ERROR_EVT_INVALID_PUBLISHER_PROPERTY_VALUE: DWORD = 15024; -pub const ERROR_EVT_CHANNEL_CANNOT_ACTIVATE: DWORD = 15025; -pub const ERROR_EVT_FILTER_TOO_COMPLEX: DWORD = 15026; -pub const ERROR_EVT_MESSAGE_NOT_FOUND: DWORD = 15027; -pub const ERROR_EVT_MESSAGE_ID_NOT_FOUND: DWORD = 15028; -pub const ERROR_EVT_UNRESOLVED_VALUE_INSERT: DWORD = 15029; -pub const ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: DWORD = 15030; -pub const ERROR_EVT_MAX_INSERTS_REACHED: DWORD = 15031; -pub const ERROR_EVT_EVENT_DEFINITION_NOT_FOUND: DWORD = 15032; -pub const ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND: DWORD = 15033; -pub const ERROR_EVT_VERSION_TOO_OLD: DWORD = 15034; -pub const ERROR_EVT_VERSION_TOO_NEW: DWORD = 15035; -pub const ERROR_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY: DWORD = 15036; -pub const ERROR_EVT_PUBLISHER_DISABLED: DWORD = 15037; -pub const ERROR_EVT_FILTER_OUT_OF_RANGE: DWORD = 15038; -pub const ERROR_EC_SUBSCRIPTION_CANNOT_ACTIVATE: DWORD = 15080; -pub const ERROR_EC_LOG_DISABLED: DWORD = 15081; -pub const ERROR_EC_CIRCULAR_FORWARDING: DWORD = 15082; -pub const ERROR_EC_CREDSTORE_FULL: DWORD = 15083; -pub const ERROR_EC_CRED_NOT_FOUND: DWORD = 15084; -pub const ERROR_EC_NO_ACTIVE_CHANNEL: DWORD = 15085; -pub const ERROR_MUI_FILE_NOT_FOUND: DWORD = 15100; -pub const ERROR_MUI_INVALID_FILE: DWORD = 15101; -pub const ERROR_MUI_INVALID_RC_CONFIG: DWORD = 15102; -pub const ERROR_MUI_INVALID_LOCALE_NAME: DWORD = 15103; -pub const ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME: DWORD = 15104; -pub const ERROR_MUI_FILE_NOT_LOADED: DWORD = 15105; -pub const ERROR_RESOURCE_ENUM_USER_STOP: DWORD = 15106; -pub const ERROR_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED: DWORD = 15107; -pub const ERROR_MUI_INTLSETTINGS_INVALID_LOCALE_NAME: DWORD = 15108; -pub const ERROR_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE: DWORD = 15110; -pub const ERROR_MRM_INVALID_PRICONFIG: DWORD = 15111; -pub const ERROR_MRM_INVALID_FILE_TYPE: DWORD = 15112; -pub const ERROR_MRM_UNKNOWN_QUALIFIER: DWORD = 15113; -pub const ERROR_MRM_INVALID_QUALIFIER_VALUE: DWORD = 15114; -pub const ERROR_MRM_NO_CANDIDATE: DWORD = 15115; -pub const ERROR_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE: DWORD = 15116; -pub const ERROR_MRM_RESOURCE_TYPE_MISMATCH: DWORD = 15117; -pub const ERROR_MRM_DUPLICATE_MAP_NAME: DWORD = 15118; -pub const ERROR_MRM_DUPLICATE_ENTRY: DWORD = 15119; -pub const ERROR_MRM_INVALID_RESOURCE_IDENTIFIER: DWORD = 15120; -pub const ERROR_MRM_FILEPATH_TOO_LONG: DWORD = 15121; -pub const ERROR_MRM_UNSUPPORTED_DIRECTORY_TYPE: DWORD = 15122; -pub const ERROR_MRM_INVALID_PRI_FILE: DWORD = 15126; -pub const ERROR_MRM_NAMED_RESOURCE_NOT_FOUND: DWORD = 15127; -pub const ERROR_MRM_MAP_NOT_FOUND: DWORD = 15135; -pub const ERROR_MRM_UNSUPPORTED_PROFILE_TYPE: DWORD = 15136; -pub const ERROR_MRM_INVALID_QUALIFIER_OPERATOR: DWORD = 15137; -pub const ERROR_MRM_INDETERMINATE_QUALIFIER_VALUE: DWORD = 15138; -pub const ERROR_MRM_AUTOMERGE_ENABLED: DWORD = 15139; -pub const ERROR_MRM_TOO_MANY_RESOURCES: DWORD = 15140; -pub const ERROR_MCA_INVALID_CAPABILITIES_STRING: DWORD = 15200; -pub const ERROR_MCA_INVALID_VCP_VERSION: DWORD = 15201; -pub const ERROR_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION: DWORD = 15202; -pub const ERROR_MCA_MCCS_VERSION_MISMATCH: DWORD = 15203; -pub const ERROR_MCA_UNSUPPORTED_MCCS_VERSION: DWORD = 15204; -pub const ERROR_MCA_INTERNAL_ERROR: DWORD = 15205; -pub const ERROR_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED: DWORD = 15206; -pub const ERROR_MCA_UNSUPPORTED_COLOR_TEMPERATURE: DWORD = 15207; -pub const ERROR_AMBIGUOUS_SYSTEM_DEVICE: DWORD = 15250; -pub const ERROR_SYSTEM_DEVICE_NOT_FOUND: DWORD = 15299; -pub const ERROR_HASH_NOT_SUPPORTED: DWORD = 15300; -pub const ERROR_HASH_NOT_PRESENT: DWORD = 15301; -pub const ERROR_SECONDARY_IC_PROVIDER_NOT_REGISTERED: DWORD = 15321; -pub const ERROR_GPIO_CLIENT_INFORMATION_INVALID: DWORD = 15322; -pub const ERROR_GPIO_VERSION_NOT_SUPPORTED: DWORD = 15323; -pub const ERROR_GPIO_INVALID_REGISTRATION_PACKET: DWORD = 15324; -pub const ERROR_GPIO_OPERATION_DENIED: DWORD = 15325; -pub const ERROR_GPIO_INCOMPATIBLE_CONNECT_MODE: DWORD = 15326; -pub const ERROR_GPIO_INTERRUPT_ALREADY_UNMASKED: DWORD = 15327; -pub const ERROR_CANNOT_SWITCH_RUNLEVEL: DWORD = 15400; -pub const ERROR_INVALID_RUNLEVEL_SETTING: DWORD = 15401; -pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402; -pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403; -pub const ERROR_RUNLEVEL_SWITCH_IN_PROGRESS: DWORD = 15404; -pub const ERROR_SERVICES_FAILED_AUTOSTART: DWORD = 15405; -pub const ERROR_COM_TASK_STOP_PENDING: DWORD = 15501; -pub const ERROR_INSTALL_OPEN_PACKAGE_FAILED: DWORD = 15600; -pub const ERROR_INSTALL_PACKAGE_NOT_FOUND: DWORD = 15601; -pub const ERROR_INSTALL_INVALID_PACKAGE: DWORD = 15602; -pub const ERROR_INSTALL_RESOLVE_DEPENDENCY_FAILED: DWORD = 15603; -pub const ERROR_INSTALL_OUT_OF_DISK_SPACE: DWORD = 15604; -pub const ERROR_INSTALL_NETWORK_FAILURE: DWORD = 15605; -pub const ERROR_INSTALL_REGISTRATION_FAILURE: DWORD = 15606; -pub const ERROR_INSTALL_DEREGISTRATION_FAILURE: DWORD = 15607; -pub const ERROR_INSTALL_CANCEL: DWORD = 15608; -pub const ERROR_INSTALL_FAILED: DWORD = 15609; -pub const ERROR_REMOVE_FAILED: DWORD = 15610; -pub const ERROR_PACKAGE_ALREADY_EXISTS: DWORD = 15611; -pub const ERROR_NEEDS_REMEDIATION: DWORD = 15612; -pub const ERROR_INSTALL_PREREQUISITE_FAILED: DWORD = 15613; -pub const ERROR_PACKAGE_REPOSITORY_CORRUPTED: DWORD = 15614; -pub const ERROR_INSTALL_POLICY_FAILURE: DWORD = 15615; -pub const ERROR_PACKAGE_UPDATING: DWORD = 15616; -pub const ERROR_DEPLOYMENT_BLOCKED_BY_POLICY: DWORD = 15617; -pub const ERROR_PACKAGES_IN_USE: DWORD = 15618; -pub const ERROR_RECOVERY_FILE_CORRUPT: DWORD = 15619; -pub const ERROR_INVALID_STAGED_SIGNATURE: DWORD = 15620; -pub const ERROR_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED: DWORD = 15621; -pub const ERROR_INSTALL_PACKAGE_DOWNGRADE: DWORD = 15622; -pub const ERROR_SYSTEM_NEEDS_REMEDIATION: DWORD = 15623; -pub const ERROR_APPX_INTEGRITY_FAILURE_CLR_NGEN: DWORD = 15624; -pub const ERROR_RESILIENCY_FILE_CORRUPT: DWORD = 15625; -pub const ERROR_INSTALL_FIREWALL_SERVICE_NOT_RUNNING: DWORD = 15626; -pub const ERROR_STATE_LOAD_STORE_FAILED: DWORD = 15800; -pub const ERROR_STATE_GET_VERSION_FAILED: DWORD = 15801; -pub const ERROR_STATE_SET_VERSION_FAILED: DWORD = 15802; -pub const ERROR_STATE_STRUCTURED_RESET_FAILED: DWORD = 15803; -pub const ERROR_STATE_OPEN_CONTAINER_FAILED: DWORD = 15804; -pub const ERROR_STATE_CREATE_CONTAINER_FAILED: DWORD = 15805; -pub const ERROR_STATE_DELETE_CONTAINER_FAILED: DWORD = 15806; -pub const ERROR_STATE_READ_SETTING_FAILED: DWORD = 15807; -pub const ERROR_STATE_WRITE_SETTING_FAILED: DWORD = 15808; -pub const ERROR_STATE_DELETE_SETTING_FAILED: DWORD = 15809; -pub const ERROR_STATE_QUERY_SETTING_FAILED: DWORD = 15810; -pub const ERROR_STATE_READ_COMPOSITE_SETTING_FAILED: DWORD = 15811; -pub const ERROR_STATE_WRITE_COMPOSITE_SETTING_FAILED: DWORD = 15812; -pub const ERROR_STATE_ENUMERATE_CONTAINER_FAILED: DWORD = 15813; -pub const ERROR_STATE_ENUMERATE_SETTINGS_FAILED: DWORD = 15814; -pub const ERROR_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED: DWORD = 15815; -pub const ERROR_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED: DWORD = 15816; -pub const ERROR_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED: DWORD = 15817; -pub const ERROR_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED: DWORD = 15818; -pub const ERROR_API_UNAVAILABLE: DWORD = 15841; -pub const ERROR_AUDITING_DISABLED: DWORD = 0xC0090001; -pub const ERROR_ALL_SIDS_FILTERED: DWORD = 0xC0090002; - -pub const WSABASEERR: c_int = 10000; -pub const WSAEINTR: c_int = WSABASEERR + 4; -pub const WSAEBADF: c_int = WSABASEERR + 9; -pub const WSAEACCES: c_int = WSABASEERR + 13; -pub const WSAEFAULT: c_int = WSABASEERR + 14; -pub const WSAEINVAL: c_int = WSABASEERR + 22; -pub const WSAEMFILE: c_int = WSABASEERR + 24; -pub const WSAEWOULDBLOCK: c_int = WSABASEERR + 35; -pub const WSAEINPROGRESS: c_int = WSABASEERR + 36; -pub const WSAEALREADY: c_int = WSABASEERR + 37; -pub const WSAENOTSOCK: c_int = WSABASEERR + 38; -pub const WSAEDESTADDRREQ: c_int = WSABASEERR + 39; -pub const WSAEMSGSIZE: c_int = WSABASEERR + 40; -pub const WSAEPROTOTYPE: c_int = WSABASEERR + 41; -pub const WSAENOPROTOOPT: c_int = WSABASEERR + 42; -pub const WSAEPROTONOSUPPORT: c_int = WSABASEERR + 43; -pub const WSAESOCKTNOSUPPORT: c_int = WSABASEERR + 44; -pub const WSAEOPNOTSUPP: c_int = WSABASEERR + 45; -pub const WSAEPFNOSUPPORT: c_int = WSABASEERR + 46; -pub const WSAEAFNOSUPPORT: c_int = WSABASEERR + 47; -pub const WSAEADDRINUSE: c_int = WSABASEERR + 48; -pub const WSAEADDRNOTAVAIL: c_int = WSABASEERR + 49; -pub const WSAENETDOWN: c_int = WSABASEERR + 50; -pub const WSAENETUNREACH: c_int = WSABASEERR + 51; -pub const WSAENETRESET: c_int = WSABASEERR + 52; -pub const WSAECONNABORTED: c_int = WSABASEERR + 53; -pub const WSAECONNRESET: c_int = WSABASEERR + 54; -pub const WSAENOBUFS: c_int = WSABASEERR + 55; -pub const WSAEISCONN: c_int = WSABASEERR + 56; -pub const WSAENOTCONN: c_int = WSABASEERR + 57; -pub const WSAESHUTDOWN: c_int = WSABASEERR + 58; -pub const WSAETOOMANYREFS: c_int = WSABASEERR + 59; -pub const WSAETIMEDOUT: c_int = WSABASEERR + 60; -pub const WSAECONNREFUSED: c_int = WSABASEERR + 61; -pub const WSAELOOP: c_int = WSABASEERR + 62; -pub const WSAENAMETOOLONG: c_int = WSABASEERR + 63; -pub const WSAEHOSTDOWN: c_int = WSABASEERR + 64; -pub const WSAEHOSTUNREACH: c_int = WSABASEERR + 65; -pub const WSAENOTEMPTY: c_int = WSABASEERR + 66; -pub const WSAEPROCLIM: c_int = WSABASEERR + 67; -pub const WSAEUSERS: c_int = WSABASEERR + 68; -pub const WSAEDQUOT: c_int = WSABASEERR + 69; -pub const WSAESTALE: c_int = WSABASEERR + 70; -pub const WSAEREMOTE: c_int = WSABASEERR + 71; -pub const WSASYSNOTREADY: c_int = WSABASEERR + 91; -pub const WSAVERNOTSUPPORTED: c_int = WSABASEERR + 92; -pub const WSANOTINITIALISED: c_int = WSABASEERR + 93; -pub const WSAEDISCON: c_int = WSABASEERR + 101; -pub const WSAENOMORE: c_int = WSABASEERR + 102; -pub const WSAECANCELLED: c_int = WSABASEERR + 103; -pub const WSAEINVALIDPROCTABLE: c_int = WSABASEERR + 104; -pub const WSAEINVALIDPROVIDER: c_int = WSABASEERR + 105; -pub const WSAEPROVIDERFAILEDINIT: c_int = WSABASEERR + 106; -pub const WSASYSCALLFAILURE: c_int = WSABASEERR + 107; -pub const WSASERVICE_NOT_FOUND: c_int = WSABASEERR + 108; -pub const WSATYPE_NOT_FOUND: c_int = WSABASEERR + 109; -pub const WSA_E_NO_MORE: c_int = WSABASEERR + 110; -pub const WSA_E_CANCELLED: c_int = WSABASEERR + 111; -pub const WSAEREFUSED: c_int = WSABASEERR + 112; -pub const WSAHOST_NOT_FOUND: c_int = WSABASEERR + 1001; -pub const WSATRY_AGAIN: c_int = WSABASEERR + 1002; -pub const WSANO_RECOVERY: c_int = WSABASEERR + 1003; -pub const WSANO_DATA: c_int = WSABASEERR + 1004; -pub const WSA_QOS_RECEIVERS: c_int = WSABASEERR + 1005; -pub const WSA_QOS_SENDERS: c_int = WSABASEERR + 1006; -pub const WSA_QOS_NO_SENDERS: c_int = WSABASEERR + 1007; -pub const WSA_QOS_NO_RECEIVERS: c_int = WSABASEERR + 1008; -pub const WSA_QOS_REQUEST_CONFIRMED: c_int = WSABASEERR + 1009; -pub const WSA_QOS_ADMISSION_FAILURE: c_int = WSABASEERR + 1010; -pub const WSA_QOS_POLICY_FAILURE: c_int = WSABASEERR + 1011; -pub const WSA_QOS_BAD_STYLE: c_int = WSABASEERR + 1012; -pub const WSA_QOS_BAD_OBJECT: c_int = WSABASEERR + 1013; -pub const WSA_QOS_TRAFFIC_CTRL_ERROR: c_int = WSABASEERR + 1014; -pub const WSA_QOS_GENERIC_ERROR: c_int = WSABASEERR + 1015; -pub const WSA_QOS_ESERVICETYPE: c_int = WSABASEERR + 1016; -pub const WSA_QOS_EFLOWSPEC: c_int = WSABASEERR + 1017; -pub const WSA_QOS_EPROVSPECBUF: c_int = WSABASEERR + 1018; -pub const WSA_QOS_EFILTERSTYLE: c_int = WSABASEERR + 1019; -pub const WSA_QOS_EFILTERTYPE: c_int = WSABASEERR + 1020; -pub const WSA_QOS_EFILTERCOUNT: c_int = WSABASEERR + 1021; -pub const WSA_QOS_EOBJLENGTH: c_int = WSABASEERR + 1022; -pub const WSA_QOS_EFLOWCOUNT: c_int = WSABASEERR + 1023; -pub const WSA_QOS_EUNKNOWNPSOBJ: c_int = WSABASEERR + 1024; -pub const WSA_QOS_EUNKOWNPSOBJ: c_int = WSA_QOS_EUNKNOWNPSOBJ; -pub const WSA_QOS_EPOLICYOBJ: c_int = WSABASEERR + 1025; -pub const WSA_QOS_EFLOWDESC: c_int = WSABASEERR + 1026; -pub const WSA_QOS_EPSFLOWSPEC: c_int = WSABASEERR + 1027; -pub const WSA_QOS_EPSFILTERSPEC: c_int = WSABASEERR + 1028; -pub const WSA_QOS_ESDMODEOBJ: c_int = WSABASEERR + 1029; -pub const WSA_QOS_ESHAPERATEOBJ: c_int = WSABASEERR + 1030; -pub const WSA_QOS_RESERVED_PETYPE: c_int = WSABASEERR + 1031; diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst new file mode 100644 index 00000000000..3e454199f13 --- /dev/null +++ b/library/std/src/sys/windows/c/windows_sys.lst @@ -0,0 +1,2590 @@ +// tidy-alphabetical-start +Windows.Wdk.Storage.FileSystem.FILE_COMPLETE_IF_OPLOCKED +Windows.Wdk.Storage.FileSystem.FILE_CONTAINS_EXTENDED_CREATE_INFORMATION +Windows.Wdk.Storage.FileSystem.FILE_CREATE +Windows.Wdk.Storage.FileSystem.FILE_CREATE_TREE_CONNECTION +Windows.Wdk.Storage.FileSystem.FILE_DELETE_ON_CLOSE +Windows.Wdk.Storage.FileSystem.FILE_DIRECTORY_FILE +Windows.Wdk.Storage.FileSystem.FILE_DISALLOW_EXCLUSIVE +Windows.Wdk.Storage.FileSystem.FILE_NO_COMPRESSION +Windows.Wdk.Storage.FileSystem.FILE_NO_EA_KNOWLEDGE +Windows.Wdk.Storage.FileSystem.FILE_NO_INTERMEDIATE_BUFFERING +Windows.Wdk.Storage.FileSystem.FILE_NON_DIRECTORY_FILE +Windows.Wdk.Storage.FileSystem.FILE_OPEN +Windows.Wdk.Storage.FileSystem.FILE_OPEN_BY_FILE_ID +Windows.Wdk.Storage.FileSystem.FILE_OPEN_FOR_BACKUP_INTENT +Windows.Wdk.Storage.FileSystem.FILE_OPEN_FOR_FREE_SPACE_QUERY +Windows.Wdk.Storage.FileSystem.FILE_OPEN_IF +Windows.Wdk.Storage.FileSystem.FILE_OPEN_NO_RECALL +Windows.Wdk.Storage.FileSystem.FILE_OPEN_REPARSE_POINT +Windows.Wdk.Storage.FileSystem.FILE_OPEN_REQUIRING_OPLOCK +Windows.Wdk.Storage.FileSystem.FILE_OVERWRITE +Windows.Wdk.Storage.FileSystem.FILE_OVERWRITE_IF +Windows.Wdk.Storage.FileSystem.FILE_RANDOM_ACCESS +Windows.Wdk.Storage.FileSystem.FILE_RESERVE_OPFILTER +Windows.Wdk.Storage.FileSystem.FILE_SEQUENTIAL_ONLY +Windows.Wdk.Storage.FileSystem.FILE_SESSION_AWARE +Windows.Wdk.Storage.FileSystem.FILE_SUPERSEDE +Windows.Wdk.Storage.FileSystem.FILE_SYNCHRONOUS_IO_ALERT +Windows.Wdk.Storage.FileSystem.FILE_SYNCHRONOUS_IO_NONALERT +Windows.Wdk.Storage.FileSystem.FILE_WRITE_THROUGH +Windows.Wdk.Storage.FileSystem.NtCreateFile +Windows.Wdk.Storage.FileSystem.NTCREATEFILE_CREATE_DISPOSITION +Windows.Wdk.Storage.FileSystem.NTCREATEFILE_CREATE_OPTIONS +Windows.Wdk.Storage.FileSystem.NtReadFile +Windows.Wdk.Storage.FileSystem.NtWriteFile +Windows.Wdk.Storage.FileSystem.SYMLINK_FLAG_RELATIVE +Windows.Win32.Foundation.BOOL +Windows.Win32.Foundation.BOOLEAN +Windows.Win32.Foundation.CloseHandle +Windows.Win32.Foundation.DNS_ERROR_ADDRESS_REQUIRED +Windows.Win32.Foundation.DNS_ERROR_ALIAS_LOOP +Windows.Win32.Foundation.DNS_ERROR_AUTOZONE_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_AXFR +Windows.Win32.Foundation.DNS_ERROR_BACKGROUND_LOADING +Windows.Win32.Foundation.DNS_ERROR_BAD_KEYMASTER +Windows.Win32.Foundation.DNS_ERROR_BAD_PACKET +Windows.Win32.Foundation.DNS_ERROR_CANNOT_FIND_ROOT_HINTS +Windows.Win32.Foundation.DNS_ERROR_CLIENT_SUBNET_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_CLIENT_SUBNET_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_CLIENT_SUBNET_IS_ACCESSED +Windows.Win32.Foundation.DNS_ERROR_CNAME_COLLISION +Windows.Win32.Foundation.DNS_ERROR_CNAME_LOOP +Windows.Win32.Foundation.DNS_ERROR_DATAFILE_OPEN_FAILURE +Windows.Win32.Foundation.DNS_ERROR_DATAFILE_PARSING +Windows.Win32.Foundation.DNS_ERROR_DEFAULT_SCOPE +Windows.Win32.Foundation.DNS_ERROR_DEFAULT_VIRTUALIZATION_INSTANCE +Windows.Win32.Foundation.DNS_ERROR_DEFAULT_ZONESCOPE +Windows.Win32.Foundation.DNS_ERROR_DELEGATION_REQUIRED +Windows.Win32.Foundation.DNS_ERROR_DNAME_COLLISION +Windows.Win32.Foundation.DNS_ERROR_DNSSEC_IS_DISABLED +Windows.Win32.Foundation.DNS_ERROR_DP_ALREADY_ENLISTED +Windows.Win32.Foundation.DNS_ERROR_DP_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_DP_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_DP_FSMO_ERROR +Windows.Win32.Foundation.DNS_ERROR_DP_NOT_AVAILABLE +Windows.Win32.Foundation.DNS_ERROR_DP_NOT_ENLISTED +Windows.Win32.Foundation.DNS_ERROR_DS_UNAVAILABLE +Windows.Win32.Foundation.DNS_ERROR_DS_ZONE_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_DWORD_VALUE_TOO_LARGE +Windows.Win32.Foundation.DNS_ERROR_DWORD_VALUE_TOO_SMALL +Windows.Win32.Foundation.DNS_ERROR_FILE_WRITEBACK_FAILED +Windows.Win32.Foundation.DNS_ERROR_FORWARDER_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_INCONSISTENT_ROOT_HINTS +Windows.Win32.Foundation.DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME +Windows.Win32.Foundation.DNS_ERROR_INVALID_CLIENT_SUBNET_NAME +Windows.Win32.Foundation.DNS_ERROR_INVALID_DATA +Windows.Win32.Foundation.DNS_ERROR_INVALID_DATAFILE_NAME +Windows.Win32.Foundation.DNS_ERROR_INVALID_INITIAL_ROLLOVER_OFFSET +Windows.Win32.Foundation.DNS_ERROR_INVALID_IP_ADDRESS +Windows.Win32.Foundation.DNS_ERROR_INVALID_KEY_SIZE +Windows.Win32.Foundation.DNS_ERROR_INVALID_NAME +Windows.Win32.Foundation.DNS_ERROR_INVALID_NAME_CHAR +Windows.Win32.Foundation.DNS_ERROR_INVALID_NSEC3_ITERATION_COUNT +Windows.Win32.Foundation.DNS_ERROR_INVALID_POLICY_TABLE +Windows.Win32.Foundation.DNS_ERROR_INVALID_PROPERTY +Windows.Win32.Foundation.DNS_ERROR_INVALID_ROLLOVER_PERIOD +Windows.Win32.Foundation.DNS_ERROR_INVALID_SCOPE_NAME +Windows.Win32.Foundation.DNS_ERROR_INVALID_SCOPE_OPERATION +Windows.Win32.Foundation.DNS_ERROR_INVALID_SIGNATURE_VALIDITY_PERIOD +Windows.Win32.Foundation.DNS_ERROR_INVALID_TYPE +Windows.Win32.Foundation.DNS_ERROR_INVALID_XML +Windows.Win32.Foundation.DNS_ERROR_INVALID_ZONE_OPERATION +Windows.Win32.Foundation.DNS_ERROR_INVALID_ZONE_TYPE +Windows.Win32.Foundation.DNS_ERROR_INVALID_ZONESCOPE_NAME +Windows.Win32.Foundation.DNS_ERROR_KEYMASTER_REQUIRED +Windows.Win32.Foundation.DNS_ERROR_KSP_DOES_NOT_SUPPORT_PROTECTION +Windows.Win32.Foundation.DNS_ERROR_KSP_NOT_ACCESSIBLE +Windows.Win32.Foundation.DNS_ERROR_LOAD_ZONESCOPE_FAILED +Windows.Win32.Foundation.DNS_ERROR_NAME_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_NAME_NOT_IN_ZONE +Windows.Win32.Foundation.DNS_ERROR_NBSTAT_INIT_FAILED +Windows.Win32.Foundation.DNS_ERROR_NEED_SECONDARY_ADDRESSES +Windows.Win32.Foundation.DNS_ERROR_NEED_WINS_SERVERS +Windows.Win32.Foundation.DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE +Windows.Win32.Foundation.DNS_ERROR_NO_CREATE_CACHE_DATA +Windows.Win32.Foundation.DNS_ERROR_NO_DNS_SERVERS +Windows.Win32.Foundation.DNS_ERROR_NO_MEMORY +Windows.Win32.Foundation.DNS_ERROR_NO_PACKET +Windows.Win32.Foundation.DNS_ERROR_NO_TCPIP +Windows.Win32.Foundation.DNS_ERROR_NO_VALID_TRUST_ANCHORS +Windows.Win32.Foundation.DNS_ERROR_NO_ZONE_INFO +Windows.Win32.Foundation.DNS_ERROR_NODE_CREATION_FAILED +Windows.Win32.Foundation.DNS_ERROR_NODE_IS_CNAME +Windows.Win32.Foundation.DNS_ERROR_NODE_IS_DNAME +Windows.Win32.Foundation.DNS_ERROR_NON_RFC_NAME +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_ON_ACTIVE_SKD +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_ON_RODC +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_ON_SIGNED_ZONE +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_ON_UNSIGNED_ZONE +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_ON_ZSK +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_UNDER_DNAME +Windows.Win32.Foundation.DNS_ERROR_NOT_ALLOWED_WITH_ZONESCOPES +Windows.Win32.Foundation.DNS_ERROR_NOT_ENOUGH_SIGNING_KEY_DESCRIPTORS +Windows.Win32.Foundation.DNS_ERROR_NOT_UNIQUE +Windows.Win32.Foundation.DNS_ERROR_NSEC3_INCOMPATIBLE_WITH_RSA_SHA1 +Windows.Win32.Foundation.DNS_ERROR_NSEC3_NAME_COLLISION +Windows.Win32.Foundation.DNS_ERROR_NSEC_INCOMPATIBLE_WITH_NSEC3_RSA_SHA1 +Windows.Win32.Foundation.DNS_ERROR_NUMERIC_NAME +Windows.Win32.Foundation.DNS_ERROR_POLICY_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_POLICY_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_CRITERIA +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_CRITERIA_CLIENT_SUBNET +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_CRITERIA_FQDN +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_CRITERIA_INTERFACE +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_CRITERIA_NETWORK_PROTOCOL +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_CRITERIA_QUERY_TYPE +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_CRITERIA_TIME_OF_DAY +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_CRITERIA_TRANSPORT_PROTOCOL +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_NAME +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_SETTINGS +Windows.Win32.Foundation.DNS_ERROR_POLICY_INVALID_WEIGHT +Windows.Win32.Foundation.DNS_ERROR_POLICY_LOCKED +Windows.Win32.Foundation.DNS_ERROR_POLICY_MISSING_CRITERIA +Windows.Win32.Foundation.DNS_ERROR_POLICY_PROCESSING_ORDER_INVALID +Windows.Win32.Foundation.DNS_ERROR_POLICY_SCOPE_MISSING +Windows.Win32.Foundation.DNS_ERROR_POLICY_SCOPE_NOT_ALLOWED +Windows.Win32.Foundation.DNS_ERROR_PRIMARY_REQUIRES_DATAFILE +Windows.Win32.Foundation.DNS_ERROR_RCODE +Windows.Win32.Foundation.DNS_ERROR_RCODE_BADKEY +Windows.Win32.Foundation.DNS_ERROR_RCODE_BADSIG +Windows.Win32.Foundation.DNS_ERROR_RCODE_BADTIME +Windows.Win32.Foundation.DNS_ERROR_RCODE_FORMAT_ERROR +Windows.Win32.Foundation.DNS_ERROR_RCODE_NAME_ERROR +Windows.Win32.Foundation.DNS_ERROR_RCODE_NOT_IMPLEMENTED +Windows.Win32.Foundation.DNS_ERROR_RCODE_NOTAUTH +Windows.Win32.Foundation.DNS_ERROR_RCODE_NOTZONE +Windows.Win32.Foundation.DNS_ERROR_RCODE_NXRRSET +Windows.Win32.Foundation.DNS_ERROR_RCODE_REFUSED +Windows.Win32.Foundation.DNS_ERROR_RCODE_SERVER_FAILURE +Windows.Win32.Foundation.DNS_ERROR_RCODE_YXDOMAIN +Windows.Win32.Foundation.DNS_ERROR_RCODE_YXRRSET +Windows.Win32.Foundation.DNS_ERROR_RECORD_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_RECORD_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_RECORD_FORMAT +Windows.Win32.Foundation.DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT +Windows.Win32.Foundation.DNS_ERROR_RECORD_TIMED_OUT +Windows.Win32.Foundation.DNS_ERROR_ROLLOVER_ALREADY_QUEUED +Windows.Win32.Foundation.DNS_ERROR_ROLLOVER_IN_PROGRESS +Windows.Win32.Foundation.DNS_ERROR_ROLLOVER_NOT_POKEABLE +Windows.Win32.Foundation.DNS_ERROR_RRL_INVALID_IPV4_PREFIX +Windows.Win32.Foundation.DNS_ERROR_RRL_INVALID_IPV6_PREFIX +Windows.Win32.Foundation.DNS_ERROR_RRL_INVALID_LEAK_RATE +Windows.Win32.Foundation.DNS_ERROR_RRL_INVALID_TC_RATE +Windows.Win32.Foundation.DNS_ERROR_RRL_INVALID_WINDOW_SIZE +Windows.Win32.Foundation.DNS_ERROR_RRL_LEAK_RATE_LESSTHAN_TC_RATE +Windows.Win32.Foundation.DNS_ERROR_RRL_NOT_ENABLED +Windows.Win32.Foundation.DNS_ERROR_SCOPE_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_SCOPE_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_SCOPE_LOCKED +Windows.Win32.Foundation.DNS_ERROR_SECONDARY_DATA +Windows.Win32.Foundation.DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP +Windows.Win32.Foundation.DNS_ERROR_SERVERSCOPE_IS_REFERENCED +Windows.Win32.Foundation.DNS_ERROR_SIGNING_KEY_NOT_ACCESSIBLE +Windows.Win32.Foundation.DNS_ERROR_SOA_DELETE_INVALID +Windows.Win32.Foundation.DNS_ERROR_STANDBY_KEY_NOT_PRESENT +Windows.Win32.Foundation.DNS_ERROR_SUBNET_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_SUBNET_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_TOO_MANY_SKDS +Windows.Win32.Foundation.DNS_ERROR_TRY_AGAIN_LATER +Windows.Win32.Foundation.DNS_ERROR_UNEXPECTED_CNG_ERROR +Windows.Win32.Foundation.DNS_ERROR_UNEXPECTED_DATA_PROTECTION_ERROR +Windows.Win32.Foundation.DNS_ERROR_UNKNOWN_RECORD_TYPE +Windows.Win32.Foundation.DNS_ERROR_UNKNOWN_SIGNING_PARAMETER_VERSION +Windows.Win32.Foundation.DNS_ERROR_UNSECURE_PACKET +Windows.Win32.Foundation.DNS_ERROR_UNSUPPORTED_ALGORITHM +Windows.Win32.Foundation.DNS_ERROR_VIRTUALIZATION_INSTANCE_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_VIRTUALIZATION_INSTANCE_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_VIRTUALIZATION_TREE_LOCKED +Windows.Win32.Foundation.DNS_ERROR_WINS_INIT_FAILED +Windows.Win32.Foundation.DNS_ERROR_ZONE_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_ZONE_CONFIGURATION_ERROR +Windows.Win32.Foundation.DNS_ERROR_ZONE_CREATION_FAILED +Windows.Win32.Foundation.DNS_ERROR_ZONE_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_ZONE_HAS_NO_NS_RECORDS +Windows.Win32.Foundation.DNS_ERROR_ZONE_HAS_NO_SOA_RECORD +Windows.Win32.Foundation.DNS_ERROR_ZONE_IS_SHUTDOWN +Windows.Win32.Foundation.DNS_ERROR_ZONE_LOCKED +Windows.Win32.Foundation.DNS_ERROR_ZONE_LOCKED_FOR_SIGNING +Windows.Win32.Foundation.DNS_ERROR_ZONE_NOT_SECONDARY +Windows.Win32.Foundation.DNS_ERROR_ZONE_REQUIRES_MASTER_IP +Windows.Win32.Foundation.DNS_ERROR_ZONESCOPE_ALREADY_EXISTS +Windows.Win32.Foundation.DNS_ERROR_ZONESCOPE_DOES_NOT_EXIST +Windows.Win32.Foundation.DNS_ERROR_ZONESCOPE_FILE_WRITEBACK_FAILED +Windows.Win32.Foundation.DNS_ERROR_ZONESCOPE_IS_REFERENCED +Windows.Win32.Foundation.DUPLICATE_CLOSE_SOURCE +Windows.Win32.Foundation.DUPLICATE_HANDLE_OPTIONS +Windows.Win32.Foundation.DUPLICATE_SAME_ACCESS +Windows.Win32.Foundation.DuplicateHandle +Windows.Win32.Foundation.E_NOTIMPL +Windows.Win32.Foundation.ERROR_ABANDON_HIBERFILE +Windows.Win32.Foundation.ERROR_ABANDONED_WAIT_0 +Windows.Win32.Foundation.ERROR_ABANDONED_WAIT_63 +Windows.Win32.Foundation.ERROR_ABIOS_ERROR +Windows.Win32.Foundation.ERROR_ACCESS_AUDIT_BY_POLICY +Windows.Win32.Foundation.ERROR_ACCESS_DENIED +Windows.Win32.Foundation.ERROR_ACCESS_DENIED_APPDATA +Windows.Win32.Foundation.ERROR_ACCESS_DISABLED_BY_POLICY +Windows.Win32.Foundation.ERROR_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY +Windows.Win32.Foundation.ERROR_ACCESS_DISABLED_WEBBLADE +Windows.Win32.Foundation.ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER +Windows.Win32.Foundation.ERROR_ACCOUNT_DISABLED +Windows.Win32.Foundation.ERROR_ACCOUNT_EXPIRED +Windows.Win32.Foundation.ERROR_ACCOUNT_LOCKED_OUT +Windows.Win32.Foundation.ERROR_ACCOUNT_RESTRICTION +Windows.Win32.Foundation.ERROR_ACPI_ERROR +Windows.Win32.Foundation.ERROR_ACTIVE_CONNECTIONS +Windows.Win32.Foundation.ERROR_ADAP_HDW_ERR +Windows.Win32.Foundation.ERROR_ADDRESS_ALREADY_ASSOCIATED +Windows.Win32.Foundation.ERROR_ADDRESS_NOT_ASSOCIATED +Windows.Win32.Foundation.ERROR_ALERTED +Windows.Win32.Foundation.ERROR_ALIAS_EXISTS +Windows.Win32.Foundation.ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED +Windows.Win32.Foundation.ERROR_ALLOCATE_BUCKET +Windows.Win32.Foundation.ERROR_ALLOTTED_SPACE_EXCEEDED +Windows.Win32.Foundation.ERROR_ALREADY_ASSIGNED +Windows.Win32.Foundation.ERROR_ALREADY_EXISTS +Windows.Win32.Foundation.ERROR_ALREADY_FIBER +Windows.Win32.Foundation.ERROR_ALREADY_HAS_STREAM_ID +Windows.Win32.Foundation.ERROR_ALREADY_INITIALIZED +Windows.Win32.Foundation.ERROR_ALREADY_REGISTERED +Windows.Win32.Foundation.ERROR_ALREADY_RUNNING_LKG +Windows.Win32.Foundation.ERROR_ALREADY_THREAD +Windows.Win32.Foundation.ERROR_ALREADY_WAITING +Windows.Win32.Foundation.ERROR_ALREADY_WIN32 +Windows.Win32.Foundation.ERROR_API_UNAVAILABLE +Windows.Win32.Foundation.ERROR_APP_HANG +Windows.Win32.Foundation.ERROR_APP_INIT_FAILURE +Windows.Win32.Foundation.ERROR_APP_WRONG_OS +Windows.Win32.Foundation.ERROR_APPCONTAINER_REQUIRED +Windows.Win32.Foundation.ERROR_APPEXEC_APP_COMPAT_BLOCK +Windows.Win32.Foundation.ERROR_APPEXEC_CALLER_WAIT_TIMEOUT +Windows.Win32.Foundation.ERROR_APPEXEC_CALLER_WAIT_TIMEOUT_LICENSING +Windows.Win32.Foundation.ERROR_APPEXEC_CALLER_WAIT_TIMEOUT_RESOURCES +Windows.Win32.Foundation.ERROR_APPEXEC_CALLER_WAIT_TIMEOUT_TERMINATION +Windows.Win32.Foundation.ERROR_APPEXEC_CONDITION_NOT_SATISFIED +Windows.Win32.Foundation.ERROR_APPEXEC_HANDLE_INVALIDATED +Windows.Win32.Foundation.ERROR_APPEXEC_HOST_ID_MISMATCH +Windows.Win32.Foundation.ERROR_APPEXEC_INVALID_HOST_GENERATION +Windows.Win32.Foundation.ERROR_APPEXEC_INVALID_HOST_STATE +Windows.Win32.Foundation.ERROR_APPEXEC_NO_DONOR +Windows.Win32.Foundation.ERROR_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION +Windows.Win32.Foundation.ERROR_APPEXEC_UNKNOWN_USER +Windows.Win32.Foundation.ERROR_APPHELP_BLOCK +Windows.Win32.Foundation.ERROR_APPX_FILE_NOT_ENCRYPTED +Windows.Win32.Foundation.ERROR_ARBITRATION_UNHANDLED +Windows.Win32.Foundation.ERROR_ARENA_TRASHED +Windows.Win32.Foundation.ERROR_ARITHMETIC_OVERFLOW +Windows.Win32.Foundation.ERROR_ASSERTION_FAILURE +Windows.Win32.Foundation.ERROR_ATOMIC_LOCKS_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_AUDIT_FAILED +Windows.Win32.Foundation.ERROR_AUTHENTICATION_FIREWALL_FAILED +Windows.Win32.Foundation.ERROR_AUTHIP_FAILURE +Windows.Win32.Foundation.ERROR_AUTODATASEG_EXCEEDS_64k +Windows.Win32.Foundation.ERROR_BACKUP_CONTROLLER +Windows.Win32.Foundation.ERROR_BAD_ACCESSOR_FLAGS +Windows.Win32.Foundation.ERROR_BAD_ARGUMENTS +Windows.Win32.Foundation.ERROR_BAD_COMMAND +Windows.Win32.Foundation.ERROR_BAD_COMPRESSION_BUFFER +Windows.Win32.Foundation.ERROR_BAD_CONFIGURATION +Windows.Win32.Foundation.ERROR_BAD_CURRENT_DIRECTORY +Windows.Win32.Foundation.ERROR_BAD_DESCRIPTOR_FORMAT +Windows.Win32.Foundation.ERROR_BAD_DEV_TYPE +Windows.Win32.Foundation.ERROR_BAD_DEVICE +Windows.Win32.Foundation.ERROR_BAD_DEVICE_PATH +Windows.Win32.Foundation.ERROR_BAD_DLL_ENTRYPOINT +Windows.Win32.Foundation.ERROR_BAD_DRIVER_LEVEL +Windows.Win32.Foundation.ERROR_BAD_ENVIRONMENT +Windows.Win32.Foundation.ERROR_BAD_EXE_FORMAT +Windows.Win32.Foundation.ERROR_BAD_FILE_TYPE +Windows.Win32.Foundation.ERROR_BAD_FORMAT +Windows.Win32.Foundation.ERROR_BAD_FUNCTION_TABLE +Windows.Win32.Foundation.ERROR_BAD_IMPERSONATION_LEVEL +Windows.Win32.Foundation.ERROR_BAD_INHERITANCE_ACL +Windows.Win32.Foundation.ERROR_BAD_LENGTH +Windows.Win32.Foundation.ERROR_BAD_LOGON_SESSION_STATE +Windows.Win32.Foundation.ERROR_BAD_MCFG_TABLE +Windows.Win32.Foundation.ERROR_BAD_NET_NAME +Windows.Win32.Foundation.ERROR_BAD_NET_RESP +Windows.Win32.Foundation.ERROR_BAD_NETPATH +Windows.Win32.Foundation.ERROR_BAD_PATHNAME +Windows.Win32.Foundation.ERROR_BAD_PIPE +Windows.Win32.Foundation.ERROR_BAD_PROFILE +Windows.Win32.Foundation.ERROR_BAD_PROVIDER +Windows.Win32.Foundation.ERROR_BAD_QUERY_SYNTAX +Windows.Win32.Foundation.ERROR_BAD_RECOVERY_POLICY +Windows.Win32.Foundation.ERROR_BAD_REM_ADAP +Windows.Win32.Foundation.ERROR_BAD_SERVICE_ENTRYPOINT +Windows.Win32.Foundation.ERROR_BAD_STACK +Windows.Win32.Foundation.ERROR_BAD_THREADID_ADDR +Windows.Win32.Foundation.ERROR_BAD_TOKEN_TYPE +Windows.Win32.Foundation.ERROR_BAD_UNIT +Windows.Win32.Foundation.ERROR_BAD_USER_PROFILE +Windows.Win32.Foundation.ERROR_BAD_USERNAME +Windows.Win32.Foundation.ERROR_BAD_VALIDATION_CLASS +Windows.Win32.Foundation.ERROR_BADDB +Windows.Win32.Foundation.ERROR_BADKEY +Windows.Win32.Foundation.ERROR_BADSTARTPOSITION +Windows.Win32.Foundation.ERROR_BEGINNING_OF_MEDIA +Windows.Win32.Foundation.ERROR_BEYOND_VDL +Windows.Win32.Foundation.ERROR_BIOS_FAILED_TO_CONNECT_INTERRUPT +Windows.Win32.Foundation.ERROR_BLOCK_SHARED +Windows.Win32.Foundation.ERROR_BLOCK_SOURCE_WEAK_REFERENCE_INVALID +Windows.Win32.Foundation.ERROR_BLOCK_TARGET_WEAK_REFERENCE_INVALID +Windows.Win32.Foundation.ERROR_BLOCK_TOO_MANY_REFERENCES +Windows.Win32.Foundation.ERROR_BLOCK_WEAK_REFERENCE_INVALID +Windows.Win32.Foundation.ERROR_BLOCKED_BY_PARENTAL_CONTROLS +Windows.Win32.Foundation.ERROR_BOOT_ALREADY_ACCEPTED +Windows.Win32.Foundation.ERROR_BROKEN_PIPE +Windows.Win32.Foundation.ERROR_BUFFER_ALL_ZEROS +Windows.Win32.Foundation.ERROR_BUFFER_OVERFLOW +Windows.Win32.Foundation.ERROR_BUS_RESET +Windows.Win32.Foundation.ERROR_BUSY +Windows.Win32.Foundation.ERROR_BUSY_DRIVE +Windows.Win32.Foundation.ERROR_BYPASSIO_FLT_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_CACHE_PAGE_LOCKED +Windows.Win32.Foundation.ERROR_CALL_NOT_IMPLEMENTED +Windows.Win32.Foundation.ERROR_CALLBACK_INVOKE_INLINE +Windows.Win32.Foundation.ERROR_CALLBACK_POP_STACK +Windows.Win32.Foundation.ERROR_CALLBACK_SUPPLIED_INVALID_DATA +Windows.Win32.Foundation.ERROR_CAN_NOT_COMPLETE +Windows.Win32.Foundation.ERROR_CANCEL_VIOLATION +Windows.Win32.Foundation.ERROR_CANCELLED +Windows.Win32.Foundation.ERROR_CANNOT_BREAK_OPLOCK +Windows.Win32.Foundation.ERROR_CANNOT_COPY +Windows.Win32.Foundation.ERROR_CANNOT_DETECT_DRIVER_FAILURE +Windows.Win32.Foundation.ERROR_CANNOT_DETECT_PROCESS_ABORT +Windows.Win32.Foundation.ERROR_CANNOT_FIND_WND_CLASS +Windows.Win32.Foundation.ERROR_CANNOT_GRANT_REQUESTED_OPLOCK +Windows.Win32.Foundation.ERROR_CANNOT_IMPERSONATE +Windows.Win32.Foundation.ERROR_CANNOT_LOAD_REGISTRY_FILE +Windows.Win32.Foundation.ERROR_CANNOT_MAKE +Windows.Win32.Foundation.ERROR_CANNOT_OPEN_PROFILE +Windows.Win32.Foundation.ERROR_CANT_ACCESS_DOMAIN_INFO +Windows.Win32.Foundation.ERROR_CANT_ACCESS_FILE +Windows.Win32.Foundation.ERROR_CANT_CLEAR_ENCRYPTION_FLAG +Windows.Win32.Foundation.ERROR_CANT_DISABLE_MANDATORY +Windows.Win32.Foundation.ERROR_CANT_ENABLE_DENY_ONLY +Windows.Win32.Foundation.ERROR_CANT_OPEN_ANONYMOUS +Windows.Win32.Foundation.ERROR_CANT_RESOLVE_FILENAME +Windows.Win32.Foundation.ERROR_CANT_TERMINATE_SELF +Windows.Win32.Foundation.ERROR_CANT_WAIT +Windows.Win32.Foundation.ERROR_CANTFETCHBACKWARDS +Windows.Win32.Foundation.ERROR_CANTOPEN +Windows.Win32.Foundation.ERROR_CANTREAD +Windows.Win32.Foundation.ERROR_CANTSCROLLBACKWARDS +Windows.Win32.Foundation.ERROR_CANTWRITE +Windows.Win32.Foundation.ERROR_CAPAUTHZ_CHANGE_TYPE +Windows.Win32.Foundation.ERROR_CAPAUTHZ_DB_CORRUPTED +Windows.Win32.Foundation.ERROR_CAPAUTHZ_NO_POLICY +Windows.Win32.Foundation.ERROR_CAPAUTHZ_NOT_AUTHORIZED +Windows.Win32.Foundation.ERROR_CAPAUTHZ_NOT_DEVUNLOCKED +Windows.Win32.Foundation.ERROR_CAPAUTHZ_NOT_PROVISIONED +Windows.Win32.Foundation.ERROR_CAPAUTHZ_SCCD_DEV_MODE_REQUIRED +Windows.Win32.Foundation.ERROR_CAPAUTHZ_SCCD_INVALID_CATALOG +Windows.Win32.Foundation.ERROR_CAPAUTHZ_SCCD_NO_AUTH_ENTITY +Windows.Win32.Foundation.ERROR_CAPAUTHZ_SCCD_NO_CAPABILITY_MATCH +Windows.Win32.Foundation.ERROR_CAPAUTHZ_SCCD_PARSE_ERROR +Windows.Win32.Foundation.ERROR_CARDBUS_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_CASE_DIFFERING_NAMES_IN_DIR +Windows.Win32.Foundation.ERROR_CASE_SENSITIVE_PATH +Windows.Win32.Foundation.ERROR_CERTIFICATE_VALIDATION_PREFERENCE_CONFLICT +Windows.Win32.Foundation.ERROR_CHECKING_FILE_SYSTEM +Windows.Win32.Foundation.ERROR_CHECKOUT_REQUIRED +Windows.Win32.Foundation.ERROR_CHILD_MUST_BE_VOLATILE +Windows.Win32.Foundation.ERROR_CHILD_NOT_COMPLETE +Windows.Win32.Foundation.ERROR_CHILD_PROCESS_BLOCKED +Windows.Win32.Foundation.ERROR_CHILD_WINDOW_MENU +Windows.Win32.Foundation.ERROR_CIMFS_IMAGE_CORRUPT +Windows.Win32.Foundation.ERROR_CIMFS_IMAGE_VERSION_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_CIRCULAR_DEPENDENCY +Windows.Win32.Foundation.ERROR_CLASS_ALREADY_EXISTS +Windows.Win32.Foundation.ERROR_CLASS_DOES_NOT_EXIST +Windows.Win32.Foundation.ERROR_CLASS_HAS_WINDOWS +Windows.Win32.Foundation.ERROR_CLIENT_SERVER_PARAMETERS_INVALID +Windows.Win32.Foundation.ERROR_CLIPBOARD_NOT_OPEN +Windows.Win32.Foundation.ERROR_CLOUD_FILE_ACCESS_DENIED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_ALREADY_CONNECTED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_AUTHENTICATION_FAILED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_CONNECTED_PROVIDER_ONLY +Windows.Win32.Foundation.ERROR_CLOUD_FILE_DEHYDRATION_DISALLOWED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_IN_USE +Windows.Win32.Foundation.ERROR_CLOUD_FILE_INCOMPATIBLE_HARDLINKS +Windows.Win32.Foundation.ERROR_CLOUD_FILE_INSUFFICIENT_RESOURCES +Windows.Win32.Foundation.ERROR_CLOUD_FILE_INVALID_REQUEST +Windows.Win32.Foundation.ERROR_CLOUD_FILE_METADATA_CORRUPT +Windows.Win32.Foundation.ERROR_CLOUD_FILE_METADATA_TOO_LARGE +Windows.Win32.Foundation.ERROR_CLOUD_FILE_NETWORK_UNAVAILABLE +Windows.Win32.Foundation.ERROR_CLOUD_FILE_NOT_IN_SYNC +Windows.Win32.Foundation.ERROR_CLOUD_FILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_NOT_UNDER_SYNC_ROOT +Windows.Win32.Foundation.ERROR_CLOUD_FILE_PINNED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH +Windows.Win32.Foundation.ERROR_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE +Windows.Win32.Foundation.ERROR_CLOUD_FILE_PROPERTY_CORRUPT +Windows.Win32.Foundation.ERROR_CLOUD_FILE_PROPERTY_LOCK_CONFLICT +Windows.Win32.Foundation.ERROR_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_PROVIDER_NOT_RUNNING +Windows.Win32.Foundation.ERROR_CLOUD_FILE_PROVIDER_TERMINATED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_READ_ONLY_VOLUME +Windows.Win32.Foundation.ERROR_CLOUD_FILE_REQUEST_ABORTED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_REQUEST_CANCELED +Windows.Win32.Foundation.ERROR_CLOUD_FILE_REQUEST_TIMEOUT +Windows.Win32.Foundation.ERROR_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT +Windows.Win32.Foundation.ERROR_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS +Windows.Win32.Foundation.ERROR_CLOUD_FILE_UNSUCCESSFUL +Windows.Win32.Foundation.ERROR_CLOUD_FILE_US_MESSAGE_TIMEOUT +Windows.Win32.Foundation.ERROR_CLOUD_FILE_VALIDATION_FAILED +Windows.Win32.Foundation.ERROR_COMMITMENT_LIMIT +Windows.Win32.Foundation.ERROR_COMMITMENT_MINIMUM +Windows.Win32.Foundation.ERROR_COMPRESSED_FILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_COMPRESSION_DISABLED +Windows.Win32.Foundation.ERROR_COMPRESSION_NOT_BENEFICIAL +Windows.Win32.Foundation.ERROR_CONNECTED_OTHER_PASSWORD +Windows.Win32.Foundation.ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT +Windows.Win32.Foundation.ERROR_CONNECTION_ABORTED +Windows.Win32.Foundation.ERROR_CONNECTION_ACTIVE +Windows.Win32.Foundation.ERROR_CONNECTION_COUNT_LIMIT +Windows.Win32.Foundation.ERROR_CONNECTION_INVALID +Windows.Win32.Foundation.ERROR_CONNECTION_REFUSED +Windows.Win32.Foundation.ERROR_CONNECTION_UNAVAIL +Windows.Win32.Foundation.ERROR_CONTAINER_ASSIGNED +Windows.Win32.Foundation.ERROR_CONTENT_BLOCKED +Windows.Win32.Foundation.ERROR_CONTEXT_EXPIRED +Windows.Win32.Foundation.ERROR_CONTINUE +Windows.Win32.Foundation.ERROR_CONTROL_C_EXIT +Windows.Win32.Foundation.ERROR_CONTROL_ID_NOT_FOUND +Windows.Win32.Foundation.ERROR_CONVERT_TO_LARGE +Windows.Win32.Foundation.ERROR_CORRUPT_LOG_CLEARED +Windows.Win32.Foundation.ERROR_CORRUPT_LOG_CORRUPTED +Windows.Win32.Foundation.ERROR_CORRUPT_LOG_DELETED_FULL +Windows.Win32.Foundation.ERROR_CORRUPT_LOG_OVERFULL +Windows.Win32.Foundation.ERROR_CORRUPT_LOG_UNAVAILABLE +Windows.Win32.Foundation.ERROR_CORRUPT_SYSTEM_FILE +Windows.Win32.Foundation.ERROR_COULD_NOT_INTERPRET +Windows.Win32.Foundation.ERROR_COUNTER_TIMEOUT +Windows.Win32.Foundation.ERROR_CPU_SET_INVALID +Windows.Win32.Foundation.ERROR_CRASH_DUMP +Windows.Win32.Foundation.ERROR_CRC +Windows.Win32.Foundation.ERROR_CREATE_FAILED +Windows.Win32.Foundation.ERROR_CROSS_PARTITION_VIOLATION +Windows.Win32.Foundation.ERROR_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE +Windows.Win32.Foundation.ERROR_CS_ENCRYPTION_FILE_NOT_CSE +Windows.Win32.Foundation.ERROR_CS_ENCRYPTION_INVALID_SERVER_RESPONSE +Windows.Win32.Foundation.ERROR_CS_ENCRYPTION_NEW_ENCRYPTED_FILE +Windows.Win32.Foundation.ERROR_CS_ENCRYPTION_UNSUPPORTED_SERVER +Windows.Win32.Foundation.ERROR_CSCSHARE_OFFLINE +Windows.Win32.Foundation.ERROR_CTX_CLIENT_QUERY_TIMEOUT +Windows.Win32.Foundation.ERROR_CTX_MODEM_RESPONSE_TIMEOUT +Windows.Win32.Foundation.ERROR_CURRENT_DIRECTORY +Windows.Win32.Foundation.ERROR_CURRENT_DOMAIN_NOT_ALLOWED +Windows.Win32.Foundation.ERROR_DATA_CHECKSUM_ERROR +Windows.Win32.Foundation.ERROR_DATA_NOT_ACCEPTED +Windows.Win32.Foundation.ERROR_DATABASE_DOES_NOT_EXIST +Windows.Win32.Foundation.ERROR_DATATYPE_MISMATCH +Windows.Win32.Foundation.ERROR_DAX_MAPPING_EXISTS +Windows.Win32.Foundation.ERROR_DBG_COMMAND_EXCEPTION +Windows.Win32.Foundation.ERROR_DBG_CONTINUE +Windows.Win32.Foundation.ERROR_DBG_CONTROL_BREAK +Windows.Win32.Foundation.ERROR_DBG_CONTROL_C +Windows.Win32.Foundation.ERROR_DBG_EXCEPTION_HANDLED +Windows.Win32.Foundation.ERROR_DBG_EXCEPTION_NOT_HANDLED +Windows.Win32.Foundation.ERROR_DBG_PRINTEXCEPTION_C +Windows.Win32.Foundation.ERROR_DBG_REPLY_LATER +Windows.Win32.Foundation.ERROR_DBG_RIPEXCEPTION +Windows.Win32.Foundation.ERROR_DBG_TERMINATE_PROCESS +Windows.Win32.Foundation.ERROR_DBG_TERMINATE_THREAD +Windows.Win32.Foundation.ERROR_DBG_UNABLE_TO_PROVIDE_HANDLE +Windows.Win32.Foundation.ERROR_DC_NOT_FOUND +Windows.Win32.Foundation.ERROR_DDE_FAIL +Windows.Win32.Foundation.ERROR_DEBUG_ATTACH_FAILED +Windows.Win32.Foundation.ERROR_DEBUGGER_INACTIVE +Windows.Win32.Foundation.ERROR_DECRYPTION_FAILED +Windows.Win32.Foundation.ERROR_DELAY_LOAD_FAILED +Windows.Win32.Foundation.ERROR_DELETE_PENDING +Windows.Win32.Foundation.ERROR_DEPENDENT_SERVICES_RUNNING +Windows.Win32.Foundation.ERROR_DESTINATION_ELEMENT_FULL +Windows.Win32.Foundation.ERROR_DESTROY_OBJECT_OF_OTHER_THREAD +Windows.Win32.Foundation.ERROR_DEV_NOT_EXIST +Windows.Win32.Foundation.ERROR_DEVICE_ALREADY_ATTACHED +Windows.Win32.Foundation.ERROR_DEVICE_ALREADY_REMEMBERED +Windows.Win32.Foundation.ERROR_DEVICE_DOOR_OPEN +Windows.Win32.Foundation.ERROR_DEVICE_ENUMERATION_ERROR +Windows.Win32.Foundation.ERROR_DEVICE_FEATURE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_DEVICE_HARDWARE_ERROR +Windows.Win32.Foundation.ERROR_DEVICE_HINT_NAME_BUFFER_TOO_SMALL +Windows.Win32.Foundation.ERROR_DEVICE_IN_MAINTENANCE +Windows.Win32.Foundation.ERROR_DEVICE_IN_USE +Windows.Win32.Foundation.ERROR_DEVICE_NO_RESOURCES +Windows.Win32.Foundation.ERROR_DEVICE_NOT_CONNECTED +Windows.Win32.Foundation.ERROR_DEVICE_NOT_PARTITIONED +Windows.Win32.Foundation.ERROR_DEVICE_REINITIALIZATION_NEEDED +Windows.Win32.Foundation.ERROR_DEVICE_REMOVED +Windows.Win32.Foundation.ERROR_DEVICE_REQUIRES_CLEANING +Windows.Win32.Foundation.ERROR_DEVICE_RESET_REQUIRED +Windows.Win32.Foundation.ERROR_DEVICE_SUPPORT_IN_PROGRESS +Windows.Win32.Foundation.ERROR_DEVICE_UNREACHABLE +Windows.Win32.Foundation.ERROR_DHCP_ADDRESS_CONFLICT +Windows.Win32.Foundation.ERROR_DIFFERENT_SERVICE_ACCOUNT +Windows.Win32.Foundation.ERROR_DIR_EFS_DISALLOWED +Windows.Win32.Foundation.ERROR_DIR_NOT_EMPTY +Windows.Win32.Foundation.ERROR_DIR_NOT_ROOT +Windows.Win32.Foundation.ERROR_DIRECT_ACCESS_HANDLE +Windows.Win32.Foundation.ERROR_DIRECTORY +Windows.Win32.Foundation.ERROR_DIRECTORY_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_DISCARDED +Windows.Win32.Foundation.ERROR_DISK_CHANGE +Windows.Win32.Foundation.ERROR_DISK_CORRUPT +Windows.Win32.Foundation.ERROR_DISK_FULL +Windows.Win32.Foundation.ERROR_DISK_OPERATION_FAILED +Windows.Win32.Foundation.ERROR_DISK_QUOTA_EXCEEDED +Windows.Win32.Foundation.ERROR_DISK_RECALIBRATE_FAILED +Windows.Win32.Foundation.ERROR_DISK_REPAIR_DISABLED +Windows.Win32.Foundation.ERROR_DISK_REPAIR_REDIRECTED +Windows.Win32.Foundation.ERROR_DISK_REPAIR_UNSUCCESSFUL +Windows.Win32.Foundation.ERROR_DISK_RESET_FAILED +Windows.Win32.Foundation.ERROR_DISK_RESOURCES_EXHAUSTED +Windows.Win32.Foundation.ERROR_DISK_TOO_FRAGMENTED +Windows.Win32.Foundation.ERROR_DLL_INIT_FAILED +Windows.Win32.Foundation.ERROR_DLL_INIT_FAILED_LOGOFF +Windows.Win32.Foundation.ERROR_DLL_MIGHT_BE_INCOMPATIBLE +Windows.Win32.Foundation.ERROR_DLL_MIGHT_BE_INSECURE +Windows.Win32.Foundation.ERROR_DLL_NOT_FOUND +Windows.Win32.Foundation.ERROR_DLP_POLICY_DENIES_OPERATION +Windows.Win32.Foundation.ERROR_DLP_POLICY_SILENTLY_FAIL +Windows.Win32.Foundation.ERROR_DLP_POLICY_WARNS_AGAINST_OPERATION +Windows.Win32.Foundation.ERROR_DOMAIN_CONTROLLER_EXISTS +Windows.Win32.Foundation.ERROR_DOMAIN_CONTROLLER_NOT_FOUND +Windows.Win32.Foundation.ERROR_DOMAIN_CTRLR_CONFIG_ERROR +Windows.Win32.Foundation.ERROR_DOMAIN_EXISTS +Windows.Win32.Foundation.ERROR_DOMAIN_LIMIT_EXCEEDED +Windows.Win32.Foundation.ERROR_DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION +Windows.Win32.Foundation.ERROR_DOMAIN_TRUST_INCONSISTENT +Windows.Win32.Foundation.ERROR_DOWNGRADE_DETECTED +Windows.Win32.Foundation.ERROR_DPL_NOT_SUPPORTED_FOR_USER +Windows.Win32.Foundation.ERROR_DRIVE_LOCKED +Windows.Win32.Foundation.ERROR_DRIVER_BLOCKED +Windows.Win32.Foundation.ERROR_DRIVER_CANCEL_TIMEOUT +Windows.Win32.Foundation.ERROR_DRIVER_DATABASE_ERROR +Windows.Win32.Foundation.ERROR_DRIVER_FAILED_PRIOR_UNLOAD +Windows.Win32.Foundation.ERROR_DRIVER_FAILED_SLEEP +Windows.Win32.Foundation.ERROR_DRIVER_PROCESS_TERMINATED +Windows.Win32.Foundation.ERROR_DRIVERS_LEAKING_LOCKED_PAGES +Windows.Win32.Foundation.ERROR_DS_ADD_REPLICA_INHIBITED +Windows.Win32.Foundation.ERROR_DS_ADMIN_LIMIT_EXCEEDED +Windows.Win32.Foundation.ERROR_DS_AFFECTS_MULTIPLE_DSAS +Windows.Win32.Foundation.ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER +Windows.Win32.Foundation.ERROR_DS_ALIAS_DEREF_PROBLEM +Windows.Win32.Foundation.ERROR_DS_ALIAS_POINTS_TO_ALIAS +Windows.Win32.Foundation.ERROR_DS_ALIAS_PROBLEM +Windows.Win32.Foundation.ERROR_DS_ALIASED_OBJ_MISSING +Windows.Win32.Foundation.ERROR_DS_ATT_ALREADY_EXISTS +Windows.Win32.Foundation.ERROR_DS_ATT_IS_NOT_ON_OBJ +Windows.Win32.Foundation.ERROR_DS_ATT_NOT_DEF_FOR_CLASS +Windows.Win32.Foundation.ERROR_DS_ATT_NOT_DEF_IN_SCHEMA +Windows.Win32.Foundation.ERROR_DS_ATT_SCHEMA_REQ_ID +Windows.Win32.Foundation.ERROR_DS_ATT_SCHEMA_REQ_SYNTAX +Windows.Win32.Foundation.ERROR_DS_ATT_VAL_ALREADY_EXISTS +Windows.Win32.Foundation.ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS +Windows.Win32.Foundation.ERROR_DS_ATTRIBUTE_OWNED_BY_SAM +Windows.Win32.Foundation.ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED +Windows.Win32.Foundation.ERROR_DS_AUDIT_FAILURE +Windows.Win32.Foundation.ERROR_DS_AUTH_METHOD_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_DS_AUTH_UNKNOWN +Windows.Win32.Foundation.ERROR_DS_AUTHORIZATION_FAILED +Windows.Win32.Foundation.ERROR_DS_AUX_CLS_TEST_FAIL +Windows.Win32.Foundation.ERROR_DS_BACKLINK_WITHOUT_LINK +Windows.Win32.Foundation.ERROR_DS_BAD_ATT_SCHEMA_SYNTAX +Windows.Win32.Foundation.ERROR_DS_BAD_HIERARCHY_FILE +Windows.Win32.Foundation.ERROR_DS_BAD_INSTANCE_TYPE +Windows.Win32.Foundation.ERROR_DS_BAD_NAME_SYNTAX +Windows.Win32.Foundation.ERROR_DS_BAD_RDN_ATT_ID_SYNTAX +Windows.Win32.Foundation.ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED +Windows.Win32.Foundation.ERROR_DS_BUSY +Windows.Win32.Foundation.ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD +Windows.Win32.Foundation.ERROR_DS_CANT_ADD_ATT_VALUES +Windows.Win32.Foundation.ERROR_DS_CANT_ADD_SYSTEM_ONLY +Windows.Win32.Foundation.ERROR_DS_CANT_ADD_TO_GC +Windows.Win32.Foundation.ERROR_DS_CANT_CACHE_ATT +Windows.Win32.Foundation.ERROR_DS_CANT_CACHE_CLASS +Windows.Win32.Foundation.ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC +Windows.Win32.Foundation.ERROR_DS_CANT_CREATE_UNDER_SCHEMA +Windows.Win32.Foundation.ERROR_DS_CANT_DEL_MASTER_CROSSREF +Windows.Win32.Foundation.ERROR_DS_CANT_DELETE +Windows.Win32.Foundation.ERROR_DS_CANT_DELETE_DSA_OBJ +Windows.Win32.Foundation.ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC +Windows.Win32.Foundation.ERROR_DS_CANT_DEREF_ALIAS +Windows.Win32.Foundation.ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN +Windows.Win32.Foundation.ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF +Windows.Win32.Foundation.ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN +Windows.Win32.Foundation.ERROR_DS_CANT_FIND_DSA_OBJ +Windows.Win32.Foundation.ERROR_DS_CANT_FIND_EXPECTED_NC +Windows.Win32.Foundation.ERROR_DS_CANT_FIND_NC_IN_CACHE +Windows.Win32.Foundation.ERROR_DS_CANT_MIX_MASTER_AND_REPS +Windows.Win32.Foundation.ERROR_DS_CANT_MOD_OBJ_CLASS +Windows.Win32.Foundation.ERROR_DS_CANT_MOD_PRIMARYGROUPID +Windows.Win32.Foundation.ERROR_DS_CANT_MOD_SYSTEM_ONLY +Windows.Win32.Foundation.ERROR_DS_CANT_MOVE_ACCOUNT_GROUP +Windows.Win32.Foundation.ERROR_DS_CANT_MOVE_APP_BASIC_GROUP +Windows.Win32.Foundation.ERROR_DS_CANT_MOVE_APP_QUERY_GROUP +Windows.Win32.Foundation.ERROR_DS_CANT_MOVE_DELETED_OBJECT +Windows.Win32.Foundation.ERROR_DS_CANT_MOVE_RESOURCE_GROUP +Windows.Win32.Foundation.ERROR_DS_CANT_ON_NON_LEAF +Windows.Win32.Foundation.ERROR_DS_CANT_ON_RDN +Windows.Win32.Foundation.ERROR_DS_CANT_REM_MISSING_ATT +Windows.Win32.Foundation.ERROR_DS_CANT_REM_MISSING_ATT_VAL +Windows.Win32.Foundation.ERROR_DS_CANT_REMOVE_ATT_CACHE +Windows.Win32.Foundation.ERROR_DS_CANT_REMOVE_CLASS_CACHE +Windows.Win32.Foundation.ERROR_DS_CANT_REPLACE_HIDDEN_REC +Windows.Win32.Foundation.ERROR_DS_CANT_RETRIEVE_ATTS +Windows.Win32.Foundation.ERROR_DS_CANT_RETRIEVE_CHILD +Windows.Win32.Foundation.ERROR_DS_CANT_RETRIEVE_DN +Windows.Win32.Foundation.ERROR_DS_CANT_RETRIEVE_INSTANCE +Windows.Win32.Foundation.ERROR_DS_CANT_RETRIEVE_SD +Windows.Win32.Foundation.ERROR_DS_CANT_START +Windows.Win32.Foundation.ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ +Windows.Win32.Foundation.ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS +Windows.Win32.Foundation.ERROR_DS_CHILDREN_EXIST +Windows.Win32.Foundation.ERROR_DS_CLASS_MUST_BE_CONCRETE +Windows.Win32.Foundation.ERROR_DS_CLASS_NOT_DSA +Windows.Win32.Foundation.ERROR_DS_CLIENT_LOOP +Windows.Win32.Foundation.ERROR_DS_CODE_INCONSISTENCY +Windows.Win32.Foundation.ERROR_DS_COMPARE_FALSE +Windows.Win32.Foundation.ERROR_DS_COMPARE_TRUE +Windows.Win32.Foundation.ERROR_DS_CONFIDENTIALITY_REQUIRED +Windows.Win32.Foundation.ERROR_DS_CONFIG_PARAM_MISSING +Windows.Win32.Foundation.ERROR_DS_CONSTRAINT_VIOLATION +Windows.Win32.Foundation.ERROR_DS_CONSTRUCTED_ATT_MOD +Windows.Win32.Foundation.ERROR_DS_CONTROL_NOT_FOUND +Windows.Win32.Foundation.ERROR_DS_COULDNT_CONTACT_FSMO +Windows.Win32.Foundation.ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE +Windows.Win32.Foundation.ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE +Windows.Win32.Foundation.ERROR_DS_COULDNT_UPDATE_SPNS +Windows.Win32.Foundation.ERROR_DS_COUNTING_AB_INDICES_FAILED +Windows.Win32.Foundation.ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE +Windows.Win32.Foundation.ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2 +Windows.Win32.Foundation.ERROR_DS_CROSS_DOM_MOVE_ERROR +Windows.Win32.Foundation.ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD +Windows.Win32.Foundation.ERROR_DS_CROSS_NC_DN_RENAME +Windows.Win32.Foundation.ERROR_DS_CROSS_REF_BUSY +Windows.Win32.Foundation.ERROR_DS_CROSS_REF_EXISTS +Windows.Win32.Foundation.ERROR_DS_DATABASE_ERROR +Windows.Win32.Foundation.ERROR_DS_DECODING_ERROR +Windows.Win32.Foundation.ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED +Windows.Win32.Foundation.ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST +Windows.Win32.Foundation.ERROR_DS_DIFFERENT_REPL_EPOCHS +Windows.Win32.Foundation.ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER +Windows.Win32.Foundation.ERROR_DS_DISALLOWED_NC_REDIRECT +Windows.Win32.Foundation.ERROR_DS_DNS_LOOKUP_FAILURE +Windows.Win32.Foundation.ERROR_DS_DOMAIN_NAME_EXISTS_IN_FOREST +Windows.Win32.Foundation.ERROR_DS_DOMAIN_RENAME_IN_PROGRESS +Windows.Win32.Foundation.ERROR_DS_DOMAIN_VERSION_TOO_HIGH +Windows.Win32.Foundation.ERROR_DS_DOMAIN_VERSION_TOO_LOW +Windows.Win32.Foundation.ERROR_DS_DRA_ABANDON_SYNC +Windows.Win32.Foundation.ERROR_DS_DRA_ACCESS_DENIED +Windows.Win32.Foundation.ERROR_DS_DRA_BAD_DN +Windows.Win32.Foundation.ERROR_DS_DRA_BAD_INSTANCE_TYPE +Windows.Win32.Foundation.ERROR_DS_DRA_BAD_NC +Windows.Win32.Foundation.ERROR_DS_DRA_BUSY +Windows.Win32.Foundation.ERROR_DS_DRA_CONNECTION_FAILED +Windows.Win32.Foundation.ERROR_DS_DRA_CORRUPT_UTD_VECTOR +Windows.Win32.Foundation.ERROR_DS_DRA_DB_ERROR +Windows.Win32.Foundation.ERROR_DS_DRA_DN_EXISTS +Windows.Win32.Foundation.ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT +Windows.Win32.Foundation.ERROR_DS_DRA_EXTN_CONNECTION_FAILED +Windows.Win32.Foundation.ERROR_DS_DRA_GENERIC +Windows.Win32.Foundation.ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET +Windows.Win32.Foundation.ERROR_DS_DRA_INCONSISTENT_DIT +Windows.Win32.Foundation.ERROR_DS_DRA_INTERNAL_ERROR +Windows.Win32.Foundation.ERROR_DS_DRA_INVALID_PARAMETER +Windows.Win32.Foundation.ERROR_DS_DRA_MAIL_PROBLEM +Windows.Win32.Foundation.ERROR_DS_DRA_MISSING_KRBTGT_SECRET +Windows.Win32.Foundation.ERROR_DS_DRA_MISSING_PARENT +Windows.Win32.Foundation.ERROR_DS_DRA_NAME_COLLISION +Windows.Win32.Foundation.ERROR_DS_DRA_NO_REPLICA +Windows.Win32.Foundation.ERROR_DS_DRA_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_DS_DRA_OBJ_IS_REP_SOURCE +Windows.Win32.Foundation.ERROR_DS_DRA_OBJ_NC_MISMATCH +Windows.Win32.Foundation.ERROR_DS_DRA_OUT_OF_MEM +Windows.Win32.Foundation.ERROR_DS_DRA_OUT_SCHEDULE_WINDOW +Windows.Win32.Foundation.ERROR_DS_DRA_PREEMPTED +Windows.Win32.Foundation.ERROR_DS_DRA_RECYCLED_TARGET +Windows.Win32.Foundation.ERROR_DS_DRA_REF_ALREADY_EXISTS +Windows.Win32.Foundation.ERROR_DS_DRA_REF_NOT_FOUND +Windows.Win32.Foundation.ERROR_DS_DRA_REPL_PENDING +Windows.Win32.Foundation.ERROR_DS_DRA_RPC_CANCELLED +Windows.Win32.Foundation.ERROR_DS_DRA_SCHEMA_CONFLICT +Windows.Win32.Foundation.ERROR_DS_DRA_SCHEMA_INFO_SHIP +Windows.Win32.Foundation.ERROR_DS_DRA_SCHEMA_MISMATCH +Windows.Win32.Foundation.ERROR_DS_DRA_SECRETS_DENIED +Windows.Win32.Foundation.ERROR_DS_DRA_SHUTDOWN +Windows.Win32.Foundation.ERROR_DS_DRA_SINK_DISABLED +Windows.Win32.Foundation.ERROR_DS_DRA_SOURCE_DISABLED +Windows.Win32.Foundation.ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA +Windows.Win32.Foundation.ERROR_DS_DRA_SOURCE_REINSTALLED +Windows.Win32.Foundation.ERROR_DS_DRS_EXTENSIONS_CHANGED +Windows.Win32.Foundation.ERROR_DS_DS_REQUIRED +Windows.Win32.Foundation.ERROR_DS_DSA_MUST_BE_INT_MASTER +Windows.Win32.Foundation.ERROR_DS_DST_DOMAIN_NOT_NATIVE +Windows.Win32.Foundation.ERROR_DS_DST_NC_MISMATCH +Windows.Win32.Foundation.ERROR_DS_DUP_LDAP_DISPLAY_NAME +Windows.Win32.Foundation.ERROR_DS_DUP_LINK_ID +Windows.Win32.Foundation.ERROR_DS_DUP_MAPI_ID +Windows.Win32.Foundation.ERROR_DS_DUP_MSDS_INTID +Windows.Win32.Foundation.ERROR_DS_DUP_OID +Windows.Win32.Foundation.ERROR_DS_DUP_RDN +Windows.Win32.Foundation.ERROR_DS_DUP_SCHEMA_ID_GUID +Windows.Win32.Foundation.ERROR_DS_DUPLICATE_ID_FOUND +Windows.Win32.Foundation.ERROR_DS_ENCODING_ERROR +Windows.Win32.Foundation.ERROR_DS_EPOCH_MISMATCH +Windows.Win32.Foundation.ERROR_DS_EXISTING_AD_CHILD_NC +Windows.Win32.Foundation.ERROR_DS_EXISTS_IN_AUX_CLS +Windows.Win32.Foundation.ERROR_DS_EXISTS_IN_MAY_HAVE +Windows.Win32.Foundation.ERROR_DS_EXISTS_IN_MUST_HAVE +Windows.Win32.Foundation.ERROR_DS_EXISTS_IN_POSS_SUP +Windows.Win32.Foundation.ERROR_DS_EXISTS_IN_RDNATTID +Windows.Win32.Foundation.ERROR_DS_EXISTS_IN_SUB_CLS +Windows.Win32.Foundation.ERROR_DS_FILTER_UNKNOWN +Windows.Win32.Foundation.ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS +Windows.Win32.Foundation.ERROR_DS_FLAT_NAME_EXISTS_IN_FOREST +Windows.Win32.Foundation.ERROR_DS_FOREST_VERSION_TOO_HIGH +Windows.Win32.Foundation.ERROR_DS_FOREST_VERSION_TOO_LOW +Windows.Win32.Foundation.ERROR_DS_GC_NOT_AVAILABLE +Windows.Win32.Foundation.ERROR_DS_GC_REQUIRED +Windows.Win32.Foundation.ERROR_DS_GCVERIFY_ERROR +Windows.Win32.Foundation.ERROR_DS_GENERIC_ERROR +Windows.Win32.Foundation.ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER +Windows.Win32.Foundation.ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER +Windows.Win32.Foundation.ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER +Windows.Win32.Foundation.ERROR_DS_GOVERNSID_MISSING +Windows.Win32.Foundation.ERROR_DS_GROUP_CONVERSION_ERROR +Windows.Win32.Foundation.ERROR_DS_HAVE_PRIMARY_MEMBERS +Windows.Win32.Foundation.ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED +Windows.Win32.Foundation.ERROR_DS_HIERARCHY_TABLE_TOO_DEEP +Windows.Win32.Foundation.ERROR_DS_HIGH_ADLDS_FFL +Windows.Win32.Foundation.ERROR_DS_HIGH_DSA_VERSION +Windows.Win32.Foundation.ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD +Windows.Win32.Foundation.ERROR_DS_ILLEGAL_MOD_OPERATION +Windows.Win32.Foundation.ERROR_DS_ILLEGAL_SUPERIOR +Windows.Win32.Foundation.ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION +Windows.Win32.Foundation.ERROR_DS_INAPPROPRIATE_AUTH +Windows.Win32.Foundation.ERROR_DS_INAPPROPRIATE_MATCHING +Windows.Win32.Foundation.ERROR_DS_INCOMPATIBLE_CONTROLS_USED +Windows.Win32.Foundation.ERROR_DS_INCOMPATIBLE_VERSION +Windows.Win32.Foundation.ERROR_DS_INCORRECT_ROLE_OWNER +Windows.Win32.Foundation.ERROR_DS_INIT_FAILURE +Windows.Win32.Foundation.ERROR_DS_INIT_FAILURE_CONSOLE +Windows.Win32.Foundation.ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE +Windows.Win32.Foundation.ERROR_DS_INSTALL_NO_SRC_SCH_VERSION +Windows.Win32.Foundation.ERROR_DS_INSTALL_SCHEMA_MISMATCH +Windows.Win32.Foundation.ERROR_DS_INSUFF_ACCESS_RIGHTS +Windows.Win32.Foundation.ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT +Windows.Win32.Foundation.ERROR_DS_INTERNAL_FAILURE +Windows.Win32.Foundation.ERROR_DS_INVALID_ATTRIBUTE_SYNTAX +Windows.Win32.Foundation.ERROR_DS_INVALID_DMD +Windows.Win32.Foundation.ERROR_DS_INVALID_DN_SYNTAX +Windows.Win32.Foundation.ERROR_DS_INVALID_GROUP_TYPE +Windows.Win32.Foundation.ERROR_DS_INVALID_LDAP_DISPLAY_NAME +Windows.Win32.Foundation.ERROR_DS_INVALID_NAME_FOR_SPN +Windows.Win32.Foundation.ERROR_DS_INVALID_ROLE_OWNER +Windows.Win32.Foundation.ERROR_DS_INVALID_SCRIPT +Windows.Win32.Foundation.ERROR_DS_INVALID_SEARCH_FLAG +Windows.Win32.Foundation.ERROR_DS_INVALID_SEARCH_FLAG_SUBTREE +Windows.Win32.Foundation.ERROR_DS_INVALID_SEARCH_FLAG_TUPLE +Windows.Win32.Foundation.ERROR_DS_IS_LEAF +Windows.Win32.Foundation.ERROR_DS_KEY_NOT_UNIQUE +Windows.Win32.Foundation.ERROR_DS_LDAP_SEND_QUEUE_FULL +Windows.Win32.Foundation.ERROR_DS_LINK_ID_NOT_AVAILABLE +Windows.Win32.Foundation.ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER +Windows.Win32.Foundation.ERROR_DS_LOCAL_ERROR +Windows.Win32.Foundation.ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY +Windows.Win32.Foundation.ERROR_DS_LOOP_DETECT +Windows.Win32.Foundation.ERROR_DS_LOW_ADLDS_FFL +Windows.Win32.Foundation.ERROR_DS_LOW_DSA_VERSION +Windows.Win32.Foundation.ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4 +Windows.Win32.Foundation.ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED +Windows.Win32.Foundation.ERROR_DS_MAPI_ID_NOT_AVAILABLE +Windows.Win32.Foundation.ERROR_DS_MASTERDSA_REQUIRED +Windows.Win32.Foundation.ERROR_DS_MAX_OBJ_SIZE_EXCEEDED +Windows.Win32.Foundation.ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY +Windows.Win32.Foundation.ERROR_DS_MISSING_EXPECTED_ATT +Windows.Win32.Foundation.ERROR_DS_MISSING_FOREST_TRUST +Windows.Win32.Foundation.ERROR_DS_MISSING_FSMO_SETTINGS +Windows.Win32.Foundation.ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER +Windows.Win32.Foundation.ERROR_DS_MISSING_REQUIRED_ATT +Windows.Win32.Foundation.ERROR_DS_MISSING_SUPREF +Windows.Win32.Foundation.ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG +Windows.Win32.Foundation.ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE +Windows.Win32.Foundation.ERROR_DS_MODIFYDN_WRONG_GRANDPARENT +Windows.Win32.Foundation.ERROR_DS_MUST_BE_RUN_ON_DST_DC +Windows.Win32.Foundation.ERROR_DS_NAME_ERROR_DOMAIN_ONLY +Windows.Win32.Foundation.ERROR_DS_NAME_ERROR_NO_MAPPING +Windows.Win32.Foundation.ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING +Windows.Win32.Foundation.ERROR_DS_NAME_ERROR_NOT_FOUND +Windows.Win32.Foundation.ERROR_DS_NAME_ERROR_NOT_UNIQUE +Windows.Win32.Foundation.ERROR_DS_NAME_ERROR_RESOLVING +Windows.Win32.Foundation.ERROR_DS_NAME_ERROR_TRUST_REFERRAL +Windows.Win32.Foundation.ERROR_DS_NAME_NOT_UNIQUE +Windows.Win32.Foundation.ERROR_DS_NAME_REFERENCE_INVALID +Windows.Win32.Foundation.ERROR_DS_NAME_TOO_LONG +Windows.Win32.Foundation.ERROR_DS_NAME_TOO_MANY_PARTS +Windows.Win32.Foundation.ERROR_DS_NAME_TYPE_UNKNOWN +Windows.Win32.Foundation.ERROR_DS_NAME_UNPARSEABLE +Windows.Win32.Foundation.ERROR_DS_NAME_VALUE_TOO_LONG +Windows.Win32.Foundation.ERROR_DS_NAMING_MASTER_GC +Windows.Win32.Foundation.ERROR_DS_NAMING_VIOLATION +Windows.Win32.Foundation.ERROR_DS_NC_MUST_HAVE_NC_PARENT +Windows.Win32.Foundation.ERROR_DS_NC_STILL_HAS_DSAS +Windows.Win32.Foundation.ERROR_DS_NCNAME_MISSING_CR_REF +Windows.Win32.Foundation.ERROR_DS_NCNAME_MUST_BE_NC +Windows.Win32.Foundation.ERROR_DS_NO_ATTRIBUTE_OR_VALUE +Windows.Win32.Foundation.ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN +Windows.Win32.Foundation.ERROR_DS_NO_CHAINED_EVAL +Windows.Win32.Foundation.ERROR_DS_NO_CHAINING +Windows.Win32.Foundation.ERROR_DS_NO_CHECKPOINT_WITH_PDC +Windows.Win32.Foundation.ERROR_DS_NO_CROSSREF_FOR_NC +Windows.Win32.Foundation.ERROR_DS_NO_DELETED_NAME +Windows.Win32.Foundation.ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS +Windows.Win32.Foundation.ERROR_DS_NO_MORE_RIDS +Windows.Win32.Foundation.ERROR_DS_NO_MSDS_INTID +Windows.Win32.Foundation.ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN +Windows.Win32.Foundation.ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN +Windows.Win32.Foundation.ERROR_DS_NO_NTDSA_OBJECT +Windows.Win32.Foundation.ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC +Windows.Win32.Foundation.ERROR_DS_NO_PARENT_OBJECT +Windows.Win32.Foundation.ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION +Windows.Win32.Foundation.ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA +Windows.Win32.Foundation.ERROR_DS_NO_REF_DOMAIN +Windows.Win32.Foundation.ERROR_DS_NO_REQUESTED_ATTS_FOUND +Windows.Win32.Foundation.ERROR_DS_NO_RESULTS_RETURNED +Windows.Win32.Foundation.ERROR_DS_NO_RIDS_ALLOCATED +Windows.Win32.Foundation.ERROR_DS_NO_SERVER_OBJECT +Windows.Win32.Foundation.ERROR_DS_NO_SUCH_OBJECT +Windows.Win32.Foundation.ERROR_DS_NO_TREE_DELETE_ABOVE_NC +Windows.Win32.Foundation.ERROR_DS_NON_ASQ_SEARCH +Windows.Win32.Foundation.ERROR_DS_NON_BASE_SEARCH +Windows.Win32.Foundation.ERROR_DS_NONEXISTENT_MAY_HAVE +Windows.Win32.Foundation.ERROR_DS_NONEXISTENT_MUST_HAVE +Windows.Win32.Foundation.ERROR_DS_NONEXISTENT_POSS_SUP +Windows.Win32.Foundation.ERROR_DS_NONSAFE_SCHEMA_CHANGE +Windows.Win32.Foundation.ERROR_DS_NOT_AN_OBJECT +Windows.Win32.Foundation.ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC +Windows.Win32.Foundation.ERROR_DS_NOT_CLOSEST +Windows.Win32.Foundation.ERROR_DS_NOT_INSTALLED +Windows.Win32.Foundation.ERROR_DS_NOT_ON_BACKLINK +Windows.Win32.Foundation.ERROR_DS_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_DS_NOT_SUPPORTED_SORT_ORDER +Windows.Win32.Foundation.ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX +Windows.Win32.Foundation.ERROR_DS_NTDSCRIPT_PROCESS_ERROR +Windows.Win32.Foundation.ERROR_DS_NTDSCRIPT_SYNTAX_ERROR +Windows.Win32.Foundation.ERROR_DS_OBJ_CLASS_NOT_DEFINED +Windows.Win32.Foundation.ERROR_DS_OBJ_CLASS_NOT_SUBCLASS +Windows.Win32.Foundation.ERROR_DS_OBJ_CLASS_VIOLATION +Windows.Win32.Foundation.ERROR_DS_OBJ_GUID_EXISTS +Windows.Win32.Foundation.ERROR_DS_OBJ_NOT_FOUND +Windows.Win32.Foundation.ERROR_DS_OBJ_STRING_NAME_EXISTS +Windows.Win32.Foundation.ERROR_DS_OBJ_TOO_LARGE +Windows.Win32.Foundation.ERROR_DS_OBJECT_BEING_REMOVED +Windows.Win32.Foundation.ERROR_DS_OBJECT_CLASS_REQUIRED +Windows.Win32.Foundation.ERROR_DS_OBJECT_RESULTS_TOO_LARGE +Windows.Win32.Foundation.ERROR_DS_OFFSET_RANGE_ERROR +Windows.Win32.Foundation.ERROR_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS +Windows.Win32.Foundation.ERROR_DS_OID_NOT_FOUND +Windows.Win32.Foundation.ERROR_DS_OPERATIONS_ERROR +Windows.Win32.Foundation.ERROR_DS_OUT_OF_SCOPE +Windows.Win32.Foundation.ERROR_DS_OUT_OF_VERSION_STORE +Windows.Win32.Foundation.ERROR_DS_PARAM_ERROR +Windows.Win32.Foundation.ERROR_DS_PARENT_IS_AN_ALIAS +Windows.Win32.Foundation.ERROR_DS_PDC_OPERATION_IN_PROGRESS +Windows.Win32.Foundation.ERROR_DS_PER_ATTRIBUTE_AUTHZ_FAILED_DURING_ADD +Windows.Win32.Foundation.ERROR_DS_POLICY_NOT_KNOWN +Windows.Win32.Foundation.ERROR_DS_PROTOCOL_ERROR +Windows.Win32.Foundation.ERROR_DS_RANGE_CONSTRAINT +Windows.Win32.Foundation.ERROR_DS_RDN_DOESNT_MATCH_SCHEMA +Windows.Win32.Foundation.ERROR_DS_RECALCSCHEMA_FAILED +Windows.Win32.Foundation.ERROR_DS_REFERRAL +Windows.Win32.Foundation.ERROR_DS_REFERRAL_LIMIT_EXCEEDED +Windows.Win32.Foundation.ERROR_DS_REFUSING_FSMO_ROLES +Windows.Win32.Foundation.ERROR_DS_REMOTE_CROSSREF_OP_FAILED +Windows.Win32.Foundation.ERROR_DS_REPL_LIFETIME_EXCEEDED +Windows.Win32.Foundation.ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR +Windows.Win32.Foundation.ERROR_DS_REPLICATOR_ONLY +Windows.Win32.Foundation.ERROR_DS_RESERVED_LINK_ID +Windows.Win32.Foundation.ERROR_DS_RESERVED_MAPI_ID +Windows.Win32.Foundation.ERROR_DS_RIDMGR_DISABLED +Windows.Win32.Foundation.ERROR_DS_RIDMGR_INIT_ERROR +Windows.Win32.Foundation.ERROR_DS_ROLE_NOT_VERIFIED +Windows.Win32.Foundation.ERROR_DS_ROOT_CANT_BE_SUBREF +Windows.Win32.Foundation.ERROR_DS_ROOT_MUST_BE_NC +Windows.Win32.Foundation.ERROR_DS_ROOT_REQUIRES_CLASS_TOP +Windows.Win32.Foundation.ERROR_DS_SAM_INIT_FAILURE +Windows.Win32.Foundation.ERROR_DS_SAM_INIT_FAILURE_CONSOLE +Windows.Win32.Foundation.ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY +Windows.Win32.Foundation.ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD +Windows.Win32.Foundation.ERROR_DS_SCHEMA_ALLOC_FAILED +Windows.Win32.Foundation.ERROR_DS_SCHEMA_NOT_LOADED +Windows.Win32.Foundation.ERROR_DS_SCHEMA_UPDATE_DISALLOWED +Windows.Win32.Foundation.ERROR_DS_SEC_DESC_INVALID +Windows.Win32.Foundation.ERROR_DS_SEC_DESC_TOO_SHORT +Windows.Win32.Foundation.ERROR_DS_SECURITY_CHECKING_ERROR +Windows.Win32.Foundation.ERROR_DS_SECURITY_ILLEGAL_MODIFY +Windows.Win32.Foundation.ERROR_DS_SEMANTIC_ATT_TEST +Windows.Win32.Foundation.ERROR_DS_SENSITIVE_GROUP_VIOLATION +Windows.Win32.Foundation.ERROR_DS_SERVER_DOWN +Windows.Win32.Foundation.ERROR_DS_SHUTTING_DOWN +Windows.Win32.Foundation.ERROR_DS_SINGLE_USER_MODE_FAILED +Windows.Win32.Foundation.ERROR_DS_SINGLE_VALUE_CONSTRAINT +Windows.Win32.Foundation.ERROR_DS_SIZELIMIT_EXCEEDED +Windows.Win32.Foundation.ERROR_DS_SORT_CONTROL_MISSING +Windows.Win32.Foundation.ERROR_DS_SOURCE_AUDITING_NOT_ENABLED +Windows.Win32.Foundation.ERROR_DS_SOURCE_DOMAIN_IN_FOREST +Windows.Win32.Foundation.ERROR_DS_SPN_VALUE_NOT_UNIQUE_IN_FOREST +Windows.Win32.Foundation.ERROR_DS_SRC_AND_DST_NC_IDENTICAL +Windows.Win32.Foundation.ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH +Windows.Win32.Foundation.ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER +Windows.Win32.Foundation.ERROR_DS_SRC_GUID_MISMATCH +Windows.Win32.Foundation.ERROR_DS_SRC_NAME_MISMATCH +Windows.Win32.Foundation.ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER +Windows.Win32.Foundation.ERROR_DS_SRC_SID_EXISTS_IN_FOREST +Windows.Win32.Foundation.ERROR_DS_STRING_SD_CONVERSION_FAILED +Windows.Win32.Foundation.ERROR_DS_STRONG_AUTH_REQUIRED +Windows.Win32.Foundation.ERROR_DS_SUB_CLS_TEST_FAIL +Windows.Win32.Foundation.ERROR_DS_SUBREF_MUST_HAVE_PARENT +Windows.Win32.Foundation.ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD +Windows.Win32.Foundation.ERROR_DS_SYNTAX_MISMATCH +Windows.Win32.Foundation.ERROR_DS_THREAD_LIMIT_EXCEEDED +Windows.Win32.Foundation.ERROR_DS_TIMELIMIT_EXCEEDED +Windows.Win32.Foundation.ERROR_DS_TREE_DELETE_NOT_FINISHED +Windows.Win32.Foundation.ERROR_DS_UNABLE_TO_SURRENDER_ROLES +Windows.Win32.Foundation.ERROR_DS_UNAVAILABLE +Windows.Win32.Foundation.ERROR_DS_UNAVAILABLE_CRIT_EXTENSION +Windows.Win32.Foundation.ERROR_DS_UNDELETE_SAM_VALIDATION_FAILED +Windows.Win32.Foundation.ERROR_DS_UNICODEPWD_NOT_IN_QUOTES +Windows.Win32.Foundation.ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER +Windows.Win32.Foundation.ERROR_DS_UNKNOWN_ERROR +Windows.Win32.Foundation.ERROR_DS_UNKNOWN_OPERATION +Windows.Win32.Foundation.ERROR_DS_UNWILLING_TO_PERFORM +Windows.Win32.Foundation.ERROR_DS_UPN_VALUE_NOT_UNIQUE_IN_FOREST +Windows.Win32.Foundation.ERROR_DS_USER_BUFFER_TO_SMALL +Windows.Win32.Foundation.ERROR_DS_VALUE_KEY_NOT_UNIQUE +Windows.Win32.Foundation.ERROR_DS_VERSION_CHECK_FAILURE +Windows.Win32.Foundation.ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL +Windows.Win32.Foundation.ERROR_DS_WRONG_LINKED_ATT_SYNTAX +Windows.Win32.Foundation.ERROR_DS_WRONG_OM_OBJ_CLASS +Windows.Win32.Foundation.ERROR_DUP_DOMAINNAME +Windows.Win32.Foundation.ERROR_DUP_NAME +Windows.Win32.Foundation.ERROR_DUPLICATE_PRIVILEGES +Windows.Win32.Foundation.ERROR_DUPLICATE_SERVICE_NAME +Windows.Win32.Foundation.ERROR_DYNAMIC_CODE_BLOCKED +Windows.Win32.Foundation.ERROR_DYNLINK_FROM_INVALID_RING +Windows.Win32.Foundation.ERROR_EA_ACCESS_DENIED +Windows.Win32.Foundation.ERROR_EA_FILE_CORRUPT +Windows.Win32.Foundation.ERROR_EA_LIST_INCONSISTENT +Windows.Win32.Foundation.ERROR_EA_TABLE_FULL +Windows.Win32.Foundation.ERROR_EAS_DIDNT_FIT +Windows.Win32.Foundation.ERROR_EAS_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_EDP_DPL_POLICY_CANT_BE_SATISFIED +Windows.Win32.Foundation.ERROR_EDP_POLICY_DENIES_OPERATION +Windows.Win32.Foundation.ERROR_EFS_ALG_BLOB_TOO_BIG +Windows.Win32.Foundation.ERROR_EFS_DISABLED +Windows.Win32.Foundation.ERROR_EFS_SERVER_NOT_TRUSTED +Windows.Win32.Foundation.ERROR_EFS_VERSION_NOT_SUPPORT +Windows.Win32.Foundation.ERROR_ELEVATION_REQUIRED +Windows.Win32.Foundation.ERROR_ENCLAVE_FAILURE +Windows.Win32.Foundation.ERROR_ENCLAVE_NOT_TERMINATED +Windows.Win32.Foundation.ERROR_ENCLAVE_VIOLATION +Windows.Win32.Foundation.ERROR_ENCRYPTED_FILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_ENCRYPTED_IO_NOT_POSSIBLE +Windows.Win32.Foundation.ERROR_ENCRYPTING_METADATA_DISALLOWED +Windows.Win32.Foundation.ERROR_ENCRYPTION_DISABLED +Windows.Win32.Foundation.ERROR_ENCRYPTION_FAILED +Windows.Win32.Foundation.ERROR_ENCRYPTION_POLICY_DENIES_OPERATION +Windows.Win32.Foundation.ERROR_END_OF_MEDIA +Windows.Win32.Foundation.ERROR_ENVVAR_NOT_FOUND +Windows.Win32.Foundation.ERROR_EOM_OVERFLOW +Windows.Win32.Foundation.ERROR_ERRORS_ENCOUNTERED +Windows.Win32.Foundation.ERROR_EVALUATION_EXPIRATION +Windows.Win32.Foundation.ERROR_EVENT_DONE +Windows.Win32.Foundation.ERROR_EVENT_PENDING +Windows.Win32.Foundation.ERROR_EVENTLOG_CANT_START +Windows.Win32.Foundation.ERROR_EVENTLOG_FILE_CHANGED +Windows.Win32.Foundation.ERROR_EVENTLOG_FILE_CORRUPT +Windows.Win32.Foundation.ERROR_EXCEPTION_IN_SERVICE +Windows.Win32.Foundation.ERROR_EXCL_SEM_ALREADY_OWNED +Windows.Win32.Foundation.ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY +Windows.Win32.Foundation.ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY +Windows.Win32.Foundation.ERROR_EXE_MACHINE_TYPE_MISMATCH +Windows.Win32.Foundation.ERROR_EXE_MARKED_INVALID +Windows.Win32.Foundation.ERROR_EXTENDED_ERROR +Windows.Win32.Foundation.ERROR_EXTERNAL_BACKING_PROVIDER_UNKNOWN +Windows.Win32.Foundation.ERROR_EXTERNAL_SYSKEY_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_EXTRANEOUS_INFORMATION +Windows.Win32.Foundation.ERROR_FAIL_FAST_EXCEPTION +Windows.Win32.Foundation.ERROR_FAIL_I24 +Windows.Win32.Foundation.ERROR_FAIL_NOACTION_REBOOT +Windows.Win32.Foundation.ERROR_FAIL_RESTART +Windows.Win32.Foundation.ERROR_FAIL_SHUTDOWN +Windows.Win32.Foundation.ERROR_FAILED_DRIVER_ENTRY +Windows.Win32.Foundation.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT +Windows.Win32.Foundation.ERROR_FATAL_APP_EXIT +Windows.Win32.Foundation.ERROR_FILE_CHECKED_OUT +Windows.Win32.Foundation.ERROR_FILE_CORRUPT +Windows.Win32.Foundation.ERROR_FILE_ENCRYPTED +Windows.Win32.Foundation.ERROR_FILE_EXISTS +Windows.Win32.Foundation.ERROR_FILE_HANDLE_REVOKED +Windows.Win32.Foundation.ERROR_FILE_INVALID +Windows.Win32.Foundation.ERROR_FILE_LEVEL_TRIM_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_FILE_METADATA_OPTIMIZATION_IN_PROGRESS +Windows.Win32.Foundation.ERROR_FILE_NOT_ENCRYPTED +Windows.Win32.Foundation.ERROR_FILE_NOT_FOUND +Windows.Win32.Foundation.ERROR_FILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_FILE_OFFLINE +Windows.Win32.Foundation.ERROR_FILE_PROTECTED_UNDER_DPL +Windows.Win32.Foundation.ERROR_FILE_READ_ONLY +Windows.Win32.Foundation.ERROR_FILE_SNAP_IN_PROGRESS +Windows.Win32.Foundation.ERROR_FILE_SNAP_INVALID_PARAMETER +Windows.Win32.Foundation.ERROR_FILE_SNAP_IO_NOT_COORDINATED +Windows.Win32.Foundation.ERROR_FILE_SNAP_MODIFY_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_FILE_SNAP_UNEXPECTED_ERROR +Windows.Win32.Foundation.ERROR_FILE_SNAP_USER_SECTION_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_FILE_SYSTEM_LIMITATION +Windows.Win32.Foundation.ERROR_FILE_SYSTEM_VIRTUALIZATION_BUSY +Windows.Win32.Foundation.ERROR_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION +Windows.Win32.Foundation.ERROR_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT +Windows.Win32.Foundation.ERROR_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN +Windows.Win32.Foundation.ERROR_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE +Windows.Win32.Foundation.ERROR_FILE_TOO_LARGE +Windows.Win32.Foundation.ERROR_FILEMARK_DETECTED +Windows.Win32.Foundation.ERROR_FILENAME_EXCED_RANGE +Windows.Win32.Foundation.ERROR_FIRMWARE_UPDATED +Windows.Win32.Foundation.ERROR_FLOAT_MULTIPLE_FAULTS +Windows.Win32.Foundation.ERROR_FLOAT_MULTIPLE_TRAPS +Windows.Win32.Foundation.ERROR_FLOPPY_BAD_REGISTERS +Windows.Win32.Foundation.ERROR_FLOPPY_ID_MARK_NOT_FOUND +Windows.Win32.Foundation.ERROR_FLOPPY_UNKNOWN_ERROR +Windows.Win32.Foundation.ERROR_FLOPPY_VOLUME +Windows.Win32.Foundation.ERROR_FLOPPY_WRONG_CYLINDER +Windows.Win32.Foundation.ERROR_FORMS_AUTH_REQUIRED +Windows.Win32.Foundation.ERROR_FOUND_OUT_OF_SCOPE +Windows.Win32.Foundation.ERROR_FS_DRIVER_REQUIRED +Windows.Win32.Foundation.ERROR_FS_METADATA_INCONSISTENT +Windows.Win32.Foundation.ERROR_FSFILTER_OP_COMPLETED_SUCCESSFULLY +Windows.Win32.Foundation.ERROR_FT_DI_SCAN_REQUIRED +Windows.Win32.Foundation.ERROR_FT_READ_FAILURE +Windows.Win32.Foundation.ERROR_FT_READ_FROM_COPY_FAILURE +Windows.Win32.Foundation.ERROR_FT_READ_RECOVERY_FROM_BACKUP +Windows.Win32.Foundation.ERROR_FT_WRITE_FAILURE +Windows.Win32.Foundation.ERROR_FT_WRITE_RECOVERY +Windows.Win32.Foundation.ERROR_FULLSCREEN_MODE +Windows.Win32.Foundation.ERROR_FUNCTION_FAILED +Windows.Win32.Foundation.ERROR_FUNCTION_NOT_CALLED +Windows.Win32.Foundation.ERROR_GDI_HANDLE_LEAK +Windows.Win32.Foundation.ERROR_GEN_FAILURE +Windows.Win32.Foundation.ERROR_GENERIC_NOT_MAPPED +Windows.Win32.Foundation.ERROR_GLOBAL_ONLY_HOOK +Windows.Win32.Foundation.ERROR_GRACEFUL_DISCONNECT +Windows.Win32.Foundation.ERROR_GROUP_EXISTS +Windows.Win32.Foundation.ERROR_GUID_SUBSTITUTION_MADE +Windows.Win32.Foundation.ERROR_HANDLE_DISK_FULL +Windows.Win32.Foundation.ERROR_HANDLE_EOF +Windows.Win32.Foundation.ERROR_HANDLE_REVOKED +Windows.Win32.Foundation.ERROR_HANDLES_CLOSED +Windows.Win32.Foundation.ERROR_HAS_SYSTEM_CRITICAL_FILES +Windows.Win32.Foundation.ERROR_HIBERNATED +Windows.Win32.Foundation.ERROR_HIBERNATION_FAILURE +Windows.Win32.Foundation.ERROR_HOOK_NEEDS_HMOD +Windows.Win32.Foundation.ERROR_HOOK_NOT_INSTALLED +Windows.Win32.Foundation.ERROR_HOOK_TYPE_NOT_ALLOWED +Windows.Win32.Foundation.ERROR_HOST_DOWN +Windows.Win32.Foundation.ERROR_HOST_UNREACHABLE +Windows.Win32.Foundation.ERROR_HOTKEY_ALREADY_REGISTERED +Windows.Win32.Foundation.ERROR_HOTKEY_NOT_REGISTERED +Windows.Win32.Foundation.ERROR_HWNDS_HAVE_DIFF_PARENT +Windows.Win32.Foundation.ERROR_ILL_FORMED_PASSWORD +Windows.Win32.Foundation.ERROR_ILLEGAL_CHARACTER +Windows.Win32.Foundation.ERROR_ILLEGAL_DLL_RELOCATION +Windows.Win32.Foundation.ERROR_ILLEGAL_ELEMENT_ADDRESS +Windows.Win32.Foundation.ERROR_ILLEGAL_FLOAT_CONTEXT +Windows.Win32.Foundation.ERROR_IMAGE_AT_DIFFERENT_BASE +Windows.Win32.Foundation.ERROR_IMAGE_MACHINE_TYPE_MISMATCH +Windows.Win32.Foundation.ERROR_IMAGE_MACHINE_TYPE_MISMATCH_EXE +Windows.Win32.Foundation.ERROR_IMAGE_NOT_AT_BASE +Windows.Win32.Foundation.ERROR_IMAGE_SUBSYSTEM_NOT_PRESENT +Windows.Win32.Foundation.ERROR_IMPLEMENTATION_LIMIT +Windows.Win32.Foundation.ERROR_INCOMPATIBLE_SERVICE_PRIVILEGE +Windows.Win32.Foundation.ERROR_INCOMPATIBLE_SERVICE_SID_TYPE +Windows.Win32.Foundation.ERROR_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING +Windows.Win32.Foundation.ERROR_INCORRECT_ACCOUNT_TYPE +Windows.Win32.Foundation.ERROR_INCORRECT_ADDRESS +Windows.Win32.Foundation.ERROR_INCORRECT_SIZE +Windows.Win32.Foundation.ERROR_INDEX_ABSENT +Windows.Win32.Foundation.ERROR_INDEX_OUT_OF_BOUNDS +Windows.Win32.Foundation.ERROR_INFLOOP_IN_RELOC_CHAIN +Windows.Win32.Foundation.ERROR_INSTALL_ALREADY_RUNNING +Windows.Win32.Foundation.ERROR_INSTALL_FAILURE +Windows.Win32.Foundation.ERROR_INSTALL_LANGUAGE_UNSUPPORTED +Windows.Win32.Foundation.ERROR_INSTALL_LOG_FAILURE +Windows.Win32.Foundation.ERROR_INSTALL_NOTUSED +Windows.Win32.Foundation.ERROR_INSTALL_PACKAGE_INVALID +Windows.Win32.Foundation.ERROR_INSTALL_PACKAGE_OPEN_FAILED +Windows.Win32.Foundation.ERROR_INSTALL_PACKAGE_REJECTED +Windows.Win32.Foundation.ERROR_INSTALL_PACKAGE_VERSION +Windows.Win32.Foundation.ERROR_INSTALL_PLATFORM_UNSUPPORTED +Windows.Win32.Foundation.ERROR_INSTALL_REJECTED +Windows.Win32.Foundation.ERROR_INSTALL_REMOTE_DISALLOWED +Windows.Win32.Foundation.ERROR_INSTALL_REMOTE_PROHIBITED +Windows.Win32.Foundation.ERROR_INSTALL_SERVICE_FAILURE +Windows.Win32.Foundation.ERROR_INSTALL_SERVICE_SAFEBOOT +Windows.Win32.Foundation.ERROR_INSTALL_SOURCE_ABSENT +Windows.Win32.Foundation.ERROR_INSTALL_SUSPEND +Windows.Win32.Foundation.ERROR_INSTALL_TEMP_UNWRITABLE +Windows.Win32.Foundation.ERROR_INSTALL_TRANSFORM_FAILURE +Windows.Win32.Foundation.ERROR_INSTALL_TRANSFORM_REJECTED +Windows.Win32.Foundation.ERROR_INSTALL_UI_FAILURE +Windows.Win32.Foundation.ERROR_INSTALL_USEREXIT +Windows.Win32.Foundation.ERROR_INSTRUCTION_MISALIGNMENT +Windows.Win32.Foundation.ERROR_INSUFFICIENT_BUFFER +Windows.Win32.Foundation.ERROR_INSUFFICIENT_LOGON_INFO +Windows.Win32.Foundation.ERROR_INSUFFICIENT_POWER +Windows.Win32.Foundation.ERROR_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE +Windows.Win32.Foundation.ERROR_INSUFFICIENT_VIRTUAL_ADDR_RESOURCES +Windows.Win32.Foundation.ERROR_INTERMIXED_KERNEL_EA_OPERATION +Windows.Win32.Foundation.ERROR_INTERNAL_DB_CORRUPTION +Windows.Win32.Foundation.ERROR_INTERNAL_DB_ERROR +Windows.Win32.Foundation.ERROR_INTERNAL_ERROR +Windows.Win32.Foundation.ERROR_INTERRUPT_STILL_CONNECTED +Windows.Win32.Foundation.ERROR_INTERRUPT_VECTOR_ALREADY_CONNECTED +Windows.Win32.Foundation.ERROR_INVALID_ACCEL_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_ACCESS +Windows.Win32.Foundation.ERROR_INVALID_ACCOUNT_NAME +Windows.Win32.Foundation.ERROR_INVALID_ACE_CONDITION +Windows.Win32.Foundation.ERROR_INVALID_ACL +Windows.Win32.Foundation.ERROR_INVALID_ADDRESS +Windows.Win32.Foundation.ERROR_INVALID_AT_INTERRUPT_TIME +Windows.Win32.Foundation.ERROR_INVALID_BLOCK +Windows.Win32.Foundation.ERROR_INVALID_BLOCK_LENGTH +Windows.Win32.Foundation.ERROR_INVALID_CAP +Windows.Win32.Foundation.ERROR_INVALID_CATEGORY +Windows.Win32.Foundation.ERROR_INVALID_COMBOBOX_MESSAGE +Windows.Win32.Foundation.ERROR_INVALID_COMMAND_LINE +Windows.Win32.Foundation.ERROR_INVALID_COMPUTERNAME +Windows.Win32.Foundation.ERROR_INVALID_CRUNTIME_PARAMETER +Windows.Win32.Foundation.ERROR_INVALID_CURSOR_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_DATA +Windows.Win32.Foundation.ERROR_INVALID_DATATYPE +Windows.Win32.Foundation.ERROR_INVALID_DEVICE_OBJECT_PARAMETER +Windows.Win32.Foundation.ERROR_INVALID_DLL +Windows.Win32.Foundation.ERROR_INVALID_DOMAIN_ROLE +Windows.Win32.Foundation.ERROR_INVALID_DOMAIN_STATE +Windows.Win32.Foundation.ERROR_INVALID_DOMAINNAME +Windows.Win32.Foundation.ERROR_INVALID_DRIVE +Windows.Win32.Foundation.ERROR_INVALID_DWP_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_EA_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_EA_NAME +Windows.Win32.Foundation.ERROR_INVALID_EDIT_HEIGHT +Windows.Win32.Foundation.ERROR_INVALID_ENVIRONMENT +Windows.Win32.Foundation.ERROR_INVALID_EVENT_COUNT +Windows.Win32.Foundation.ERROR_INVALID_EVENTNAME +Windows.Win32.Foundation.ERROR_INVALID_EXCEPTION_HANDLER +Windows.Win32.Foundation.ERROR_INVALID_EXE_SIGNATURE +Windows.Win32.Foundation.ERROR_INVALID_FIELD +Windows.Win32.Foundation.ERROR_INVALID_FIELD_IN_PARAMETER_LIST +Windows.Win32.Foundation.ERROR_INVALID_FILTER_PROC +Windows.Win32.Foundation.ERROR_INVALID_FLAG_NUMBER +Windows.Win32.Foundation.ERROR_INVALID_FLAGS +Windows.Win32.Foundation.ERROR_INVALID_FORM_NAME +Windows.Win32.Foundation.ERROR_INVALID_FORM_SIZE +Windows.Win32.Foundation.ERROR_INVALID_FUNCTION +Windows.Win32.Foundation.ERROR_INVALID_GROUP_ATTRIBUTES +Windows.Win32.Foundation.ERROR_INVALID_GROUPNAME +Windows.Win32.Foundation.ERROR_INVALID_GW_COMMAND +Windows.Win32.Foundation.ERROR_INVALID_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_HANDLE_STATE +Windows.Win32.Foundation.ERROR_INVALID_HOOK_FILTER +Windows.Win32.Foundation.ERROR_INVALID_HOOK_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_HW_PROFILE +Windows.Win32.Foundation.ERROR_INVALID_ICON_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_ID_AUTHORITY +Windows.Win32.Foundation.ERROR_INVALID_IMAGE_HASH +Windows.Win32.Foundation.ERROR_INVALID_IMPORT_OF_NON_DLL +Windows.Win32.Foundation.ERROR_INVALID_INDEX +Windows.Win32.Foundation.ERROR_INVALID_KERNEL_INFO_VERSION +Windows.Win32.Foundation.ERROR_INVALID_KEYBOARD_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_LABEL +Windows.Win32.Foundation.ERROR_INVALID_LB_MESSAGE +Windows.Win32.Foundation.ERROR_INVALID_LDT_DESCRIPTOR +Windows.Win32.Foundation.ERROR_INVALID_LDT_OFFSET +Windows.Win32.Foundation.ERROR_INVALID_LDT_SIZE +Windows.Win32.Foundation.ERROR_INVALID_LEVEL +Windows.Win32.Foundation.ERROR_INVALID_LIST_FORMAT +Windows.Win32.Foundation.ERROR_INVALID_LOCK_RANGE +Windows.Win32.Foundation.ERROR_INVALID_LOGON_HOURS +Windows.Win32.Foundation.ERROR_INVALID_LOGON_TYPE +Windows.Win32.Foundation.ERROR_INVALID_MEMBER +Windows.Win32.Foundation.ERROR_INVALID_MENU_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_MESSAGE +Windows.Win32.Foundation.ERROR_INVALID_MESSAGEDEST +Windows.Win32.Foundation.ERROR_INVALID_MESSAGENAME +Windows.Win32.Foundation.ERROR_INVALID_MINALLOCSIZE +Windows.Win32.Foundation.ERROR_INVALID_MODULETYPE +Windows.Win32.Foundation.ERROR_INVALID_MONITOR_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_MSGBOX_STYLE +Windows.Win32.Foundation.ERROR_INVALID_NAME +Windows.Win32.Foundation.ERROR_INVALID_NETNAME +Windows.Win32.Foundation.ERROR_INVALID_OPLOCK_PROTOCOL +Windows.Win32.Foundation.ERROR_INVALID_ORDINAL +Windows.Win32.Foundation.ERROR_INVALID_OWNER +Windows.Win32.Foundation.ERROR_INVALID_PACKAGE_SID_LENGTH +Windows.Win32.Foundation.ERROR_INVALID_PARAMETER +Windows.Win32.Foundation.ERROR_INVALID_PASSWORD +Windows.Win32.Foundation.ERROR_INVALID_PASSWORDNAME +Windows.Win32.Foundation.ERROR_INVALID_PATCH_XML +Windows.Win32.Foundation.ERROR_INVALID_PEP_INFO_VERSION +Windows.Win32.Foundation.ERROR_INVALID_PLUGPLAY_DEVICE_PATH +Windows.Win32.Foundation.ERROR_INVALID_PORT_ATTRIBUTES +Windows.Win32.Foundation.ERROR_INVALID_PRIMARY_GROUP +Windows.Win32.Foundation.ERROR_INVALID_PRINTER_COMMAND +Windows.Win32.Foundation.ERROR_INVALID_PRINTER_NAME +Windows.Win32.Foundation.ERROR_INVALID_PRINTER_STATE +Windows.Win32.Foundation.ERROR_INVALID_PRIORITY +Windows.Win32.Foundation.ERROR_INVALID_QUOTA_LOWER +Windows.Win32.Foundation.ERROR_INVALID_REPARSE_DATA +Windows.Win32.Foundation.ERROR_INVALID_SCROLLBAR_RANGE +Windows.Win32.Foundation.ERROR_INVALID_SECURITY_DESCR +Windows.Win32.Foundation.ERROR_INVALID_SEGDPL +Windows.Win32.Foundation.ERROR_INVALID_SEGMENT_NUMBER +Windows.Win32.Foundation.ERROR_INVALID_SEPARATOR_FILE +Windows.Win32.Foundation.ERROR_INVALID_SERVER_STATE +Windows.Win32.Foundation.ERROR_INVALID_SERVICE_ACCOUNT +Windows.Win32.Foundation.ERROR_INVALID_SERVICE_CONTROL +Windows.Win32.Foundation.ERROR_INVALID_SERVICE_LOCK +Windows.Win32.Foundation.ERROR_INVALID_SERVICENAME +Windows.Win32.Foundation.ERROR_INVALID_SHARENAME +Windows.Win32.Foundation.ERROR_INVALID_SHOWWIN_COMMAND +Windows.Win32.Foundation.ERROR_INVALID_SID +Windows.Win32.Foundation.ERROR_INVALID_SIGNAL_NUMBER +Windows.Win32.Foundation.ERROR_INVALID_SPI_VALUE +Windows.Win32.Foundation.ERROR_INVALID_STACKSEG +Windows.Win32.Foundation.ERROR_INVALID_STARTING_CODESEG +Windows.Win32.Foundation.ERROR_INVALID_SUB_AUTHORITY +Windows.Win32.Foundation.ERROR_INVALID_TABLE +Windows.Win32.Foundation.ERROR_INVALID_TARGET_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_TASK_INDEX +Windows.Win32.Foundation.ERROR_INVALID_TASK_NAME +Windows.Win32.Foundation.ERROR_INVALID_THREAD_ID +Windows.Win32.Foundation.ERROR_INVALID_TIME +Windows.Win32.Foundation.ERROR_INVALID_TOKEN +Windows.Win32.Foundation.ERROR_INVALID_UNWIND_TARGET +Windows.Win32.Foundation.ERROR_INVALID_USER_BUFFER +Windows.Win32.Foundation.ERROR_INVALID_USER_PRINCIPAL_NAME +Windows.Win32.Foundation.ERROR_INVALID_VARIANT +Windows.Win32.Foundation.ERROR_INVALID_VERIFY_SWITCH +Windows.Win32.Foundation.ERROR_INVALID_WINDOW_HANDLE +Windows.Win32.Foundation.ERROR_INVALID_WORKSTATION +Windows.Win32.Foundation.ERROR_IO_DEVICE +Windows.Win32.Foundation.ERROR_IO_INCOMPLETE +Windows.Win32.Foundation.ERROR_IO_PENDING +Windows.Win32.Foundation.ERROR_IO_PRIVILEGE_FAILED +Windows.Win32.Foundation.ERROR_IO_REISSUE_AS_CACHED +Windows.Win32.Foundation.ERROR_IOPL_NOT_ENABLED +Windows.Win32.Foundation.ERROR_IP_ADDRESS_CONFLICT1 +Windows.Win32.Foundation.ERROR_IP_ADDRESS_CONFLICT2 +Windows.Win32.Foundation.ERROR_IPSEC_IKE_TIMED_OUT +Windows.Win32.Foundation.ERROR_IRQ_BUSY +Windows.Win32.Foundation.ERROR_IS_JOIN_PATH +Windows.Win32.Foundation.ERROR_IS_JOIN_TARGET +Windows.Win32.Foundation.ERROR_IS_JOINED +Windows.Win32.Foundation.ERROR_IS_SUBST_PATH +Windows.Win32.Foundation.ERROR_IS_SUBST_TARGET +Windows.Win32.Foundation.ERROR_IS_SUBSTED +Windows.Win32.Foundation.ERROR_ITERATED_DATA_EXCEEDS_64k +Windows.Win32.Foundation.ERROR_JOB_NO_CONTAINER +Windows.Win32.Foundation.ERROR_JOIN_TO_JOIN +Windows.Win32.Foundation.ERROR_JOIN_TO_SUBST +Windows.Win32.Foundation.ERROR_JOURNAL_DELETE_IN_PROGRESS +Windows.Win32.Foundation.ERROR_JOURNAL_ENTRY_DELETED +Windows.Win32.Foundation.ERROR_JOURNAL_HOOK_SET +Windows.Win32.Foundation.ERROR_JOURNAL_NOT_ACTIVE +Windows.Win32.Foundation.ERROR_KERNEL_APC +Windows.Win32.Foundation.ERROR_KEY_DELETED +Windows.Win32.Foundation.ERROR_KEY_HAS_CHILDREN +Windows.Win32.Foundation.ERROR_KM_DRIVER_BLOCKED +Windows.Win32.Foundation.ERROR_LABEL_TOO_LONG +Windows.Win32.Foundation.ERROR_LAST_ADMIN +Windows.Win32.Foundation.ERROR_LB_WITHOUT_TABSTOPS +Windows.Win32.Foundation.ERROR_LICENSE_QUOTA_EXCEEDED +Windows.Win32.Foundation.ERROR_LINUX_SUBSYSTEM_NOT_PRESENT +Windows.Win32.Foundation.ERROR_LINUX_SUBSYSTEM_UPDATE_REQUIRED +Windows.Win32.Foundation.ERROR_LISTBOX_ID_NOT_FOUND +Windows.Win32.Foundation.ERROR_LM_CROSS_ENCRYPTION_REQUIRED +Windows.Win32.Foundation.ERROR_LOCAL_POLICY_MODIFICATION_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_LOCAL_USER_SESSION_KEY +Windows.Win32.Foundation.ERROR_LOCK_FAILED +Windows.Win32.Foundation.ERROR_LOCK_VIOLATION +Windows.Win32.Foundation.ERROR_LOCKED +Windows.Win32.Foundation.ERROR_LOG_FILE_FULL +Windows.Win32.Foundation.ERROR_LOG_HARD_ERROR +Windows.Win32.Foundation.ERROR_LOGIN_TIME_RESTRICTION +Windows.Win32.Foundation.ERROR_LOGIN_WKSTA_RESTRICTION +Windows.Win32.Foundation.ERROR_LOGON_FAILURE +Windows.Win32.Foundation.ERROR_LOGON_NOT_GRANTED +Windows.Win32.Foundation.ERROR_LOGON_SERVER_CONFLICT +Windows.Win32.Foundation.ERROR_LOGON_SESSION_COLLISION +Windows.Win32.Foundation.ERROR_LOGON_SESSION_EXISTS +Windows.Win32.Foundation.ERROR_LOGON_TYPE_NOT_GRANTED +Windows.Win32.Foundation.ERROR_LONGJUMP +Windows.Win32.Foundation.ERROR_LOST_MODE_LOGON_RESTRICTION +Windows.Win32.Foundation.ERROR_LOST_WRITEBEHIND_DATA +Windows.Win32.Foundation.ERROR_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR +Windows.Win32.Foundation.ERROR_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED +Windows.Win32.Foundation.ERROR_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR +Windows.Win32.Foundation.ERROR_LUIDS_EXHAUSTED +Windows.Win32.Foundation.ERROR_MACHINE_LOCKED +Windows.Win32.Foundation.ERROR_MAGAZINE_NOT_PRESENT +Windows.Win32.Foundation.ERROR_MAPPED_ALIGNMENT +Windows.Win32.Foundation.ERROR_MARKED_TO_DISALLOW_WRITES +Windows.Win32.Foundation.ERROR_MARSHALL_OVERFLOW +Windows.Win32.Foundation.ERROR_MAX_SESSIONS_REACHED +Windows.Win32.Foundation.ERROR_MAX_THRDS_REACHED +Windows.Win32.Foundation.ERROR_MCA_EXCEPTION +Windows.Win32.Foundation.ERROR_MCA_OCCURED +Windows.Win32.Foundation.ERROR_MEDIA_CHANGED +Windows.Win32.Foundation.ERROR_MEDIA_CHECK +Windows.Win32.Foundation.ERROR_MEMBER_IN_ALIAS +Windows.Win32.Foundation.ERROR_MEMBER_IN_GROUP +Windows.Win32.Foundation.ERROR_MEMBER_NOT_IN_ALIAS +Windows.Win32.Foundation.ERROR_MEMBER_NOT_IN_GROUP +Windows.Win32.Foundation.ERROR_MEMBERS_PRIMARY_GROUP +Windows.Win32.Foundation.ERROR_MEMORY_HARDWARE +Windows.Win32.Foundation.ERROR_MENU_ITEM_NOT_FOUND +Windows.Win32.Foundation.ERROR_MESSAGE_SYNC_ONLY +Windows.Win32.Foundation.ERROR_META_EXPANSION_TOO_LONG +Windows.Win32.Foundation.ERROR_MISSING_SYSTEMFILE +Windows.Win32.Foundation.ERROR_MOD_NOT_FOUND +Windows.Win32.Foundation.ERROR_MORE_DATA +Windows.Win32.Foundation.ERROR_MORE_WRITES +Windows.Win32.Foundation.ERROR_MOUNT_POINT_NOT_RESOLVED +Windows.Win32.Foundation.ERROR_MP_PROCESSOR_MISMATCH +Windows.Win32.Foundation.ERROR_MR_MID_NOT_FOUND +Windows.Win32.Foundation.ERROR_MULTIPLE_FAULT_VIOLATION +Windows.Win32.Foundation.ERROR_MUTANT_LIMIT_EXCEEDED +Windows.Win32.Foundation.ERROR_MUTUAL_AUTH_FAILED +Windows.Win32.Foundation.ERROR_NEGATIVE_SEEK +Windows.Win32.Foundation.ERROR_NESTING_NOT_ALLOWED +Windows.Win32.Foundation.ERROR_NET_OPEN_FAILED +Windows.Win32.Foundation.ERROR_NET_WRITE_FAULT +Windows.Win32.Foundation.ERROR_NETLOGON_NOT_STARTED +Windows.Win32.Foundation.ERROR_NETNAME_DELETED +Windows.Win32.Foundation.ERROR_NETWORK_ACCESS_DENIED +Windows.Win32.Foundation.ERROR_NETWORK_ACCESS_DENIED_EDP +Windows.Win32.Foundation.ERROR_NETWORK_BUSY +Windows.Win32.Foundation.ERROR_NETWORK_UNREACHABLE +Windows.Win32.Foundation.ERROR_NO_ACE_CONDITION +Windows.Win32.Foundation.ERROR_NO_ASSOCIATION +Windows.Win32.Foundation.ERROR_NO_BYPASSIO_DRIVER_SUPPORT +Windows.Win32.Foundation.ERROR_NO_CALLBACK_ACTIVE +Windows.Win32.Foundation.ERROR_NO_DATA +Windows.Win32.Foundation.ERROR_NO_DATA_DETECTED +Windows.Win32.Foundation.ERROR_NO_EFS +Windows.Win32.Foundation.ERROR_NO_EVENT_PAIR +Windows.Win32.Foundation.ERROR_NO_GUID_TRANSLATION +Windows.Win32.Foundation.ERROR_NO_IMPERSONATION_TOKEN +Windows.Win32.Foundation.ERROR_NO_INHERITANCE +Windows.Win32.Foundation.ERROR_NO_LOG_SPACE +Windows.Win32.Foundation.ERROR_NO_LOGON_SERVERS +Windows.Win32.Foundation.ERROR_NO_MATCH +Windows.Win32.Foundation.ERROR_NO_MEDIA_IN_DRIVE +Windows.Win32.Foundation.ERROR_NO_MORE_DEVICES +Windows.Win32.Foundation.ERROR_NO_MORE_FILES +Windows.Win32.Foundation.ERROR_NO_MORE_ITEMS +Windows.Win32.Foundation.ERROR_NO_MORE_MATCHES +Windows.Win32.Foundation.ERROR_NO_MORE_SEARCH_HANDLES +Windows.Win32.Foundation.ERROR_NO_MORE_USER_HANDLES +Windows.Win32.Foundation.ERROR_NO_NET_OR_BAD_PATH +Windows.Win32.Foundation.ERROR_NO_NETWORK +Windows.Win32.Foundation.ERROR_NO_NVRAM_RESOURCES +Windows.Win32.Foundation.ERROR_NO_PAGEFILE +Windows.Win32.Foundation.ERROR_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND +Windows.Win32.Foundation.ERROR_NO_PROC_SLOTS +Windows.Win32.Foundation.ERROR_NO_PROMOTION_ACTIVE +Windows.Win32.Foundation.ERROR_NO_QUOTAS_FOR_ACCOUNT +Windows.Win32.Foundation.ERROR_NO_RANGES_PROCESSED +Windows.Win32.Foundation.ERROR_NO_RECOVERY_POLICY +Windows.Win32.Foundation.ERROR_NO_RECOVERY_PROGRAM +Windows.Win32.Foundation.ERROR_NO_SCROLLBARS +Windows.Win32.Foundation.ERROR_NO_SECRETS +Windows.Win32.Foundation.ERROR_NO_SECURITY_ON_OBJECT +Windows.Win32.Foundation.ERROR_NO_SHUTDOWN_IN_PROGRESS +Windows.Win32.Foundation.ERROR_NO_SIGNAL_SENT +Windows.Win32.Foundation.ERROR_NO_SITE_SETTINGS_OBJECT +Windows.Win32.Foundation.ERROR_NO_SITENAME +Windows.Win32.Foundation.ERROR_NO_SPOOL_SPACE +Windows.Win32.Foundation.ERROR_NO_SUCH_ALIAS +Windows.Win32.Foundation.ERROR_NO_SUCH_DEVICE +Windows.Win32.Foundation.ERROR_NO_SUCH_DOMAIN +Windows.Win32.Foundation.ERROR_NO_SUCH_GROUP +Windows.Win32.Foundation.ERROR_NO_SUCH_LOGON_SESSION +Windows.Win32.Foundation.ERROR_NO_SUCH_MEMBER +Windows.Win32.Foundation.ERROR_NO_SUCH_PACKAGE +Windows.Win32.Foundation.ERROR_NO_SUCH_PRIVILEGE +Windows.Win32.Foundation.ERROR_NO_SUCH_SITE +Windows.Win32.Foundation.ERROR_NO_SUCH_USER +Windows.Win32.Foundation.ERROR_NO_SYSTEM_MENU +Windows.Win32.Foundation.ERROR_NO_SYSTEM_RESOURCES +Windows.Win32.Foundation.ERROR_NO_TASK_QUEUE +Windows.Win32.Foundation.ERROR_NO_TOKEN +Windows.Win32.Foundation.ERROR_NO_TRACKING_SERVICE +Windows.Win32.Foundation.ERROR_NO_TRUST_LSA_SECRET +Windows.Win32.Foundation.ERROR_NO_TRUST_SAM_ACCOUNT +Windows.Win32.Foundation.ERROR_NO_UNICODE_TRANSLATION +Windows.Win32.Foundation.ERROR_NO_USER_KEYS +Windows.Win32.Foundation.ERROR_NO_USER_SESSION_KEY +Windows.Win32.Foundation.ERROR_NO_VOLUME_ID +Windows.Win32.Foundation.ERROR_NO_VOLUME_LABEL +Windows.Win32.Foundation.ERROR_NO_WILDCARD_CHARACTERS +Windows.Win32.Foundation.ERROR_NO_WORK_DONE +Windows.Win32.Foundation.ERROR_NO_WRITABLE_DC_FOUND +Windows.Win32.Foundation.ERROR_NO_YIELD_PERFORMED +Windows.Win32.Foundation.ERROR_NOACCESS +Windows.Win32.Foundation.ERROR_NOINTERFACE +Windows.Win32.Foundation.ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT +Windows.Win32.Foundation.ERROR_NOLOGON_SERVER_TRUST_ACCOUNT +Windows.Win32.Foundation.ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT +Windows.Win32.Foundation.ERROR_NON_ACCOUNT_SID +Windows.Win32.Foundation.ERROR_NON_DOMAIN_SID +Windows.Win32.Foundation.ERROR_NON_MDICHILD_WINDOW +Windows.Win32.Foundation.ERROR_NONE_MAPPED +Windows.Win32.Foundation.ERROR_NONPAGED_SYSTEM_RESOURCES +Windows.Win32.Foundation.ERROR_NOT_A_CLOUD_FILE +Windows.Win32.Foundation.ERROR_NOT_A_CLOUD_SYNC_ROOT +Windows.Win32.Foundation.ERROR_NOT_A_DAX_VOLUME +Windows.Win32.Foundation.ERROR_NOT_A_REPARSE_POINT +Windows.Win32.Foundation.ERROR_NOT_ALL_ASSIGNED +Windows.Win32.Foundation.ERROR_NOT_ALLOWED_ON_SYSTEM_FILE +Windows.Win32.Foundation.ERROR_NOT_APPCONTAINER +Windows.Win32.Foundation.ERROR_NOT_AUTHENTICATED +Windows.Win32.Foundation.ERROR_NOT_CAPABLE +Windows.Win32.Foundation.ERROR_NOT_CHILD_WINDOW +Windows.Win32.Foundation.ERROR_NOT_CONNECTED +Windows.Win32.Foundation.ERROR_NOT_CONTAINER +Windows.Win32.Foundation.ERROR_NOT_DAX_MAPPABLE +Windows.Win32.Foundation.ERROR_NOT_DOS_DISK +Windows.Win32.Foundation.ERROR_NOT_ENOUGH_MEMORY +Windows.Win32.Foundation.ERROR_NOT_ENOUGH_QUOTA +Windows.Win32.Foundation.ERROR_NOT_ENOUGH_SERVER_MEMORY +Windows.Win32.Foundation.ERROR_NOT_EXPORT_FORMAT +Windows.Win32.Foundation.ERROR_NOT_FOUND +Windows.Win32.Foundation.ERROR_NOT_GUI_PROCESS +Windows.Win32.Foundation.ERROR_NOT_JOINED +Windows.Win32.Foundation.ERROR_NOT_LOCKED +Windows.Win32.Foundation.ERROR_NOT_LOGGED_ON +Windows.Win32.Foundation.ERROR_NOT_LOGON_PROCESS +Windows.Win32.Foundation.ERROR_NOT_OWNER +Windows.Win32.Foundation.ERROR_NOT_READ_FROM_COPY +Windows.Win32.Foundation.ERROR_NOT_READY +Windows.Win32.Foundation.ERROR_NOT_REDUNDANT_STORAGE +Windows.Win32.Foundation.ERROR_NOT_REGISTRY_FILE +Windows.Win32.Foundation.ERROR_NOT_SAFE_MODE_DRIVER +Windows.Win32.Foundation.ERROR_NOT_SAFEBOOT_SERVICE +Windows.Win32.Foundation.ERROR_NOT_SAME_DEVICE +Windows.Win32.Foundation.ERROR_NOT_SAME_OBJECT +Windows.Win32.Foundation.ERROR_NOT_SUBSTED +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_IN_APPCONTAINER +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_ON_DAX +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_ON_SBS +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_AUDITING +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_BTT +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_BYPASSIO +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_CACHED_HANDLE +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_COMPRESSION +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_DEDUPLICATION +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_ENCRYPTION +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_MONITORING +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_REPLICATION +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_SNAPSHOT +Windows.Win32.Foundation.ERROR_NOT_SUPPORTED_WITH_VIRTUALIZATION +Windows.Win32.Foundation.ERROR_NOT_TINY_STREAM +Windows.Win32.Foundation.ERROR_NOTHING_TO_TERMINATE +Windows.Win32.Foundation.ERROR_NOTIFICATION_GUID_ALREADY_DEFINED +Windows.Win32.Foundation.ERROR_NOTIFY_CLEANUP +Windows.Win32.Foundation.ERROR_NOTIFY_ENUM_DIR +Windows.Win32.Foundation.ERROR_NT_CROSS_ENCRYPTION_REQUIRED +Windows.Win32.Foundation.ERROR_NTLM_BLOCKED +Windows.Win32.Foundation.ERROR_NULL_LM_PASSWORD +Windows.Win32.Foundation.ERROR_OBJECT_IS_IMMUTABLE +Windows.Win32.Foundation.ERROR_OBJECT_NAME_EXISTS +Windows.Win32.Foundation.ERROR_OBJECT_NOT_EXTERNALLY_BACKED +Windows.Win32.Foundation.ERROR_OFFLOAD_READ_FILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_OFFLOAD_READ_FLT_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_OFFLOAD_WRITE_FILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_OFFLOAD_WRITE_FLT_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_OFFSET_ALIGNMENT_VIOLATION +Windows.Win32.Foundation.ERROR_OLD_WIN_VERSION +Windows.Win32.Foundation.ERROR_ONLY_IF_CONNECTED +Windows.Win32.Foundation.ERROR_OPEN_FAILED +Windows.Win32.Foundation.ERROR_OPEN_FILES +Windows.Win32.Foundation.ERROR_OPERATION_ABORTED +Windows.Win32.Foundation.ERROR_OPERATION_IN_PROGRESS +Windows.Win32.Foundation.ERROR_OPLOCK_BREAK_IN_PROGRESS +Windows.Win32.Foundation.ERROR_OPLOCK_HANDLE_CLOSED +Windows.Win32.Foundation.ERROR_OPLOCK_NOT_GRANTED +Windows.Win32.Foundation.ERROR_OPLOCK_SWITCHED_TO_NEW_HANDLE +Windows.Win32.Foundation.ERROR_ORPHAN_NAME_EXHAUSTED +Windows.Win32.Foundation.ERROR_OUT_OF_PAPER +Windows.Win32.Foundation.ERROR_OUT_OF_STRUCTURES +Windows.Win32.Foundation.ERROR_OUTOFMEMORY +Windows.Win32.Foundation.ERROR_OVERRIDE_NOCHANGES +Windows.Win32.Foundation.ERROR_PAGE_FAULT_COPY_ON_WRITE +Windows.Win32.Foundation.ERROR_PAGE_FAULT_DEMAND_ZERO +Windows.Win32.Foundation.ERROR_PAGE_FAULT_GUARD_PAGE +Windows.Win32.Foundation.ERROR_PAGE_FAULT_PAGING_FILE +Windows.Win32.Foundation.ERROR_PAGE_FAULT_TRANSITION +Windows.Win32.Foundation.ERROR_PAGED_SYSTEM_RESOURCES +Windows.Win32.Foundation.ERROR_PAGEFILE_CREATE_FAILED +Windows.Win32.Foundation.ERROR_PAGEFILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_PAGEFILE_QUOTA +Windows.Win32.Foundation.ERROR_PAGEFILE_QUOTA_EXCEEDED +Windows.Win32.Foundation.ERROR_PARAMETER_QUOTA_EXCEEDED +Windows.Win32.Foundation.ERROR_PARTIAL_COPY +Windows.Win32.Foundation.ERROR_PARTITION_FAILURE +Windows.Win32.Foundation.ERROR_PARTITION_TERMINATING +Windows.Win32.Foundation.ERROR_PASSWORD_CHANGE_REQUIRED +Windows.Win32.Foundation.ERROR_PASSWORD_EXPIRED +Windows.Win32.Foundation.ERROR_PASSWORD_MUST_CHANGE +Windows.Win32.Foundation.ERROR_PASSWORD_RESTRICTION +Windows.Win32.Foundation.ERROR_PATCH_MANAGED_ADVERTISED_PRODUCT +Windows.Win32.Foundation.ERROR_PATCH_NO_SEQUENCE +Windows.Win32.Foundation.ERROR_PATCH_PACKAGE_INVALID +Windows.Win32.Foundation.ERROR_PATCH_PACKAGE_OPEN_FAILED +Windows.Win32.Foundation.ERROR_PATCH_PACKAGE_REJECTED +Windows.Win32.Foundation.ERROR_PATCH_PACKAGE_UNSUPPORTED +Windows.Win32.Foundation.ERROR_PATCH_REMOVAL_DISALLOWED +Windows.Win32.Foundation.ERROR_PATCH_REMOVAL_UNSUPPORTED +Windows.Win32.Foundation.ERROR_PATCH_TARGET_NOT_FOUND +Windows.Win32.Foundation.ERROR_PATH_BUSY +Windows.Win32.Foundation.ERROR_PATH_NOT_FOUND +Windows.Win32.Foundation.ERROR_PER_USER_TRUST_QUOTA_EXCEEDED +Windows.Win32.Foundation.ERROR_PIPE_BUSY +Windows.Win32.Foundation.ERROR_PIPE_CONNECTED +Windows.Win32.Foundation.ERROR_PIPE_LISTENING +Windows.Win32.Foundation.ERROR_PIPE_LOCAL +Windows.Win32.Foundation.ERROR_PIPE_NOT_CONNECTED +Windows.Win32.Foundation.ERROR_PKINIT_FAILURE +Windows.Win32.Foundation.ERROR_PLUGPLAY_QUERY_VETOED +Windows.Win32.Foundation.ERROR_PNP_BAD_MPS_TABLE +Windows.Win32.Foundation.ERROR_PNP_INVALID_ID +Windows.Win32.Foundation.ERROR_PNP_IRQ_TRANSLATION_FAILED +Windows.Win32.Foundation.ERROR_PNP_QUERY_REMOVE_DEVICE_TIMEOUT +Windows.Win32.Foundation.ERROR_PNP_QUERY_REMOVE_RELATED_DEVICE_TIMEOUT +Windows.Win32.Foundation.ERROR_PNP_QUERY_REMOVE_UNRELATED_DEVICE_TIMEOUT +Windows.Win32.Foundation.ERROR_PNP_REBOOT_REQUIRED +Windows.Win32.Foundation.ERROR_PNP_RESTART_ENUMERATION +Windows.Win32.Foundation.ERROR_PNP_TRANSLATION_FAILED +Windows.Win32.Foundation.ERROR_POINT_NOT_FOUND +Windows.Win32.Foundation.ERROR_POLICY_OBJECT_NOT_FOUND +Windows.Win32.Foundation.ERROR_POLICY_ONLY_IN_DS +Windows.Win32.Foundation.ERROR_POPUP_ALREADY_ACTIVE +Windows.Win32.Foundation.ERROR_PORT_MESSAGE_TOO_LONG +Windows.Win32.Foundation.ERROR_PORT_NOT_SET +Windows.Win32.Foundation.ERROR_PORT_UNREACHABLE +Windows.Win32.Foundation.ERROR_POSSIBLE_DEADLOCK +Windows.Win32.Foundation.ERROR_POTENTIAL_FILE_FOUND +Windows.Win32.Foundation.ERROR_PREDEFINED_HANDLE +Windows.Win32.Foundation.ERROR_PRIMARY_TRANSPORT_CONNECT_FAILED +Windows.Win32.Foundation.ERROR_PRINT_CANCELLED +Windows.Win32.Foundation.ERROR_PRINTER_ALREADY_EXISTS +Windows.Win32.Foundation.ERROR_PRINTER_DELETED +Windows.Win32.Foundation.ERROR_PRINTER_DRIVER_ALREADY_INSTALLED +Windows.Win32.Foundation.ERROR_PRINTQ_FULL +Windows.Win32.Foundation.ERROR_PRIVATE_DIALOG_INDEX +Windows.Win32.Foundation.ERROR_PRIVILEGE_NOT_HELD +Windows.Win32.Foundation.ERROR_PROC_NOT_FOUND +Windows.Win32.Foundation.ERROR_PROCESS_ABORTED +Windows.Win32.Foundation.ERROR_PROCESS_IN_JOB +Windows.Win32.Foundation.ERROR_PROCESS_IS_PROTECTED +Windows.Win32.Foundation.ERROR_PROCESS_MODE_ALREADY_BACKGROUND +Windows.Win32.Foundation.ERROR_PROCESS_MODE_NOT_BACKGROUND +Windows.Win32.Foundation.ERROR_PROCESS_NOT_IN_JOB +Windows.Win32.Foundation.ERROR_PRODUCT_UNINSTALLED +Windows.Win32.Foundation.ERROR_PRODUCT_VERSION +Windows.Win32.Foundation.ERROR_PROFILING_AT_LIMIT +Windows.Win32.Foundation.ERROR_PROFILING_NOT_STARTED +Windows.Win32.Foundation.ERROR_PROFILING_NOT_STOPPED +Windows.Win32.Foundation.ERROR_PROMOTION_ACTIVE +Windows.Win32.Foundation.ERROR_PROTOCOL_UNREACHABLE +Windows.Win32.Foundation.ERROR_PWD_HISTORY_CONFLICT +Windows.Win32.Foundation.ERROR_PWD_TOO_LONG +Windows.Win32.Foundation.ERROR_PWD_TOO_RECENT +Windows.Win32.Foundation.ERROR_PWD_TOO_SHORT +Windows.Win32.Foundation.ERROR_QUOTA_ACTIVITY +Windows.Win32.Foundation.ERROR_QUOTA_LIST_INCONSISTENT +Windows.Win32.Foundation.ERROR_RANGE_LIST_CONFLICT +Windows.Win32.Foundation.ERROR_RANGE_NOT_FOUND +Windows.Win32.Foundation.ERROR_READ_FAULT +Windows.Win32.Foundation.ERROR_RECEIVE_EXPEDITED +Windows.Win32.Foundation.ERROR_RECEIVE_PARTIAL +Windows.Win32.Foundation.ERROR_RECEIVE_PARTIAL_EXPEDITED +Windows.Win32.Foundation.ERROR_RECOVERY_FAILURE +Windows.Win32.Foundation.ERROR_REDIR_PAUSED +Windows.Win32.Foundation.ERROR_REDIRECTOR_HAS_OPEN_HANDLES +Windows.Win32.Foundation.ERROR_REG_NAT_CONSUMPTION +Windows.Win32.Foundation.ERROR_REGISTRY_CORRUPT +Windows.Win32.Foundation.ERROR_REGISTRY_HIVE_RECOVERED +Windows.Win32.Foundation.ERROR_REGISTRY_IO_FAILED +Windows.Win32.Foundation.ERROR_REGISTRY_QUOTA_LIMIT +Windows.Win32.Foundation.ERROR_REGISTRY_RECOVERED +Windows.Win32.Foundation.ERROR_RELOC_CHAIN_XEEDS_SEGLIM +Windows.Win32.Foundation.ERROR_REM_NOT_LIST +Windows.Win32.Foundation.ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED +Windows.Win32.Foundation.ERROR_REMOTE_SESSION_LIMIT_EXCEEDED +Windows.Win32.Foundation.ERROR_REMOTE_STORAGE_MEDIA_ERROR +Windows.Win32.Foundation.ERROR_REMOTE_STORAGE_NOT_ACTIVE +Windows.Win32.Foundation.ERROR_REPARSE +Windows.Win32.Foundation.ERROR_REPARSE_ATTRIBUTE_CONFLICT +Windows.Win32.Foundation.ERROR_REPARSE_OBJECT +Windows.Win32.Foundation.ERROR_REPARSE_POINT_ENCOUNTERED +Windows.Win32.Foundation.ERROR_REPARSE_TAG_INVALID +Windows.Win32.Foundation.ERROR_REPARSE_TAG_MISMATCH +Windows.Win32.Foundation.ERROR_REPLY_MESSAGE_MISMATCH +Windows.Win32.Foundation.ERROR_REQ_NOT_ACCEP +Windows.Win32.Foundation.ERROR_REQUEST_ABORTED +Windows.Win32.Foundation.ERROR_REQUEST_OUT_OF_SEQUENCE +Windows.Win32.Foundation.ERROR_REQUEST_PAUSED +Windows.Win32.Foundation.ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION +Windows.Win32.Foundation.ERROR_RESIDENT_FILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_RESOURCE_CALL_TIMED_OUT +Windows.Win32.Foundation.ERROR_RESOURCE_DATA_NOT_FOUND +Windows.Win32.Foundation.ERROR_RESOURCE_LANG_NOT_FOUND +Windows.Win32.Foundation.ERROR_RESOURCE_NAME_NOT_FOUND +Windows.Win32.Foundation.ERROR_RESOURCE_REQUIREMENTS_CHANGED +Windows.Win32.Foundation.ERROR_RESOURCE_TYPE_NOT_FOUND +Windows.Win32.Foundation.ERROR_RESTART_APPLICATION +Windows.Win32.Foundation.ERROR_RESUME_HIBERNATION +Windows.Win32.Foundation.ERROR_RETRY +Windows.Win32.Foundation.ERROR_RETURN_ADDRESS_HIJACK_ATTEMPT +Windows.Win32.Foundation.ERROR_REVISION_MISMATCH +Windows.Win32.Foundation.ERROR_RING2_STACK_IN_USE +Windows.Win32.Foundation.ERROR_RING2SEG_MUST_BE_MOVABLE +Windows.Win32.Foundation.ERROR_RMODE_APP +Windows.Win32.Foundation.ERROR_ROWSNOTRELEASED +Windows.Win32.Foundation.ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT +Windows.Win32.Foundation.ERROR_RUNLEVEL_SWITCH_TIMEOUT +Windows.Win32.Foundation.ERROR_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED +Windows.Win32.Foundation.ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET +Windows.Win32.Foundation.ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE +Windows.Win32.Foundation.ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER +Windows.Win32.Foundation.ERROR_RXACT_COMMIT_FAILURE +Windows.Win32.Foundation.ERROR_RXACT_COMMIT_NECESSARY +Windows.Win32.Foundation.ERROR_RXACT_COMMITTED +Windows.Win32.Foundation.ERROR_RXACT_INVALID_STATE +Windows.Win32.Foundation.ERROR_RXACT_STATE_CREATED +Windows.Win32.Foundation.ERROR_SAM_INIT_FAILURE +Windows.Win32.Foundation.ERROR_SAME_DRIVE +Windows.Win32.Foundation.ERROR_SCOPE_NOT_FOUND +Windows.Win32.Foundation.ERROR_SCREEN_ALREADY_LOCKED +Windows.Win32.Foundation.ERROR_SCRUB_DATA_DISABLED +Windows.Win32.Foundation.ERROR_SECRET_TOO_LONG +Windows.Win32.Foundation.ERROR_SECTION_DIRECT_MAP_ONLY +Windows.Win32.Foundation.ERROR_SECTOR_NOT_FOUND +Windows.Win32.Foundation.ERROR_SECURITY_DENIES_OPERATION +Windows.Win32.Foundation.ERROR_SECURITY_STREAM_IS_INCONSISTENT +Windows.Win32.Foundation.ERROR_SEEK +Windows.Win32.Foundation.ERROR_SEEK_ON_DEVICE +Windows.Win32.Foundation.ERROR_SEGMENT_NOTIFICATION +Windows.Win32.Foundation.ERROR_SEM_IS_SET +Windows.Win32.Foundation.ERROR_SEM_NOT_FOUND +Windows.Win32.Foundation.ERROR_SEM_OWNER_DIED +Windows.Win32.Foundation.ERROR_SEM_TIMEOUT +Windows.Win32.Foundation.ERROR_SEM_USER_LIMIT +Windows.Win32.Foundation.ERROR_SERIAL_NO_DEVICE +Windows.Win32.Foundation.ERROR_SERVER_DISABLED +Windows.Win32.Foundation.ERROR_SERVER_HAS_OPEN_HANDLES +Windows.Win32.Foundation.ERROR_SERVER_NOT_DISABLED +Windows.Win32.Foundation.ERROR_SERVER_SHUTDOWN_IN_PROGRESS +Windows.Win32.Foundation.ERROR_SERVER_SID_MISMATCH +Windows.Win32.Foundation.ERROR_SERVER_TRANSPORT_CONFLICT +Windows.Win32.Foundation.ERROR_SERVICE_ALREADY_RUNNING +Windows.Win32.Foundation.ERROR_SERVICE_CANNOT_ACCEPT_CTRL +Windows.Win32.Foundation.ERROR_SERVICE_DATABASE_LOCKED +Windows.Win32.Foundation.ERROR_SERVICE_DEPENDENCY_DELETED +Windows.Win32.Foundation.ERROR_SERVICE_DEPENDENCY_FAIL +Windows.Win32.Foundation.ERROR_SERVICE_DISABLED +Windows.Win32.Foundation.ERROR_SERVICE_DOES_NOT_EXIST +Windows.Win32.Foundation.ERROR_SERVICE_EXISTS +Windows.Win32.Foundation.ERROR_SERVICE_LOGON_FAILED +Windows.Win32.Foundation.ERROR_SERVICE_MARKED_FOR_DELETE +Windows.Win32.Foundation.ERROR_SERVICE_NEVER_STARTED +Windows.Win32.Foundation.ERROR_SERVICE_NO_THREAD +Windows.Win32.Foundation.ERROR_SERVICE_NOT_ACTIVE +Windows.Win32.Foundation.ERROR_SERVICE_NOT_FOUND +Windows.Win32.Foundation.ERROR_SERVICE_NOT_IN_EXE +Windows.Win32.Foundation.ERROR_SERVICE_NOTIFICATION +Windows.Win32.Foundation.ERROR_SERVICE_NOTIFY_CLIENT_LAGGING +Windows.Win32.Foundation.ERROR_SERVICE_REQUEST_TIMEOUT +Windows.Win32.Foundation.ERROR_SERVICE_SPECIFIC_ERROR +Windows.Win32.Foundation.ERROR_SERVICE_START_HANG +Windows.Win32.Foundation.ERROR_SESSION_CREDENTIAL_CONFLICT +Windows.Win32.Foundation.ERROR_SESSION_KEY_TOO_SHORT +Windows.Win32.Foundation.ERROR_SET_CONTEXT_DENIED +Windows.Win32.Foundation.ERROR_SET_NOT_FOUND +Windows.Win32.Foundation.ERROR_SET_POWER_STATE_FAILED +Windows.Win32.Foundation.ERROR_SET_POWER_STATE_VETOED +Windows.Win32.Foundation.ERROR_SETCOUNT_ON_BAD_LB +Windows.Win32.Foundation.ERROR_SETMARK_DETECTED +Windows.Win32.Foundation.ERROR_SHARED_POLICY +Windows.Win32.Foundation.ERROR_SHARING_BUFFER_EXCEEDED +Windows.Win32.Foundation.ERROR_SHARING_PAUSED +Windows.Win32.Foundation.ERROR_SHARING_VIOLATION +Windows.Win32.Foundation.ERROR_SHORT_NAMES_NOT_ENABLED_ON_VOLUME +Windows.Win32.Foundation.ERROR_SHUTDOWN_DISKS_NOT_IN_MAINTENANCE_MODE +Windows.Win32.Foundation.ERROR_SHUTDOWN_IN_PROGRESS +Windows.Win32.Foundation.ERROR_SHUTDOWN_IS_SCHEDULED +Windows.Win32.Foundation.ERROR_SHUTDOWN_USERS_LOGGED_ON +Windows.Win32.Foundation.ERROR_SIGNAL_PENDING +Windows.Win32.Foundation.ERROR_SIGNAL_REFUSED +Windows.Win32.Foundation.ERROR_SINGLE_INSTANCE_APP +Windows.Win32.Foundation.ERROR_SMARTCARD_SUBSYSTEM_FAILURE +Windows.Win32.Foundation.ERROR_SMB1_NOT_AVAILABLE +Windows.Win32.Foundation.ERROR_SMB_GUEST_LOGON_BLOCKED +Windows.Win32.Foundation.ERROR_SMR_GARBAGE_COLLECTION_REQUIRED +Windows.Win32.Foundation.ERROR_SOME_NOT_MAPPED +Windows.Win32.Foundation.ERROR_SOURCE_ELEMENT_EMPTY +Windows.Win32.Foundation.ERROR_SPARSE_FILE_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_SPECIAL_ACCOUNT +Windows.Win32.Foundation.ERROR_SPECIAL_GROUP +Windows.Win32.Foundation.ERROR_SPECIAL_USER +Windows.Win32.Foundation.ERROR_SRC_SRV_DLL_LOAD_FAILED +Windows.Win32.Foundation.ERROR_STACK_BUFFER_OVERRUN +Windows.Win32.Foundation.ERROR_STACK_OVERFLOW +Windows.Win32.Foundation.ERROR_STACK_OVERFLOW_READ +Windows.Win32.Foundation.ERROR_STOPPED_ON_SYMLINK +Windows.Win32.Foundation.ERROR_STORAGE_LOST_DATA_PERSISTENCE +Windows.Win32.Foundation.ERROR_STORAGE_RESERVE_ALREADY_EXISTS +Windows.Win32.Foundation.ERROR_STORAGE_RESERVE_DOES_NOT_EXIST +Windows.Win32.Foundation.ERROR_STORAGE_RESERVE_ID_INVALID +Windows.Win32.Foundation.ERROR_STORAGE_RESERVE_NOT_EMPTY +Windows.Win32.Foundation.ERROR_STORAGE_STACK_ACCESS_DENIED +Windows.Win32.Foundation.ERROR_STORAGE_TOPOLOGY_ID_MISMATCH +Windows.Win32.Foundation.ERROR_STRICT_CFG_VIOLATION +Windows.Win32.Foundation.ERROR_SUBST_TO_JOIN +Windows.Win32.Foundation.ERROR_SUBST_TO_SUBST +Windows.Win32.Foundation.ERROR_SUCCESS +Windows.Win32.Foundation.ERROR_SUCCESS_REBOOT_INITIATED +Windows.Win32.Foundation.ERROR_SWAPERROR +Windows.Win32.Foundation.ERROR_SYMLINK_CLASS_DISABLED +Windows.Win32.Foundation.ERROR_SYMLINK_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED +Windows.Win32.Foundation.ERROR_SYNCHRONIZATION_REQUIRED +Windows.Win32.Foundation.ERROR_SYSTEM_HIVE_TOO_LARGE +Windows.Win32.Foundation.ERROR_SYSTEM_IMAGE_BAD_SIGNATURE +Windows.Win32.Foundation.ERROR_SYSTEM_POWERSTATE_COMPLEX_TRANSITION +Windows.Win32.Foundation.ERROR_SYSTEM_POWERSTATE_TRANSITION +Windows.Win32.Foundation.ERROR_SYSTEM_PROCESS_TERMINATED +Windows.Win32.Foundation.ERROR_SYSTEM_SHUTDOWN +Windows.Win32.Foundation.ERROR_SYSTEM_TRACE +Windows.Win32.Foundation.ERROR_THREAD_1_INACTIVE +Windows.Win32.Foundation.ERROR_THREAD_ALREADY_IN_TASK +Windows.Win32.Foundation.ERROR_THREAD_MODE_ALREADY_BACKGROUND +Windows.Win32.Foundation.ERROR_THREAD_MODE_NOT_BACKGROUND +Windows.Win32.Foundation.ERROR_THREAD_NOT_IN_PROCESS +Windows.Win32.Foundation.ERROR_THREAD_WAS_SUSPENDED +Windows.Win32.Foundation.ERROR_TIME_SENSITIVE_THREAD +Windows.Win32.Foundation.ERROR_TIME_SKEW +Windows.Win32.Foundation.ERROR_TIMEOUT +Windows.Win32.Foundation.ERROR_TIMER_NOT_CANCELED +Windows.Win32.Foundation.ERROR_TIMER_RESOLUTION_NOT_SET +Windows.Win32.Foundation.ERROR_TIMER_RESUME_IGNORED +Windows.Win32.Foundation.ERROR_TLW_WITH_WSCHILD +Windows.Win32.Foundation.ERROR_TOKEN_ALREADY_IN_USE +Windows.Win32.Foundation.ERROR_TOO_MANY_CMDS +Windows.Win32.Foundation.ERROR_TOO_MANY_CONTEXT_IDS +Windows.Win32.Foundation.ERROR_TOO_MANY_DESCRIPTORS +Windows.Win32.Foundation.ERROR_TOO_MANY_LINKS +Windows.Win32.Foundation.ERROR_TOO_MANY_LUIDS_REQUESTED +Windows.Win32.Foundation.ERROR_TOO_MANY_MODULES +Windows.Win32.Foundation.ERROR_TOO_MANY_MUXWAITERS +Windows.Win32.Foundation.ERROR_TOO_MANY_NAMES +Windows.Win32.Foundation.ERROR_TOO_MANY_OPEN_FILES +Windows.Win32.Foundation.ERROR_TOO_MANY_POSTS +Windows.Win32.Foundation.ERROR_TOO_MANY_SECRETS +Windows.Win32.Foundation.ERROR_TOO_MANY_SEM_REQUESTS +Windows.Win32.Foundation.ERROR_TOO_MANY_SEMAPHORES +Windows.Win32.Foundation.ERROR_TOO_MANY_SESS +Windows.Win32.Foundation.ERROR_TOO_MANY_SIDS +Windows.Win32.Foundation.ERROR_TOO_MANY_TCBS +Windows.Win32.Foundation.ERROR_TOO_MANY_THREADS +Windows.Win32.Foundation.ERROR_TRANSLATION_COMPLETE +Windows.Win32.Foundation.ERROR_TRUST_FAILURE +Windows.Win32.Foundation.ERROR_TRUSTED_DOMAIN_FAILURE +Windows.Win32.Foundation.ERROR_TRUSTED_RELATIONSHIP_FAILURE +Windows.Win32.Foundation.ERROR_UNABLE_TO_LOCK_MEDIA +Windows.Win32.Foundation.ERROR_UNABLE_TO_MOVE_REPLACEMENT +Windows.Win32.Foundation.ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 +Windows.Win32.Foundation.ERROR_UNABLE_TO_REMOVE_REPLACED +Windows.Win32.Foundation.ERROR_UNABLE_TO_UNLOAD_MEDIA +Windows.Win32.Foundation.ERROR_UNDEFINED_CHARACTER +Windows.Win32.Foundation.ERROR_UNDEFINED_SCOPE +Windows.Win32.Foundation.ERROR_UNEXP_NET_ERR +Windows.Win32.Foundation.ERROR_UNEXPECTED_MM_CREATE_ERR +Windows.Win32.Foundation.ERROR_UNEXPECTED_MM_EXTEND_ERR +Windows.Win32.Foundation.ERROR_UNEXPECTED_MM_MAP_ERROR +Windows.Win32.Foundation.ERROR_UNEXPECTED_NTCACHEMANAGER_ERROR +Windows.Win32.Foundation.ERROR_UNHANDLED_EXCEPTION +Windows.Win32.Foundation.ERROR_UNIDENTIFIED_ERROR +Windows.Win32.Foundation.ERROR_UNKNOWN_COMPONENT +Windows.Win32.Foundation.ERROR_UNKNOWN_FEATURE +Windows.Win32.Foundation.ERROR_UNKNOWN_PATCH +Windows.Win32.Foundation.ERROR_UNKNOWN_PORT +Windows.Win32.Foundation.ERROR_UNKNOWN_PRINTER_DRIVER +Windows.Win32.Foundation.ERROR_UNKNOWN_PRINTPROCESSOR +Windows.Win32.Foundation.ERROR_UNKNOWN_PRODUCT +Windows.Win32.Foundation.ERROR_UNKNOWN_PROPERTY +Windows.Win32.Foundation.ERROR_UNKNOWN_REVISION +Windows.Win32.Foundation.ERROR_UNRECOGNIZED_MEDIA +Windows.Win32.Foundation.ERROR_UNRECOGNIZED_VOLUME +Windows.Win32.Foundation.ERROR_UNSATISFIED_DEPENDENCIES +Windows.Win32.Foundation.ERROR_UNSUPPORTED_COMPRESSION +Windows.Win32.Foundation.ERROR_UNSUPPORTED_TYPE +Windows.Win32.Foundation.ERROR_UNTRUSTED_MOUNT_POINT +Windows.Win32.Foundation.ERROR_UNWIND +Windows.Win32.Foundation.ERROR_UNWIND_CONSOLIDATE +Windows.Win32.Foundation.ERROR_USER_APC +Windows.Win32.Foundation.ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED +Windows.Win32.Foundation.ERROR_USER_EXISTS +Windows.Win32.Foundation.ERROR_USER_MAPPED_FILE +Windows.Win32.Foundation.ERROR_USER_PROFILE_LOAD +Windows.Win32.Foundation.ERROR_VALIDATE_CONTINUE +Windows.Win32.Foundation.ERROR_VC_DISCONNECTED +Windows.Win32.Foundation.ERROR_VDM_DISALLOWED +Windows.Win32.Foundation.ERROR_VDM_HARD_ERROR +Windows.Win32.Foundation.ERROR_VERIFIER_STOP +Windows.Win32.Foundation.ERROR_VERSION_PARSE_ERROR +Windows.Win32.Foundation.ERROR_VIRUS_DELETED +Windows.Win32.Foundation.ERROR_VIRUS_INFECTED +Windows.Win32.Foundation.ERROR_VOLSNAP_HIBERNATE_READY +Windows.Win32.Foundation.ERROR_VOLSNAP_PREPARE_HIBERNATE +Windows.Win32.Foundation.ERROR_VOLUME_MOUNTED +Windows.Win32.Foundation.ERROR_VOLUME_NOT_CLUSTER_ALIGNED +Windows.Win32.Foundation.ERROR_VOLUME_NOT_SIS_ENABLED +Windows.Win32.Foundation.ERROR_VOLUME_NOT_SUPPORT_EFS +Windows.Win32.Foundation.ERROR_VOLUME_NOT_SUPPORTED +Windows.Win32.Foundation.ERROR_VOLUME_WRITE_ACCESS_DENIED +Windows.Win32.Foundation.ERROR_WAIT_1 +Windows.Win32.Foundation.ERROR_WAIT_2 +Windows.Win32.Foundation.ERROR_WAIT_3 +Windows.Win32.Foundation.ERROR_WAIT_63 +Windows.Win32.Foundation.ERROR_WAIT_FOR_OPLOCK +Windows.Win32.Foundation.ERROR_WAIT_NO_CHILDREN +Windows.Win32.Foundation.ERROR_WAKE_SYSTEM +Windows.Win32.Foundation.ERROR_WAKE_SYSTEM_DEBUGGER +Windows.Win32.Foundation.ERROR_WAS_LOCKED +Windows.Win32.Foundation.ERROR_WAS_UNLOCKED +Windows.Win32.Foundation.ERROR_WEAK_WHFBKEY_BLOCKED +Windows.Win32.Foundation.ERROR_WINDOW_NOT_COMBOBOX +Windows.Win32.Foundation.ERROR_WINDOW_NOT_DIALOG +Windows.Win32.Foundation.ERROR_WINDOW_OF_OTHER_THREAD +Windows.Win32.Foundation.ERROR_WIP_ENCRYPTION_FAILED +Windows.Win32.Foundation.ERROR_WOF_FILE_RESOURCE_TABLE_CORRUPT +Windows.Win32.Foundation.ERROR_WOF_WIM_HEADER_CORRUPT +Windows.Win32.Foundation.ERROR_WOF_WIM_RESOURCE_TABLE_CORRUPT +Windows.Win32.Foundation.ERROR_WORKING_SET_QUOTA +Windows.Win32.Foundation.ERROR_WOW_ASSERTION +Windows.Win32.Foundation.ERROR_WRITE_FAULT +Windows.Win32.Foundation.ERROR_WRITE_PROTECT +Windows.Win32.Foundation.ERROR_WRONG_COMPARTMENT +Windows.Win32.Foundation.ERROR_WRONG_DISK +Windows.Win32.Foundation.ERROR_WRONG_EFS +Windows.Win32.Foundation.ERROR_WRONG_PASSWORD +Windows.Win32.Foundation.ERROR_WRONG_TARGET_NAME +Windows.Win32.Foundation.ERROR_WX86_ERROR +Windows.Win32.Foundation.ERROR_WX86_WARNING +Windows.Win32.Foundation.ERROR_XML_PARSE_ERROR +Windows.Win32.Foundation.ERROR_XMLDSIG_ERROR +Windows.Win32.Foundation.EXCEPTION_STACK_OVERFLOW +Windows.Win32.Foundation.FALSE +Windows.Win32.Foundation.FARPROC +Windows.Win32.Foundation.FILETIME +Windows.Win32.Foundation.FRS_ERR_SYSVOL_POPULATE_TIMEOUT +Windows.Win32.Foundation.GENERIC_ACCESS_RIGHTS +Windows.Win32.Foundation.GENERIC_ALL +Windows.Win32.Foundation.GENERIC_EXECUTE +Windows.Win32.Foundation.GENERIC_READ +Windows.Win32.Foundation.GENERIC_WRITE +Windows.Win32.Foundation.GetLastError +Windows.Win32.Foundation.HANDLE +Windows.Win32.Foundation.HANDLE_FLAG_INHERIT +Windows.Win32.Foundation.HANDLE_FLAG_PROTECT_FROM_CLOSE +Windows.Win32.Foundation.HANDLE_FLAGS +Windows.Win32.Foundation.HMODULE +Windows.Win32.Foundation.INVALID_HANDLE_VALUE +Windows.Win32.Foundation.MAX_PATH +Windows.Win32.Foundation.NO_ERROR +Windows.Win32.Foundation.NTSTATUS +Windows.Win32.Foundation.RtlNtStatusToDosError +Windows.Win32.Foundation.SetHandleInformation +Windows.Win32.Foundation.SetLastError +Windows.Win32.Foundation.STATUS_DELETE_PENDING +Windows.Win32.Foundation.STATUS_END_OF_FILE +Windows.Win32.Foundation.STATUS_INVALID_PARAMETER +Windows.Win32.Foundation.STATUS_PENDING +Windows.Win32.Foundation.STATUS_SUCCESS +Windows.Win32.Foundation.TRUE +Windows.Win32.Foundation.UNICODE_STRING +Windows.Win32.Foundation.WAIT_ABANDONED +Windows.Win32.Foundation.WAIT_ABANDONED_0 +Windows.Win32.Foundation.WAIT_FAILED +Windows.Win32.Foundation.WAIT_IO_COMPLETION +Windows.Win32.Foundation.WAIT_OBJECT_0 +Windows.Win32.Foundation.WAIT_TIMEOUT +Windows.Win32.Foundation.WIN32_ERROR +Windows.Win32.Globalization.COMPARESTRING_RESULT +Windows.Win32.Globalization.CompareStringOrdinal +Windows.Win32.Globalization.CP_UTF8 +Windows.Win32.Globalization.CSTR_EQUAL +Windows.Win32.Globalization.CSTR_GREATER_THAN +Windows.Win32.Globalization.CSTR_LESS_THAN +Windows.Win32.Globalization.MB_COMPOSITE +Windows.Win32.Globalization.MB_ERR_INVALID_CHARS +Windows.Win32.Globalization.MB_PRECOMPOSED +Windows.Win32.Globalization.MB_USEGLYPHCHARS +Windows.Win32.Globalization.MULTI_BYTE_TO_WIDE_CHAR_FLAGS +Windows.Win32.Globalization.MultiByteToWideChar +Windows.Win32.Globalization.WC_ERR_INVALID_CHARS +Windows.Win32.Globalization.WideCharToMultiByte +Windows.Win32.Networking.WinSock.accept +Windows.Win32.Networking.WinSock.ADDRESS_FAMILY +Windows.Win32.Networking.WinSock.ADDRINFOA +Windows.Win32.Networking.WinSock.AF_INET +Windows.Win32.Networking.WinSock.AF_INET6 +Windows.Win32.Networking.WinSock.AF_UNSPEC +Windows.Win32.Networking.WinSock.bind +Windows.Win32.Networking.WinSock.closesocket +Windows.Win32.Networking.WinSock.connect +Windows.Win32.Networking.WinSock.FD_SET +Windows.Win32.Networking.WinSock.FIONBIO +Windows.Win32.Networking.WinSock.freeaddrinfo +Windows.Win32.Networking.WinSock.getaddrinfo +Windows.Win32.Networking.WinSock.getpeername +Windows.Win32.Networking.WinSock.getsockname +Windows.Win32.Networking.WinSock.getsockopt +Windows.Win32.Networking.WinSock.IN6_ADDR +Windows.Win32.Networking.WinSock.IN_ADDR +Windows.Win32.Networking.WinSock.INVALID_SOCKET +Windows.Win32.Networking.WinSock.ioctlsocket +Windows.Win32.Networking.WinSock.IP_ADD_MEMBERSHIP +Windows.Win32.Networking.WinSock.IP_DROP_MEMBERSHIP +Windows.Win32.Networking.WinSock.IP_MREQ +Windows.Win32.Networking.WinSock.IP_MULTICAST_LOOP +Windows.Win32.Networking.WinSock.IP_MULTICAST_TTL +Windows.Win32.Networking.WinSock.IP_TTL +Windows.Win32.Networking.WinSock.IPPROTO +Windows.Win32.Networking.WinSock.IPPROTO_AH +Windows.Win32.Networking.WinSock.IPPROTO_CBT +Windows.Win32.Networking.WinSock.IPPROTO_DSTOPTS +Windows.Win32.Networking.WinSock.IPPROTO_EGP +Windows.Win32.Networking.WinSock.IPPROTO_ESP +Windows.Win32.Networking.WinSock.IPPROTO_FRAGMENT +Windows.Win32.Networking.WinSock.IPPROTO_GGP +Windows.Win32.Networking.WinSock.IPPROTO_HOPOPTS +Windows.Win32.Networking.WinSock.IPPROTO_ICLFXBM +Windows.Win32.Networking.WinSock.IPPROTO_ICMP +Windows.Win32.Networking.WinSock.IPPROTO_ICMPV6 +Windows.Win32.Networking.WinSock.IPPROTO_IDP +Windows.Win32.Networking.WinSock.IPPROTO_IGMP +Windows.Win32.Networking.WinSock.IPPROTO_IGP +Windows.Win32.Networking.WinSock.IPPROTO_IP +Windows.Win32.Networking.WinSock.IPPROTO_IPV4 +Windows.Win32.Networking.WinSock.IPPROTO_IPV6 +Windows.Win32.Networking.WinSock.IPPROTO_L2TP +Windows.Win32.Networking.WinSock.IPPROTO_MAX +Windows.Win32.Networking.WinSock.IPPROTO_ND +Windows.Win32.Networking.WinSock.IPPROTO_NONE +Windows.Win32.Networking.WinSock.IPPROTO_PGM +Windows.Win32.Networking.WinSock.IPPROTO_PIM +Windows.Win32.Networking.WinSock.IPPROTO_PUP +Windows.Win32.Networking.WinSock.IPPROTO_RAW +Windows.Win32.Networking.WinSock.IPPROTO_RDP +Windows.Win32.Networking.WinSock.IPPROTO_RESERVED_IPSEC +Windows.Win32.Networking.WinSock.IPPROTO_RESERVED_IPSECOFFLOAD +Windows.Win32.Networking.WinSock.IPPROTO_RESERVED_MAX +Windows.Win32.Networking.WinSock.IPPROTO_RESERVED_RAW +Windows.Win32.Networking.WinSock.IPPROTO_RESERVED_WNV +Windows.Win32.Networking.WinSock.IPPROTO_RM +Windows.Win32.Networking.WinSock.IPPROTO_ROUTING +Windows.Win32.Networking.WinSock.IPPROTO_SCTP +Windows.Win32.Networking.WinSock.IPPROTO_ST +Windows.Win32.Networking.WinSock.IPPROTO_TCP +Windows.Win32.Networking.WinSock.IPPROTO_UDP +Windows.Win32.Networking.WinSock.IPV6_ADD_MEMBERSHIP +Windows.Win32.Networking.WinSock.IPV6_DROP_MEMBERSHIP +Windows.Win32.Networking.WinSock.IPV6_MREQ +Windows.Win32.Networking.WinSock.IPV6_MULTICAST_LOOP +Windows.Win32.Networking.WinSock.IPV6_V6ONLY +Windows.Win32.Networking.WinSock.LINGER +Windows.Win32.Networking.WinSock.listen +Windows.Win32.Networking.WinSock.LPWSAOVERLAPPED_COMPLETION_ROUTINE +Windows.Win32.Networking.WinSock.MSG_DONTROUTE +Windows.Win32.Networking.WinSock.MSG_OOB +Windows.Win32.Networking.WinSock.MSG_PEEK +Windows.Win32.Networking.WinSock.MSG_PUSH_IMMEDIATE +Windows.Win32.Networking.WinSock.MSG_WAITALL +Windows.Win32.Networking.WinSock.recv +Windows.Win32.Networking.WinSock.recvfrom +Windows.Win32.Networking.WinSock.SD_BOTH +Windows.Win32.Networking.WinSock.SD_RECEIVE +Windows.Win32.Networking.WinSock.SD_SEND +Windows.Win32.Networking.WinSock.select +Windows.Win32.Networking.WinSock.send +Windows.Win32.Networking.WinSock.SEND_RECV_FLAGS +Windows.Win32.Networking.WinSock.sendto +Windows.Win32.Networking.WinSock.setsockopt +Windows.Win32.Networking.WinSock.shutdown +Windows.Win32.Networking.WinSock.SO_BROADCAST +Windows.Win32.Networking.WinSock.SO_ERROR +Windows.Win32.Networking.WinSock.SO_LINGER +Windows.Win32.Networking.WinSock.SO_RCVTIMEO +Windows.Win32.Networking.WinSock.SO_SNDTIMEO +Windows.Win32.Networking.WinSock.SOCK_DGRAM +Windows.Win32.Networking.WinSock.SOCK_RAW +Windows.Win32.Networking.WinSock.SOCK_RDM +Windows.Win32.Networking.WinSock.SOCK_SEQPACKET +Windows.Win32.Networking.WinSock.SOCK_STREAM +Windows.Win32.Networking.WinSock.SOCKADDR +Windows.Win32.Networking.WinSock.SOCKET +Windows.Win32.Networking.WinSock.SOCKET_ERROR +Windows.Win32.Networking.WinSock.SOL_SOCKET +Windows.Win32.Networking.WinSock.TCP_NODELAY +Windows.Win32.Networking.WinSock.TIMEVAL +Windows.Win32.Networking.WinSock.WINSOCK_SHUTDOWN_HOW +Windows.Win32.Networking.WinSock.WINSOCK_SOCKET_TYPE +Windows.Win32.Networking.WinSock.WSA_E_CANCELLED +Windows.Win32.Networking.WinSock.WSA_E_NO_MORE +Windows.Win32.Networking.WinSock.WSA_ERROR +Windows.Win32.Networking.WinSock.WSA_FLAG_NO_HANDLE_INHERIT +Windows.Win32.Networking.WinSock.WSA_FLAG_OVERLAPPED +Windows.Win32.Networking.WinSock.WSA_INVALID_HANDLE +Windows.Win32.Networking.WinSock.WSA_INVALID_PARAMETER +Windows.Win32.Networking.WinSock.WSA_IO_INCOMPLETE +Windows.Win32.Networking.WinSock.WSA_IO_PENDING +Windows.Win32.Networking.WinSock.WSA_IPSEC_NAME_POLICY_ERROR +Windows.Win32.Networking.WinSock.WSA_NOT_ENOUGH_MEMORY +Windows.Win32.Networking.WinSock.WSA_OPERATION_ABORTED +Windows.Win32.Networking.WinSock.WSA_QOS_ADMISSION_FAILURE +Windows.Win32.Networking.WinSock.WSA_QOS_BAD_OBJECT +Windows.Win32.Networking.WinSock.WSA_QOS_BAD_STYLE +Windows.Win32.Networking.WinSock.WSA_QOS_EFILTERCOUNT +Windows.Win32.Networking.WinSock.WSA_QOS_EFILTERSTYLE +Windows.Win32.Networking.WinSock.WSA_QOS_EFILTERTYPE +Windows.Win32.Networking.WinSock.WSA_QOS_EFLOWCOUNT +Windows.Win32.Networking.WinSock.WSA_QOS_EFLOWDESC +Windows.Win32.Networking.WinSock.WSA_QOS_EFLOWSPEC +Windows.Win32.Networking.WinSock.WSA_QOS_EOBJLENGTH +Windows.Win32.Networking.WinSock.WSA_QOS_EPOLICYOBJ +Windows.Win32.Networking.WinSock.WSA_QOS_EPROVSPECBUF +Windows.Win32.Networking.WinSock.WSA_QOS_EPSFILTERSPEC +Windows.Win32.Networking.WinSock.WSA_QOS_EPSFLOWSPEC +Windows.Win32.Networking.WinSock.WSA_QOS_ESDMODEOBJ +Windows.Win32.Networking.WinSock.WSA_QOS_ESERVICETYPE +Windows.Win32.Networking.WinSock.WSA_QOS_ESHAPERATEOBJ +Windows.Win32.Networking.WinSock.WSA_QOS_EUNKOWNPSOBJ +Windows.Win32.Networking.WinSock.WSA_QOS_GENERIC_ERROR +Windows.Win32.Networking.WinSock.WSA_QOS_NO_RECEIVERS +Windows.Win32.Networking.WinSock.WSA_QOS_NO_SENDERS +Windows.Win32.Networking.WinSock.WSA_QOS_POLICY_FAILURE +Windows.Win32.Networking.WinSock.WSA_QOS_RECEIVERS +Windows.Win32.Networking.WinSock.WSA_QOS_REQUEST_CONFIRMED +Windows.Win32.Networking.WinSock.WSA_QOS_RESERVED_PETYPE +Windows.Win32.Networking.WinSock.WSA_QOS_SENDERS +Windows.Win32.Networking.WinSock.WSA_QOS_TRAFFIC_CTRL_ERROR +Windows.Win32.Networking.WinSock.WSA_SECURE_HOST_NOT_FOUND +Windows.Win32.Networking.WinSock.WSA_WAIT_EVENT_0 +Windows.Win32.Networking.WinSock.WSA_WAIT_IO_COMPLETION +Windows.Win32.Networking.WinSock.WSABASEERR +Windows.Win32.Networking.WinSock.WSABUF +Windows.Win32.Networking.WinSock.WSACleanup +Windows.Win32.Networking.WinSock.WSADATA +Windows.Win32.Networking.WinSock.WSADATA +Windows.Win32.Networking.WinSock.WSADuplicateSocketW +Windows.Win32.Networking.WinSock.WSAEACCES +Windows.Win32.Networking.WinSock.WSAEADDRINUSE +Windows.Win32.Networking.WinSock.WSAEADDRNOTAVAIL +Windows.Win32.Networking.WinSock.WSAEAFNOSUPPORT +Windows.Win32.Networking.WinSock.WSAEALREADY +Windows.Win32.Networking.WinSock.WSAEBADF +Windows.Win32.Networking.WinSock.WSAECANCELLED +Windows.Win32.Networking.WinSock.WSAECONNABORTED +Windows.Win32.Networking.WinSock.WSAECONNREFUSED +Windows.Win32.Networking.WinSock.WSAECONNRESET +Windows.Win32.Networking.WinSock.WSAEDESTADDRREQ +Windows.Win32.Networking.WinSock.WSAEDISCON +Windows.Win32.Networking.WinSock.WSAEDQUOT +Windows.Win32.Networking.WinSock.WSAEFAULT +Windows.Win32.Networking.WinSock.WSAEHOSTDOWN +Windows.Win32.Networking.WinSock.WSAEHOSTUNREACH +Windows.Win32.Networking.WinSock.WSAEINPROGRESS +Windows.Win32.Networking.WinSock.WSAEINTR +Windows.Win32.Networking.WinSock.WSAEINVAL +Windows.Win32.Networking.WinSock.WSAEINVALIDPROCTABLE +Windows.Win32.Networking.WinSock.WSAEINVALIDPROVIDER +Windows.Win32.Networking.WinSock.WSAEISCONN +Windows.Win32.Networking.WinSock.WSAELOOP +Windows.Win32.Networking.WinSock.WSAEMFILE +Windows.Win32.Networking.WinSock.WSAEMSGSIZE +Windows.Win32.Networking.WinSock.WSAENAMETOOLONG +Windows.Win32.Networking.WinSock.WSAENETDOWN +Windows.Win32.Networking.WinSock.WSAENETRESET +Windows.Win32.Networking.WinSock.WSAENETUNREACH +Windows.Win32.Networking.WinSock.WSAENOBUFS +Windows.Win32.Networking.WinSock.WSAENOMORE +Windows.Win32.Networking.WinSock.WSAENOPROTOOPT +Windows.Win32.Networking.WinSock.WSAENOTCONN +Windows.Win32.Networking.WinSock.WSAENOTEMPTY +Windows.Win32.Networking.WinSock.WSAENOTSOCK +Windows.Win32.Networking.WinSock.WSAEOPNOTSUPP +Windows.Win32.Networking.WinSock.WSAEPFNOSUPPORT +Windows.Win32.Networking.WinSock.WSAEPROCLIM +Windows.Win32.Networking.WinSock.WSAEPROTONOSUPPORT +Windows.Win32.Networking.WinSock.WSAEPROTOTYPE +Windows.Win32.Networking.WinSock.WSAEPROVIDERFAILEDINIT +Windows.Win32.Networking.WinSock.WSAEREFUSED +Windows.Win32.Networking.WinSock.WSAEREMOTE +Windows.Win32.Networking.WinSock.WSAESHUTDOWN +Windows.Win32.Networking.WinSock.WSAESOCKTNOSUPPORT +Windows.Win32.Networking.WinSock.WSAESTALE +Windows.Win32.Networking.WinSock.WSAETIMEDOUT +Windows.Win32.Networking.WinSock.WSAETOOMANYREFS +Windows.Win32.Networking.WinSock.WSAEUSERS +Windows.Win32.Networking.WinSock.WSAEWOULDBLOCK +Windows.Win32.Networking.WinSock.WSAGetLastError +Windows.Win32.Networking.WinSock.WSAHOST_NOT_FOUND +Windows.Win32.Networking.WinSock.WSANO_DATA +Windows.Win32.Networking.WinSock.WSANO_RECOVERY +Windows.Win32.Networking.WinSock.WSANOTINITIALISED +Windows.Win32.Networking.WinSock.WSAPROTOCOL_INFOW +Windows.Win32.Networking.WinSock.WSAPROTOCOLCHAIN +Windows.Win32.Networking.WinSock.WSARecv +Windows.Win32.Networking.WinSock.WSASend +Windows.Win32.Networking.WinSock.WSASERVICE_NOT_FOUND +Windows.Win32.Networking.WinSock.WSASocketW +Windows.Win32.Networking.WinSock.WSAStartup +Windows.Win32.Networking.WinSock.WSASYSCALLFAILURE +Windows.Win32.Networking.WinSock.WSASYSNOTREADY +Windows.Win32.Networking.WinSock.WSATRY_AGAIN +Windows.Win32.Networking.WinSock.WSATYPE_NOT_FOUND +Windows.Win32.Networking.WinSock.WSAVERNOTSUPPORTED +Windows.Win32.Security.Authentication.Identity.RtlGenRandom +Windows.Win32.Security.Cryptography.BCRYPT_ALG_HANDLE +Windows.Win32.Security.Cryptography.BCRYPT_USE_SYSTEM_PREFERRED_RNG +Windows.Win32.Security.Cryptography.BCryptGenRandom +Windows.Win32.Security.Cryptography.BCRYPTGENRANDOM_FLAGS +Windows.Win32.Security.SECURITY_ATTRIBUTES +Windows.Win32.Security.TOKEN_ACCESS_MASK +Windows.Win32.Security.TOKEN_ACCESS_PSEUDO_HANDLE +Windows.Win32.Security.TOKEN_ACCESS_PSEUDO_HANDLE_WIN8 +Windows.Win32.Security.TOKEN_ACCESS_SYSTEM_SECURITY +Windows.Win32.Security.TOKEN_ADJUST_DEFAULT +Windows.Win32.Security.TOKEN_ADJUST_GROUPS +Windows.Win32.Security.TOKEN_ADJUST_PRIVILEGES +Windows.Win32.Security.TOKEN_ADJUST_SESSIONID +Windows.Win32.Security.TOKEN_ALL_ACCESS +Windows.Win32.Security.TOKEN_ASSIGN_PRIMARY +Windows.Win32.Security.TOKEN_DELETE +Windows.Win32.Security.TOKEN_DUPLICATE +Windows.Win32.Security.TOKEN_EXECUTE +Windows.Win32.Security.TOKEN_IMPERSONATE +Windows.Win32.Security.TOKEN_QUERY +Windows.Win32.Security.TOKEN_QUERY_SOURCE +Windows.Win32.Security.TOKEN_READ +Windows.Win32.Security.TOKEN_READ_CONTROL +Windows.Win32.Security.TOKEN_TRUST_CONSTRAINT_MASK +Windows.Win32.Security.TOKEN_WRITE +Windows.Win32.Security.TOKEN_WRITE_DAC +Windows.Win32.Security.TOKEN_WRITE_OWNER +Windows.Win32.Storage.FileSystem.BY_HANDLE_FILE_INFORMATION +Windows.Win32.Storage.FileSystem.CALLBACK_CHUNK_FINISHED +Windows.Win32.Storage.FileSystem.CALLBACK_STREAM_SWITCH +Windows.Win32.Storage.FileSystem.CopyFileExW +Windows.Win32.Storage.FileSystem.CREATE_ALWAYS +Windows.Win32.Storage.FileSystem.CREATE_NEW +Windows.Win32.Storage.FileSystem.CreateDirectoryW +Windows.Win32.Storage.FileSystem.CreateFileW +Windows.Win32.Storage.FileSystem.CreateHardLinkW +Windows.Win32.Storage.FileSystem.CreateSymbolicLinkW +Windows.Win32.Storage.FileSystem.DELETE +Windows.Win32.Storage.FileSystem.DeleteFileW +Windows.Win32.Storage.FileSystem.FILE_ACCESS_RIGHTS +Windows.Win32.Storage.FileSystem.FILE_ADD_FILE +Windows.Win32.Storage.FileSystem.FILE_ADD_SUBDIRECTORY +Windows.Win32.Storage.FileSystem.FILE_ALL_ACCESS +Windows.Win32.Storage.FileSystem.FILE_APPEND_DATA +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_ARCHIVE +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_COMPRESSED +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_DEVICE +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_DIRECTORY +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_EA +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_ENCRYPTED +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_HIDDEN +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_INTEGRITY_STREAM +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_NO_SCRUB_DATA +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_NORMAL +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_OFFLINE +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_PINNED +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_READONLY +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_RECALL_ON_OPEN +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_REPARSE_POINT +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_SPARSE_FILE +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_SYSTEM +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_TAG_INFO +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_TEMPORARY +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_UNPINNED +Windows.Win32.Storage.FileSystem.FILE_ATTRIBUTE_VIRTUAL +Windows.Win32.Storage.FileSystem.FILE_BASIC_INFO +Windows.Win32.Storage.FileSystem.FILE_BEGIN +Windows.Win32.Storage.FileSystem.FILE_CREATE_PIPE_INSTANCE +Windows.Win32.Storage.FileSystem.FILE_CREATION_DISPOSITION +Windows.Win32.Storage.FileSystem.FILE_CURRENT +Windows.Win32.Storage.FileSystem.FILE_DELETE_CHILD +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_FLAG_DELETE +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_FLAG_DO_NOT_DELETE +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_FLAG_FORCE_IMAGE_SECTION_CHECK +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_FLAG_ON_CLOSE +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_FLAG_POSIX_SEMANTICS +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_INFO +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_INFO_EX +Windows.Win32.Storage.FileSystem.FILE_DISPOSITION_INFO_EX_FLAGS +Windows.Win32.Storage.FileSystem.FILE_END +Windows.Win32.Storage.FileSystem.FILE_END_OF_FILE_INFO +Windows.Win32.Storage.FileSystem.FILE_EXECUTE +Windows.Win32.Storage.FileSystem.FILE_FLAG_BACKUP_SEMANTICS +Windows.Win32.Storage.FileSystem.FILE_FLAG_DELETE_ON_CLOSE +Windows.Win32.Storage.FileSystem.FILE_FLAG_FIRST_PIPE_INSTANCE +Windows.Win32.Storage.FileSystem.FILE_FLAG_NO_BUFFERING +Windows.Win32.Storage.FileSystem.FILE_FLAG_OPEN_NO_RECALL +Windows.Win32.Storage.FileSystem.FILE_FLAG_OPEN_REPARSE_POINT +Windows.Win32.Storage.FileSystem.FILE_FLAG_OVERLAPPED +Windows.Win32.Storage.FileSystem.FILE_FLAG_POSIX_SEMANTICS +Windows.Win32.Storage.FileSystem.FILE_FLAG_RANDOM_ACCESS +Windows.Win32.Storage.FileSystem.FILE_FLAG_SEQUENTIAL_SCAN +Windows.Win32.Storage.FileSystem.FILE_FLAG_SESSION_AWARE +Windows.Win32.Storage.FileSystem.FILE_FLAG_WRITE_THROUGH +Windows.Win32.Storage.FileSystem.FILE_FLAGS_AND_ATTRIBUTES +Windows.Win32.Storage.FileSystem.FILE_GENERIC_EXECUTE +Windows.Win32.Storage.FileSystem.FILE_GENERIC_READ +Windows.Win32.Storage.FileSystem.FILE_GENERIC_WRITE +Windows.Win32.Storage.FileSystem.FILE_ID_BOTH_DIR_INFO +Windows.Win32.Storage.FileSystem.FILE_INFO_BY_HANDLE_CLASS +Windows.Win32.Storage.FileSystem.FILE_LIST_DIRECTORY +Windows.Win32.Storage.FileSystem.FILE_NAME_NORMALIZED +Windows.Win32.Storage.FileSystem.FILE_NAME_OPENED +Windows.Win32.Storage.FileSystem.FILE_READ_ATTRIBUTES +Windows.Win32.Storage.FileSystem.FILE_READ_DATA +Windows.Win32.Storage.FileSystem.FILE_READ_EA +Windows.Win32.Storage.FileSystem.FILE_SHARE_DELETE +Windows.Win32.Storage.FileSystem.FILE_SHARE_MODE +Windows.Win32.Storage.FileSystem.FILE_SHARE_NONE +Windows.Win32.Storage.FileSystem.FILE_SHARE_READ +Windows.Win32.Storage.FileSystem.FILE_SHARE_WRITE +Windows.Win32.Storage.FileSystem.FILE_STANDARD_INFO +Windows.Win32.Storage.FileSystem.FILE_TRAVERSE +Windows.Win32.Storage.FileSystem.FILE_TYPE +Windows.Win32.Storage.FileSystem.FILE_TYPE_CHAR +Windows.Win32.Storage.FileSystem.FILE_TYPE_DISK +Windows.Win32.Storage.FileSystem.FILE_TYPE_PIPE +Windows.Win32.Storage.FileSystem.FILE_TYPE_REMOTE +Windows.Win32.Storage.FileSystem.FILE_TYPE_UNKNOWN +Windows.Win32.Storage.FileSystem.FILE_WRITE_ATTRIBUTES +Windows.Win32.Storage.FileSystem.FILE_WRITE_DATA +Windows.Win32.Storage.FileSystem.FILE_WRITE_EA +Windows.Win32.Storage.FileSystem.FileAlignmentInfo +Windows.Win32.Storage.FileSystem.FileAllocationInfo +Windows.Win32.Storage.FileSystem.FileAttributeTagInfo +Windows.Win32.Storage.FileSystem.FileBasicInfo +Windows.Win32.Storage.FileSystem.FileCaseSensitiveInfo +Windows.Win32.Storage.FileSystem.FileCompressionInfo +Windows.Win32.Storage.FileSystem.FileDispositionInfo +Windows.Win32.Storage.FileSystem.FileDispositionInfoEx +Windows.Win32.Storage.FileSystem.FileEndOfFileInfo +Windows.Win32.Storage.FileSystem.FileFullDirectoryInfo +Windows.Win32.Storage.FileSystem.FileFullDirectoryRestartInfo +Windows.Win32.Storage.FileSystem.FileIdBothDirectoryInfo +Windows.Win32.Storage.FileSystem.FileIdBothDirectoryRestartInfo +Windows.Win32.Storage.FileSystem.FileIdExtdDirectoryInfo +Windows.Win32.Storage.FileSystem.FileIdExtdDirectoryRestartInfo +Windows.Win32.Storage.FileSystem.FileIdInfo +Windows.Win32.Storage.FileSystem.FileIoPriorityHintInfo +Windows.Win32.Storage.FileSystem.FileNameInfo +Windows.Win32.Storage.FileSystem.FileNormalizedNameInfo +Windows.Win32.Storage.FileSystem.FileRemoteProtocolInfo +Windows.Win32.Storage.FileSystem.FileRenameInfo +Windows.Win32.Storage.FileSystem.FileRenameInfoEx +Windows.Win32.Storage.FileSystem.FileStandardInfo +Windows.Win32.Storage.FileSystem.FileStorageInfo +Windows.Win32.Storage.FileSystem.FileStreamInfo +Windows.Win32.Storage.FileSystem.FindClose +Windows.Win32.Storage.FileSystem.FindFileHandle +Windows.Win32.Storage.FileSystem.FindFirstFileW +Windows.Win32.Storage.FileSystem.FindNextFileW +Windows.Win32.Storage.FileSystem.FlushFileBuffers +Windows.Win32.Storage.FileSystem.GetFileAttributesW +Windows.Win32.Storage.FileSystem.GetFileInformationByHandle +Windows.Win32.Storage.FileSystem.GetFileInformationByHandleEx +Windows.Win32.Storage.FileSystem.GetFileType +Windows.Win32.Storage.FileSystem.GETFINALPATHNAMEBYHANDLE_FLAGS +Windows.Win32.Storage.FileSystem.GetFinalPathNameByHandleW +Windows.Win32.Storage.FileSystem.GetFullPathNameW +Windows.Win32.Storage.FileSystem.GetTempPathW +Windows.Win32.Storage.FileSystem.INVALID_FILE_ATTRIBUTES +Windows.Win32.Storage.FileSystem.LPPROGRESS_ROUTINE +Windows.Win32.Storage.FileSystem.LPPROGRESS_ROUTINE_CALLBACK_REASON +Windows.Win32.Storage.FileSystem.MAXIMUM_REPARSE_DATA_BUFFER_SIZE +Windows.Win32.Storage.FileSystem.MaximumFileInfoByHandleClass +Windows.Win32.Storage.FileSystem.MOVE_FILE_FLAGS +Windows.Win32.Storage.FileSystem.MOVEFILE_COPY_ALLOWED +Windows.Win32.Storage.FileSystem.MOVEFILE_CREATE_HARDLINK +Windows.Win32.Storage.FileSystem.MOVEFILE_DELAY_UNTIL_REBOOT +Windows.Win32.Storage.FileSystem.MOVEFILE_FAIL_IF_NOT_TRACKABLE +Windows.Win32.Storage.FileSystem.MOVEFILE_REPLACE_EXISTING +Windows.Win32.Storage.FileSystem.MOVEFILE_WRITE_THROUGH +Windows.Win32.Storage.FileSystem.MoveFileExW +Windows.Win32.Storage.FileSystem.OPEN_ALWAYS +Windows.Win32.Storage.FileSystem.OPEN_EXISTING +Windows.Win32.Storage.FileSystem.PIPE_ACCESS_DUPLEX +Windows.Win32.Storage.FileSystem.PIPE_ACCESS_INBOUND +Windows.Win32.Storage.FileSystem.PIPE_ACCESS_OUTBOUND +Windows.Win32.Storage.FileSystem.READ_CONTROL +Windows.Win32.Storage.FileSystem.ReadFile +Windows.Win32.Storage.FileSystem.ReadFileEx +Windows.Win32.Storage.FileSystem.RemoveDirectoryW +Windows.Win32.Storage.FileSystem.SECURITY_ANONYMOUS +Windows.Win32.Storage.FileSystem.SECURITY_CONTEXT_TRACKING +Windows.Win32.Storage.FileSystem.SECURITY_DELEGATION +Windows.Win32.Storage.FileSystem.SECURITY_EFFECTIVE_ONLY +Windows.Win32.Storage.FileSystem.SECURITY_IDENTIFICATION +Windows.Win32.Storage.FileSystem.SECURITY_IMPERSONATION +Windows.Win32.Storage.FileSystem.SECURITY_SQOS_PRESENT +Windows.Win32.Storage.FileSystem.SECURITY_VALID_SQOS_FLAGS +Windows.Win32.Storage.FileSystem.SET_FILE_POINTER_MOVE_METHOD +Windows.Win32.Storage.FileSystem.SetFileAttributesW +Windows.Win32.Storage.FileSystem.SetFileInformationByHandle +Windows.Win32.Storage.FileSystem.SetFilePointerEx +Windows.Win32.Storage.FileSystem.SetFileTime +Windows.Win32.Storage.FileSystem.SPECIFIC_RIGHTS_ALL +Windows.Win32.Storage.FileSystem.STANDARD_RIGHTS_ALL +Windows.Win32.Storage.FileSystem.STANDARD_RIGHTS_EXECUTE +Windows.Win32.Storage.FileSystem.STANDARD_RIGHTS_READ +Windows.Win32.Storage.FileSystem.STANDARD_RIGHTS_REQUIRED +Windows.Win32.Storage.FileSystem.STANDARD_RIGHTS_WRITE +Windows.Win32.Storage.FileSystem.SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE +Windows.Win32.Storage.FileSystem.SYMBOLIC_LINK_FLAG_DIRECTORY +Windows.Win32.Storage.FileSystem.SYMBOLIC_LINK_FLAGS +Windows.Win32.Storage.FileSystem.SYNCHRONIZE +Windows.Win32.Storage.FileSystem.TRUNCATE_EXISTING +Windows.Win32.Storage.FileSystem.VOLUME_NAME_DOS +Windows.Win32.Storage.FileSystem.VOLUME_NAME_GUID +Windows.Win32.Storage.FileSystem.VOLUME_NAME_NONE +Windows.Win32.Storage.FileSystem.WIN32_FIND_DATAW +Windows.Win32.Storage.FileSystem.WRITE_DAC +Windows.Win32.Storage.FileSystem.WRITE_OWNER +Windows.Win32.Storage.FileSystem.WriteFileEx +Windows.Win32.System.Console.CONSOLE_MODE +Windows.Win32.System.Console.CONSOLE_READCONSOLE_CONTROL +Windows.Win32.System.Console.DISABLE_NEWLINE_AUTO_RETURN +Windows.Win32.System.Console.ENABLE_AUTO_POSITION +Windows.Win32.System.Console.ENABLE_ECHO_INPUT +Windows.Win32.System.Console.ENABLE_EXTENDED_FLAGS +Windows.Win32.System.Console.ENABLE_INSERT_MODE +Windows.Win32.System.Console.ENABLE_LINE_INPUT +Windows.Win32.System.Console.ENABLE_LVB_GRID_WORLDWIDE +Windows.Win32.System.Console.ENABLE_MOUSE_INPUT +Windows.Win32.System.Console.ENABLE_PROCESSED_INPUT +Windows.Win32.System.Console.ENABLE_PROCESSED_OUTPUT +Windows.Win32.System.Console.ENABLE_QUICK_EDIT_MODE +Windows.Win32.System.Console.ENABLE_VIRTUAL_TERMINAL_INPUT +Windows.Win32.System.Console.ENABLE_VIRTUAL_TERMINAL_PROCESSING +Windows.Win32.System.Console.ENABLE_WINDOW_INPUT +Windows.Win32.System.Console.ENABLE_WRAP_AT_EOL_OUTPUT +Windows.Win32.System.Console.GetConsoleMode +Windows.Win32.System.Console.GetStdHandle +Windows.Win32.System.Console.ReadConsoleW +Windows.Win32.System.Console.STD_ERROR_HANDLE +Windows.Win32.System.Console.STD_HANDLE +Windows.Win32.System.Console.STD_INPUT_HANDLE +Windows.Win32.System.Console.STD_OUTPUT_HANDLE +Windows.Win32.System.Console.WriteConsoleW +Windows.Win32.System.Diagnostics.Debug.AddVectoredExceptionHandler +Windows.Win32.System.Diagnostics.Debug.ARM64_NT_NEON128 +Windows.Win32.System.Diagnostics.Debug.CONTEXT +Windows.Win32.System.Diagnostics.Debug.CONTEXT +Windows.Win32.System.Diagnostics.Debug.CONTEXT +Windows.Win32.System.Diagnostics.Debug.EXCEPTION_POINTERS +Windows.Win32.System.Diagnostics.Debug.EXCEPTION_RECORD +Windows.Win32.System.Diagnostics.Debug.FACILITY_CODE +Windows.Win32.System.Diagnostics.Debug.FACILITY_NT_BIT +Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_ALLOCATE_BUFFER +Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_ARGUMENT_ARRAY +Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_FROM_HMODULE +Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_FROM_STRING +Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_FROM_SYSTEM +Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_IGNORE_INSERTS +Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_OPTIONS +Windows.Win32.System.Diagnostics.Debug.FormatMessageW +Windows.Win32.System.Diagnostics.Debug.M128A +Windows.Win32.System.Diagnostics.Debug.PVECTORED_EXCEPTION_HANDLER +Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT +Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT +Windows.Win32.System.Environment.FreeEnvironmentStringsW +Windows.Win32.System.Environment.GetCommandLineW +Windows.Win32.System.Environment.GetCurrentDirectoryW +Windows.Win32.System.Environment.GetEnvironmentStringsW +Windows.Win32.System.Environment.GetEnvironmentVariableW +Windows.Win32.System.Environment.SetCurrentDirectoryW +Windows.Win32.System.Environment.SetEnvironmentVariableW +Windows.Win32.System.IO.CancelIo +Windows.Win32.System.IO.DeviceIoControl +Windows.Win32.System.IO.GetOverlappedResult +Windows.Win32.System.IO.LPOVERLAPPED_COMPLETION_ROUTINE +Windows.Win32.System.IO.OVERLAPPED +Windows.Win32.System.Ioctl.FSCTL_GET_REPARSE_POINT +Windows.Win32.System.Ioctl.FSCTL_SET_REPARSE_POINT +Windows.Win32.System.Kernel.EXCEPTION_DISPOSITION +Windows.Win32.System.Kernel.ExceptionCollidedUnwind +Windows.Win32.System.Kernel.ExceptionContinueExecution +Windows.Win32.System.Kernel.ExceptionContinueSearch +Windows.Win32.System.Kernel.ExceptionNestedException +Windows.Win32.System.Kernel.FLOATING_SAVE_AREA +Windows.Win32.System.Kernel.FLOATING_SAVE_AREA +Windows.Win32.System.Kernel.OBJ_DONT_REPARSE +Windows.Win32.System.LibraryLoader.GetModuleFileNameW +Windows.Win32.System.LibraryLoader.GetModuleHandleA +Windows.Win32.System.LibraryLoader.GetModuleHandleW +Windows.Win32.System.LibraryLoader.GetProcAddress +Windows.Win32.System.Performance.QueryPerformanceCounter +Windows.Win32.System.Performance.QueryPerformanceFrequency +Windows.Win32.System.Pipes.CreateNamedPipeW +Windows.Win32.System.Pipes.NAMED_PIPE_MODE +Windows.Win32.System.Pipes.PIPE_ACCEPT_REMOTE_CLIENTS +Windows.Win32.System.Pipes.PIPE_CLIENT_END +Windows.Win32.System.Pipes.PIPE_NOWAIT +Windows.Win32.System.Pipes.PIPE_READMODE_BYTE +Windows.Win32.System.Pipes.PIPE_READMODE_MESSAGE +Windows.Win32.System.Pipes.PIPE_REJECT_REMOTE_CLIENTS +Windows.Win32.System.Pipes.PIPE_SERVER_END +Windows.Win32.System.Pipes.PIPE_TYPE_BYTE +Windows.Win32.System.Pipes.PIPE_TYPE_MESSAGE +Windows.Win32.System.Pipes.PIPE_WAIT +Windows.Win32.System.SystemInformation.GetSystemDirectoryW +Windows.Win32.System.SystemInformation.GetSystemInfo +Windows.Win32.System.SystemInformation.GetSystemTimeAsFileTime +Windows.Win32.System.SystemInformation.GetWindowsDirectoryW +Windows.Win32.System.SystemInformation.PROCESSOR_ARCHITECTURE +Windows.Win32.System.SystemInformation.SYSTEM_INFO +Windows.Win32.System.SystemServices.DLL_PROCESS_DETACH +Windows.Win32.System.SystemServices.DLL_THREAD_DETACH +Windows.Win32.System.SystemServices.EXCEPTION_MAXIMUM_PARAMETERS +Windows.Win32.System.SystemServices.IO_REPARSE_TAG_MOUNT_POINT +Windows.Win32.System.SystemServices.IO_REPARSE_TAG_SYMLINK +Windows.Win32.System.Threading.ABOVE_NORMAL_PRIORITY_CLASS +Windows.Win32.System.Threading.AcquireSRWLockExclusive +Windows.Win32.System.Threading.AcquireSRWLockShared +Windows.Win32.System.Threading.BELOW_NORMAL_PRIORITY_CLASS +Windows.Win32.System.Threading.CREATE_BREAKAWAY_FROM_JOB +Windows.Win32.System.Threading.CREATE_DEFAULT_ERROR_MODE +Windows.Win32.System.Threading.CREATE_FORCEDOS +Windows.Win32.System.Threading.CREATE_IGNORE_SYSTEM_DEFAULT +Windows.Win32.System.Threading.CREATE_NEW_CONSOLE +Windows.Win32.System.Threading.CREATE_NEW_PROCESS_GROUP +Windows.Win32.System.Threading.CREATE_NO_WINDOW +Windows.Win32.System.Threading.CREATE_PRESERVE_CODE_AUTHZ_LEVEL +Windows.Win32.System.Threading.CREATE_PROTECTED_PROCESS +Windows.Win32.System.Threading.CREATE_SECURE_PROCESS +Windows.Win32.System.Threading.CREATE_SEPARATE_WOW_VDM +Windows.Win32.System.Threading.CREATE_SHARED_WOW_VDM +Windows.Win32.System.Threading.CREATE_SUSPENDED +Windows.Win32.System.Threading.CREATE_UNICODE_ENVIRONMENT +Windows.Win32.System.Threading.CreateEventW +Windows.Win32.System.Threading.CreateProcessW +Windows.Win32.System.Threading.CreateThread +Windows.Win32.System.Threading.DEBUG_ONLY_THIS_PROCESS +Windows.Win32.System.Threading.DEBUG_PROCESS +Windows.Win32.System.Threading.DETACHED_PROCESS +Windows.Win32.System.Threading.ExitProcess +Windows.Win32.System.Threading.EXTENDED_STARTUPINFO_PRESENT +Windows.Win32.System.Threading.GetCurrentProcess +Windows.Win32.System.Threading.GetCurrentProcessId +Windows.Win32.System.Threading.GetCurrentThread +Windows.Win32.System.Threading.GetExitCodeProcess +Windows.Win32.System.Threading.GetProcessId +Windows.Win32.System.Threading.HIGH_PRIORITY_CLASS +Windows.Win32.System.Threading.IDLE_PRIORITY_CLASS +Windows.Win32.System.Threading.INFINITE +Windows.Win32.System.Threading.INHERIT_CALLER_PRIORITY +Windows.Win32.System.Threading.INHERIT_PARENT_AFFINITY +Windows.Win32.System.Threading.INIT_ONCE_INIT_FAILED +Windows.Win32.System.Threading.InitOnceBeginInitialize +Windows.Win32.System.Threading.InitOnceComplete +Windows.Win32.System.Threading.LPTHREAD_START_ROUTINE +Windows.Win32.System.Threading.NORMAL_PRIORITY_CLASS +Windows.Win32.System.Threading.OpenProcessToken +Windows.Win32.System.Threading.PROCESS_CREATION_FLAGS +Windows.Win32.System.Threading.PROCESS_INFORMATION +Windows.Win32.System.Threading.PROCESS_MODE_BACKGROUND_BEGIN +Windows.Win32.System.Threading.PROCESS_MODE_BACKGROUND_END +Windows.Win32.System.Threading.PROFILE_KERNEL +Windows.Win32.System.Threading.PROFILE_SERVER +Windows.Win32.System.Threading.PROFILE_USER +Windows.Win32.System.Threading.REALTIME_PRIORITY_CLASS +Windows.Win32.System.Threading.ReleaseSRWLockExclusive +Windows.Win32.System.Threading.ReleaseSRWLockShared +Windows.Win32.System.Threading.RTL_CONDITION_VARIABLE +Windows.Win32.System.Threading.RTL_RUN_ONCE +Windows.Win32.System.Threading.RTL_SRWLOCK +Windows.Win32.System.Threading.SetThreadStackGuarantee +Windows.Win32.System.Threading.Sleep +Windows.Win32.System.Threading.SleepConditionVariableSRW +Windows.Win32.System.Threading.SleepEx +Windows.Win32.System.Threading.STACK_SIZE_PARAM_IS_A_RESERVATION +Windows.Win32.System.Threading.STARTF_FORCEOFFFEEDBACK +Windows.Win32.System.Threading.STARTF_FORCEONFEEDBACK +Windows.Win32.System.Threading.STARTF_PREVENTPINNING +Windows.Win32.System.Threading.STARTF_RUNFULLSCREEN +Windows.Win32.System.Threading.STARTF_TITLEISAPPID +Windows.Win32.System.Threading.STARTF_TITLEISLINKNAME +Windows.Win32.System.Threading.STARTF_UNTRUSTEDSOURCE +Windows.Win32.System.Threading.STARTF_USECOUNTCHARS +Windows.Win32.System.Threading.STARTF_USEFILLATTRIBUTE +Windows.Win32.System.Threading.STARTF_USEHOTKEY +Windows.Win32.System.Threading.STARTF_USEPOSITION +Windows.Win32.System.Threading.STARTF_USESHOWWINDOW +Windows.Win32.System.Threading.STARTF_USESIZE +Windows.Win32.System.Threading.STARTF_USESTDHANDLES +Windows.Win32.System.Threading.STARTUPINFOW +Windows.Win32.System.Threading.STARTUPINFOW_FLAGS +Windows.Win32.System.Threading.SwitchToThread +Windows.Win32.System.Threading.TerminateProcess +Windows.Win32.System.Threading.THREAD_CREATE_RUN_IMMEDIATELY +Windows.Win32.System.Threading.THREAD_CREATE_SUSPENDED +Windows.Win32.System.Threading.THREAD_CREATION_FLAGS +Windows.Win32.System.Threading.TLS_OUT_OF_INDEXES +Windows.Win32.System.Threading.TlsAlloc +Windows.Win32.System.Threading.TlsFree +Windows.Win32.System.Threading.TlsGetValue +Windows.Win32.System.Threading.TlsSetValue +Windows.Win32.System.Threading.TryAcquireSRWLockExclusive +Windows.Win32.System.Threading.TryAcquireSRWLockShared +Windows.Win32.System.Threading.WaitForMultipleObjects +Windows.Win32.System.Threading.WaitForSingleObject +Windows.Win32.System.Threading.WakeAllConditionVariable +Windows.Win32.System.Threading.WakeConditionVariable +Windows.Win32.System.WindowsProgramming.IO_STATUS_BLOCK +Windows.Win32.System.WindowsProgramming.OBJECT_ATTRIBUTES +Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE +Windows.Win32.UI.Shell.GetUserProfileDirectoryW +// tidy-alphabetical-end + diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs new file mode 100644 index 00000000000..36a30f6ba56 --- /dev/null +++ b/library/std/src/sys/windows/c/windows_sys.rs @@ -0,0 +1,4276 @@ +// This file is autogenerated. +// +// To add bindings, edit windows_sys.lst then use `./x run generate-windows-sys` to +// regenerate the bindings. +// +// ignore-tidy-filelength +// Bindings generated by `windows-bindgen` 0.49.0 + +#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] +#[link(name = "advapi32")] +extern "system" { + pub fn OpenProcessToken( + processhandle: HANDLE, + desiredaccess: TOKEN_ACCESS_MASK, + tokenhandle: *mut HANDLE, + ) -> BOOL; +} +#[link(name = "advapi32")] +extern "system" { + #[link_name = "SystemFunction036"] + pub fn RtlGenRandom(randombuffer: *mut ::core::ffi::c_void, randombufferlength: u32) + -> BOOLEAN; +} +#[link(name = "bcrypt")] +extern "system" { + pub fn BCryptGenRandom( + halgorithm: BCRYPT_ALG_HANDLE, + pbbuffer: *mut u8, + cbbuffer: u32, + dwflags: BCRYPTGENRANDOM_FLAGS, + ) -> NTSTATUS; +} +#[link(name = "kernel32")] +extern "system" { + pub fn AcquireSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn AcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut ::core::ffi::c_void; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CancelIo(hfile: HANDLE) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CloseHandle(hobject: HANDLE) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CompareStringOrdinal( + lpstring1: PCWSTR, + cchcount1: i32, + lpstring2: PCWSTR, + cchcount2: i32, + bignorecase: BOOL, + ) -> COMPARESTRING_RESULT; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CopyFileExW( + lpexistingfilename: PCWSTR, + lpnewfilename: PCWSTR, + lpprogressroutine: LPPROGRESS_ROUTINE, + lpdata: *const ::core::ffi::c_void, + pbcancel: *mut i32, + dwcopyflags: u32, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CreateDirectoryW( + lppathname: PCWSTR, + lpsecurityattributes: *const SECURITY_ATTRIBUTES, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CreateEventW( + lpeventattributes: *const SECURITY_ATTRIBUTES, + bmanualreset: BOOL, + binitialstate: BOOL, + lpname: PCWSTR, + ) -> HANDLE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CreateFileW( + lpfilename: PCWSTR, + dwdesiredaccess: u32, + dwsharemode: FILE_SHARE_MODE, + lpsecurityattributes: *const SECURITY_ATTRIBUTES, + dwcreationdisposition: FILE_CREATION_DISPOSITION, + dwflagsandattributes: FILE_FLAGS_AND_ATTRIBUTES, + htemplatefile: HANDLE, + ) -> HANDLE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CreateHardLinkW( + lpfilename: PCWSTR, + lpexistingfilename: PCWSTR, + lpsecurityattributes: *const SECURITY_ATTRIBUTES, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CreateNamedPipeW( + lpname: PCWSTR, + dwopenmode: FILE_FLAGS_AND_ATTRIBUTES, + dwpipemode: NAMED_PIPE_MODE, + nmaxinstances: u32, + noutbuffersize: u32, + ninbuffersize: u32, + ndefaulttimeout: u32, + lpsecurityattributes: *const SECURITY_ATTRIBUTES, + ) -> HANDLE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CreateProcessW( + lpapplicationname: PCWSTR, + lpcommandline: PWSTR, + lpprocessattributes: *const SECURITY_ATTRIBUTES, + lpthreadattributes: *const SECURITY_ATTRIBUTES, + binherithandles: BOOL, + dwcreationflags: PROCESS_CREATION_FLAGS, + lpenvironment: *const ::core::ffi::c_void, + lpcurrentdirectory: PCWSTR, + lpstartupinfo: *const STARTUPINFOW, + lpprocessinformation: *mut PROCESS_INFORMATION, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CreateSymbolicLinkW( + lpsymlinkfilename: PCWSTR, + lptargetfilename: PCWSTR, + dwflags: SYMBOLIC_LINK_FLAGS, + ) -> BOOLEAN; +} +#[link(name = "kernel32")] +extern "system" { + pub fn CreateThread( + lpthreadattributes: *const SECURITY_ATTRIBUTES, + dwstacksize: usize, + lpstartaddress: LPTHREAD_START_ROUTINE, + lpparameter: *const ::core::ffi::c_void, + dwcreationflags: THREAD_CREATION_FLAGS, + lpthreadid: *mut u32, + ) -> HANDLE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn DeleteFileW(lpfilename: PCWSTR) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn DeviceIoControl( + hdevice: HANDLE, + dwiocontrolcode: u32, + lpinbuffer: *const ::core::ffi::c_void, + ninbuffersize: u32, + lpoutbuffer: *mut ::core::ffi::c_void, + noutbuffersize: u32, + lpbytesreturned: *mut u32, + lpoverlapped: *mut OVERLAPPED, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn DuplicateHandle( + hsourceprocesshandle: HANDLE, + hsourcehandle: HANDLE, + htargetprocesshandle: HANDLE, + lptargethandle: *mut HANDLE, + dwdesiredaccess: u32, + binherithandle: BOOL, + dwoptions: DUPLICATE_HANDLE_OPTIONS, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn ExitProcess(uexitcode: u32) -> !; +} +#[link(name = "kernel32")] +extern "system" { + pub fn FindClose(hfindfile: FindFileHandle) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn FindFirstFileW( + lpfilename: PCWSTR, + lpfindfiledata: *mut WIN32_FIND_DATAW, + ) -> FindFileHandle; +} +#[link(name = "kernel32")] +extern "system" { + pub fn FindNextFileW(hfindfile: FindFileHandle, lpfindfiledata: *mut WIN32_FIND_DATAW) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn FlushFileBuffers(hfile: HANDLE) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn FormatMessageW( + dwflags: FORMAT_MESSAGE_OPTIONS, + lpsource: *const ::core::ffi::c_void, + dwmessageid: u32, + dwlanguageid: u32, + lpbuffer: PWSTR, + nsize: u32, + arguments: *const *const i8, + ) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn FreeEnvironmentStringsW(penv: PCWSTR) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetCommandLineW() -> PCWSTR; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetConsoleMode(hconsolehandle: HANDLE, lpmode: *mut CONSOLE_MODE) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetCurrentDirectoryW(nbufferlength: u32, lpbuffer: PWSTR) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetCurrentProcess() -> HANDLE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetCurrentProcessId() -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetCurrentThread() -> HANDLE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetEnvironmentStringsW() -> PWSTR; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetEnvironmentVariableW(lpname: PCWSTR, lpbuffer: PWSTR, nsize: u32) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetExitCodeProcess(hprocess: HANDLE, lpexitcode: *mut u32) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetFileAttributesW(lpfilename: PCWSTR) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetFileInformationByHandle( + hfile: HANDLE, + lpfileinformation: *mut BY_HANDLE_FILE_INFORMATION, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetFileInformationByHandleEx( + hfile: HANDLE, + fileinformationclass: FILE_INFO_BY_HANDLE_CLASS, + lpfileinformation: *mut ::core::ffi::c_void, + dwbuffersize: u32, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetFileType(hfile: HANDLE) -> FILE_TYPE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetFinalPathNameByHandleW( + hfile: HANDLE, + lpszfilepath: PWSTR, + cchfilepath: u32, + dwflags: GETFINALPATHNAMEBYHANDLE_FLAGS, + ) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetFullPathNameW( + lpfilename: PCWSTR, + nbufferlength: u32, + lpbuffer: PWSTR, + lpfilepart: *mut PWSTR, + ) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetLastError() -> WIN32_ERROR; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetModuleFileNameW(hmodule: HMODULE, lpfilename: PWSTR, nsize: u32) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetModuleHandleA(lpmodulename: PCSTR) -> HMODULE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetModuleHandleW(lpmodulename: PCWSTR) -> HMODULE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetOverlappedResult( + hfile: HANDLE, + lpoverlapped: *const OVERLAPPED, + lpnumberofbytestransferred: *mut u32, + bwait: BOOL, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetProcAddress(hmodule: HMODULE, lpprocname: PCSTR) -> FARPROC; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetProcessId(process: HANDLE) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetStdHandle(nstdhandle: STD_HANDLE) -> HANDLE; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetSystemDirectoryW(lpbuffer: PWSTR, usize: u32) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetSystemInfo(lpsysteminfo: *mut SYSTEM_INFO) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetSystemTimeAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetTempPathW(nbufferlength: u32, lpbuffer: PWSTR) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn GetWindowsDirectoryW(lpbuffer: PWSTR, usize: u32) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn InitOnceBeginInitialize( + lpinitonce: *mut RTL_RUN_ONCE, + dwflags: u32, + fpending: *mut BOOL, + lpcontext: *mut *mut ::core::ffi::c_void, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn InitOnceComplete( + lpinitonce: *mut RTL_RUN_ONCE, + dwflags: u32, + lpcontext: *const ::core::ffi::c_void, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn MoveFileExW( + lpexistingfilename: PCWSTR, + lpnewfilename: PCWSTR, + dwflags: MOVE_FILE_FLAGS, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn MultiByteToWideChar( + codepage: u32, + dwflags: MULTI_BYTE_TO_WIDE_CHAR_FLAGS, + lpmultibytestr: PCSTR, + cbmultibyte: i32, + lpwidecharstr: PWSTR, + cchwidechar: i32, + ) -> i32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn QueryPerformanceCounter(lpperformancecount: *mut i64) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn QueryPerformanceFrequency(lpfrequency: *mut i64) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn ReadConsoleW( + hconsoleinput: HANDLE, + lpbuffer: *mut ::core::ffi::c_void, + nnumberofcharstoread: u32, + lpnumberofcharsread: *mut u32, + pinputcontrol: *const CONSOLE_READCONSOLE_CONTROL, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn ReadFile( + hfile: HANDLE, + lpbuffer: *mut ::core::ffi::c_void, + nnumberofbytestoread: u32, + lpnumberofbytesread: *mut u32, + lpoverlapped: *mut OVERLAPPED, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn ReadFileEx( + hfile: HANDLE, + lpbuffer: *mut ::core::ffi::c_void, + nnumberofbytestoread: u32, + lpoverlapped: *mut OVERLAPPED, + lpcompletionroutine: LPOVERLAPPED_COMPLETION_ROUTINE, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn ReleaseSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn ReleaseSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn RemoveDirectoryW(lppathname: PCWSTR) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetCurrentDirectoryW(lppathname: PCWSTR) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetEnvironmentVariableW(lpname: PCWSTR, lpvalue: PCWSTR) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetFileAttributesW( + lpfilename: PCWSTR, + dwfileattributes: FILE_FLAGS_AND_ATTRIBUTES, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetFileInformationByHandle( + hfile: HANDLE, + fileinformationclass: FILE_INFO_BY_HANDLE_CLASS, + lpfileinformation: *const ::core::ffi::c_void, + dwbuffersize: u32, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetFilePointerEx( + hfile: HANDLE, + lidistancetomove: i64, + lpnewfilepointer: *mut i64, + dwmovemethod: SET_FILE_POINTER_MOVE_METHOD, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetFileTime( + hfile: HANDLE, + lpcreationtime: *const FILETIME, + lplastaccesstime: *const FILETIME, + lplastwritetime: *const FILETIME, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetHandleInformation(hobject: HANDLE, dwmask: u32, dwflags: HANDLE_FLAGS) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetLastError(dwerrcode: WIN32_ERROR) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn Sleep(dwmilliseconds: u32) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn SleepConditionVariableSRW( + conditionvariable: *mut RTL_CONDITION_VARIABLE, + srwlock: *mut RTL_SRWLOCK, + dwmilliseconds: u32, + flags: u32, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SleepEx(dwmilliseconds: u32, balertable: BOOL) -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn SwitchToThread() -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn TerminateProcess(hprocess: HANDLE, uexitcode: u32) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn TlsAlloc() -> u32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn TlsFree(dwtlsindex: u32) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn TlsGetValue(dwtlsindex: u32) -> *mut ::core::ffi::c_void; +} +#[link(name = "kernel32")] +extern "system" { + pub fn TlsSetValue(dwtlsindex: u32, lptlsvalue: *const ::core::ffi::c_void) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn TryAcquireSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> BOOLEAN; +} +#[link(name = "kernel32")] +extern "system" { + pub fn TryAcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> BOOLEAN; +} +#[link(name = "kernel32")] +extern "system" { + pub fn WaitForMultipleObjects( + ncount: u32, + lphandles: *const HANDLE, + bwaitall: BOOL, + dwmilliseconds: u32, + ) -> WIN32_ERROR; +} +#[link(name = "kernel32")] +extern "system" { + pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WIN32_ERROR; +} +#[link(name = "kernel32")] +extern "system" { + pub fn WakeAllConditionVariable(conditionvariable: *mut RTL_CONDITION_VARIABLE) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn WakeConditionVariable(conditionvariable: *mut RTL_CONDITION_VARIABLE) -> (); +} +#[link(name = "kernel32")] +extern "system" { + pub fn WideCharToMultiByte( + codepage: u32, + dwflags: u32, + lpwidecharstr: PCWSTR, + cchwidechar: i32, + lpmultibytestr: PSTR, + cbmultibyte: i32, + lpdefaultchar: PCSTR, + lpuseddefaultchar: *mut i32, + ) -> i32; +} +#[link(name = "kernel32")] +extern "system" { + pub fn WriteConsoleW( + hconsoleoutput: HANDLE, + lpbuffer: *const ::core::ffi::c_void, + nnumberofcharstowrite: u32, + lpnumberofcharswritten: *mut u32, + lpreserved: *const ::core::ffi::c_void, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { + pub fn WriteFileEx( + hfile: HANDLE, + lpbuffer: *const u8, + nnumberofbytestowrite: u32, + lpoverlapped: *mut OVERLAPPED, + lpcompletionroutine: LPOVERLAPPED_COMPLETION_ROUTINE, + ) -> BOOL; +} +#[link(name = "ntdll")] +extern "system" { + pub fn NtCreateFile( + filehandle: *mut HANDLE, + desiredaccess: FILE_ACCESS_RIGHTS, + objectattributes: *const OBJECT_ATTRIBUTES, + iostatusblock: *mut IO_STATUS_BLOCK, + allocationsize: *const i64, + fileattributes: FILE_FLAGS_AND_ATTRIBUTES, + shareaccess: FILE_SHARE_MODE, + createdisposition: NTCREATEFILE_CREATE_DISPOSITION, + createoptions: NTCREATEFILE_CREATE_OPTIONS, + eabuffer: *const ::core::ffi::c_void, + ealength: u32, + ) -> NTSTATUS; +} +#[link(name = "ntdll")] +extern "system" { + pub fn NtReadFile( + filehandle: HANDLE, + event: HANDLE, + apcroutine: PIO_APC_ROUTINE, + apccontext: *const ::core::ffi::c_void, + iostatusblock: *mut IO_STATUS_BLOCK, + buffer: *mut ::core::ffi::c_void, + length: u32, + byteoffset: *const i64, + key: *const u32, + ) -> NTSTATUS; +} +#[link(name = "ntdll")] +extern "system" { + pub fn NtWriteFile( + filehandle: HANDLE, + event: HANDLE, + apcroutine: PIO_APC_ROUTINE, + apccontext: *const ::core::ffi::c_void, + iostatusblock: *mut IO_STATUS_BLOCK, + buffer: *const ::core::ffi::c_void, + length: u32, + byteoffset: *const i64, + key: *const u32, + ) -> NTSTATUS; +} +#[link(name = "ntdll")] +extern "system" { + pub fn RtlNtStatusToDosError(status: NTSTATUS) -> u32; +} +#[link(name = "userenv")] +extern "system" { + pub fn GetUserProfileDirectoryW( + htoken: HANDLE, + lpprofiledir: PWSTR, + lpcchsize: *mut u32, + ) -> BOOL; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn WSACleanup() -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn WSADuplicateSocketW( + s: SOCKET, + dwprocessid: u32, + lpprotocolinfo: *mut WSAPROTOCOL_INFOW, + ) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn WSAGetLastError() -> WSA_ERROR; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn WSARecv( + s: SOCKET, + lpbuffers: *const WSABUF, + dwbuffercount: u32, + lpnumberofbytesrecvd: *mut u32, + lpflags: *mut u32, + lpoverlapped: *mut OVERLAPPED, + lpcompletionroutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, + ) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn WSASend( + s: SOCKET, + lpbuffers: *const WSABUF, + dwbuffercount: u32, + lpnumberofbytessent: *mut u32, + dwflags: u32, + lpoverlapped: *mut OVERLAPPED, + lpcompletionroutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, + ) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn WSASocketW( + af: i32, + r#type: i32, + protocol: i32, + lpprotocolinfo: *const WSAPROTOCOL_INFOW, + g: u32, + dwflags: u32, + ) -> SOCKET; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn accept(s: SOCKET, addr: *mut SOCKADDR, addrlen: *mut i32) -> SOCKET; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn bind(s: SOCKET, name: *const SOCKADDR, namelen: i32) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn closesocket(s: SOCKET) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn connect(s: SOCKET, name: *const SOCKADDR, namelen: i32) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn freeaddrinfo(paddrinfo: *const ADDRINFOA) -> (); +} +#[link(name = "ws2_32")] +extern "system" { + pub fn getaddrinfo( + pnodename: PCSTR, + pservicename: PCSTR, + phints: *const ADDRINFOA, + ppresult: *mut *mut ADDRINFOA, + ) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn getpeername(s: SOCKET, name: *mut SOCKADDR, namelen: *mut i32) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn getsockname(s: SOCKET, name: *mut SOCKADDR, namelen: *mut i32) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn getsockopt(s: SOCKET, level: i32, optname: i32, optval: PSTR, optlen: *mut i32) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn ioctlsocket(s: SOCKET, cmd: i32, argp: *mut u32) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn listen(s: SOCKET, backlog: i32) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn recv(s: SOCKET, buf: PSTR, len: i32, flags: SEND_RECV_FLAGS) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn recvfrom( + s: SOCKET, + buf: PSTR, + len: i32, + flags: i32, + from: *mut SOCKADDR, + fromlen: *mut i32, + ) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn select( + nfds: i32, + readfds: *mut FD_SET, + writefds: *mut FD_SET, + exceptfds: *mut FD_SET, + timeout: *const TIMEVAL, + ) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn send(s: SOCKET, buf: PCSTR, len: i32, flags: SEND_RECV_FLAGS) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn sendto( + s: SOCKET, + buf: PCSTR, + len: i32, + flags: i32, + to: *const SOCKADDR, + tolen: i32, + ) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn setsockopt(s: SOCKET, level: i32, optname: i32, optval: PCSTR, optlen: i32) -> i32; +} +#[link(name = "ws2_32")] +extern "system" { + pub fn shutdown(s: SOCKET, how: WINSOCK_SHUTDOWN_HOW) -> i32; +} +pub const ABOVE_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 32768u32; +pub type ADDRESS_FAMILY = u16; +#[repr(C)] +pub struct ADDRINFOA { + pub ai_flags: i32, + pub ai_family: i32, + pub ai_socktype: i32, + pub ai_protocol: i32, + pub ai_addrlen: usize, + pub ai_canonname: PSTR, + pub ai_addr: *mut SOCKADDR, + pub ai_next: *mut ADDRINFOA, +} +impl ::core::marker::Copy for ADDRINFOA {} +impl ::core::clone::Clone for ADDRINFOA { + fn clone(&self) -> Self { + *self + } +} +pub const AF_INET: ADDRESS_FAMILY = 2u16; +pub const AF_INET6: ADDRESS_FAMILY = 23u16; +pub const AF_UNSPEC: ADDRESS_FAMILY = 0u16; +#[repr(C)] +pub union ARM64_NT_NEON128 { + pub Anonymous: ARM64_NT_NEON128_0, + pub D: [f64; 2], + pub S: [f32; 4], + pub H: [u16; 8], + pub B: [u8; 16], +} +impl ::core::marker::Copy for ARM64_NT_NEON128 {} +impl ::core::clone::Clone for ARM64_NT_NEON128 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct ARM64_NT_NEON128_0 { + pub Low: u64, + pub High: i64, +} +impl ::core::marker::Copy for ARM64_NT_NEON128_0 {} +impl ::core::clone::Clone for ARM64_NT_NEON128_0 { + fn clone(&self) -> Self { + *self + } +} +pub type BCRYPTGENRANDOM_FLAGS = u32; +pub type BCRYPT_ALG_HANDLE = *mut ::core::ffi::c_void; +pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: BCRYPTGENRANDOM_FLAGS = 2u32; +pub const BELOW_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 16384u32; +pub type BOOL = i32; +pub type BOOLEAN = u8; +#[repr(C)] +pub struct BY_HANDLE_FILE_INFORMATION { + pub dwFileAttributes: u32, + pub ftCreationTime: FILETIME, + pub ftLastAccessTime: FILETIME, + pub ftLastWriteTime: FILETIME, + pub dwVolumeSerialNumber: u32, + pub nFileSizeHigh: u32, + pub nFileSizeLow: u32, + pub nNumberOfLinks: u32, + pub nFileIndexHigh: u32, + pub nFileIndexLow: u32, +} +impl ::core::marker::Copy for BY_HANDLE_FILE_INFORMATION {} +impl ::core::clone::Clone for BY_HANDLE_FILE_INFORMATION { + fn clone(&self) -> Self { + *self + } +} +pub const CALLBACK_CHUNK_FINISHED: LPPROGRESS_ROUTINE_CALLBACK_REASON = 0u32; +pub const CALLBACK_STREAM_SWITCH: LPPROGRESS_ROUTINE_CALLBACK_REASON = 1u32; +pub type COMPARESTRING_RESULT = u32; +pub type CONSOLE_MODE = u32; +#[repr(C)] +pub struct CONSOLE_READCONSOLE_CONTROL { + pub nLength: u32, + pub nInitialChars: u32, + pub dwCtrlWakeupMask: u32, + pub dwControlKeyState: u32, +} +impl ::core::marker::Copy for CONSOLE_READCONSOLE_CONTROL {} +impl ::core::clone::Clone for CONSOLE_READCONSOLE_CONTROL { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "aarch64")] +pub struct CONTEXT { + pub ContextFlags: u32, + pub Cpsr: u32, + pub Anonymous: CONTEXT_0, + pub Sp: u64, + pub Pc: u64, + pub V: [ARM64_NT_NEON128; 32], + pub Fpcr: u32, + pub Fpsr: u32, + pub Bcr: [u32; 8], + pub Bvr: [u64; 8], + pub Wcr: [u32; 2], + pub Wvr: [u64; 2], +} +#[cfg(target_arch = "aarch64")] +impl ::core::marker::Copy for CONTEXT {} +#[cfg(target_arch = "aarch64")] +impl ::core::clone::Clone for CONTEXT { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "aarch64")] +pub union CONTEXT_0 { + pub Anonymous: CONTEXT_0_0, + pub X: [u64; 31], +} +#[cfg(target_arch = "aarch64")] +impl ::core::marker::Copy for CONTEXT_0 {} +#[cfg(target_arch = "aarch64")] +impl ::core::clone::Clone for CONTEXT_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "aarch64")] +pub struct CONTEXT_0_0 { + pub X0: u64, + pub X1: u64, + pub X2: u64, + pub X3: u64, + pub X4: u64, + pub X5: u64, + pub X6: u64, + pub X7: u64, + pub X8: u64, + pub X9: u64, + pub X10: u64, + pub X11: u64, + pub X12: u64, + pub X13: u64, + pub X14: u64, + pub X15: u64, + pub X16: u64, + pub X17: u64, + pub X18: u64, + pub X19: u64, + pub X20: u64, + pub X21: u64, + pub X22: u64, + pub X23: u64, + pub X24: u64, + pub X25: u64, + pub X26: u64, + pub X27: u64, + pub X28: u64, + pub Fp: u64, + pub Lr: u64, +} +#[cfg(target_arch = "aarch64")] +impl ::core::marker::Copy for CONTEXT_0_0 {} +#[cfg(target_arch = "aarch64")] +impl ::core::clone::Clone for CONTEXT_0_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "x86_64")] +pub struct CONTEXT { + pub P1Home: u64, + pub P2Home: u64, + pub P3Home: u64, + pub P4Home: u64, + pub P5Home: u64, + pub P6Home: u64, + pub ContextFlags: u32, + pub MxCsr: u32, + pub SegCs: u16, + pub SegDs: u16, + pub SegEs: u16, + pub SegFs: u16, + pub SegGs: u16, + pub SegSs: u16, + pub EFlags: u32, + pub Dr0: u64, + pub Dr1: u64, + pub Dr2: u64, + pub Dr3: u64, + pub Dr6: u64, + pub Dr7: u64, + pub Rax: u64, + pub Rcx: u64, + pub Rdx: u64, + pub Rbx: u64, + pub Rsp: u64, + pub Rbp: u64, + pub Rsi: u64, + pub Rdi: u64, + pub R8: u64, + pub R9: u64, + pub R10: u64, + pub R11: u64, + pub R12: u64, + pub R13: u64, + pub R14: u64, + pub R15: u64, + pub Rip: u64, + pub Anonymous: CONTEXT_0, + pub VectorRegister: [M128A; 26], + pub VectorControl: u64, + pub DebugControl: u64, + pub LastBranchToRip: u64, + pub LastBranchFromRip: u64, + pub LastExceptionToRip: u64, + pub LastExceptionFromRip: u64, +} +#[cfg(target_arch = "x86_64")] +impl ::core::marker::Copy for CONTEXT {} +#[cfg(target_arch = "x86_64")] +impl ::core::clone::Clone for CONTEXT { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "x86_64")] +pub union CONTEXT_0 { + pub FltSave: XSAVE_FORMAT, + pub Anonymous: CONTEXT_0_0, +} +#[cfg(target_arch = "x86_64")] +impl ::core::marker::Copy for CONTEXT_0 {} +#[cfg(target_arch = "x86_64")] +impl ::core::clone::Clone for CONTEXT_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "x86_64")] +pub struct CONTEXT_0_0 { + pub Header: [M128A; 2], + pub Legacy: [M128A; 8], + pub Xmm0: M128A, + pub Xmm1: M128A, + pub Xmm2: M128A, + pub Xmm3: M128A, + pub Xmm4: M128A, + pub Xmm5: M128A, + pub Xmm6: M128A, + pub Xmm7: M128A, + pub Xmm8: M128A, + pub Xmm9: M128A, + pub Xmm10: M128A, + pub Xmm11: M128A, + pub Xmm12: M128A, + pub Xmm13: M128A, + pub Xmm14: M128A, + pub Xmm15: M128A, +} +#[cfg(target_arch = "x86_64")] +impl ::core::marker::Copy for CONTEXT_0_0 {} +#[cfg(target_arch = "x86_64")] +impl ::core::clone::Clone for CONTEXT_0_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "x86")] +pub struct CONTEXT { + pub ContextFlags: u32, + pub Dr0: u32, + pub Dr1: u32, + pub Dr2: u32, + pub Dr3: u32, + pub Dr6: u32, + pub Dr7: u32, + pub FloatSave: FLOATING_SAVE_AREA, + pub SegGs: u32, + pub SegFs: u32, + pub SegEs: u32, + pub SegDs: u32, + pub Edi: u32, + pub Esi: u32, + pub Ebx: u32, + pub Edx: u32, + pub Ecx: u32, + pub Eax: u32, + pub Ebp: u32, + pub Eip: u32, + pub SegCs: u32, + pub EFlags: u32, + pub Esp: u32, + pub SegSs: u32, + pub ExtendedRegisters: [u8; 512], +} +#[cfg(target_arch = "x86")] +impl ::core::marker::Copy for CONTEXT {} +#[cfg(target_arch = "x86")] +impl ::core::clone::Clone for CONTEXT { + fn clone(&self) -> Self { + *self + } +} +pub const CP_UTF8: u32 = 65001u32; +pub const CREATE_ALWAYS: FILE_CREATION_DISPOSITION = 2u32; +pub const CREATE_BREAKAWAY_FROM_JOB: PROCESS_CREATION_FLAGS = 16777216u32; +pub const CREATE_DEFAULT_ERROR_MODE: PROCESS_CREATION_FLAGS = 67108864u32; +pub const CREATE_FORCEDOS: PROCESS_CREATION_FLAGS = 8192u32; +pub const CREATE_IGNORE_SYSTEM_DEFAULT: PROCESS_CREATION_FLAGS = 2147483648u32; +pub const CREATE_NEW: FILE_CREATION_DISPOSITION = 1u32; +pub const CREATE_NEW_CONSOLE: PROCESS_CREATION_FLAGS = 16u32; +pub const CREATE_NEW_PROCESS_GROUP: PROCESS_CREATION_FLAGS = 512u32; +pub const CREATE_NO_WINDOW: PROCESS_CREATION_FLAGS = 134217728u32; +pub const CREATE_PRESERVE_CODE_AUTHZ_LEVEL: PROCESS_CREATION_FLAGS = 33554432u32; +pub const CREATE_PROTECTED_PROCESS: PROCESS_CREATION_FLAGS = 262144u32; +pub const CREATE_SECURE_PROCESS: PROCESS_CREATION_FLAGS = 4194304u32; +pub const CREATE_SEPARATE_WOW_VDM: PROCESS_CREATION_FLAGS = 2048u32; +pub const CREATE_SHARED_WOW_VDM: PROCESS_CREATION_FLAGS = 4096u32; +pub const CREATE_SUSPENDED: PROCESS_CREATION_FLAGS = 4u32; +pub const CREATE_UNICODE_ENVIRONMENT: PROCESS_CREATION_FLAGS = 1024u32; +pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2u32; +pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3u32; +pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1u32; +pub const DEBUG_ONLY_THIS_PROCESS: PROCESS_CREATION_FLAGS = 2u32; +pub const DEBUG_PROCESS: PROCESS_CREATION_FLAGS = 1u32; +pub const DELETE: FILE_ACCESS_RIGHTS = 65536u32; +pub const DETACHED_PROCESS: PROCESS_CREATION_FLAGS = 8u32; +pub const DISABLE_NEWLINE_AUTO_RETURN: CONSOLE_MODE = 8u32; +pub const DLL_PROCESS_DETACH: u32 = 0u32; +pub const DLL_THREAD_DETACH: u32 = 3u32; +pub const DNS_ERROR_ADDRESS_REQUIRED: WIN32_ERROR = 9573u32; +pub const DNS_ERROR_ALIAS_LOOP: WIN32_ERROR = 9722u32; +pub const DNS_ERROR_AUTOZONE_ALREADY_EXISTS: WIN32_ERROR = 9610u32; +pub const DNS_ERROR_AXFR: WIN32_ERROR = 9752u32; +pub const DNS_ERROR_BACKGROUND_LOADING: WIN32_ERROR = 9568u32; +pub const DNS_ERROR_BAD_KEYMASTER: WIN32_ERROR = 9122u32; +pub const DNS_ERROR_BAD_PACKET: WIN32_ERROR = 9502u32; +pub const DNS_ERROR_CANNOT_FIND_ROOT_HINTS: WIN32_ERROR = 9564u32; +pub const DNS_ERROR_CLIENT_SUBNET_ALREADY_EXISTS: WIN32_ERROR = 9977u32; +pub const DNS_ERROR_CLIENT_SUBNET_DOES_NOT_EXIST: WIN32_ERROR = 9976u32; +pub const DNS_ERROR_CLIENT_SUBNET_IS_ACCESSED: WIN32_ERROR = 9975u32; +pub const DNS_ERROR_CNAME_COLLISION: WIN32_ERROR = 9709u32; +pub const DNS_ERROR_CNAME_LOOP: WIN32_ERROR = 9707u32; +pub const DNS_ERROR_DATAFILE_OPEN_FAILURE: WIN32_ERROR = 9653u32; +pub const DNS_ERROR_DATAFILE_PARSING: WIN32_ERROR = 9655u32; +pub const DNS_ERROR_DEFAULT_SCOPE: WIN32_ERROR = 9960u32; +pub const DNS_ERROR_DEFAULT_VIRTUALIZATION_INSTANCE: WIN32_ERROR = 9925u32; +pub const DNS_ERROR_DEFAULT_ZONESCOPE: WIN32_ERROR = 9953u32; +pub const DNS_ERROR_DELEGATION_REQUIRED: WIN32_ERROR = 9571u32; +pub const DNS_ERROR_DNAME_COLLISION: WIN32_ERROR = 9721u32; +pub const DNS_ERROR_DNSSEC_IS_DISABLED: WIN32_ERROR = 9125u32; +pub const DNS_ERROR_DP_ALREADY_ENLISTED: WIN32_ERROR = 9904u32; +pub const DNS_ERROR_DP_ALREADY_EXISTS: WIN32_ERROR = 9902u32; +pub const DNS_ERROR_DP_DOES_NOT_EXIST: WIN32_ERROR = 9901u32; +pub const DNS_ERROR_DP_FSMO_ERROR: WIN32_ERROR = 9906u32; +pub const DNS_ERROR_DP_NOT_AVAILABLE: WIN32_ERROR = 9905u32; +pub const DNS_ERROR_DP_NOT_ENLISTED: WIN32_ERROR = 9903u32; +pub const DNS_ERROR_DS_UNAVAILABLE: WIN32_ERROR = 9717u32; +pub const DNS_ERROR_DS_ZONE_ALREADY_EXISTS: WIN32_ERROR = 9718u32; +pub const DNS_ERROR_DWORD_VALUE_TOO_LARGE: WIN32_ERROR = 9567u32; +pub const DNS_ERROR_DWORD_VALUE_TOO_SMALL: WIN32_ERROR = 9566u32; +pub const DNS_ERROR_FILE_WRITEBACK_FAILED: WIN32_ERROR = 9654u32; +pub const DNS_ERROR_FORWARDER_ALREADY_EXISTS: WIN32_ERROR = 9619u32; +pub const DNS_ERROR_INCONSISTENT_ROOT_HINTS: WIN32_ERROR = 9565u32; +pub const DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME: WIN32_ERROR = 9924u32; +pub const DNS_ERROR_INVALID_CLIENT_SUBNET_NAME: WIN32_ERROR = 9984u32; +pub const DNS_ERROR_INVALID_DATA: WIN32_ERROR = 13u32; +pub const DNS_ERROR_INVALID_DATAFILE_NAME: WIN32_ERROR = 9652u32; +pub const DNS_ERROR_INVALID_INITIAL_ROLLOVER_OFFSET: WIN32_ERROR = 9115u32; +pub const DNS_ERROR_INVALID_IP_ADDRESS: WIN32_ERROR = 9552u32; +pub const DNS_ERROR_INVALID_KEY_SIZE: WIN32_ERROR = 9106u32; +pub const DNS_ERROR_INVALID_NAME: WIN32_ERROR = 123u32; +pub const DNS_ERROR_INVALID_NAME_CHAR: WIN32_ERROR = 9560u32; +pub const DNS_ERROR_INVALID_NSEC3_ITERATION_COUNT: WIN32_ERROR = 9124u32; +pub const DNS_ERROR_INVALID_POLICY_TABLE: WIN32_ERROR = 9572u32; +pub const DNS_ERROR_INVALID_PROPERTY: WIN32_ERROR = 9553u32; +pub const DNS_ERROR_INVALID_ROLLOVER_PERIOD: WIN32_ERROR = 9114u32; +pub const DNS_ERROR_INVALID_SCOPE_NAME: WIN32_ERROR = 9958u32; +pub const DNS_ERROR_INVALID_SCOPE_OPERATION: WIN32_ERROR = 9961u32; +pub const DNS_ERROR_INVALID_SIGNATURE_VALIDITY_PERIOD: WIN32_ERROR = 9123u32; +pub const DNS_ERROR_INVALID_TYPE: WIN32_ERROR = 9551u32; +pub const DNS_ERROR_INVALID_XML: WIN32_ERROR = 9126u32; +pub const DNS_ERROR_INVALID_ZONESCOPE_NAME: WIN32_ERROR = 9954u32; +pub const DNS_ERROR_INVALID_ZONE_OPERATION: WIN32_ERROR = 9603u32; +pub const DNS_ERROR_INVALID_ZONE_TYPE: WIN32_ERROR = 9611u32; +pub const DNS_ERROR_KEYMASTER_REQUIRED: WIN32_ERROR = 9101u32; +pub const DNS_ERROR_KSP_DOES_NOT_SUPPORT_PROTECTION: WIN32_ERROR = 9108u32; +pub const DNS_ERROR_KSP_NOT_ACCESSIBLE: WIN32_ERROR = 9112u32; +pub const DNS_ERROR_LOAD_ZONESCOPE_FAILED: WIN32_ERROR = 9956u32; +pub const DNS_ERROR_NAME_DOES_NOT_EXIST: WIN32_ERROR = 9714u32; +pub const DNS_ERROR_NAME_NOT_IN_ZONE: WIN32_ERROR = 9706u32; +pub const DNS_ERROR_NBSTAT_INIT_FAILED: WIN32_ERROR = 9617u32; +pub const DNS_ERROR_NEED_SECONDARY_ADDRESSES: WIN32_ERROR = 9614u32; +pub const DNS_ERROR_NEED_WINS_SERVERS: WIN32_ERROR = 9616u32; +pub const DNS_ERROR_NODE_CREATION_FAILED: WIN32_ERROR = 9703u32; +pub const DNS_ERROR_NODE_IS_CNAME: WIN32_ERROR = 9708u32; +pub const DNS_ERROR_NODE_IS_DNAME: WIN32_ERROR = 9720u32; +pub const DNS_ERROR_NON_RFC_NAME: WIN32_ERROR = 9556u32; +pub const DNS_ERROR_NOT_ALLOWED_ON_ACTIVE_SKD: WIN32_ERROR = 9119u32; +pub const DNS_ERROR_NOT_ALLOWED_ON_RODC: WIN32_ERROR = 9569u32; +pub const DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER: WIN32_ERROR = 9562u32; +pub const DNS_ERROR_NOT_ALLOWED_ON_SIGNED_ZONE: WIN32_ERROR = 9102u32; +pub const DNS_ERROR_NOT_ALLOWED_ON_UNSIGNED_ZONE: WIN32_ERROR = 9121u32; +pub const DNS_ERROR_NOT_ALLOWED_ON_ZSK: WIN32_ERROR = 9118u32; +pub const DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION: WIN32_ERROR = 9563u32; +pub const DNS_ERROR_NOT_ALLOWED_UNDER_DNAME: WIN32_ERROR = 9570u32; +pub const DNS_ERROR_NOT_ALLOWED_WITH_ZONESCOPES: WIN32_ERROR = 9955u32; +pub const DNS_ERROR_NOT_ENOUGH_SIGNING_KEY_DESCRIPTORS: WIN32_ERROR = 9104u32; +pub const DNS_ERROR_NOT_UNIQUE: WIN32_ERROR = 9555u32; +pub const DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE: WIN32_ERROR = 9719u32; +pub const DNS_ERROR_NO_CREATE_CACHE_DATA: WIN32_ERROR = 9713u32; +pub const DNS_ERROR_NO_DNS_SERVERS: WIN32_ERROR = 9852u32; +pub const DNS_ERROR_NO_MEMORY: WIN32_ERROR = 14u32; +pub const DNS_ERROR_NO_PACKET: WIN32_ERROR = 9503u32; +pub const DNS_ERROR_NO_TCPIP: WIN32_ERROR = 9851u32; +pub const DNS_ERROR_NO_VALID_TRUST_ANCHORS: WIN32_ERROR = 9127u32; +pub const DNS_ERROR_NO_ZONE_INFO: WIN32_ERROR = 9602u32; +pub const DNS_ERROR_NSEC3_INCOMPATIBLE_WITH_RSA_SHA1: WIN32_ERROR = 9103u32; +pub const DNS_ERROR_NSEC3_NAME_COLLISION: WIN32_ERROR = 9129u32; +pub const DNS_ERROR_NSEC_INCOMPATIBLE_WITH_NSEC3_RSA_SHA1: WIN32_ERROR = 9130u32; +pub const DNS_ERROR_NUMERIC_NAME: WIN32_ERROR = 9561u32; +pub const DNS_ERROR_POLICY_ALREADY_EXISTS: WIN32_ERROR = 9971u32; +pub const DNS_ERROR_POLICY_DOES_NOT_EXIST: WIN32_ERROR = 9972u32; +pub const DNS_ERROR_POLICY_INVALID_CRITERIA: WIN32_ERROR = 9973u32; +pub const DNS_ERROR_POLICY_INVALID_CRITERIA_CLIENT_SUBNET: WIN32_ERROR = 9990u32; +pub const DNS_ERROR_POLICY_INVALID_CRITERIA_FQDN: WIN32_ERROR = 9994u32; +pub const DNS_ERROR_POLICY_INVALID_CRITERIA_INTERFACE: WIN32_ERROR = 9993u32; +pub const DNS_ERROR_POLICY_INVALID_CRITERIA_NETWORK_PROTOCOL: WIN32_ERROR = 9992u32; +pub const DNS_ERROR_POLICY_INVALID_CRITERIA_QUERY_TYPE: WIN32_ERROR = 9995u32; +pub const DNS_ERROR_POLICY_INVALID_CRITERIA_TIME_OF_DAY: WIN32_ERROR = 9996u32; +pub const DNS_ERROR_POLICY_INVALID_CRITERIA_TRANSPORT_PROTOCOL: WIN32_ERROR = 9991u32; +pub const DNS_ERROR_POLICY_INVALID_NAME: WIN32_ERROR = 9982u32; +pub const DNS_ERROR_POLICY_INVALID_SETTINGS: WIN32_ERROR = 9974u32; +pub const DNS_ERROR_POLICY_INVALID_WEIGHT: WIN32_ERROR = 9981u32; +pub const DNS_ERROR_POLICY_LOCKED: WIN32_ERROR = 9980u32; +pub const DNS_ERROR_POLICY_MISSING_CRITERIA: WIN32_ERROR = 9983u32; +pub const DNS_ERROR_POLICY_PROCESSING_ORDER_INVALID: WIN32_ERROR = 9985u32; +pub const DNS_ERROR_POLICY_SCOPE_MISSING: WIN32_ERROR = 9986u32; +pub const DNS_ERROR_POLICY_SCOPE_NOT_ALLOWED: WIN32_ERROR = 9987u32; +pub const DNS_ERROR_PRIMARY_REQUIRES_DATAFILE: WIN32_ERROR = 9651u32; +pub const DNS_ERROR_RCODE: WIN32_ERROR = 9504u32; +pub const DNS_ERROR_RCODE_BADKEY: WIN32_ERROR = 9017u32; +pub const DNS_ERROR_RCODE_BADSIG: WIN32_ERROR = 9016u32; +pub const DNS_ERROR_RCODE_BADTIME: WIN32_ERROR = 9018u32; +pub const DNS_ERROR_RCODE_FORMAT_ERROR: WIN32_ERROR = 9001u32; +pub const DNS_ERROR_RCODE_NAME_ERROR: WIN32_ERROR = 9003u32; +pub const DNS_ERROR_RCODE_NOTAUTH: WIN32_ERROR = 9009u32; +pub const DNS_ERROR_RCODE_NOTZONE: WIN32_ERROR = 9010u32; +pub const DNS_ERROR_RCODE_NOT_IMPLEMENTED: WIN32_ERROR = 9004u32; +pub const DNS_ERROR_RCODE_NXRRSET: WIN32_ERROR = 9008u32; +pub const DNS_ERROR_RCODE_REFUSED: WIN32_ERROR = 9005u32; +pub const DNS_ERROR_RCODE_SERVER_FAILURE: WIN32_ERROR = 9002u32; +pub const DNS_ERROR_RCODE_YXDOMAIN: WIN32_ERROR = 9006u32; +pub const DNS_ERROR_RCODE_YXRRSET: WIN32_ERROR = 9007u32; +pub const DNS_ERROR_RECORD_ALREADY_EXISTS: WIN32_ERROR = 9711u32; +pub const DNS_ERROR_RECORD_DOES_NOT_EXIST: WIN32_ERROR = 9701u32; +pub const DNS_ERROR_RECORD_FORMAT: WIN32_ERROR = 9702u32; +pub const DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT: WIN32_ERROR = 9710u32; +pub const DNS_ERROR_RECORD_TIMED_OUT: WIN32_ERROR = 9705u32; +pub const DNS_ERROR_ROLLOVER_ALREADY_QUEUED: WIN32_ERROR = 9120u32; +pub const DNS_ERROR_ROLLOVER_IN_PROGRESS: WIN32_ERROR = 9116u32; +pub const DNS_ERROR_ROLLOVER_NOT_POKEABLE: WIN32_ERROR = 9128u32; +pub const DNS_ERROR_RRL_INVALID_IPV4_PREFIX: WIN32_ERROR = 9913u32; +pub const DNS_ERROR_RRL_INVALID_IPV6_PREFIX: WIN32_ERROR = 9914u32; +pub const DNS_ERROR_RRL_INVALID_LEAK_RATE: WIN32_ERROR = 9916u32; +pub const DNS_ERROR_RRL_INVALID_TC_RATE: WIN32_ERROR = 9915u32; +pub const DNS_ERROR_RRL_INVALID_WINDOW_SIZE: WIN32_ERROR = 9912u32; +pub const DNS_ERROR_RRL_LEAK_RATE_LESSTHAN_TC_RATE: WIN32_ERROR = 9917u32; +pub const DNS_ERROR_RRL_NOT_ENABLED: WIN32_ERROR = 9911u32; +pub const DNS_ERROR_SCOPE_ALREADY_EXISTS: WIN32_ERROR = 9963u32; +pub const DNS_ERROR_SCOPE_DOES_NOT_EXIST: WIN32_ERROR = 9959u32; +pub const DNS_ERROR_SCOPE_LOCKED: WIN32_ERROR = 9962u32; +pub const DNS_ERROR_SECONDARY_DATA: WIN32_ERROR = 9712u32; +pub const DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP: WIN32_ERROR = 9612u32; +pub const DNS_ERROR_SERVERSCOPE_IS_REFERENCED: WIN32_ERROR = 9988u32; +pub const DNS_ERROR_SIGNING_KEY_NOT_ACCESSIBLE: WIN32_ERROR = 9107u32; +pub const DNS_ERROR_SOA_DELETE_INVALID: WIN32_ERROR = 9618u32; +pub const DNS_ERROR_STANDBY_KEY_NOT_PRESENT: WIN32_ERROR = 9117u32; +pub const DNS_ERROR_SUBNET_ALREADY_EXISTS: WIN32_ERROR = 9979u32; +pub const DNS_ERROR_SUBNET_DOES_NOT_EXIST: WIN32_ERROR = 9978u32; +pub const DNS_ERROR_TOO_MANY_SKDS: WIN32_ERROR = 9113u32; +pub const DNS_ERROR_TRY_AGAIN_LATER: WIN32_ERROR = 9554u32; +pub const DNS_ERROR_UNEXPECTED_CNG_ERROR: WIN32_ERROR = 9110u32; +pub const DNS_ERROR_UNEXPECTED_DATA_PROTECTION_ERROR: WIN32_ERROR = 9109u32; +pub const DNS_ERROR_UNKNOWN_RECORD_TYPE: WIN32_ERROR = 9704u32; +pub const DNS_ERROR_UNKNOWN_SIGNING_PARAMETER_VERSION: WIN32_ERROR = 9111u32; +pub const DNS_ERROR_UNSECURE_PACKET: WIN32_ERROR = 9505u32; +pub const DNS_ERROR_UNSUPPORTED_ALGORITHM: WIN32_ERROR = 9105u32; +pub const DNS_ERROR_VIRTUALIZATION_INSTANCE_ALREADY_EXISTS: WIN32_ERROR = 9921u32; +pub const DNS_ERROR_VIRTUALIZATION_INSTANCE_DOES_NOT_EXIST: WIN32_ERROR = 9922u32; +pub const DNS_ERROR_VIRTUALIZATION_TREE_LOCKED: WIN32_ERROR = 9923u32; +pub const DNS_ERROR_WINS_INIT_FAILED: WIN32_ERROR = 9615u32; +pub const DNS_ERROR_ZONESCOPE_ALREADY_EXISTS: WIN32_ERROR = 9951u32; +pub const DNS_ERROR_ZONESCOPE_DOES_NOT_EXIST: WIN32_ERROR = 9952u32; +pub const DNS_ERROR_ZONESCOPE_FILE_WRITEBACK_FAILED: WIN32_ERROR = 9957u32; +pub const DNS_ERROR_ZONESCOPE_IS_REFERENCED: WIN32_ERROR = 9989u32; +pub const DNS_ERROR_ZONE_ALREADY_EXISTS: WIN32_ERROR = 9609u32; +pub const DNS_ERROR_ZONE_CONFIGURATION_ERROR: WIN32_ERROR = 9604u32; +pub const DNS_ERROR_ZONE_CREATION_FAILED: WIN32_ERROR = 9608u32; +pub const DNS_ERROR_ZONE_DOES_NOT_EXIST: WIN32_ERROR = 9601u32; +pub const DNS_ERROR_ZONE_HAS_NO_NS_RECORDS: WIN32_ERROR = 9606u32; +pub const DNS_ERROR_ZONE_HAS_NO_SOA_RECORD: WIN32_ERROR = 9605u32; +pub const DNS_ERROR_ZONE_IS_SHUTDOWN: WIN32_ERROR = 9621u32; +pub const DNS_ERROR_ZONE_LOCKED: WIN32_ERROR = 9607u32; +pub const DNS_ERROR_ZONE_LOCKED_FOR_SIGNING: WIN32_ERROR = 9622u32; +pub const DNS_ERROR_ZONE_NOT_SECONDARY: WIN32_ERROR = 9613u32; +pub const DNS_ERROR_ZONE_REQUIRES_MASTER_IP: WIN32_ERROR = 9620u32; +pub const DUPLICATE_CLOSE_SOURCE: DUPLICATE_HANDLE_OPTIONS = 1u32; +pub type DUPLICATE_HANDLE_OPTIONS = u32; +pub const DUPLICATE_SAME_ACCESS: DUPLICATE_HANDLE_OPTIONS = 2u32; +pub const ENABLE_AUTO_POSITION: CONSOLE_MODE = 256u32; +pub const ENABLE_ECHO_INPUT: CONSOLE_MODE = 4u32; +pub const ENABLE_EXTENDED_FLAGS: CONSOLE_MODE = 128u32; +pub const ENABLE_INSERT_MODE: CONSOLE_MODE = 32u32; +pub const ENABLE_LINE_INPUT: CONSOLE_MODE = 2u32; +pub const ENABLE_LVB_GRID_WORLDWIDE: CONSOLE_MODE = 16u32; +pub const ENABLE_MOUSE_INPUT: CONSOLE_MODE = 16u32; +pub const ENABLE_PROCESSED_INPUT: CONSOLE_MODE = 1u32; +pub const ENABLE_PROCESSED_OUTPUT: CONSOLE_MODE = 1u32; +pub const ENABLE_QUICK_EDIT_MODE: CONSOLE_MODE = 64u32; +pub const ENABLE_VIRTUAL_TERMINAL_INPUT: CONSOLE_MODE = 512u32; +pub const ENABLE_VIRTUAL_TERMINAL_PROCESSING: CONSOLE_MODE = 4u32; +pub const ENABLE_WINDOW_INPUT: CONSOLE_MODE = 8u32; +pub const ENABLE_WRAP_AT_EOL_OUTPUT: CONSOLE_MODE = 2u32; +pub const ERROR_ABANDONED_WAIT_0: WIN32_ERROR = 735u32; +pub const ERROR_ABANDONED_WAIT_63: WIN32_ERROR = 736u32; +pub const ERROR_ABANDON_HIBERFILE: WIN32_ERROR = 787u32; +pub const ERROR_ABIOS_ERROR: WIN32_ERROR = 538u32; +pub const ERROR_ACCESS_AUDIT_BY_POLICY: WIN32_ERROR = 785u32; +pub const ERROR_ACCESS_DENIED: WIN32_ERROR = 5u32; +pub const ERROR_ACCESS_DENIED_APPDATA: WIN32_ERROR = 502u32; +pub const ERROR_ACCESS_DISABLED_BY_POLICY: WIN32_ERROR = 1260u32; +pub const ERROR_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY: WIN32_ERROR = 786u32; +pub const ERROR_ACCESS_DISABLED_WEBBLADE: WIN32_ERROR = 1277u32; +pub const ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER: WIN32_ERROR = 1278u32; +pub const ERROR_ACCOUNT_DISABLED: WIN32_ERROR = 1331u32; +pub const ERROR_ACCOUNT_EXPIRED: WIN32_ERROR = 1793u32; +pub const ERROR_ACCOUNT_LOCKED_OUT: WIN32_ERROR = 1909u32; +pub const ERROR_ACCOUNT_RESTRICTION: WIN32_ERROR = 1327u32; +pub const ERROR_ACPI_ERROR: WIN32_ERROR = 669u32; +pub const ERROR_ACTIVE_CONNECTIONS: WIN32_ERROR = 2402u32; +pub const ERROR_ADAP_HDW_ERR: WIN32_ERROR = 57u32; +pub const ERROR_ADDRESS_ALREADY_ASSOCIATED: WIN32_ERROR = 1227u32; +pub const ERROR_ADDRESS_NOT_ASSOCIATED: WIN32_ERROR = 1228u32; +pub const ERROR_ALERTED: WIN32_ERROR = 739u32; +pub const ERROR_ALIAS_EXISTS: WIN32_ERROR = 1379u32; +pub const ERROR_ALLOCATE_BUCKET: WIN32_ERROR = 602u32; +pub const ERROR_ALLOTTED_SPACE_EXCEEDED: WIN32_ERROR = 1344u32; +pub const ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED: WIN32_ERROR = 1933u32; +pub const ERROR_ALREADY_ASSIGNED: WIN32_ERROR = 85u32; +pub const ERROR_ALREADY_EXISTS: WIN32_ERROR = 183u32; +pub const ERROR_ALREADY_FIBER: WIN32_ERROR = 1280u32; +pub const ERROR_ALREADY_HAS_STREAM_ID: WIN32_ERROR = 4444u32; +pub const ERROR_ALREADY_INITIALIZED: WIN32_ERROR = 1247u32; +pub const ERROR_ALREADY_REGISTERED: WIN32_ERROR = 1242u32; +pub const ERROR_ALREADY_RUNNING_LKG: WIN32_ERROR = 1074u32; +pub const ERROR_ALREADY_THREAD: WIN32_ERROR = 1281u32; +pub const ERROR_ALREADY_WAITING: WIN32_ERROR = 1904u32; +pub const ERROR_ALREADY_WIN32: WIN32_ERROR = 719u32; +pub const ERROR_API_UNAVAILABLE: WIN32_ERROR = 15841u32; +pub const ERROR_APPCONTAINER_REQUIRED: WIN32_ERROR = 4251u32; +pub const ERROR_APPEXEC_APP_COMPAT_BLOCK: WIN32_ERROR = 3068u32; +pub const ERROR_APPEXEC_CALLER_WAIT_TIMEOUT: WIN32_ERROR = 3069u32; +pub const ERROR_APPEXEC_CALLER_WAIT_TIMEOUT_LICENSING: WIN32_ERROR = 3071u32; +pub const ERROR_APPEXEC_CALLER_WAIT_TIMEOUT_RESOURCES: WIN32_ERROR = 3072u32; +pub const ERROR_APPEXEC_CALLER_WAIT_TIMEOUT_TERMINATION: WIN32_ERROR = 3070u32; +pub const ERROR_APPEXEC_CONDITION_NOT_SATISFIED: WIN32_ERROR = 3060u32; +pub const ERROR_APPEXEC_HANDLE_INVALIDATED: WIN32_ERROR = 3061u32; +pub const ERROR_APPEXEC_HOST_ID_MISMATCH: WIN32_ERROR = 3066u32; +pub const ERROR_APPEXEC_INVALID_HOST_GENERATION: WIN32_ERROR = 3062u32; +pub const ERROR_APPEXEC_INVALID_HOST_STATE: WIN32_ERROR = 3064u32; +pub const ERROR_APPEXEC_NO_DONOR: WIN32_ERROR = 3065u32; +pub const ERROR_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION: WIN32_ERROR = 3063u32; +pub const ERROR_APPEXEC_UNKNOWN_USER: WIN32_ERROR = 3067u32; +pub const ERROR_APPHELP_BLOCK: WIN32_ERROR = 1259u32; +pub const ERROR_APPX_FILE_NOT_ENCRYPTED: WIN32_ERROR = 409u32; +pub const ERROR_APP_HANG: WIN32_ERROR = 1298u32; +pub const ERROR_APP_INIT_FAILURE: WIN32_ERROR = 575u32; +pub const ERROR_APP_WRONG_OS: WIN32_ERROR = 1151u32; +pub const ERROR_ARBITRATION_UNHANDLED: WIN32_ERROR = 723u32; +pub const ERROR_ARENA_TRASHED: WIN32_ERROR = 7u32; +pub const ERROR_ARITHMETIC_OVERFLOW: WIN32_ERROR = 534u32; +pub const ERROR_ASSERTION_FAILURE: WIN32_ERROR = 668u32; +pub const ERROR_ATOMIC_LOCKS_NOT_SUPPORTED: WIN32_ERROR = 174u32; +pub const ERROR_AUDIT_FAILED: WIN32_ERROR = 606u32; +pub const ERROR_AUTHENTICATION_FIREWALL_FAILED: WIN32_ERROR = 1935u32; +pub const ERROR_AUTHIP_FAILURE: WIN32_ERROR = 1469u32; +pub const ERROR_AUTODATASEG_EXCEEDS_64k: WIN32_ERROR = 199u32; +pub const ERROR_BACKUP_CONTROLLER: WIN32_ERROR = 586u32; +pub const ERROR_BADDB: WIN32_ERROR = 1009u32; +pub const ERROR_BADKEY: WIN32_ERROR = 1010u32; +pub const ERROR_BADSTARTPOSITION: WIN32_ERROR = 778u32; +pub const ERROR_BAD_ACCESSOR_FLAGS: WIN32_ERROR = 773u32; +pub const ERROR_BAD_ARGUMENTS: WIN32_ERROR = 160u32; +pub const ERROR_BAD_COMMAND: WIN32_ERROR = 22u32; +pub const ERROR_BAD_COMPRESSION_BUFFER: WIN32_ERROR = 605u32; +pub const ERROR_BAD_CONFIGURATION: WIN32_ERROR = 1610u32; +pub const ERROR_BAD_CURRENT_DIRECTORY: WIN32_ERROR = 703u32; +pub const ERROR_BAD_DESCRIPTOR_FORMAT: WIN32_ERROR = 1361u32; +pub const ERROR_BAD_DEVICE: WIN32_ERROR = 1200u32; +pub const ERROR_BAD_DEVICE_PATH: WIN32_ERROR = 330u32; +pub const ERROR_BAD_DEV_TYPE: WIN32_ERROR = 66u32; +pub const ERROR_BAD_DLL_ENTRYPOINT: WIN32_ERROR = 609u32; +pub const ERROR_BAD_DRIVER_LEVEL: WIN32_ERROR = 119u32; +pub const ERROR_BAD_ENVIRONMENT: WIN32_ERROR = 10u32; +pub const ERROR_BAD_EXE_FORMAT: WIN32_ERROR = 193u32; +pub const ERROR_BAD_FILE_TYPE: WIN32_ERROR = 222u32; +pub const ERROR_BAD_FORMAT: WIN32_ERROR = 11u32; +pub const ERROR_BAD_FUNCTION_TABLE: WIN32_ERROR = 559u32; +pub const ERROR_BAD_IMPERSONATION_LEVEL: WIN32_ERROR = 1346u32; +pub const ERROR_BAD_INHERITANCE_ACL: WIN32_ERROR = 1340u32; +pub const ERROR_BAD_LENGTH: WIN32_ERROR = 24u32; +pub const ERROR_BAD_LOGON_SESSION_STATE: WIN32_ERROR = 1365u32; +pub const ERROR_BAD_MCFG_TABLE: WIN32_ERROR = 791u32; +pub const ERROR_BAD_NETPATH: WIN32_ERROR = 53u32; +pub const ERROR_BAD_NET_NAME: WIN32_ERROR = 67u32; +pub const ERROR_BAD_NET_RESP: WIN32_ERROR = 58u32; +pub const ERROR_BAD_PATHNAME: WIN32_ERROR = 161u32; +pub const ERROR_BAD_PIPE: WIN32_ERROR = 230u32; +pub const ERROR_BAD_PROFILE: WIN32_ERROR = 1206u32; +pub const ERROR_BAD_PROVIDER: WIN32_ERROR = 1204u32; +pub const ERROR_BAD_QUERY_SYNTAX: WIN32_ERROR = 1615u32; +pub const ERROR_BAD_RECOVERY_POLICY: WIN32_ERROR = 6012u32; +pub const ERROR_BAD_REM_ADAP: WIN32_ERROR = 60u32; +pub const ERROR_BAD_SERVICE_ENTRYPOINT: WIN32_ERROR = 610u32; +pub const ERROR_BAD_STACK: WIN32_ERROR = 543u32; +pub const ERROR_BAD_THREADID_ADDR: WIN32_ERROR = 159u32; +pub const ERROR_BAD_TOKEN_TYPE: WIN32_ERROR = 1349u32; +pub const ERROR_BAD_UNIT: WIN32_ERROR = 20u32; +pub const ERROR_BAD_USERNAME: WIN32_ERROR = 2202u32; +pub const ERROR_BAD_USER_PROFILE: WIN32_ERROR = 1253u32; +pub const ERROR_BAD_VALIDATION_CLASS: WIN32_ERROR = 1348u32; +pub const ERROR_BEGINNING_OF_MEDIA: WIN32_ERROR = 1102u32; +pub const ERROR_BEYOND_VDL: WIN32_ERROR = 1289u32; +pub const ERROR_BIOS_FAILED_TO_CONNECT_INTERRUPT: WIN32_ERROR = 585u32; +pub const ERROR_BLOCKED_BY_PARENTAL_CONTROLS: WIN32_ERROR = 346u32; +pub const ERROR_BLOCK_SHARED: WIN32_ERROR = 514u32; +pub const ERROR_BLOCK_SOURCE_WEAK_REFERENCE_INVALID: WIN32_ERROR = 512u32; +pub const ERROR_BLOCK_TARGET_WEAK_REFERENCE_INVALID: WIN32_ERROR = 513u32; +pub const ERROR_BLOCK_TOO_MANY_REFERENCES: WIN32_ERROR = 347u32; +pub const ERROR_BLOCK_WEAK_REFERENCE_INVALID: WIN32_ERROR = 511u32; +pub const ERROR_BOOT_ALREADY_ACCEPTED: WIN32_ERROR = 1076u32; +pub const ERROR_BROKEN_PIPE: WIN32_ERROR = 109u32; +pub const ERROR_BUFFER_ALL_ZEROS: WIN32_ERROR = 754u32; +pub const ERROR_BUFFER_OVERFLOW: WIN32_ERROR = 111u32; +pub const ERROR_BUSY: WIN32_ERROR = 170u32; +pub const ERROR_BUSY_DRIVE: WIN32_ERROR = 142u32; +pub const ERROR_BUS_RESET: WIN32_ERROR = 1111u32; +pub const ERROR_BYPASSIO_FLT_NOT_SUPPORTED: WIN32_ERROR = 506u32; +pub const ERROR_CACHE_PAGE_LOCKED: WIN32_ERROR = 752u32; +pub const ERROR_CALLBACK_INVOKE_INLINE: WIN32_ERROR = 812u32; +pub const ERROR_CALLBACK_POP_STACK: WIN32_ERROR = 768u32; +pub const ERROR_CALLBACK_SUPPLIED_INVALID_DATA: WIN32_ERROR = 1273u32; +pub const ERROR_CALL_NOT_IMPLEMENTED: WIN32_ERROR = 120u32; +pub const ERROR_CANCELLED: WIN32_ERROR = 1223u32; +pub const ERROR_CANCEL_VIOLATION: WIN32_ERROR = 173u32; +pub const ERROR_CANNOT_BREAK_OPLOCK: WIN32_ERROR = 802u32; +pub const ERROR_CANNOT_COPY: WIN32_ERROR = 266u32; +pub const ERROR_CANNOT_DETECT_DRIVER_FAILURE: WIN32_ERROR = 1080u32; +pub const ERROR_CANNOT_DETECT_PROCESS_ABORT: WIN32_ERROR = 1081u32; +pub const ERROR_CANNOT_FIND_WND_CLASS: WIN32_ERROR = 1407u32; +pub const ERROR_CANNOT_GRANT_REQUESTED_OPLOCK: WIN32_ERROR = 801u32; +pub const ERROR_CANNOT_IMPERSONATE: WIN32_ERROR = 1368u32; +pub const ERROR_CANNOT_LOAD_REGISTRY_FILE: WIN32_ERROR = 589u32; +pub const ERROR_CANNOT_MAKE: WIN32_ERROR = 82u32; +pub const ERROR_CANNOT_OPEN_PROFILE: WIN32_ERROR = 1205u32; +pub const ERROR_CANTFETCHBACKWARDS: WIN32_ERROR = 770u32; +pub const ERROR_CANTOPEN: WIN32_ERROR = 1011u32; +pub const ERROR_CANTREAD: WIN32_ERROR = 1012u32; +pub const ERROR_CANTSCROLLBACKWARDS: WIN32_ERROR = 771u32; +pub const ERROR_CANTWRITE: WIN32_ERROR = 1013u32; +pub const ERROR_CANT_ACCESS_DOMAIN_INFO: WIN32_ERROR = 1351u32; +pub const ERROR_CANT_ACCESS_FILE: WIN32_ERROR = 1920u32; +pub const ERROR_CANT_CLEAR_ENCRYPTION_FLAG: WIN32_ERROR = 432u32; +pub const ERROR_CANT_DISABLE_MANDATORY: WIN32_ERROR = 1310u32; +pub const ERROR_CANT_ENABLE_DENY_ONLY: WIN32_ERROR = 629u32; +pub const ERROR_CANT_OPEN_ANONYMOUS: WIN32_ERROR = 1347u32; +pub const ERROR_CANT_RESOLVE_FILENAME: WIN32_ERROR = 1921u32; +pub const ERROR_CANT_TERMINATE_SELF: WIN32_ERROR = 555u32; +pub const ERROR_CANT_WAIT: WIN32_ERROR = 554u32; +pub const ERROR_CAN_NOT_COMPLETE: WIN32_ERROR = 1003u32; +pub const ERROR_CAPAUTHZ_CHANGE_TYPE: WIN32_ERROR = 451u32; +pub const ERROR_CAPAUTHZ_DB_CORRUPTED: WIN32_ERROR = 455u32; +pub const ERROR_CAPAUTHZ_NOT_AUTHORIZED: WIN32_ERROR = 453u32; +pub const ERROR_CAPAUTHZ_NOT_DEVUNLOCKED: WIN32_ERROR = 450u32; +pub const ERROR_CAPAUTHZ_NOT_PROVISIONED: WIN32_ERROR = 452u32; +pub const ERROR_CAPAUTHZ_NO_POLICY: WIN32_ERROR = 454u32; +pub const ERROR_CAPAUTHZ_SCCD_DEV_MODE_REQUIRED: WIN32_ERROR = 459u32; +pub const ERROR_CAPAUTHZ_SCCD_INVALID_CATALOG: WIN32_ERROR = 456u32; +pub const ERROR_CAPAUTHZ_SCCD_NO_AUTH_ENTITY: WIN32_ERROR = 457u32; +pub const ERROR_CAPAUTHZ_SCCD_NO_CAPABILITY_MATCH: WIN32_ERROR = 460u32; +pub const ERROR_CAPAUTHZ_SCCD_PARSE_ERROR: WIN32_ERROR = 458u32; +pub const ERROR_CARDBUS_NOT_SUPPORTED: WIN32_ERROR = 724u32; +pub const ERROR_CASE_DIFFERING_NAMES_IN_DIR: WIN32_ERROR = 424u32; +pub const ERROR_CASE_SENSITIVE_PATH: WIN32_ERROR = 442u32; +pub const ERROR_CERTIFICATE_VALIDATION_PREFERENCE_CONFLICT: WIN32_ERROR = 817u32; +pub const ERROR_CHECKING_FILE_SYSTEM: WIN32_ERROR = 712u32; +pub const ERROR_CHECKOUT_REQUIRED: WIN32_ERROR = 221u32; +pub const ERROR_CHILD_MUST_BE_VOLATILE: WIN32_ERROR = 1021u32; +pub const ERROR_CHILD_NOT_COMPLETE: WIN32_ERROR = 129u32; +pub const ERROR_CHILD_PROCESS_BLOCKED: WIN32_ERROR = 367u32; +pub const ERROR_CHILD_WINDOW_MENU: WIN32_ERROR = 1436u32; +pub const ERROR_CIMFS_IMAGE_CORRUPT: WIN32_ERROR = 470u32; +pub const ERROR_CIMFS_IMAGE_VERSION_NOT_SUPPORTED: WIN32_ERROR = 471u32; +pub const ERROR_CIRCULAR_DEPENDENCY: WIN32_ERROR = 1059u32; +pub const ERROR_CLASS_ALREADY_EXISTS: WIN32_ERROR = 1410u32; +pub const ERROR_CLASS_DOES_NOT_EXIST: WIN32_ERROR = 1411u32; +pub const ERROR_CLASS_HAS_WINDOWS: WIN32_ERROR = 1412u32; +pub const ERROR_CLIENT_SERVER_PARAMETERS_INVALID: WIN32_ERROR = 597u32; +pub const ERROR_CLIPBOARD_NOT_OPEN: WIN32_ERROR = 1418u32; +pub const ERROR_CLOUD_FILE_ACCESS_DENIED: WIN32_ERROR = 395u32; +pub const ERROR_CLOUD_FILE_ALREADY_CONNECTED: WIN32_ERROR = 378u32; +pub const ERROR_CLOUD_FILE_AUTHENTICATION_FAILED: WIN32_ERROR = 386u32; +pub const ERROR_CLOUD_FILE_CONNECTED_PROVIDER_ONLY: WIN32_ERROR = 382u32; +pub const ERROR_CLOUD_FILE_DEHYDRATION_DISALLOWED: WIN32_ERROR = 434u32; +pub const ERROR_CLOUD_FILE_INCOMPATIBLE_HARDLINKS: WIN32_ERROR = 396u32; +pub const ERROR_CLOUD_FILE_INSUFFICIENT_RESOURCES: WIN32_ERROR = 387u32; +pub const ERROR_CLOUD_FILE_INVALID_REQUEST: WIN32_ERROR = 380u32; +pub const ERROR_CLOUD_FILE_IN_USE: WIN32_ERROR = 391u32; +pub const ERROR_CLOUD_FILE_METADATA_CORRUPT: WIN32_ERROR = 363u32; +pub const ERROR_CLOUD_FILE_METADATA_TOO_LARGE: WIN32_ERROR = 364u32; +pub const ERROR_CLOUD_FILE_NETWORK_UNAVAILABLE: WIN32_ERROR = 388u32; +pub const ERROR_CLOUD_FILE_NOT_IN_SYNC: WIN32_ERROR = 377u32; +pub const ERROR_CLOUD_FILE_NOT_SUPPORTED: WIN32_ERROR = 379u32; +pub const ERROR_CLOUD_FILE_NOT_UNDER_SYNC_ROOT: WIN32_ERROR = 390u32; +pub const ERROR_CLOUD_FILE_PINNED: WIN32_ERROR = 392u32; +pub const ERROR_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH: WIN32_ERROR = 366u32; +pub const ERROR_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE: WIN32_ERROR = 365u32; +pub const ERROR_CLOUD_FILE_PROPERTY_CORRUPT: WIN32_ERROR = 394u32; +pub const ERROR_CLOUD_FILE_PROPERTY_LOCK_CONFLICT: WIN32_ERROR = 397u32; +pub const ERROR_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED: WIN32_ERROR = 375u32; +pub const ERROR_CLOUD_FILE_PROVIDER_NOT_RUNNING: WIN32_ERROR = 362u32; +pub const ERROR_CLOUD_FILE_PROVIDER_TERMINATED: WIN32_ERROR = 404u32; +pub const ERROR_CLOUD_FILE_READ_ONLY_VOLUME: WIN32_ERROR = 381u32; +pub const ERROR_CLOUD_FILE_REQUEST_ABORTED: WIN32_ERROR = 393u32; +pub const ERROR_CLOUD_FILE_REQUEST_CANCELED: WIN32_ERROR = 398u32; +pub const ERROR_CLOUD_FILE_REQUEST_TIMEOUT: WIN32_ERROR = 426u32; +pub const ERROR_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT: WIN32_ERROR = 358u32; +pub const ERROR_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS: WIN32_ERROR = 374u32; +pub const ERROR_CLOUD_FILE_UNSUCCESSFUL: WIN32_ERROR = 389u32; +pub const ERROR_CLOUD_FILE_US_MESSAGE_TIMEOUT: WIN32_ERROR = 475u32; +pub const ERROR_CLOUD_FILE_VALIDATION_FAILED: WIN32_ERROR = 383u32; +pub const ERROR_COMMITMENT_LIMIT: WIN32_ERROR = 1455u32; +pub const ERROR_COMMITMENT_MINIMUM: WIN32_ERROR = 635u32; +pub const ERROR_COMPRESSED_FILE_NOT_SUPPORTED: WIN32_ERROR = 335u32; +pub const ERROR_COMPRESSION_DISABLED: WIN32_ERROR = 769u32; +pub const ERROR_COMPRESSION_NOT_BENEFICIAL: WIN32_ERROR = 344u32; +pub const ERROR_CONNECTED_OTHER_PASSWORD: WIN32_ERROR = 2108u32; +pub const ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT: WIN32_ERROR = 2109u32; +pub const ERROR_CONNECTION_ABORTED: WIN32_ERROR = 1236u32; +pub const ERROR_CONNECTION_ACTIVE: WIN32_ERROR = 1230u32; +pub const ERROR_CONNECTION_COUNT_LIMIT: WIN32_ERROR = 1238u32; +pub const ERROR_CONNECTION_INVALID: WIN32_ERROR = 1229u32; +pub const ERROR_CONNECTION_REFUSED: WIN32_ERROR = 1225u32; +pub const ERROR_CONNECTION_UNAVAIL: WIN32_ERROR = 1201u32; +pub const ERROR_CONTAINER_ASSIGNED: WIN32_ERROR = 1504u32; +pub const ERROR_CONTENT_BLOCKED: WIN32_ERROR = 1296u32; +pub const ERROR_CONTEXT_EXPIRED: WIN32_ERROR = 1931u32; +pub const ERROR_CONTINUE: WIN32_ERROR = 1246u32; +pub const ERROR_CONTROL_C_EXIT: WIN32_ERROR = 572u32; +pub const ERROR_CONTROL_ID_NOT_FOUND: WIN32_ERROR = 1421u32; +pub const ERROR_CONVERT_TO_LARGE: WIN32_ERROR = 600u32; +pub const ERROR_CORRUPT_LOG_CLEARED: WIN32_ERROR = 798u32; +pub const ERROR_CORRUPT_LOG_CORRUPTED: WIN32_ERROR = 795u32; +pub const ERROR_CORRUPT_LOG_DELETED_FULL: WIN32_ERROR = 797u32; +pub const ERROR_CORRUPT_LOG_OVERFULL: WIN32_ERROR = 794u32; +pub const ERROR_CORRUPT_LOG_UNAVAILABLE: WIN32_ERROR = 796u32; +pub const ERROR_CORRUPT_SYSTEM_FILE: WIN32_ERROR = 634u32; +pub const ERROR_COULD_NOT_INTERPRET: WIN32_ERROR = 552u32; +pub const ERROR_COUNTER_TIMEOUT: WIN32_ERROR = 1121u32; +pub const ERROR_CPU_SET_INVALID: WIN32_ERROR = 813u32; +pub const ERROR_CRASH_DUMP: WIN32_ERROR = 753u32; +pub const ERROR_CRC: WIN32_ERROR = 23u32; +pub const ERROR_CREATE_FAILED: WIN32_ERROR = 1631u32; +pub const ERROR_CROSS_PARTITION_VIOLATION: WIN32_ERROR = 1661u32; +pub const ERROR_CSCSHARE_OFFLINE: WIN32_ERROR = 1262u32; +pub const ERROR_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE: WIN32_ERROR = 6019u32; +pub const ERROR_CS_ENCRYPTION_FILE_NOT_CSE: WIN32_ERROR = 6021u32; +pub const ERROR_CS_ENCRYPTION_INVALID_SERVER_RESPONSE: WIN32_ERROR = 6017u32; +pub const ERROR_CS_ENCRYPTION_NEW_ENCRYPTED_FILE: WIN32_ERROR = 6020u32; +pub const ERROR_CS_ENCRYPTION_UNSUPPORTED_SERVER: WIN32_ERROR = 6018u32; +pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: WIN32_ERROR = 7040u32; +pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: WIN32_ERROR = 7012u32; +pub const ERROR_CURRENT_DIRECTORY: WIN32_ERROR = 16u32; +pub const ERROR_CURRENT_DOMAIN_NOT_ALLOWED: WIN32_ERROR = 1399u32; +pub const ERROR_DATABASE_DOES_NOT_EXIST: WIN32_ERROR = 1065u32; +pub const ERROR_DATATYPE_MISMATCH: WIN32_ERROR = 1629u32; +pub const ERROR_DATA_CHECKSUM_ERROR: WIN32_ERROR = 323u32; +pub const ERROR_DATA_NOT_ACCEPTED: WIN32_ERROR = 592u32; +pub const ERROR_DAX_MAPPING_EXISTS: WIN32_ERROR = 361u32; +pub const ERROR_DBG_COMMAND_EXCEPTION: WIN32_ERROR = 697u32; +pub const ERROR_DBG_CONTINUE: WIN32_ERROR = 767u32; +pub const ERROR_DBG_CONTROL_BREAK: WIN32_ERROR = 696u32; +pub const ERROR_DBG_CONTROL_C: WIN32_ERROR = 693u32; +pub const ERROR_DBG_EXCEPTION_HANDLED: WIN32_ERROR = 766u32; +pub const ERROR_DBG_EXCEPTION_NOT_HANDLED: WIN32_ERROR = 688u32; +pub const ERROR_DBG_PRINTEXCEPTION_C: WIN32_ERROR = 694u32; +pub const ERROR_DBG_REPLY_LATER: WIN32_ERROR = 689u32; +pub const ERROR_DBG_RIPEXCEPTION: WIN32_ERROR = 695u32; +pub const ERROR_DBG_TERMINATE_PROCESS: WIN32_ERROR = 692u32; +pub const ERROR_DBG_TERMINATE_THREAD: WIN32_ERROR = 691u32; +pub const ERROR_DBG_UNABLE_TO_PROVIDE_HANDLE: WIN32_ERROR = 690u32; +pub const ERROR_DC_NOT_FOUND: WIN32_ERROR = 1425u32; +pub const ERROR_DDE_FAIL: WIN32_ERROR = 1156u32; +pub const ERROR_DEBUGGER_INACTIVE: WIN32_ERROR = 1284u32; +pub const ERROR_DEBUG_ATTACH_FAILED: WIN32_ERROR = 590u32; +pub const ERROR_DECRYPTION_FAILED: WIN32_ERROR = 6001u32; +pub const ERROR_DELAY_LOAD_FAILED: WIN32_ERROR = 1285u32; +pub const ERROR_DELETE_PENDING: WIN32_ERROR = 303u32; +pub const ERROR_DEPENDENT_SERVICES_RUNNING: WIN32_ERROR = 1051u32; +pub const ERROR_DESTINATION_ELEMENT_FULL: WIN32_ERROR = 1161u32; +pub const ERROR_DESTROY_OBJECT_OF_OTHER_THREAD: WIN32_ERROR = 1435u32; +pub const ERROR_DEVICE_ALREADY_ATTACHED: WIN32_ERROR = 548u32; +pub const ERROR_DEVICE_ALREADY_REMEMBERED: WIN32_ERROR = 1202u32; +pub const ERROR_DEVICE_DOOR_OPEN: WIN32_ERROR = 1166u32; +pub const ERROR_DEVICE_ENUMERATION_ERROR: WIN32_ERROR = 648u32; +pub const ERROR_DEVICE_FEATURE_NOT_SUPPORTED: WIN32_ERROR = 316u32; +pub const ERROR_DEVICE_HARDWARE_ERROR: WIN32_ERROR = 483u32; +pub const ERROR_DEVICE_HINT_NAME_BUFFER_TOO_SMALL: WIN32_ERROR = 355u32; +pub const ERROR_DEVICE_IN_MAINTENANCE: WIN32_ERROR = 359u32; +pub const ERROR_DEVICE_IN_USE: WIN32_ERROR = 2404u32; +pub const ERROR_DEVICE_NOT_CONNECTED: WIN32_ERROR = 1167u32; +pub const ERROR_DEVICE_NOT_PARTITIONED: WIN32_ERROR = 1107u32; +pub const ERROR_DEVICE_NO_RESOURCES: WIN32_ERROR = 322u32; +pub const ERROR_DEVICE_REINITIALIZATION_NEEDED: WIN32_ERROR = 1164u32; +pub const ERROR_DEVICE_REMOVED: WIN32_ERROR = 1617u32; +pub const ERROR_DEVICE_REQUIRES_CLEANING: WIN32_ERROR = 1165u32; +pub const ERROR_DEVICE_RESET_REQUIRED: WIN32_ERROR = 507u32; +pub const ERROR_DEVICE_SUPPORT_IN_PROGRESS: WIN32_ERROR = 171u32; +pub const ERROR_DEVICE_UNREACHABLE: WIN32_ERROR = 321u32; +pub const ERROR_DEV_NOT_EXIST: WIN32_ERROR = 55u32; +pub const ERROR_DHCP_ADDRESS_CONFLICT: WIN32_ERROR = 4100u32; +pub const ERROR_DIFFERENT_SERVICE_ACCOUNT: WIN32_ERROR = 1079u32; +pub const ERROR_DIRECTORY: WIN32_ERROR = 267u32; +pub const ERROR_DIRECTORY_NOT_SUPPORTED: WIN32_ERROR = 336u32; +pub const ERROR_DIRECT_ACCESS_HANDLE: WIN32_ERROR = 130u32; +pub const ERROR_DIR_EFS_DISALLOWED: WIN32_ERROR = 6010u32; +pub const ERROR_DIR_NOT_EMPTY: WIN32_ERROR = 145u32; +pub const ERROR_DIR_NOT_ROOT: WIN32_ERROR = 144u32; +pub const ERROR_DISCARDED: WIN32_ERROR = 157u32; +pub const ERROR_DISK_CHANGE: WIN32_ERROR = 107u32; +pub const ERROR_DISK_CORRUPT: WIN32_ERROR = 1393u32; +pub const ERROR_DISK_FULL: WIN32_ERROR = 112u32; +pub const ERROR_DISK_OPERATION_FAILED: WIN32_ERROR = 1127u32; +pub const ERROR_DISK_QUOTA_EXCEEDED: WIN32_ERROR = 1295u32; +pub const ERROR_DISK_RECALIBRATE_FAILED: WIN32_ERROR = 1126u32; +pub const ERROR_DISK_REPAIR_DISABLED: WIN32_ERROR = 780u32; +pub const ERROR_DISK_REPAIR_REDIRECTED: WIN32_ERROR = 792u32; +pub const ERROR_DISK_REPAIR_UNSUCCESSFUL: WIN32_ERROR = 793u32; +pub const ERROR_DISK_RESET_FAILED: WIN32_ERROR = 1128u32; +pub const ERROR_DISK_RESOURCES_EXHAUSTED: WIN32_ERROR = 314u32; +pub const ERROR_DISK_TOO_FRAGMENTED: WIN32_ERROR = 302u32; +pub const ERROR_DLL_INIT_FAILED: WIN32_ERROR = 1114u32; +pub const ERROR_DLL_INIT_FAILED_LOGOFF: WIN32_ERROR = 624u32; +pub const ERROR_DLL_MIGHT_BE_INCOMPATIBLE: WIN32_ERROR = 687u32; +pub const ERROR_DLL_MIGHT_BE_INSECURE: WIN32_ERROR = 686u32; +pub const ERROR_DLL_NOT_FOUND: WIN32_ERROR = 1157u32; +pub const ERROR_DLP_POLICY_DENIES_OPERATION: WIN32_ERROR = 446u32; +pub const ERROR_DLP_POLICY_SILENTLY_FAIL: WIN32_ERROR = 449u32; +pub const ERROR_DLP_POLICY_WARNS_AGAINST_OPERATION: WIN32_ERROR = 445u32; +pub const ERROR_DOMAIN_CONTROLLER_EXISTS: WIN32_ERROR = 1250u32; +pub const ERROR_DOMAIN_CONTROLLER_NOT_FOUND: WIN32_ERROR = 1908u32; +pub const ERROR_DOMAIN_CTRLR_CONFIG_ERROR: WIN32_ERROR = 581u32; +pub const ERROR_DOMAIN_EXISTS: WIN32_ERROR = 1356u32; +pub const ERROR_DOMAIN_LIMIT_EXCEEDED: WIN32_ERROR = 1357u32; +pub const ERROR_DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION: WIN32_ERROR = 8644u32; +pub const ERROR_DOMAIN_TRUST_INCONSISTENT: WIN32_ERROR = 1810u32; +pub const ERROR_DOWNGRADE_DETECTED: WIN32_ERROR = 1265u32; +pub const ERROR_DPL_NOT_SUPPORTED_FOR_USER: WIN32_ERROR = 423u32; +pub const ERROR_DRIVERS_LEAKING_LOCKED_PAGES: WIN32_ERROR = 729u32; +pub const ERROR_DRIVER_BLOCKED: WIN32_ERROR = 1275u32; +pub const ERROR_DRIVER_CANCEL_TIMEOUT: WIN32_ERROR = 594u32; +pub const ERROR_DRIVER_DATABASE_ERROR: WIN32_ERROR = 652u32; +pub const ERROR_DRIVER_FAILED_PRIOR_UNLOAD: WIN32_ERROR = 654u32; +pub const ERROR_DRIVER_FAILED_SLEEP: WIN32_ERROR = 633u32; +pub const ERROR_DRIVER_PROCESS_TERMINATED: WIN32_ERROR = 1291u32; +pub const ERROR_DRIVE_LOCKED: WIN32_ERROR = 108u32; +pub const ERROR_DS_ADD_REPLICA_INHIBITED: WIN32_ERROR = 8302u32; +pub const ERROR_DS_ADMIN_LIMIT_EXCEEDED: WIN32_ERROR = 8228u32; +pub const ERROR_DS_AFFECTS_MULTIPLE_DSAS: WIN32_ERROR = 8249u32; +pub const ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER: WIN32_ERROR = 8578u32; +pub const ERROR_DS_ALIASED_OBJ_MISSING: WIN32_ERROR = 8334u32; +pub const ERROR_DS_ALIAS_DEREF_PROBLEM: WIN32_ERROR = 8244u32; +pub const ERROR_DS_ALIAS_POINTS_TO_ALIAS: WIN32_ERROR = 8336u32; +pub const ERROR_DS_ALIAS_PROBLEM: WIN32_ERROR = 8241u32; +pub const ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS: WIN32_ERROR = 8205u32; +pub const ERROR_DS_ATTRIBUTE_OWNED_BY_SAM: WIN32_ERROR = 8346u32; +pub const ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED: WIN32_ERROR = 8204u32; +pub const ERROR_DS_ATT_ALREADY_EXISTS: WIN32_ERROR = 8318u32; +pub const ERROR_DS_ATT_IS_NOT_ON_OBJ: WIN32_ERROR = 8310u32; +pub const ERROR_DS_ATT_NOT_DEF_FOR_CLASS: WIN32_ERROR = 8317u32; +pub const ERROR_DS_ATT_NOT_DEF_IN_SCHEMA: WIN32_ERROR = 8303u32; +pub const ERROR_DS_ATT_SCHEMA_REQ_ID: WIN32_ERROR = 8399u32; +pub const ERROR_DS_ATT_SCHEMA_REQ_SYNTAX: WIN32_ERROR = 8416u32; +pub const ERROR_DS_ATT_VAL_ALREADY_EXISTS: WIN32_ERROR = 8323u32; +pub const ERROR_DS_AUDIT_FAILURE: WIN32_ERROR = 8625u32; +pub const ERROR_DS_AUTHORIZATION_FAILED: WIN32_ERROR = 8599u32; +pub const ERROR_DS_AUTH_METHOD_NOT_SUPPORTED: WIN32_ERROR = 8231u32; +pub const ERROR_DS_AUTH_UNKNOWN: WIN32_ERROR = 8234u32; +pub const ERROR_DS_AUX_CLS_TEST_FAIL: WIN32_ERROR = 8389u32; +pub const ERROR_DS_BACKLINK_WITHOUT_LINK: WIN32_ERROR = 8482u32; +pub const ERROR_DS_BAD_ATT_SCHEMA_SYNTAX: WIN32_ERROR = 8400u32; +pub const ERROR_DS_BAD_HIERARCHY_FILE: WIN32_ERROR = 8425u32; +pub const ERROR_DS_BAD_INSTANCE_TYPE: WIN32_ERROR = 8313u32; +pub const ERROR_DS_BAD_NAME_SYNTAX: WIN32_ERROR = 8335u32; +pub const ERROR_DS_BAD_RDN_ATT_ID_SYNTAX: WIN32_ERROR = 8392u32; +pub const ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED: WIN32_ERROR = 8426u32; +pub const ERROR_DS_BUSY: WIN32_ERROR = 8206u32; +pub const ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD: WIN32_ERROR = 8585u32; +pub const ERROR_DS_CANT_ADD_ATT_VALUES: WIN32_ERROR = 8320u32; +pub const ERROR_DS_CANT_ADD_SYSTEM_ONLY: WIN32_ERROR = 8358u32; +pub const ERROR_DS_CANT_ADD_TO_GC: WIN32_ERROR = 8550u32; +pub const ERROR_DS_CANT_CACHE_ATT: WIN32_ERROR = 8401u32; +pub const ERROR_DS_CANT_CACHE_CLASS: WIN32_ERROR = 8402u32; +pub const ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC: WIN32_ERROR = 8553u32; +pub const ERROR_DS_CANT_CREATE_UNDER_SCHEMA: WIN32_ERROR = 8510u32; +pub const ERROR_DS_CANT_DELETE: WIN32_ERROR = 8398u32; +pub const ERROR_DS_CANT_DELETE_DSA_OBJ: WIN32_ERROR = 8340u32; +pub const ERROR_DS_CANT_DEL_MASTER_CROSSREF: WIN32_ERROR = 8375u32; +pub const ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC: WIN32_ERROR = 8604u32; +pub const ERROR_DS_CANT_DEREF_ALIAS: WIN32_ERROR = 8337u32; +pub const ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN: WIN32_ERROR = 8603u32; +pub const ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF: WIN32_ERROR = 8589u32; +pub const ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN: WIN32_ERROR = 8537u32; +pub const ERROR_DS_CANT_FIND_DSA_OBJ: WIN32_ERROR = 8419u32; +pub const ERROR_DS_CANT_FIND_EXPECTED_NC: WIN32_ERROR = 8420u32; +pub const ERROR_DS_CANT_FIND_NC_IN_CACHE: WIN32_ERROR = 8421u32; +pub const ERROR_DS_CANT_MIX_MASTER_AND_REPS: WIN32_ERROR = 8331u32; +pub const ERROR_DS_CANT_MOD_OBJ_CLASS: WIN32_ERROR = 8215u32; +pub const ERROR_DS_CANT_MOD_PRIMARYGROUPID: WIN32_ERROR = 8506u32; +pub const ERROR_DS_CANT_MOD_SYSTEM_ONLY: WIN32_ERROR = 8369u32; +pub const ERROR_DS_CANT_MOVE_ACCOUNT_GROUP: WIN32_ERROR = 8498u32; +pub const ERROR_DS_CANT_MOVE_APP_BASIC_GROUP: WIN32_ERROR = 8608u32; +pub const ERROR_DS_CANT_MOVE_APP_QUERY_GROUP: WIN32_ERROR = 8609u32; +pub const ERROR_DS_CANT_MOVE_DELETED_OBJECT: WIN32_ERROR = 8489u32; +pub const ERROR_DS_CANT_MOVE_RESOURCE_GROUP: WIN32_ERROR = 8499u32; +pub const ERROR_DS_CANT_ON_NON_LEAF: WIN32_ERROR = 8213u32; +pub const ERROR_DS_CANT_ON_RDN: WIN32_ERROR = 8214u32; +pub const ERROR_DS_CANT_REMOVE_ATT_CACHE: WIN32_ERROR = 8403u32; +pub const ERROR_DS_CANT_REMOVE_CLASS_CACHE: WIN32_ERROR = 8404u32; +pub const ERROR_DS_CANT_REM_MISSING_ATT: WIN32_ERROR = 8324u32; +pub const ERROR_DS_CANT_REM_MISSING_ATT_VAL: WIN32_ERROR = 8325u32; +pub const ERROR_DS_CANT_REPLACE_HIDDEN_REC: WIN32_ERROR = 8424u32; +pub const ERROR_DS_CANT_RETRIEVE_ATTS: WIN32_ERROR = 8481u32; +pub const ERROR_DS_CANT_RETRIEVE_CHILD: WIN32_ERROR = 8422u32; +pub const ERROR_DS_CANT_RETRIEVE_DN: WIN32_ERROR = 8405u32; +pub const ERROR_DS_CANT_RETRIEVE_INSTANCE: WIN32_ERROR = 8407u32; +pub const ERROR_DS_CANT_RETRIEVE_SD: WIN32_ERROR = 8526u32; +pub const ERROR_DS_CANT_START: WIN32_ERROR = 8531u32; +pub const ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ: WIN32_ERROR = 8560u32; +pub const ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS: WIN32_ERROR = 8493u32; +pub const ERROR_DS_CHILDREN_EXIST: WIN32_ERROR = 8332u32; +pub const ERROR_DS_CLASS_MUST_BE_CONCRETE: WIN32_ERROR = 8359u32; +pub const ERROR_DS_CLASS_NOT_DSA: WIN32_ERROR = 8343u32; +pub const ERROR_DS_CLIENT_LOOP: WIN32_ERROR = 8259u32; +pub const ERROR_DS_CODE_INCONSISTENCY: WIN32_ERROR = 8408u32; +pub const ERROR_DS_COMPARE_FALSE: WIN32_ERROR = 8229u32; +pub const ERROR_DS_COMPARE_TRUE: WIN32_ERROR = 8230u32; +pub const ERROR_DS_CONFIDENTIALITY_REQUIRED: WIN32_ERROR = 8237u32; +pub const ERROR_DS_CONFIG_PARAM_MISSING: WIN32_ERROR = 8427u32; +pub const ERROR_DS_CONSTRAINT_VIOLATION: WIN32_ERROR = 8239u32; +pub const ERROR_DS_CONSTRUCTED_ATT_MOD: WIN32_ERROR = 8475u32; +pub const ERROR_DS_CONTROL_NOT_FOUND: WIN32_ERROR = 8258u32; +pub const ERROR_DS_COULDNT_CONTACT_FSMO: WIN32_ERROR = 8367u32; +pub const ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE: WIN32_ERROR = 8503u32; +pub const ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE: WIN32_ERROR = 8502u32; +pub const ERROR_DS_COULDNT_UPDATE_SPNS: WIN32_ERROR = 8525u32; +pub const ERROR_DS_COUNTING_AB_INDICES_FAILED: WIN32_ERROR = 8428u32; +pub const ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD: WIN32_ERROR = 8491u32; +pub const ERROR_DS_CROSS_DOM_MOVE_ERROR: WIN32_ERROR = 8216u32; +pub const ERROR_DS_CROSS_NC_DN_RENAME: WIN32_ERROR = 8368u32; +pub const ERROR_DS_CROSS_REF_BUSY: WIN32_ERROR = 8602u32; +pub const ERROR_DS_CROSS_REF_EXISTS: WIN32_ERROR = 8374u32; +pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE: WIN32_ERROR = 8495u32; +pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2: WIN32_ERROR = 8586u32; +pub const ERROR_DS_DATABASE_ERROR: WIN32_ERROR = 8409u32; +pub const ERROR_DS_DECODING_ERROR: WIN32_ERROR = 8253u32; +pub const ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED: WIN32_ERROR = 8536u32; +pub const ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST: WIN32_ERROR = 8535u32; +pub const ERROR_DS_DIFFERENT_REPL_EPOCHS: WIN32_ERROR = 8593u32; +pub const ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER: WIN32_ERROR = 8615u32; +pub const ERROR_DS_DISALLOWED_NC_REDIRECT: WIN32_ERROR = 8640u32; +pub const ERROR_DS_DNS_LOOKUP_FAILURE: WIN32_ERROR = 8524u32; +pub const ERROR_DS_DOMAIN_NAME_EXISTS_IN_FOREST: WIN32_ERROR = 8634u32; +pub const ERROR_DS_DOMAIN_RENAME_IN_PROGRESS: WIN32_ERROR = 8612u32; +pub const ERROR_DS_DOMAIN_VERSION_TOO_HIGH: WIN32_ERROR = 8564u32; +pub const ERROR_DS_DOMAIN_VERSION_TOO_LOW: WIN32_ERROR = 8566u32; +pub const ERROR_DS_DRA_ABANDON_SYNC: WIN32_ERROR = 8462u32; +pub const ERROR_DS_DRA_ACCESS_DENIED: WIN32_ERROR = 8453u32; +pub const ERROR_DS_DRA_BAD_DN: WIN32_ERROR = 8439u32; +pub const ERROR_DS_DRA_BAD_INSTANCE_TYPE: WIN32_ERROR = 8445u32; +pub const ERROR_DS_DRA_BAD_NC: WIN32_ERROR = 8440u32; +pub const ERROR_DS_DRA_BUSY: WIN32_ERROR = 8438u32; +pub const ERROR_DS_DRA_CONNECTION_FAILED: WIN32_ERROR = 8444u32; +pub const ERROR_DS_DRA_CORRUPT_UTD_VECTOR: WIN32_ERROR = 8629u32; +pub const ERROR_DS_DRA_DB_ERROR: WIN32_ERROR = 8451u32; +pub const ERROR_DS_DRA_DN_EXISTS: WIN32_ERROR = 8441u32; +pub const ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT: WIN32_ERROR = 8544u32; +pub const ERROR_DS_DRA_EXTN_CONNECTION_FAILED: WIN32_ERROR = 8466u32; +pub const ERROR_DS_DRA_GENERIC: WIN32_ERROR = 8436u32; +pub const ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET: WIN32_ERROR = 8464u32; +pub const ERROR_DS_DRA_INCONSISTENT_DIT: WIN32_ERROR = 8443u32; +pub const ERROR_DS_DRA_INTERNAL_ERROR: WIN32_ERROR = 8442u32; +pub const ERROR_DS_DRA_INVALID_PARAMETER: WIN32_ERROR = 8437u32; +pub const ERROR_DS_DRA_MAIL_PROBLEM: WIN32_ERROR = 8447u32; +pub const ERROR_DS_DRA_MISSING_KRBTGT_SECRET: WIN32_ERROR = 8633u32; +pub const ERROR_DS_DRA_MISSING_PARENT: WIN32_ERROR = 8460u32; +pub const ERROR_DS_DRA_NAME_COLLISION: WIN32_ERROR = 8458u32; +pub const ERROR_DS_DRA_NOT_SUPPORTED: WIN32_ERROR = 8454u32; +pub const ERROR_DS_DRA_NO_REPLICA: WIN32_ERROR = 8452u32; +pub const ERROR_DS_DRA_OBJ_IS_REP_SOURCE: WIN32_ERROR = 8450u32; +pub const ERROR_DS_DRA_OBJ_NC_MISMATCH: WIN32_ERROR = 8545u32; +pub const ERROR_DS_DRA_OUT_OF_MEM: WIN32_ERROR = 8446u32; +pub const ERROR_DS_DRA_OUT_SCHEDULE_WINDOW: WIN32_ERROR = 8617u32; +pub const ERROR_DS_DRA_PREEMPTED: WIN32_ERROR = 8461u32; +pub const ERROR_DS_DRA_RECYCLED_TARGET: WIN32_ERROR = 8639u32; +pub const ERROR_DS_DRA_REF_ALREADY_EXISTS: WIN32_ERROR = 8448u32; +pub const ERROR_DS_DRA_REF_NOT_FOUND: WIN32_ERROR = 8449u32; +pub const ERROR_DS_DRA_REPL_PENDING: WIN32_ERROR = 8477u32; +pub const ERROR_DS_DRA_RPC_CANCELLED: WIN32_ERROR = 8455u32; +pub const ERROR_DS_DRA_SCHEMA_CONFLICT: WIN32_ERROR = 8543u32; +pub const ERROR_DS_DRA_SCHEMA_INFO_SHIP: WIN32_ERROR = 8542u32; +pub const ERROR_DS_DRA_SCHEMA_MISMATCH: WIN32_ERROR = 8418u32; +pub const ERROR_DS_DRA_SECRETS_DENIED: WIN32_ERROR = 8630u32; +pub const ERROR_DS_DRA_SHUTDOWN: WIN32_ERROR = 8463u32; +pub const ERROR_DS_DRA_SINK_DISABLED: WIN32_ERROR = 8457u32; +pub const ERROR_DS_DRA_SOURCE_DISABLED: WIN32_ERROR = 8456u32; +pub const ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA: WIN32_ERROR = 8465u32; +pub const ERROR_DS_DRA_SOURCE_REINSTALLED: WIN32_ERROR = 8459u32; +pub const ERROR_DS_DRS_EXTENSIONS_CHANGED: WIN32_ERROR = 8594u32; +pub const ERROR_DS_DSA_MUST_BE_INT_MASTER: WIN32_ERROR = 8342u32; +pub const ERROR_DS_DST_DOMAIN_NOT_NATIVE: WIN32_ERROR = 8496u32; +pub const ERROR_DS_DST_NC_MISMATCH: WIN32_ERROR = 8486u32; +pub const ERROR_DS_DS_REQUIRED: WIN32_ERROR = 8478u32; +pub const ERROR_DS_DUPLICATE_ID_FOUND: WIN32_ERROR = 8605u32; +pub const ERROR_DS_DUP_LDAP_DISPLAY_NAME: WIN32_ERROR = 8382u32; +pub const ERROR_DS_DUP_LINK_ID: WIN32_ERROR = 8468u32; +pub const ERROR_DS_DUP_MAPI_ID: WIN32_ERROR = 8380u32; +pub const ERROR_DS_DUP_MSDS_INTID: WIN32_ERROR = 8597u32; +pub const ERROR_DS_DUP_OID: WIN32_ERROR = 8379u32; +pub const ERROR_DS_DUP_RDN: WIN32_ERROR = 8378u32; +pub const ERROR_DS_DUP_SCHEMA_ID_GUID: WIN32_ERROR = 8381u32; +pub const ERROR_DS_ENCODING_ERROR: WIN32_ERROR = 8252u32; +pub const ERROR_DS_EPOCH_MISMATCH: WIN32_ERROR = 8483u32; +pub const ERROR_DS_EXISTING_AD_CHILD_NC: WIN32_ERROR = 8613u32; +pub const ERROR_DS_EXISTS_IN_AUX_CLS: WIN32_ERROR = 8393u32; +pub const ERROR_DS_EXISTS_IN_MAY_HAVE: WIN32_ERROR = 8386u32; +pub const ERROR_DS_EXISTS_IN_MUST_HAVE: WIN32_ERROR = 8385u32; +pub const ERROR_DS_EXISTS_IN_POSS_SUP: WIN32_ERROR = 8395u32; +pub const ERROR_DS_EXISTS_IN_RDNATTID: WIN32_ERROR = 8598u32; +pub const ERROR_DS_EXISTS_IN_SUB_CLS: WIN32_ERROR = 8394u32; +pub const ERROR_DS_FILTER_UNKNOWN: WIN32_ERROR = 8254u32; +pub const ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS: WIN32_ERROR = 8555u32; +pub const ERROR_DS_FLAT_NAME_EXISTS_IN_FOREST: WIN32_ERROR = 8635u32; +pub const ERROR_DS_FOREST_VERSION_TOO_HIGH: WIN32_ERROR = 8563u32; +pub const ERROR_DS_FOREST_VERSION_TOO_LOW: WIN32_ERROR = 8565u32; +pub const ERROR_DS_GCVERIFY_ERROR: WIN32_ERROR = 8417u32; +pub const ERROR_DS_GC_NOT_AVAILABLE: WIN32_ERROR = 8217u32; +pub const ERROR_DS_GC_REQUIRED: WIN32_ERROR = 8547u32; +pub const ERROR_DS_GENERIC_ERROR: WIN32_ERROR = 8341u32; +pub const ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER: WIN32_ERROR = 8519u32; +pub const ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER: WIN32_ERROR = 8516u32; +pub const ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER: WIN32_ERROR = 8517u32; +pub const ERROR_DS_GOVERNSID_MISSING: WIN32_ERROR = 8410u32; +pub const ERROR_DS_GROUP_CONVERSION_ERROR: WIN32_ERROR = 8607u32; +pub const ERROR_DS_HAVE_PRIMARY_MEMBERS: WIN32_ERROR = 8521u32; +pub const ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED: WIN32_ERROR = 8429u32; +pub const ERROR_DS_HIERARCHY_TABLE_TOO_DEEP: WIN32_ERROR = 8628u32; +pub const ERROR_DS_HIGH_ADLDS_FFL: WIN32_ERROR = 8641u32; +pub const ERROR_DS_HIGH_DSA_VERSION: WIN32_ERROR = 8642u32; +pub const ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD: WIN32_ERROR = 8507u32; +pub const ERROR_DS_ILLEGAL_MOD_OPERATION: WIN32_ERROR = 8311u32; +pub const ERROR_DS_ILLEGAL_SUPERIOR: WIN32_ERROR = 8345u32; +pub const ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION: WIN32_ERROR = 8492u32; +pub const ERROR_DS_INAPPROPRIATE_AUTH: WIN32_ERROR = 8233u32; +pub const ERROR_DS_INAPPROPRIATE_MATCHING: WIN32_ERROR = 8238u32; +pub const ERROR_DS_INCOMPATIBLE_CONTROLS_USED: WIN32_ERROR = 8574u32; +pub const ERROR_DS_INCOMPATIBLE_VERSION: WIN32_ERROR = 8567u32; +pub const ERROR_DS_INCORRECT_ROLE_OWNER: WIN32_ERROR = 8210u32; +pub const ERROR_DS_INIT_FAILURE: WIN32_ERROR = 8532u32; +pub const ERROR_DS_INIT_FAILURE_CONSOLE: WIN32_ERROR = 8561u32; +pub const ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE: WIN32_ERROR = 8512u32; +pub const ERROR_DS_INSTALL_NO_SRC_SCH_VERSION: WIN32_ERROR = 8511u32; +pub const ERROR_DS_INSTALL_SCHEMA_MISMATCH: WIN32_ERROR = 8467u32; +pub const ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT: WIN32_ERROR = 8606u32; +pub const ERROR_DS_INSUFF_ACCESS_RIGHTS: WIN32_ERROR = 8344u32; +pub const ERROR_DS_INTERNAL_FAILURE: WIN32_ERROR = 8430u32; +pub const ERROR_DS_INVALID_ATTRIBUTE_SYNTAX: WIN32_ERROR = 8203u32; +pub const ERROR_DS_INVALID_DMD: WIN32_ERROR = 8360u32; +pub const ERROR_DS_INVALID_DN_SYNTAX: WIN32_ERROR = 8242u32; +pub const ERROR_DS_INVALID_GROUP_TYPE: WIN32_ERROR = 8513u32; +pub const ERROR_DS_INVALID_LDAP_DISPLAY_NAME: WIN32_ERROR = 8479u32; +pub const ERROR_DS_INVALID_NAME_FOR_SPN: WIN32_ERROR = 8554u32; +pub const ERROR_DS_INVALID_ROLE_OWNER: WIN32_ERROR = 8366u32; +pub const ERROR_DS_INVALID_SCRIPT: WIN32_ERROR = 8600u32; +pub const ERROR_DS_INVALID_SEARCH_FLAG: WIN32_ERROR = 8500u32; +pub const ERROR_DS_INVALID_SEARCH_FLAG_SUBTREE: WIN32_ERROR = 8626u32; +pub const ERROR_DS_INVALID_SEARCH_FLAG_TUPLE: WIN32_ERROR = 8627u32; +pub const ERROR_DS_IS_LEAF: WIN32_ERROR = 8243u32; +pub const ERROR_DS_KEY_NOT_UNIQUE: WIN32_ERROR = 8527u32; +pub const ERROR_DS_LDAP_SEND_QUEUE_FULL: WIN32_ERROR = 8616u32; +pub const ERROR_DS_LINK_ID_NOT_AVAILABLE: WIN32_ERROR = 8577u32; +pub const ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER: WIN32_ERROR = 8520u32; +pub const ERROR_DS_LOCAL_ERROR: WIN32_ERROR = 8251u32; +pub const ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY: WIN32_ERROR = 8548u32; +pub const ERROR_DS_LOOP_DETECT: WIN32_ERROR = 8246u32; +pub const ERROR_DS_LOW_ADLDS_FFL: WIN32_ERROR = 8643u32; +pub const ERROR_DS_LOW_DSA_VERSION: WIN32_ERROR = 8568u32; +pub const ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4: WIN32_ERROR = 8572u32; +pub const ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED: WIN32_ERROR = 8557u32; +pub const ERROR_DS_MAPI_ID_NOT_AVAILABLE: WIN32_ERROR = 8632u32; +pub const ERROR_DS_MASTERDSA_REQUIRED: WIN32_ERROR = 8314u32; +pub const ERROR_DS_MAX_OBJ_SIZE_EXCEEDED: WIN32_ERROR = 8304u32; +pub const ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY: WIN32_ERROR = 8201u32; +pub const ERROR_DS_MISSING_EXPECTED_ATT: WIN32_ERROR = 8411u32; +pub const ERROR_DS_MISSING_FOREST_TRUST: WIN32_ERROR = 8649u32; +pub const ERROR_DS_MISSING_FSMO_SETTINGS: WIN32_ERROR = 8434u32; +pub const ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER: WIN32_ERROR = 8497u32; +pub const ERROR_DS_MISSING_REQUIRED_ATT: WIN32_ERROR = 8316u32; +pub const ERROR_DS_MISSING_SUPREF: WIN32_ERROR = 8406u32; +pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG: WIN32_ERROR = 8581u32; +pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE: WIN32_ERROR = 8579u32; +pub const ERROR_DS_MODIFYDN_WRONG_GRANDPARENT: WIN32_ERROR = 8582u32; +pub const ERROR_DS_MUST_BE_RUN_ON_DST_DC: WIN32_ERROR = 8558u32; +pub const ERROR_DS_NAME_ERROR_DOMAIN_ONLY: WIN32_ERROR = 8473u32; +pub const ERROR_DS_NAME_ERROR_NOT_FOUND: WIN32_ERROR = 8470u32; +pub const ERROR_DS_NAME_ERROR_NOT_UNIQUE: WIN32_ERROR = 8471u32; +pub const ERROR_DS_NAME_ERROR_NO_MAPPING: WIN32_ERROR = 8472u32; +pub const ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING: WIN32_ERROR = 8474u32; +pub const ERROR_DS_NAME_ERROR_RESOLVING: WIN32_ERROR = 8469u32; +pub const ERROR_DS_NAME_ERROR_TRUST_REFERRAL: WIN32_ERROR = 8583u32; +pub const ERROR_DS_NAME_NOT_UNIQUE: WIN32_ERROR = 8571u32; +pub const ERROR_DS_NAME_REFERENCE_INVALID: WIN32_ERROR = 8373u32; +pub const ERROR_DS_NAME_TOO_LONG: WIN32_ERROR = 8348u32; +pub const ERROR_DS_NAME_TOO_MANY_PARTS: WIN32_ERROR = 8347u32; +pub const ERROR_DS_NAME_TYPE_UNKNOWN: WIN32_ERROR = 8351u32; +pub const ERROR_DS_NAME_UNPARSEABLE: WIN32_ERROR = 8350u32; +pub const ERROR_DS_NAME_VALUE_TOO_LONG: WIN32_ERROR = 8349u32; +pub const ERROR_DS_NAMING_MASTER_GC: WIN32_ERROR = 8523u32; +pub const ERROR_DS_NAMING_VIOLATION: WIN32_ERROR = 8247u32; +pub const ERROR_DS_NCNAME_MISSING_CR_REF: WIN32_ERROR = 8412u32; +pub const ERROR_DS_NCNAME_MUST_BE_NC: WIN32_ERROR = 8357u32; +pub const ERROR_DS_NC_MUST_HAVE_NC_PARENT: WIN32_ERROR = 8494u32; +pub const ERROR_DS_NC_STILL_HAS_DSAS: WIN32_ERROR = 8546u32; +pub const ERROR_DS_NONEXISTENT_MAY_HAVE: WIN32_ERROR = 8387u32; +pub const ERROR_DS_NONEXISTENT_MUST_HAVE: WIN32_ERROR = 8388u32; +pub const ERROR_DS_NONEXISTENT_POSS_SUP: WIN32_ERROR = 8390u32; +pub const ERROR_DS_NONSAFE_SCHEMA_CHANGE: WIN32_ERROR = 8508u32; +pub const ERROR_DS_NON_ASQ_SEARCH: WIN32_ERROR = 8624u32; +pub const ERROR_DS_NON_BASE_SEARCH: WIN32_ERROR = 8480u32; +pub const ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX: WIN32_ERROR = 8377u32; +pub const ERROR_DS_NOT_AN_OBJECT: WIN32_ERROR = 8352u32; +pub const ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC: WIN32_ERROR = 8487u32; +pub const ERROR_DS_NOT_CLOSEST: WIN32_ERROR = 8588u32; +pub const ERROR_DS_NOT_INSTALLED: WIN32_ERROR = 8200u32; +pub const ERROR_DS_NOT_ON_BACKLINK: WIN32_ERROR = 8362u32; +pub const ERROR_DS_NOT_SUPPORTED: WIN32_ERROR = 8256u32; +pub const ERROR_DS_NOT_SUPPORTED_SORT_ORDER: WIN32_ERROR = 8570u32; +pub const ERROR_DS_NO_ATTRIBUTE_OR_VALUE: WIN32_ERROR = 8202u32; +pub const ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN: WIN32_ERROR = 8569u32; +pub const ERROR_DS_NO_CHAINED_EVAL: WIN32_ERROR = 8328u32; +pub const ERROR_DS_NO_CHAINING: WIN32_ERROR = 8327u32; +pub const ERROR_DS_NO_CHECKPOINT_WITH_PDC: WIN32_ERROR = 8551u32; +pub const ERROR_DS_NO_CROSSREF_FOR_NC: WIN32_ERROR = 8363u32; +pub const ERROR_DS_NO_DELETED_NAME: WIN32_ERROR = 8355u32; +pub const ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS: WIN32_ERROR = 8549u32; +pub const ERROR_DS_NO_MORE_RIDS: WIN32_ERROR = 8209u32; +pub const ERROR_DS_NO_MSDS_INTID: WIN32_ERROR = 8596u32; +pub const ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN: WIN32_ERROR = 8514u32; +pub const ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN: WIN32_ERROR = 8515u32; +pub const ERROR_DS_NO_NTDSA_OBJECT: WIN32_ERROR = 8623u32; +pub const ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC: WIN32_ERROR = 8580u32; +pub const ERROR_DS_NO_PARENT_OBJECT: WIN32_ERROR = 8329u32; +pub const ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION: WIN32_ERROR = 8533u32; +pub const ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA: WIN32_ERROR = 8306u32; +pub const ERROR_DS_NO_REF_DOMAIN: WIN32_ERROR = 8575u32; +pub const ERROR_DS_NO_REQUESTED_ATTS_FOUND: WIN32_ERROR = 8308u32; +pub const ERROR_DS_NO_RESULTS_RETURNED: WIN32_ERROR = 8257u32; +pub const ERROR_DS_NO_RIDS_ALLOCATED: WIN32_ERROR = 8208u32; +pub const ERROR_DS_NO_SERVER_OBJECT: WIN32_ERROR = 8622u32; +pub const ERROR_DS_NO_SUCH_OBJECT: WIN32_ERROR = 8240u32; +pub const ERROR_DS_NO_TREE_DELETE_ABOVE_NC: WIN32_ERROR = 8501u32; +pub const ERROR_DS_NTDSCRIPT_PROCESS_ERROR: WIN32_ERROR = 8592u32; +pub const ERROR_DS_NTDSCRIPT_SYNTAX_ERROR: WIN32_ERROR = 8591u32; +pub const ERROR_DS_OBJECT_BEING_REMOVED: WIN32_ERROR = 8339u32; +pub const ERROR_DS_OBJECT_CLASS_REQUIRED: WIN32_ERROR = 8315u32; +pub const ERROR_DS_OBJECT_RESULTS_TOO_LARGE: WIN32_ERROR = 8248u32; +pub const ERROR_DS_OBJ_CLASS_NOT_DEFINED: WIN32_ERROR = 8371u32; +pub const ERROR_DS_OBJ_CLASS_NOT_SUBCLASS: WIN32_ERROR = 8372u32; +pub const ERROR_DS_OBJ_CLASS_VIOLATION: WIN32_ERROR = 8212u32; +pub const ERROR_DS_OBJ_GUID_EXISTS: WIN32_ERROR = 8361u32; +pub const ERROR_DS_OBJ_NOT_FOUND: WIN32_ERROR = 8333u32; +pub const ERROR_DS_OBJ_STRING_NAME_EXISTS: WIN32_ERROR = 8305u32; +pub const ERROR_DS_OBJ_TOO_LARGE: WIN32_ERROR = 8312u32; +pub const ERROR_DS_OFFSET_RANGE_ERROR: WIN32_ERROR = 8262u32; +pub const ERROR_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS: WIN32_ERROR = 8637u32; +pub const ERROR_DS_OID_NOT_FOUND: WIN32_ERROR = 8638u32; +pub const ERROR_DS_OPERATIONS_ERROR: WIN32_ERROR = 8224u32; +pub const ERROR_DS_OUT_OF_SCOPE: WIN32_ERROR = 8338u32; +pub const ERROR_DS_OUT_OF_VERSION_STORE: WIN32_ERROR = 8573u32; +pub const ERROR_DS_PARAM_ERROR: WIN32_ERROR = 8255u32; +pub const ERROR_DS_PARENT_IS_AN_ALIAS: WIN32_ERROR = 8330u32; +pub const ERROR_DS_PDC_OPERATION_IN_PROGRESS: WIN32_ERROR = 8490u32; +pub const ERROR_DS_PER_ATTRIBUTE_AUTHZ_FAILED_DURING_ADD: WIN32_ERROR = 8652u32; +pub const ERROR_DS_POLICY_NOT_KNOWN: WIN32_ERROR = 8618u32; +pub const ERROR_DS_PROTOCOL_ERROR: WIN32_ERROR = 8225u32; +pub const ERROR_DS_RANGE_CONSTRAINT: WIN32_ERROR = 8322u32; +pub const ERROR_DS_RDN_DOESNT_MATCH_SCHEMA: WIN32_ERROR = 8307u32; +pub const ERROR_DS_RECALCSCHEMA_FAILED: WIN32_ERROR = 8396u32; +pub const ERROR_DS_REFERRAL: WIN32_ERROR = 8235u32; +pub const ERROR_DS_REFERRAL_LIMIT_EXCEEDED: WIN32_ERROR = 8260u32; +pub const ERROR_DS_REFUSING_FSMO_ROLES: WIN32_ERROR = 8433u32; +pub const ERROR_DS_REMOTE_CROSSREF_OP_FAILED: WIN32_ERROR = 8601u32; +pub const ERROR_DS_REPLICATOR_ONLY: WIN32_ERROR = 8370u32; +pub const ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR: WIN32_ERROR = 8595u32; +pub const ERROR_DS_REPL_LIFETIME_EXCEEDED: WIN32_ERROR = 8614u32; +pub const ERROR_DS_RESERVED_LINK_ID: WIN32_ERROR = 8576u32; +pub const ERROR_DS_RESERVED_MAPI_ID: WIN32_ERROR = 8631u32; +pub const ERROR_DS_RIDMGR_DISABLED: WIN32_ERROR = 8263u32; +pub const ERROR_DS_RIDMGR_INIT_ERROR: WIN32_ERROR = 8211u32; +pub const ERROR_DS_ROLE_NOT_VERIFIED: WIN32_ERROR = 8610u32; +pub const ERROR_DS_ROOT_CANT_BE_SUBREF: WIN32_ERROR = 8326u32; +pub const ERROR_DS_ROOT_MUST_BE_NC: WIN32_ERROR = 8301u32; +pub const ERROR_DS_ROOT_REQUIRES_CLASS_TOP: WIN32_ERROR = 8432u32; +pub const ERROR_DS_SAM_INIT_FAILURE: WIN32_ERROR = 8504u32; +pub const ERROR_DS_SAM_INIT_FAILURE_CONSOLE: WIN32_ERROR = 8562u32; +pub const ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY: WIN32_ERROR = 8530u32; +pub const ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD: WIN32_ERROR = 8529u32; +pub const ERROR_DS_SCHEMA_ALLOC_FAILED: WIN32_ERROR = 8415u32; +pub const ERROR_DS_SCHEMA_NOT_LOADED: WIN32_ERROR = 8414u32; +pub const ERROR_DS_SCHEMA_UPDATE_DISALLOWED: WIN32_ERROR = 8509u32; +pub const ERROR_DS_SECURITY_CHECKING_ERROR: WIN32_ERROR = 8413u32; +pub const ERROR_DS_SECURITY_ILLEGAL_MODIFY: WIN32_ERROR = 8423u32; +pub const ERROR_DS_SEC_DESC_INVALID: WIN32_ERROR = 8354u32; +pub const ERROR_DS_SEC_DESC_TOO_SHORT: WIN32_ERROR = 8353u32; +pub const ERROR_DS_SEMANTIC_ATT_TEST: WIN32_ERROR = 8383u32; +pub const ERROR_DS_SENSITIVE_GROUP_VIOLATION: WIN32_ERROR = 8505u32; +pub const ERROR_DS_SERVER_DOWN: WIN32_ERROR = 8250u32; +pub const ERROR_DS_SHUTTING_DOWN: WIN32_ERROR = 8364u32; +pub const ERROR_DS_SINGLE_USER_MODE_FAILED: WIN32_ERROR = 8590u32; +pub const ERROR_DS_SINGLE_VALUE_CONSTRAINT: WIN32_ERROR = 8321u32; +pub const ERROR_DS_SIZELIMIT_EXCEEDED: WIN32_ERROR = 8227u32; +pub const ERROR_DS_SORT_CONTROL_MISSING: WIN32_ERROR = 8261u32; +pub const ERROR_DS_SOURCE_AUDITING_NOT_ENABLED: WIN32_ERROR = 8552u32; +pub const ERROR_DS_SOURCE_DOMAIN_IN_FOREST: WIN32_ERROR = 8534u32; +pub const ERROR_DS_SPN_VALUE_NOT_UNIQUE_IN_FOREST: WIN32_ERROR = 8647u32; +pub const ERROR_DS_SRC_AND_DST_NC_IDENTICAL: WIN32_ERROR = 8485u32; +pub const ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH: WIN32_ERROR = 8540u32; +pub const ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER: WIN32_ERROR = 8559u32; +pub const ERROR_DS_SRC_GUID_MISMATCH: WIN32_ERROR = 8488u32; +pub const ERROR_DS_SRC_NAME_MISMATCH: WIN32_ERROR = 8484u32; +pub const ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER: WIN32_ERROR = 8538u32; +pub const ERROR_DS_SRC_SID_EXISTS_IN_FOREST: WIN32_ERROR = 8539u32; +pub const ERROR_DS_STRING_SD_CONVERSION_FAILED: WIN32_ERROR = 8522u32; +pub const ERROR_DS_STRONG_AUTH_REQUIRED: WIN32_ERROR = 8232u32; +pub const ERROR_DS_SUBREF_MUST_HAVE_PARENT: WIN32_ERROR = 8356u32; +pub const ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD: WIN32_ERROR = 8376u32; +pub const ERROR_DS_SUB_CLS_TEST_FAIL: WIN32_ERROR = 8391u32; +pub const ERROR_DS_SYNTAX_MISMATCH: WIN32_ERROR = 8384u32; +pub const ERROR_DS_THREAD_LIMIT_EXCEEDED: WIN32_ERROR = 8587u32; +pub const ERROR_DS_TIMELIMIT_EXCEEDED: WIN32_ERROR = 8226u32; +pub const ERROR_DS_TREE_DELETE_NOT_FINISHED: WIN32_ERROR = 8397u32; +pub const ERROR_DS_UNABLE_TO_SURRENDER_ROLES: WIN32_ERROR = 8435u32; +pub const ERROR_DS_UNAVAILABLE: WIN32_ERROR = 8207u32; +pub const ERROR_DS_UNAVAILABLE_CRIT_EXTENSION: WIN32_ERROR = 8236u32; +pub const ERROR_DS_UNDELETE_SAM_VALIDATION_FAILED: WIN32_ERROR = 8645u32; +pub const ERROR_DS_UNICODEPWD_NOT_IN_QUOTES: WIN32_ERROR = 8556u32; +pub const ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER: WIN32_ERROR = 8518u32; +pub const ERROR_DS_UNKNOWN_ERROR: WIN32_ERROR = 8431u32; +pub const ERROR_DS_UNKNOWN_OPERATION: WIN32_ERROR = 8365u32; +pub const ERROR_DS_UNWILLING_TO_PERFORM: WIN32_ERROR = 8245u32; +pub const ERROR_DS_UPN_VALUE_NOT_UNIQUE_IN_FOREST: WIN32_ERROR = 8648u32; +pub const ERROR_DS_USER_BUFFER_TO_SMALL: WIN32_ERROR = 8309u32; +pub const ERROR_DS_VALUE_KEY_NOT_UNIQUE: WIN32_ERROR = 8650u32; +pub const ERROR_DS_VERSION_CHECK_FAILURE: WIN32_ERROR = 643u32; +pub const ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL: WIN32_ERROR = 8611u32; +pub const ERROR_DS_WRONG_LINKED_ATT_SYNTAX: WIN32_ERROR = 8528u32; +pub const ERROR_DS_WRONG_OM_OBJ_CLASS: WIN32_ERROR = 8476u32; +pub const ERROR_DUPLICATE_PRIVILEGES: WIN32_ERROR = 311u32; +pub const ERROR_DUPLICATE_SERVICE_NAME: WIN32_ERROR = 1078u32; +pub const ERROR_DUP_DOMAINNAME: WIN32_ERROR = 1221u32; +pub const ERROR_DUP_NAME: WIN32_ERROR = 52u32; +pub const ERROR_DYNAMIC_CODE_BLOCKED: WIN32_ERROR = 1655u32; +pub const ERROR_DYNLINK_FROM_INVALID_RING: WIN32_ERROR = 196u32; +pub const ERROR_EAS_DIDNT_FIT: WIN32_ERROR = 275u32; +pub const ERROR_EAS_NOT_SUPPORTED: WIN32_ERROR = 282u32; +pub const ERROR_EA_ACCESS_DENIED: WIN32_ERROR = 994u32; +pub const ERROR_EA_FILE_CORRUPT: WIN32_ERROR = 276u32; +pub const ERROR_EA_LIST_INCONSISTENT: WIN32_ERROR = 255u32; +pub const ERROR_EA_TABLE_FULL: WIN32_ERROR = 277u32; +pub const ERROR_EDP_DPL_POLICY_CANT_BE_SATISFIED: WIN32_ERROR = 357u32; +pub const ERROR_EDP_POLICY_DENIES_OPERATION: WIN32_ERROR = 356u32; +pub const ERROR_EFS_ALG_BLOB_TOO_BIG: WIN32_ERROR = 6013u32; +pub const ERROR_EFS_DISABLED: WIN32_ERROR = 6015u32; +pub const ERROR_EFS_SERVER_NOT_TRUSTED: WIN32_ERROR = 6011u32; +pub const ERROR_EFS_VERSION_NOT_SUPPORT: WIN32_ERROR = 6016u32; +pub const ERROR_ELEVATION_REQUIRED: WIN32_ERROR = 740u32; +pub const ERROR_ENCLAVE_FAILURE: WIN32_ERROR = 349u32; +pub const ERROR_ENCLAVE_NOT_TERMINATED: WIN32_ERROR = 814u32; +pub const ERROR_ENCLAVE_VIOLATION: WIN32_ERROR = 815u32; +pub const ERROR_ENCRYPTED_FILE_NOT_SUPPORTED: WIN32_ERROR = 489u32; +pub const ERROR_ENCRYPTED_IO_NOT_POSSIBLE: WIN32_ERROR = 808u32; +pub const ERROR_ENCRYPTING_METADATA_DISALLOWED: WIN32_ERROR = 431u32; +pub const ERROR_ENCRYPTION_DISABLED: WIN32_ERROR = 430u32; +pub const ERROR_ENCRYPTION_FAILED: WIN32_ERROR = 6000u32; +pub const ERROR_ENCRYPTION_POLICY_DENIES_OPERATION: WIN32_ERROR = 6022u32; +pub const ERROR_END_OF_MEDIA: WIN32_ERROR = 1100u32; +pub const ERROR_ENVVAR_NOT_FOUND: WIN32_ERROR = 203u32; +pub const ERROR_EOM_OVERFLOW: WIN32_ERROR = 1129u32; +pub const ERROR_ERRORS_ENCOUNTERED: WIN32_ERROR = 774u32; +pub const ERROR_EVALUATION_EXPIRATION: WIN32_ERROR = 622u32; +pub const ERROR_EVENTLOG_CANT_START: WIN32_ERROR = 1501u32; +pub const ERROR_EVENTLOG_FILE_CHANGED: WIN32_ERROR = 1503u32; +pub const ERROR_EVENTLOG_FILE_CORRUPT: WIN32_ERROR = 1500u32; +pub const ERROR_EVENT_DONE: WIN32_ERROR = 710u32; +pub const ERROR_EVENT_PENDING: WIN32_ERROR = 711u32; +pub const ERROR_EXCEPTION_IN_SERVICE: WIN32_ERROR = 1064u32; +pub const ERROR_EXCL_SEM_ALREADY_OWNED: WIN32_ERROR = 101u32; +pub const ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY: WIN32_ERROR = 217u32; +pub const ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY: WIN32_ERROR = 218u32; +pub const ERROR_EXE_MACHINE_TYPE_MISMATCH: WIN32_ERROR = 216u32; +pub const ERROR_EXE_MARKED_INVALID: WIN32_ERROR = 192u32; +pub const ERROR_EXTENDED_ERROR: WIN32_ERROR = 1208u32; +pub const ERROR_EXTERNAL_BACKING_PROVIDER_UNKNOWN: WIN32_ERROR = 343u32; +pub const ERROR_EXTERNAL_SYSKEY_NOT_SUPPORTED: WIN32_ERROR = 399u32; +pub const ERROR_EXTRANEOUS_INFORMATION: WIN32_ERROR = 677u32; +pub const ERROR_FAILED_DRIVER_ENTRY: WIN32_ERROR = 647u32; +pub const ERROR_FAILED_SERVICE_CONTROLLER_CONNECT: WIN32_ERROR = 1063u32; +pub const ERROR_FAIL_FAST_EXCEPTION: WIN32_ERROR = 1653u32; +pub const ERROR_FAIL_I24: WIN32_ERROR = 83u32; +pub const ERROR_FAIL_NOACTION_REBOOT: WIN32_ERROR = 350u32; +pub const ERROR_FAIL_RESTART: WIN32_ERROR = 352u32; +pub const ERROR_FAIL_SHUTDOWN: WIN32_ERROR = 351u32; +pub const ERROR_FATAL_APP_EXIT: WIN32_ERROR = 713u32; +pub const ERROR_FILEMARK_DETECTED: WIN32_ERROR = 1101u32; +pub const ERROR_FILENAME_EXCED_RANGE: WIN32_ERROR = 206u32; +pub const ERROR_FILE_CHECKED_OUT: WIN32_ERROR = 220u32; +pub const ERROR_FILE_CORRUPT: WIN32_ERROR = 1392u32; +pub const ERROR_FILE_ENCRYPTED: WIN32_ERROR = 6002u32; +pub const ERROR_FILE_EXISTS: WIN32_ERROR = 80u32; +pub const ERROR_FILE_HANDLE_REVOKED: WIN32_ERROR = 806u32; +pub const ERROR_FILE_INVALID: WIN32_ERROR = 1006u32; +pub const ERROR_FILE_LEVEL_TRIM_NOT_SUPPORTED: WIN32_ERROR = 326u32; +pub const ERROR_FILE_METADATA_OPTIMIZATION_IN_PROGRESS: WIN32_ERROR = 809u32; +pub const ERROR_FILE_NOT_ENCRYPTED: WIN32_ERROR = 6007u32; +pub const ERROR_FILE_NOT_FOUND: WIN32_ERROR = 2u32; +pub const ERROR_FILE_NOT_SUPPORTED: WIN32_ERROR = 425u32; +pub const ERROR_FILE_OFFLINE: WIN32_ERROR = 4350u32; +pub const ERROR_FILE_PROTECTED_UNDER_DPL: WIN32_ERROR = 406u32; +pub const ERROR_FILE_READ_ONLY: WIN32_ERROR = 6009u32; +pub const ERROR_FILE_SNAP_INVALID_PARAMETER: WIN32_ERROR = 440u32; +pub const ERROR_FILE_SNAP_IN_PROGRESS: WIN32_ERROR = 435u32; +pub const ERROR_FILE_SNAP_IO_NOT_COORDINATED: WIN32_ERROR = 438u32; +pub const ERROR_FILE_SNAP_MODIFY_NOT_SUPPORTED: WIN32_ERROR = 437u32; +pub const ERROR_FILE_SNAP_UNEXPECTED_ERROR: WIN32_ERROR = 439u32; +pub const ERROR_FILE_SNAP_USER_SECTION_NOT_SUPPORTED: WIN32_ERROR = 436u32; +pub const ERROR_FILE_SYSTEM_LIMITATION: WIN32_ERROR = 665u32; +pub const ERROR_FILE_SYSTEM_VIRTUALIZATION_BUSY: WIN32_ERROR = 371u32; +pub const ERROR_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION: WIN32_ERROR = 385u32; +pub const ERROR_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT: WIN32_ERROR = 370u32; +pub const ERROR_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN: WIN32_ERROR = 372u32; +pub const ERROR_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE: WIN32_ERROR = 369u32; +pub const ERROR_FILE_TOO_LARGE: WIN32_ERROR = 223u32; +pub const ERROR_FIRMWARE_UPDATED: WIN32_ERROR = 728u32; +pub const ERROR_FLOAT_MULTIPLE_FAULTS: WIN32_ERROR = 630u32; +pub const ERROR_FLOAT_MULTIPLE_TRAPS: WIN32_ERROR = 631u32; +pub const ERROR_FLOPPY_BAD_REGISTERS: WIN32_ERROR = 1125u32; +pub const ERROR_FLOPPY_ID_MARK_NOT_FOUND: WIN32_ERROR = 1122u32; +pub const ERROR_FLOPPY_UNKNOWN_ERROR: WIN32_ERROR = 1124u32; +pub const ERROR_FLOPPY_VOLUME: WIN32_ERROR = 584u32; +pub const ERROR_FLOPPY_WRONG_CYLINDER: WIN32_ERROR = 1123u32; +pub const ERROR_FORMS_AUTH_REQUIRED: WIN32_ERROR = 224u32; +pub const ERROR_FOUND_OUT_OF_SCOPE: WIN32_ERROR = 601u32; +pub const ERROR_FSFILTER_OP_COMPLETED_SUCCESSFULLY: WIN32_ERROR = 762u32; +pub const ERROR_FS_DRIVER_REQUIRED: WIN32_ERROR = 588u32; +pub const ERROR_FS_METADATA_INCONSISTENT: WIN32_ERROR = 510u32; +pub const ERROR_FT_DI_SCAN_REQUIRED: WIN32_ERROR = 339u32; +pub const ERROR_FT_READ_FAILURE: WIN32_ERROR = 415u32; +pub const ERROR_FT_READ_FROM_COPY_FAILURE: WIN32_ERROR = 818u32; +pub const ERROR_FT_READ_RECOVERY_FROM_BACKUP: WIN32_ERROR = 704u32; +pub const ERROR_FT_WRITE_FAILURE: WIN32_ERROR = 338u32; +pub const ERROR_FT_WRITE_RECOVERY: WIN32_ERROR = 705u32; +pub const ERROR_FULLSCREEN_MODE: WIN32_ERROR = 1007u32; +pub const ERROR_FUNCTION_FAILED: WIN32_ERROR = 1627u32; +pub const ERROR_FUNCTION_NOT_CALLED: WIN32_ERROR = 1626u32; +pub const ERROR_GDI_HANDLE_LEAK: WIN32_ERROR = 373u32; +pub const ERROR_GENERIC_NOT_MAPPED: WIN32_ERROR = 1360u32; +pub const ERROR_GEN_FAILURE: WIN32_ERROR = 31u32; +pub const ERROR_GLOBAL_ONLY_HOOK: WIN32_ERROR = 1429u32; +pub const ERROR_GRACEFUL_DISCONNECT: WIN32_ERROR = 1226u32; +pub const ERROR_GROUP_EXISTS: WIN32_ERROR = 1318u32; +pub const ERROR_GUID_SUBSTITUTION_MADE: WIN32_ERROR = 680u32; +pub const ERROR_HANDLES_CLOSED: WIN32_ERROR = 676u32; +pub const ERROR_HANDLE_DISK_FULL: WIN32_ERROR = 39u32; +pub const ERROR_HANDLE_EOF: WIN32_ERROR = 38u32; +pub const ERROR_HANDLE_REVOKED: WIN32_ERROR = 811u32; +pub const ERROR_HAS_SYSTEM_CRITICAL_FILES: WIN32_ERROR = 488u32; +pub const ERROR_HIBERNATED: WIN32_ERROR = 726u32; +pub const ERROR_HIBERNATION_FAILURE: WIN32_ERROR = 656u32; +pub const ERROR_HOOK_NEEDS_HMOD: WIN32_ERROR = 1428u32; +pub const ERROR_HOOK_NOT_INSTALLED: WIN32_ERROR = 1431u32; +pub const ERROR_HOOK_TYPE_NOT_ALLOWED: WIN32_ERROR = 1458u32; +pub const ERROR_HOST_DOWN: WIN32_ERROR = 1256u32; +pub const ERROR_HOST_UNREACHABLE: WIN32_ERROR = 1232u32; +pub const ERROR_HOTKEY_ALREADY_REGISTERED: WIN32_ERROR = 1409u32; +pub const ERROR_HOTKEY_NOT_REGISTERED: WIN32_ERROR = 1419u32; +pub const ERROR_HWNDS_HAVE_DIFF_PARENT: WIN32_ERROR = 1441u32; +pub const ERROR_ILLEGAL_CHARACTER: WIN32_ERROR = 582u32; +pub const ERROR_ILLEGAL_DLL_RELOCATION: WIN32_ERROR = 623u32; +pub const ERROR_ILLEGAL_ELEMENT_ADDRESS: WIN32_ERROR = 1162u32; +pub const ERROR_ILLEGAL_FLOAT_CONTEXT: WIN32_ERROR = 579u32; +pub const ERROR_ILL_FORMED_PASSWORD: WIN32_ERROR = 1324u32; +pub const ERROR_IMAGE_AT_DIFFERENT_BASE: WIN32_ERROR = 807u32; +pub const ERROR_IMAGE_MACHINE_TYPE_MISMATCH: WIN32_ERROR = 706u32; +pub const ERROR_IMAGE_MACHINE_TYPE_MISMATCH_EXE: WIN32_ERROR = 720u32; +pub const ERROR_IMAGE_NOT_AT_BASE: WIN32_ERROR = 700u32; +pub const ERROR_IMAGE_SUBSYSTEM_NOT_PRESENT: WIN32_ERROR = 308u32; +pub const ERROR_IMPLEMENTATION_LIMIT: WIN32_ERROR = 1292u32; +pub const ERROR_INCOMPATIBLE_SERVICE_PRIVILEGE: WIN32_ERROR = 1297u32; +pub const ERROR_INCOMPATIBLE_SERVICE_SID_TYPE: WIN32_ERROR = 1290u32; +pub const ERROR_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING: WIN32_ERROR = 304u32; +pub const ERROR_INCORRECT_ACCOUNT_TYPE: WIN32_ERROR = 8646u32; +pub const ERROR_INCORRECT_ADDRESS: WIN32_ERROR = 1241u32; +pub const ERROR_INCORRECT_SIZE: WIN32_ERROR = 1462u32; +pub const ERROR_INDEX_ABSENT: WIN32_ERROR = 1611u32; +pub const ERROR_INDEX_OUT_OF_BOUNDS: WIN32_ERROR = 474u32; +pub const ERROR_INFLOOP_IN_RELOC_CHAIN: WIN32_ERROR = 202u32; +pub const ERROR_INSTALL_ALREADY_RUNNING: WIN32_ERROR = 1618u32; +pub const ERROR_INSTALL_FAILURE: WIN32_ERROR = 1603u32; +pub const ERROR_INSTALL_LANGUAGE_UNSUPPORTED: WIN32_ERROR = 1623u32; +pub const ERROR_INSTALL_LOG_FAILURE: WIN32_ERROR = 1622u32; +pub const ERROR_INSTALL_NOTUSED: WIN32_ERROR = 1634u32; +pub const ERROR_INSTALL_PACKAGE_INVALID: WIN32_ERROR = 1620u32; +pub const ERROR_INSTALL_PACKAGE_OPEN_FAILED: WIN32_ERROR = 1619u32; +pub const ERROR_INSTALL_PACKAGE_REJECTED: WIN32_ERROR = 1625u32; +pub const ERROR_INSTALL_PACKAGE_VERSION: WIN32_ERROR = 1613u32; +pub const ERROR_INSTALL_PLATFORM_UNSUPPORTED: WIN32_ERROR = 1633u32; +pub const ERROR_INSTALL_REJECTED: WIN32_ERROR = 1654u32; +pub const ERROR_INSTALL_REMOTE_DISALLOWED: WIN32_ERROR = 1640u32; +pub const ERROR_INSTALL_REMOTE_PROHIBITED: WIN32_ERROR = 1645u32; +pub const ERROR_INSTALL_SERVICE_FAILURE: WIN32_ERROR = 1601u32; +pub const ERROR_INSTALL_SERVICE_SAFEBOOT: WIN32_ERROR = 1652u32; +pub const ERROR_INSTALL_SOURCE_ABSENT: WIN32_ERROR = 1612u32; +pub const ERROR_INSTALL_SUSPEND: WIN32_ERROR = 1604u32; +pub const ERROR_INSTALL_TEMP_UNWRITABLE: WIN32_ERROR = 1632u32; +pub const ERROR_INSTALL_TRANSFORM_FAILURE: WIN32_ERROR = 1624u32; +pub const ERROR_INSTALL_TRANSFORM_REJECTED: WIN32_ERROR = 1644u32; +pub const ERROR_INSTALL_UI_FAILURE: WIN32_ERROR = 1621u32; +pub const ERROR_INSTALL_USEREXIT: WIN32_ERROR = 1602u32; +pub const ERROR_INSTRUCTION_MISALIGNMENT: WIN32_ERROR = 549u32; +pub const ERROR_INSUFFICIENT_BUFFER: WIN32_ERROR = 122u32; +pub const ERROR_INSUFFICIENT_LOGON_INFO: WIN32_ERROR = 608u32; +pub const ERROR_INSUFFICIENT_POWER: WIN32_ERROR = 639u32; +pub const ERROR_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE: WIN32_ERROR = 781u32; +pub const ERROR_INSUFFICIENT_VIRTUAL_ADDR_RESOURCES: WIN32_ERROR = 473u32; +pub const ERROR_INTERMIXED_KERNEL_EA_OPERATION: WIN32_ERROR = 324u32; +pub const ERROR_INTERNAL_DB_CORRUPTION: WIN32_ERROR = 1358u32; +pub const ERROR_INTERNAL_DB_ERROR: WIN32_ERROR = 1383u32; +pub const ERROR_INTERNAL_ERROR: WIN32_ERROR = 1359u32; +pub const ERROR_INTERRUPT_STILL_CONNECTED: WIN32_ERROR = 764u32; +pub const ERROR_INTERRUPT_VECTOR_ALREADY_CONNECTED: WIN32_ERROR = 763u32; +pub const ERROR_INVALID_ACCEL_HANDLE: WIN32_ERROR = 1403u32; +pub const ERROR_INVALID_ACCESS: WIN32_ERROR = 12u32; +pub const ERROR_INVALID_ACCOUNT_NAME: WIN32_ERROR = 1315u32; +pub const ERROR_INVALID_ACE_CONDITION: WIN32_ERROR = 805u32; +pub const ERROR_INVALID_ACL: WIN32_ERROR = 1336u32; +pub const ERROR_INVALID_ADDRESS: WIN32_ERROR = 487u32; +pub const ERROR_INVALID_AT_INTERRUPT_TIME: WIN32_ERROR = 104u32; +pub const ERROR_INVALID_BLOCK: WIN32_ERROR = 9u32; +pub const ERROR_INVALID_BLOCK_LENGTH: WIN32_ERROR = 1106u32; +pub const ERROR_INVALID_CAP: WIN32_ERROR = 320u32; +pub const ERROR_INVALID_CATEGORY: WIN32_ERROR = 117u32; +pub const ERROR_INVALID_COMBOBOX_MESSAGE: WIN32_ERROR = 1422u32; +pub const ERROR_INVALID_COMMAND_LINE: WIN32_ERROR = 1639u32; +pub const ERROR_INVALID_COMPUTERNAME: WIN32_ERROR = 1210u32; +pub const ERROR_INVALID_CRUNTIME_PARAMETER: WIN32_ERROR = 1288u32; +pub const ERROR_INVALID_CURSOR_HANDLE: WIN32_ERROR = 1402u32; +pub const ERROR_INVALID_DATA: WIN32_ERROR = 13u32; +pub const ERROR_INVALID_DATATYPE: WIN32_ERROR = 1804u32; +pub const ERROR_INVALID_DEVICE_OBJECT_PARAMETER: WIN32_ERROR = 650u32; +pub const ERROR_INVALID_DLL: WIN32_ERROR = 1154u32; +pub const ERROR_INVALID_DOMAINNAME: WIN32_ERROR = 1212u32; +pub const ERROR_INVALID_DOMAIN_ROLE: WIN32_ERROR = 1354u32; +pub const ERROR_INVALID_DOMAIN_STATE: WIN32_ERROR = 1353u32; +pub const ERROR_INVALID_DRIVE: WIN32_ERROR = 15u32; +pub const ERROR_INVALID_DWP_HANDLE: WIN32_ERROR = 1405u32; +pub const ERROR_INVALID_EA_HANDLE: WIN32_ERROR = 278u32; +pub const ERROR_INVALID_EA_NAME: WIN32_ERROR = 254u32; +pub const ERROR_INVALID_EDIT_HEIGHT: WIN32_ERROR = 1424u32; +pub const ERROR_INVALID_ENVIRONMENT: WIN32_ERROR = 1805u32; +pub const ERROR_INVALID_EVENTNAME: WIN32_ERROR = 1211u32; +pub const ERROR_INVALID_EVENT_COUNT: WIN32_ERROR = 151u32; +pub const ERROR_INVALID_EXCEPTION_HANDLER: WIN32_ERROR = 310u32; +pub const ERROR_INVALID_EXE_SIGNATURE: WIN32_ERROR = 191u32; +pub const ERROR_INVALID_FIELD: WIN32_ERROR = 1616u32; +pub const ERROR_INVALID_FIELD_IN_PARAMETER_LIST: WIN32_ERROR = 328u32; +pub const ERROR_INVALID_FILTER_PROC: WIN32_ERROR = 1427u32; +pub const ERROR_INVALID_FLAGS: WIN32_ERROR = 1004u32; +pub const ERROR_INVALID_FLAG_NUMBER: WIN32_ERROR = 186u32; +pub const ERROR_INVALID_FORM_NAME: WIN32_ERROR = 1902u32; +pub const ERROR_INVALID_FORM_SIZE: WIN32_ERROR = 1903u32; +pub const ERROR_INVALID_FUNCTION: WIN32_ERROR = 1u32; +pub const ERROR_INVALID_GROUPNAME: WIN32_ERROR = 1209u32; +pub const ERROR_INVALID_GROUP_ATTRIBUTES: WIN32_ERROR = 1345u32; +pub const ERROR_INVALID_GW_COMMAND: WIN32_ERROR = 1443u32; +pub const ERROR_INVALID_HANDLE: WIN32_ERROR = 6u32; +pub const ERROR_INVALID_HANDLE_STATE: WIN32_ERROR = 1609u32; +pub const ERROR_INVALID_HOOK_FILTER: WIN32_ERROR = 1426u32; +pub const ERROR_INVALID_HOOK_HANDLE: WIN32_ERROR = 1404u32; +pub const ERROR_INVALID_HW_PROFILE: WIN32_ERROR = 619u32; +pub const ERROR_INVALID_ICON_HANDLE: WIN32_ERROR = 1414u32; +pub const ERROR_INVALID_ID_AUTHORITY: WIN32_ERROR = 1343u32; +pub const ERROR_INVALID_IMAGE_HASH: WIN32_ERROR = 577u32; +pub const ERROR_INVALID_IMPORT_OF_NON_DLL: WIN32_ERROR = 1276u32; +pub const ERROR_INVALID_INDEX: WIN32_ERROR = 1413u32; +pub const ERROR_INVALID_KERNEL_INFO_VERSION: WIN32_ERROR = 340u32; +pub const ERROR_INVALID_KEYBOARD_HANDLE: WIN32_ERROR = 1457u32; +pub const ERROR_INVALID_LABEL: WIN32_ERROR = 1299u32; +pub const ERROR_INVALID_LB_MESSAGE: WIN32_ERROR = 1432u32; +pub const ERROR_INVALID_LDT_DESCRIPTOR: WIN32_ERROR = 564u32; +pub const ERROR_INVALID_LDT_OFFSET: WIN32_ERROR = 563u32; +pub const ERROR_INVALID_LDT_SIZE: WIN32_ERROR = 561u32; +pub const ERROR_INVALID_LEVEL: WIN32_ERROR = 124u32; +pub const ERROR_INVALID_LIST_FORMAT: WIN32_ERROR = 153u32; +pub const ERROR_INVALID_LOCK_RANGE: WIN32_ERROR = 307u32; +pub const ERROR_INVALID_LOGON_HOURS: WIN32_ERROR = 1328u32; +pub const ERROR_INVALID_LOGON_TYPE: WIN32_ERROR = 1367u32; +pub const ERROR_INVALID_MEMBER: WIN32_ERROR = 1388u32; +pub const ERROR_INVALID_MENU_HANDLE: WIN32_ERROR = 1401u32; +pub const ERROR_INVALID_MESSAGE: WIN32_ERROR = 1002u32; +pub const ERROR_INVALID_MESSAGEDEST: WIN32_ERROR = 1218u32; +pub const ERROR_INVALID_MESSAGENAME: WIN32_ERROR = 1217u32; +pub const ERROR_INVALID_MINALLOCSIZE: WIN32_ERROR = 195u32; +pub const ERROR_INVALID_MODULETYPE: WIN32_ERROR = 190u32; +pub const ERROR_INVALID_MONITOR_HANDLE: WIN32_ERROR = 1461u32; +pub const ERROR_INVALID_MSGBOX_STYLE: WIN32_ERROR = 1438u32; +pub const ERROR_INVALID_NAME: WIN32_ERROR = 123u32; +pub const ERROR_INVALID_NETNAME: WIN32_ERROR = 1214u32; +pub const ERROR_INVALID_OPLOCK_PROTOCOL: WIN32_ERROR = 301u32; +pub const ERROR_INVALID_ORDINAL: WIN32_ERROR = 182u32; +pub const ERROR_INVALID_OWNER: WIN32_ERROR = 1307u32; +pub const ERROR_INVALID_PACKAGE_SID_LENGTH: WIN32_ERROR = 4253u32; +pub const ERROR_INVALID_PARAMETER: WIN32_ERROR = 87u32; +pub const ERROR_INVALID_PASSWORD: WIN32_ERROR = 86u32; +pub const ERROR_INVALID_PASSWORDNAME: WIN32_ERROR = 1216u32; +pub const ERROR_INVALID_PATCH_XML: WIN32_ERROR = 1650u32; +pub const ERROR_INVALID_PEP_INFO_VERSION: WIN32_ERROR = 341u32; +pub const ERROR_INVALID_PLUGPLAY_DEVICE_PATH: WIN32_ERROR = 620u32; +pub const ERROR_INVALID_PORT_ATTRIBUTES: WIN32_ERROR = 545u32; +pub const ERROR_INVALID_PRIMARY_GROUP: WIN32_ERROR = 1308u32; +pub const ERROR_INVALID_PRINTER_COMMAND: WIN32_ERROR = 1803u32; +pub const ERROR_INVALID_PRINTER_NAME: WIN32_ERROR = 1801u32; +pub const ERROR_INVALID_PRINTER_STATE: WIN32_ERROR = 1906u32; +pub const ERROR_INVALID_PRIORITY: WIN32_ERROR = 1800u32; +pub const ERROR_INVALID_QUOTA_LOWER: WIN32_ERROR = 547u32; +pub const ERROR_INVALID_REPARSE_DATA: WIN32_ERROR = 4392u32; +pub const ERROR_INVALID_SCROLLBAR_RANGE: WIN32_ERROR = 1448u32; +pub const ERROR_INVALID_SECURITY_DESCR: WIN32_ERROR = 1338u32; +pub const ERROR_INVALID_SEGDPL: WIN32_ERROR = 198u32; +pub const ERROR_INVALID_SEGMENT_NUMBER: WIN32_ERROR = 180u32; +pub const ERROR_INVALID_SEPARATOR_FILE: WIN32_ERROR = 1799u32; +pub const ERROR_INVALID_SERVER_STATE: WIN32_ERROR = 1352u32; +pub const ERROR_INVALID_SERVICENAME: WIN32_ERROR = 1213u32; +pub const ERROR_INVALID_SERVICE_ACCOUNT: WIN32_ERROR = 1057u32; +pub const ERROR_INVALID_SERVICE_CONTROL: WIN32_ERROR = 1052u32; +pub const ERROR_INVALID_SERVICE_LOCK: WIN32_ERROR = 1071u32; +pub const ERROR_INVALID_SHARENAME: WIN32_ERROR = 1215u32; +pub const ERROR_INVALID_SHOWWIN_COMMAND: WIN32_ERROR = 1449u32; +pub const ERROR_INVALID_SID: WIN32_ERROR = 1337u32; +pub const ERROR_INVALID_SIGNAL_NUMBER: WIN32_ERROR = 209u32; +pub const ERROR_INVALID_SPI_VALUE: WIN32_ERROR = 1439u32; +pub const ERROR_INVALID_STACKSEG: WIN32_ERROR = 189u32; +pub const ERROR_INVALID_STARTING_CODESEG: WIN32_ERROR = 188u32; +pub const ERROR_INVALID_SUB_AUTHORITY: WIN32_ERROR = 1335u32; +pub const ERROR_INVALID_TABLE: WIN32_ERROR = 1628u32; +pub const ERROR_INVALID_TARGET_HANDLE: WIN32_ERROR = 114u32; +pub const ERROR_INVALID_TASK_INDEX: WIN32_ERROR = 1551u32; +pub const ERROR_INVALID_TASK_NAME: WIN32_ERROR = 1550u32; +pub const ERROR_INVALID_THREAD_ID: WIN32_ERROR = 1444u32; +pub const ERROR_INVALID_TIME: WIN32_ERROR = 1901u32; +pub const ERROR_INVALID_TOKEN: WIN32_ERROR = 315u32; +pub const ERROR_INVALID_UNWIND_TARGET: WIN32_ERROR = 544u32; +pub const ERROR_INVALID_USER_BUFFER: WIN32_ERROR = 1784u32; +pub const ERROR_INVALID_USER_PRINCIPAL_NAME: WIN32_ERROR = 8636u32; +pub const ERROR_INVALID_VARIANT: WIN32_ERROR = 604u32; +pub const ERROR_INVALID_VERIFY_SWITCH: WIN32_ERROR = 118u32; +pub const ERROR_INVALID_WINDOW_HANDLE: WIN32_ERROR = 1400u32; +pub const ERROR_INVALID_WORKSTATION: WIN32_ERROR = 1329u32; +pub const ERROR_IOPL_NOT_ENABLED: WIN32_ERROR = 197u32; +pub const ERROR_IO_DEVICE: WIN32_ERROR = 1117u32; +pub const ERROR_IO_INCOMPLETE: WIN32_ERROR = 996u32; +pub const ERROR_IO_PENDING: WIN32_ERROR = 997u32; +pub const ERROR_IO_PRIVILEGE_FAILED: WIN32_ERROR = 571u32; +pub const ERROR_IO_REISSUE_AS_CACHED: WIN32_ERROR = 3950u32; +pub const ERROR_IPSEC_IKE_TIMED_OUT: WIN32_ERROR = 13805u32; +pub const ERROR_IP_ADDRESS_CONFLICT1: WIN32_ERROR = 611u32; +pub const ERROR_IP_ADDRESS_CONFLICT2: WIN32_ERROR = 612u32; +pub const ERROR_IRQ_BUSY: WIN32_ERROR = 1119u32; +pub const ERROR_IS_JOINED: WIN32_ERROR = 134u32; +pub const ERROR_IS_JOIN_PATH: WIN32_ERROR = 147u32; +pub const ERROR_IS_JOIN_TARGET: WIN32_ERROR = 133u32; +pub const ERROR_IS_SUBSTED: WIN32_ERROR = 135u32; +pub const ERROR_IS_SUBST_PATH: WIN32_ERROR = 146u32; +pub const ERROR_IS_SUBST_TARGET: WIN32_ERROR = 149u32; +pub const ERROR_ITERATED_DATA_EXCEEDS_64k: WIN32_ERROR = 194u32; +pub const ERROR_JOB_NO_CONTAINER: WIN32_ERROR = 1505u32; +pub const ERROR_JOIN_TO_JOIN: WIN32_ERROR = 138u32; +pub const ERROR_JOIN_TO_SUBST: WIN32_ERROR = 140u32; +pub const ERROR_JOURNAL_DELETE_IN_PROGRESS: WIN32_ERROR = 1178u32; +pub const ERROR_JOURNAL_ENTRY_DELETED: WIN32_ERROR = 1181u32; +pub const ERROR_JOURNAL_HOOK_SET: WIN32_ERROR = 1430u32; +pub const ERROR_JOURNAL_NOT_ACTIVE: WIN32_ERROR = 1179u32; +pub const ERROR_KERNEL_APC: WIN32_ERROR = 738u32; +pub const ERROR_KEY_DELETED: WIN32_ERROR = 1018u32; +pub const ERROR_KEY_HAS_CHILDREN: WIN32_ERROR = 1020u32; +pub const ERROR_KM_DRIVER_BLOCKED: WIN32_ERROR = 1930u32; +pub const ERROR_LABEL_TOO_LONG: WIN32_ERROR = 154u32; +pub const ERROR_LAST_ADMIN: WIN32_ERROR = 1322u32; +pub const ERROR_LB_WITHOUT_TABSTOPS: WIN32_ERROR = 1434u32; +pub const ERROR_LICENSE_QUOTA_EXCEEDED: WIN32_ERROR = 1395u32; +pub const ERROR_LINUX_SUBSYSTEM_NOT_PRESENT: WIN32_ERROR = 414u32; +pub const ERROR_LINUX_SUBSYSTEM_UPDATE_REQUIRED: WIN32_ERROR = 444u32; +pub const ERROR_LISTBOX_ID_NOT_FOUND: WIN32_ERROR = 1416u32; +pub const ERROR_LM_CROSS_ENCRYPTION_REQUIRED: WIN32_ERROR = 1390u32; +pub const ERROR_LOCAL_POLICY_MODIFICATION_NOT_SUPPORTED: WIN32_ERROR = 8653u32; +pub const ERROR_LOCAL_USER_SESSION_KEY: WIN32_ERROR = 1303u32; +pub const ERROR_LOCKED: WIN32_ERROR = 212u32; +pub const ERROR_LOCK_FAILED: WIN32_ERROR = 167u32; +pub const ERROR_LOCK_VIOLATION: WIN32_ERROR = 33u32; +pub const ERROR_LOGIN_TIME_RESTRICTION: WIN32_ERROR = 1239u32; +pub const ERROR_LOGIN_WKSTA_RESTRICTION: WIN32_ERROR = 1240u32; +pub const ERROR_LOGON_FAILURE: WIN32_ERROR = 1326u32; +pub const ERROR_LOGON_NOT_GRANTED: WIN32_ERROR = 1380u32; +pub const ERROR_LOGON_SERVER_CONFLICT: WIN32_ERROR = 568u32; +pub const ERROR_LOGON_SESSION_COLLISION: WIN32_ERROR = 1366u32; +pub const ERROR_LOGON_SESSION_EXISTS: WIN32_ERROR = 1363u32; +pub const ERROR_LOGON_TYPE_NOT_GRANTED: WIN32_ERROR = 1385u32; +pub const ERROR_LOG_FILE_FULL: WIN32_ERROR = 1502u32; +pub const ERROR_LOG_HARD_ERROR: WIN32_ERROR = 718u32; +pub const ERROR_LONGJUMP: WIN32_ERROR = 682u32; +pub const ERROR_LOST_MODE_LOGON_RESTRICTION: WIN32_ERROR = 1939u32; +pub const ERROR_LOST_WRITEBEHIND_DATA: WIN32_ERROR = 596u32; +pub const ERROR_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR: WIN32_ERROR = 790u32; +pub const ERROR_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED: WIN32_ERROR = 788u32; +pub const ERROR_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR: WIN32_ERROR = 789u32; +pub const ERROR_LUIDS_EXHAUSTED: WIN32_ERROR = 1334u32; +pub const ERROR_MACHINE_LOCKED: WIN32_ERROR = 1271u32; +pub const ERROR_MAGAZINE_NOT_PRESENT: WIN32_ERROR = 1163u32; +pub const ERROR_MAPPED_ALIGNMENT: WIN32_ERROR = 1132u32; +pub const ERROR_MARKED_TO_DISALLOW_WRITES: WIN32_ERROR = 348u32; +pub const ERROR_MARSHALL_OVERFLOW: WIN32_ERROR = 603u32; +pub const ERROR_MAX_SESSIONS_REACHED: WIN32_ERROR = 353u32; +pub const ERROR_MAX_THRDS_REACHED: WIN32_ERROR = 164u32; +pub const ERROR_MCA_EXCEPTION: WIN32_ERROR = 784u32; +pub const ERROR_MCA_OCCURED: WIN32_ERROR = 651u32; +pub const ERROR_MEDIA_CHANGED: WIN32_ERROR = 1110u32; +pub const ERROR_MEDIA_CHECK: WIN32_ERROR = 679u32; +pub const ERROR_MEMBERS_PRIMARY_GROUP: WIN32_ERROR = 1374u32; +pub const ERROR_MEMBER_IN_ALIAS: WIN32_ERROR = 1378u32; +pub const ERROR_MEMBER_IN_GROUP: WIN32_ERROR = 1320u32; +pub const ERROR_MEMBER_NOT_IN_ALIAS: WIN32_ERROR = 1377u32; +pub const ERROR_MEMBER_NOT_IN_GROUP: WIN32_ERROR = 1321u32; +pub const ERROR_MEMORY_HARDWARE: WIN32_ERROR = 779u32; +pub const ERROR_MENU_ITEM_NOT_FOUND: WIN32_ERROR = 1456u32; +pub const ERROR_MESSAGE_SYNC_ONLY: WIN32_ERROR = 1159u32; +pub const ERROR_META_EXPANSION_TOO_LONG: WIN32_ERROR = 208u32; +pub const ERROR_MISSING_SYSTEMFILE: WIN32_ERROR = 573u32; +pub const ERROR_MOD_NOT_FOUND: WIN32_ERROR = 126u32; +pub const ERROR_MORE_DATA: WIN32_ERROR = 234u32; +pub const ERROR_MORE_WRITES: WIN32_ERROR = 1120u32; +pub const ERROR_MOUNT_POINT_NOT_RESOLVED: WIN32_ERROR = 649u32; +pub const ERROR_MP_PROCESSOR_MISMATCH: WIN32_ERROR = 725u32; +pub const ERROR_MR_MID_NOT_FOUND: WIN32_ERROR = 317u32; +pub const ERROR_MULTIPLE_FAULT_VIOLATION: WIN32_ERROR = 640u32; +pub const ERROR_MUTANT_LIMIT_EXCEEDED: WIN32_ERROR = 587u32; +pub const ERROR_MUTUAL_AUTH_FAILED: WIN32_ERROR = 1397u32; +pub const ERROR_NEGATIVE_SEEK: WIN32_ERROR = 131u32; +pub const ERROR_NESTING_NOT_ALLOWED: WIN32_ERROR = 215u32; +pub const ERROR_NETLOGON_NOT_STARTED: WIN32_ERROR = 1792u32; +pub const ERROR_NETNAME_DELETED: WIN32_ERROR = 64u32; +pub const ERROR_NETWORK_ACCESS_DENIED: WIN32_ERROR = 65u32; +pub const ERROR_NETWORK_ACCESS_DENIED_EDP: WIN32_ERROR = 354u32; +pub const ERROR_NETWORK_BUSY: WIN32_ERROR = 54u32; +pub const ERROR_NETWORK_UNREACHABLE: WIN32_ERROR = 1231u32; +pub const ERROR_NET_OPEN_FAILED: WIN32_ERROR = 570u32; +pub const ERROR_NET_WRITE_FAULT: WIN32_ERROR = 88u32; +pub const ERROR_NOACCESS: WIN32_ERROR = 998u32; +pub const ERROR_NOINTERFACE: WIN32_ERROR = 632u32; +pub const ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT: WIN32_ERROR = 1807u32; +pub const ERROR_NOLOGON_SERVER_TRUST_ACCOUNT: WIN32_ERROR = 1809u32; +pub const ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT: WIN32_ERROR = 1808u32; +pub const ERROR_NONE_MAPPED: WIN32_ERROR = 1332u32; +pub const ERROR_NONPAGED_SYSTEM_RESOURCES: WIN32_ERROR = 1451u32; +pub const ERROR_NON_ACCOUNT_SID: WIN32_ERROR = 1257u32; +pub const ERROR_NON_DOMAIN_SID: WIN32_ERROR = 1258u32; +pub const ERROR_NON_MDICHILD_WINDOW: WIN32_ERROR = 1445u32; +pub const ERROR_NOTHING_TO_TERMINATE: WIN32_ERROR = 758u32; +pub const ERROR_NOTIFICATION_GUID_ALREADY_DEFINED: WIN32_ERROR = 309u32; +pub const ERROR_NOTIFY_CLEANUP: WIN32_ERROR = 745u32; +pub const ERROR_NOTIFY_ENUM_DIR: WIN32_ERROR = 1022u32; +pub const ERROR_NOT_ALLOWED_ON_SYSTEM_FILE: WIN32_ERROR = 313u32; +pub const ERROR_NOT_ALL_ASSIGNED: WIN32_ERROR = 1300u32; +pub const ERROR_NOT_APPCONTAINER: WIN32_ERROR = 4250u32; +pub const ERROR_NOT_AUTHENTICATED: WIN32_ERROR = 1244u32; +pub const ERROR_NOT_A_CLOUD_FILE: WIN32_ERROR = 376u32; +pub const ERROR_NOT_A_CLOUD_SYNC_ROOT: WIN32_ERROR = 405u32; +pub const ERROR_NOT_A_DAX_VOLUME: WIN32_ERROR = 420u32; +pub const ERROR_NOT_A_REPARSE_POINT: WIN32_ERROR = 4390u32; +pub const ERROR_NOT_CAPABLE: WIN32_ERROR = 775u32; +pub const ERROR_NOT_CHILD_WINDOW: WIN32_ERROR = 1442u32; +pub const ERROR_NOT_CONNECTED: WIN32_ERROR = 2250u32; +pub const ERROR_NOT_CONTAINER: WIN32_ERROR = 1207u32; +pub const ERROR_NOT_DAX_MAPPABLE: WIN32_ERROR = 421u32; +pub const ERROR_NOT_DOS_DISK: WIN32_ERROR = 26u32; +pub const ERROR_NOT_ENOUGH_MEMORY: WIN32_ERROR = 8u32; +pub const ERROR_NOT_ENOUGH_QUOTA: WIN32_ERROR = 1816u32; +pub const ERROR_NOT_ENOUGH_SERVER_MEMORY: WIN32_ERROR = 1130u32; +pub const ERROR_NOT_EXPORT_FORMAT: WIN32_ERROR = 6008u32; +pub const ERROR_NOT_FOUND: WIN32_ERROR = 1168u32; +pub const ERROR_NOT_GUI_PROCESS: WIN32_ERROR = 1471u32; +pub const ERROR_NOT_JOINED: WIN32_ERROR = 136u32; +pub const ERROR_NOT_LOCKED: WIN32_ERROR = 158u32; +pub const ERROR_NOT_LOGGED_ON: WIN32_ERROR = 1245u32; +pub const ERROR_NOT_LOGON_PROCESS: WIN32_ERROR = 1362u32; +pub const ERROR_NOT_OWNER: WIN32_ERROR = 288u32; +pub const ERROR_NOT_READY: WIN32_ERROR = 21u32; +pub const ERROR_NOT_READ_FROM_COPY: WIN32_ERROR = 337u32; +pub const ERROR_NOT_REDUNDANT_STORAGE: WIN32_ERROR = 333u32; +pub const ERROR_NOT_REGISTRY_FILE: WIN32_ERROR = 1017u32; +pub const ERROR_NOT_SAFEBOOT_SERVICE: WIN32_ERROR = 1084u32; +pub const ERROR_NOT_SAFE_MODE_DRIVER: WIN32_ERROR = 646u32; +pub const ERROR_NOT_SAME_DEVICE: WIN32_ERROR = 17u32; +pub const ERROR_NOT_SAME_OBJECT: WIN32_ERROR = 1656u32; +pub const ERROR_NOT_SUBSTED: WIN32_ERROR = 137u32; +pub const ERROR_NOT_SUPPORTED: WIN32_ERROR = 50u32; +pub const ERROR_NOT_SUPPORTED_IN_APPCONTAINER: WIN32_ERROR = 4252u32; +pub const ERROR_NOT_SUPPORTED_ON_DAX: WIN32_ERROR = 360u32; +pub const ERROR_NOT_SUPPORTED_ON_SBS: WIN32_ERROR = 1254u32; +pub const ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER: WIN32_ERROR = 8584u32; +pub const ERROR_NOT_SUPPORTED_WITH_AUDITING: WIN32_ERROR = 499u32; +pub const ERROR_NOT_SUPPORTED_WITH_BTT: WIN32_ERROR = 429u32; +pub const ERROR_NOT_SUPPORTED_WITH_BYPASSIO: WIN32_ERROR = 493u32; +pub const ERROR_NOT_SUPPORTED_WITH_CACHED_HANDLE: WIN32_ERROR = 509u32; +pub const ERROR_NOT_SUPPORTED_WITH_COMPRESSION: WIN32_ERROR = 496u32; +pub const ERROR_NOT_SUPPORTED_WITH_DEDUPLICATION: WIN32_ERROR = 498u32; +pub const ERROR_NOT_SUPPORTED_WITH_ENCRYPTION: WIN32_ERROR = 495u32; +pub const ERROR_NOT_SUPPORTED_WITH_MONITORING: WIN32_ERROR = 503u32; +pub const ERROR_NOT_SUPPORTED_WITH_REPLICATION: WIN32_ERROR = 497u32; +pub const ERROR_NOT_SUPPORTED_WITH_SNAPSHOT: WIN32_ERROR = 504u32; +pub const ERROR_NOT_SUPPORTED_WITH_VIRTUALIZATION: WIN32_ERROR = 505u32; +pub const ERROR_NOT_TINY_STREAM: WIN32_ERROR = 598u32; +pub const ERROR_NO_ACE_CONDITION: WIN32_ERROR = 804u32; +pub const ERROR_NO_ASSOCIATION: WIN32_ERROR = 1155u32; +pub const ERROR_NO_BYPASSIO_DRIVER_SUPPORT: WIN32_ERROR = 494u32; +pub const ERROR_NO_CALLBACK_ACTIVE: WIN32_ERROR = 614u32; +pub const ERROR_NO_DATA: WIN32_ERROR = 232u32; +pub const ERROR_NO_DATA_DETECTED: WIN32_ERROR = 1104u32; +pub const ERROR_NO_EFS: WIN32_ERROR = 6004u32; +pub const ERROR_NO_EVENT_PAIR: WIN32_ERROR = 580u32; +pub const ERROR_NO_GUID_TRANSLATION: WIN32_ERROR = 560u32; +pub const ERROR_NO_IMPERSONATION_TOKEN: WIN32_ERROR = 1309u32; +pub const ERROR_NO_INHERITANCE: WIN32_ERROR = 1391u32; +pub const ERROR_NO_LOGON_SERVERS: WIN32_ERROR = 1311u32; +pub const ERROR_NO_LOG_SPACE: WIN32_ERROR = 1019u32; +pub const ERROR_NO_MATCH: WIN32_ERROR = 1169u32; +pub const ERROR_NO_MEDIA_IN_DRIVE: WIN32_ERROR = 1112u32; +pub const ERROR_NO_MORE_DEVICES: WIN32_ERROR = 1248u32; +pub const ERROR_NO_MORE_FILES: WIN32_ERROR = 18u32; +pub const ERROR_NO_MORE_ITEMS: WIN32_ERROR = 259u32; +pub const ERROR_NO_MORE_MATCHES: WIN32_ERROR = 626u32; +pub const ERROR_NO_MORE_SEARCH_HANDLES: WIN32_ERROR = 113u32; +pub const ERROR_NO_MORE_USER_HANDLES: WIN32_ERROR = 1158u32; +pub const ERROR_NO_NETWORK: WIN32_ERROR = 1222u32; +pub const ERROR_NO_NET_OR_BAD_PATH: WIN32_ERROR = 1203u32; +pub const ERROR_NO_NVRAM_RESOURCES: WIN32_ERROR = 1470u32; +pub const ERROR_NO_PAGEFILE: WIN32_ERROR = 578u32; +pub const ERROR_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND: WIN32_ERROR = 408u32; +pub const ERROR_NO_PROC_SLOTS: WIN32_ERROR = 89u32; +pub const ERROR_NO_PROMOTION_ACTIVE: WIN32_ERROR = 8222u32; +pub const ERROR_NO_QUOTAS_FOR_ACCOUNT: WIN32_ERROR = 1302u32; +pub const ERROR_NO_RANGES_PROCESSED: WIN32_ERROR = 312u32; +pub const ERROR_NO_RECOVERY_POLICY: WIN32_ERROR = 6003u32; +pub const ERROR_NO_RECOVERY_PROGRAM: WIN32_ERROR = 1082u32; +pub const ERROR_NO_SCROLLBARS: WIN32_ERROR = 1447u32; +pub const ERROR_NO_SECRETS: WIN32_ERROR = 8620u32; +pub const ERROR_NO_SECURITY_ON_OBJECT: WIN32_ERROR = 1350u32; +pub const ERROR_NO_SHUTDOWN_IN_PROGRESS: WIN32_ERROR = 1116u32; +pub const ERROR_NO_SIGNAL_SENT: WIN32_ERROR = 205u32; +pub const ERROR_NO_SITENAME: WIN32_ERROR = 1919u32; +pub const ERROR_NO_SITE_SETTINGS_OBJECT: WIN32_ERROR = 8619u32; +pub const ERROR_NO_SPOOL_SPACE: WIN32_ERROR = 62u32; +pub const ERROR_NO_SUCH_ALIAS: WIN32_ERROR = 1376u32; +pub const ERROR_NO_SUCH_DEVICE: WIN32_ERROR = 433u32; +pub const ERROR_NO_SUCH_DOMAIN: WIN32_ERROR = 1355u32; +pub const ERROR_NO_SUCH_GROUP: WIN32_ERROR = 1319u32; +pub const ERROR_NO_SUCH_LOGON_SESSION: WIN32_ERROR = 1312u32; +pub const ERROR_NO_SUCH_MEMBER: WIN32_ERROR = 1387u32; +pub const ERROR_NO_SUCH_PACKAGE: WIN32_ERROR = 1364u32; +pub const ERROR_NO_SUCH_PRIVILEGE: WIN32_ERROR = 1313u32; +pub const ERROR_NO_SUCH_SITE: WIN32_ERROR = 1249u32; +pub const ERROR_NO_SUCH_USER: WIN32_ERROR = 1317u32; +pub const ERROR_NO_SYSTEM_MENU: WIN32_ERROR = 1437u32; +pub const ERROR_NO_SYSTEM_RESOURCES: WIN32_ERROR = 1450u32; +pub const ERROR_NO_TASK_QUEUE: WIN32_ERROR = 427u32; +pub const ERROR_NO_TOKEN: WIN32_ERROR = 1008u32; +pub const ERROR_NO_TRACKING_SERVICE: WIN32_ERROR = 1172u32; +pub const ERROR_NO_TRUST_LSA_SECRET: WIN32_ERROR = 1786u32; +pub const ERROR_NO_TRUST_SAM_ACCOUNT: WIN32_ERROR = 1787u32; +pub const ERROR_NO_UNICODE_TRANSLATION: WIN32_ERROR = 1113u32; +pub const ERROR_NO_USER_KEYS: WIN32_ERROR = 6006u32; +pub const ERROR_NO_USER_SESSION_KEY: WIN32_ERROR = 1394u32; +pub const ERROR_NO_VOLUME_ID: WIN32_ERROR = 1173u32; +pub const ERROR_NO_VOLUME_LABEL: WIN32_ERROR = 125u32; +pub const ERROR_NO_WILDCARD_CHARACTERS: WIN32_ERROR = 1417u32; +pub const ERROR_NO_WORK_DONE: WIN32_ERROR = 235u32; +pub const ERROR_NO_WRITABLE_DC_FOUND: WIN32_ERROR = 8621u32; +pub const ERROR_NO_YIELD_PERFORMED: WIN32_ERROR = 721u32; +pub const ERROR_NTLM_BLOCKED: WIN32_ERROR = 1937u32; +pub const ERROR_NT_CROSS_ENCRYPTION_REQUIRED: WIN32_ERROR = 1386u32; +pub const ERROR_NULL_LM_PASSWORD: WIN32_ERROR = 1304u32; +pub const ERROR_OBJECT_IS_IMMUTABLE: WIN32_ERROR = 4449u32; +pub const ERROR_OBJECT_NAME_EXISTS: WIN32_ERROR = 698u32; +pub const ERROR_OBJECT_NOT_EXTERNALLY_BACKED: WIN32_ERROR = 342u32; +pub const ERROR_OFFLOAD_READ_FILE_NOT_SUPPORTED: WIN32_ERROR = 4442u32; +pub const ERROR_OFFLOAD_READ_FLT_NOT_SUPPORTED: WIN32_ERROR = 4440u32; +pub const ERROR_OFFLOAD_WRITE_FILE_NOT_SUPPORTED: WIN32_ERROR = 4443u32; +pub const ERROR_OFFLOAD_WRITE_FLT_NOT_SUPPORTED: WIN32_ERROR = 4441u32; +pub const ERROR_OFFSET_ALIGNMENT_VIOLATION: WIN32_ERROR = 327u32; +pub const ERROR_OLD_WIN_VERSION: WIN32_ERROR = 1150u32; +pub const ERROR_ONLY_IF_CONNECTED: WIN32_ERROR = 1251u32; +pub const ERROR_OPEN_FAILED: WIN32_ERROR = 110u32; +pub const ERROR_OPEN_FILES: WIN32_ERROR = 2401u32; +pub const ERROR_OPERATION_ABORTED: WIN32_ERROR = 995u32; +pub const ERROR_OPERATION_IN_PROGRESS: WIN32_ERROR = 329u32; +pub const ERROR_OPLOCK_BREAK_IN_PROGRESS: WIN32_ERROR = 742u32; +pub const ERROR_OPLOCK_HANDLE_CLOSED: WIN32_ERROR = 803u32; +pub const ERROR_OPLOCK_NOT_GRANTED: WIN32_ERROR = 300u32; +pub const ERROR_OPLOCK_SWITCHED_TO_NEW_HANDLE: WIN32_ERROR = 800u32; +pub const ERROR_ORPHAN_NAME_EXHAUSTED: WIN32_ERROR = 799u32; +pub const ERROR_OUTOFMEMORY: WIN32_ERROR = 14u32; +pub const ERROR_OUT_OF_PAPER: WIN32_ERROR = 28u32; +pub const ERROR_OUT_OF_STRUCTURES: WIN32_ERROR = 84u32; +pub const ERROR_OVERRIDE_NOCHANGES: WIN32_ERROR = 1252u32; +pub const ERROR_PAGED_SYSTEM_RESOURCES: WIN32_ERROR = 1452u32; +pub const ERROR_PAGEFILE_CREATE_FAILED: WIN32_ERROR = 576u32; +pub const ERROR_PAGEFILE_NOT_SUPPORTED: WIN32_ERROR = 491u32; +pub const ERROR_PAGEFILE_QUOTA: WIN32_ERROR = 1454u32; +pub const ERROR_PAGEFILE_QUOTA_EXCEEDED: WIN32_ERROR = 567u32; +pub const ERROR_PAGE_FAULT_COPY_ON_WRITE: WIN32_ERROR = 749u32; +pub const ERROR_PAGE_FAULT_DEMAND_ZERO: WIN32_ERROR = 748u32; +pub const ERROR_PAGE_FAULT_GUARD_PAGE: WIN32_ERROR = 750u32; +pub const ERROR_PAGE_FAULT_PAGING_FILE: WIN32_ERROR = 751u32; +pub const ERROR_PAGE_FAULT_TRANSITION: WIN32_ERROR = 747u32; +pub const ERROR_PARAMETER_QUOTA_EXCEEDED: WIN32_ERROR = 1283u32; +pub const ERROR_PARTIAL_COPY: WIN32_ERROR = 299u32; +pub const ERROR_PARTITION_FAILURE: WIN32_ERROR = 1105u32; +pub const ERROR_PARTITION_TERMINATING: WIN32_ERROR = 1184u32; +pub const ERROR_PASSWORD_CHANGE_REQUIRED: WIN32_ERROR = 1938u32; +pub const ERROR_PASSWORD_EXPIRED: WIN32_ERROR = 1330u32; +pub const ERROR_PASSWORD_MUST_CHANGE: WIN32_ERROR = 1907u32; +pub const ERROR_PASSWORD_RESTRICTION: WIN32_ERROR = 1325u32; +pub const ERROR_PATCH_MANAGED_ADVERTISED_PRODUCT: WIN32_ERROR = 1651u32; +pub const ERROR_PATCH_NO_SEQUENCE: WIN32_ERROR = 1648u32; +pub const ERROR_PATCH_PACKAGE_INVALID: WIN32_ERROR = 1636u32; +pub const ERROR_PATCH_PACKAGE_OPEN_FAILED: WIN32_ERROR = 1635u32; +pub const ERROR_PATCH_PACKAGE_REJECTED: WIN32_ERROR = 1643u32; +pub const ERROR_PATCH_PACKAGE_UNSUPPORTED: WIN32_ERROR = 1637u32; +pub const ERROR_PATCH_REMOVAL_DISALLOWED: WIN32_ERROR = 1649u32; +pub const ERROR_PATCH_REMOVAL_UNSUPPORTED: WIN32_ERROR = 1646u32; +pub const ERROR_PATCH_TARGET_NOT_FOUND: WIN32_ERROR = 1642u32; +pub const ERROR_PATH_BUSY: WIN32_ERROR = 148u32; +pub const ERROR_PATH_NOT_FOUND: WIN32_ERROR = 3u32; +pub const ERROR_PER_USER_TRUST_QUOTA_EXCEEDED: WIN32_ERROR = 1932u32; +pub const ERROR_PIPE_BUSY: WIN32_ERROR = 231u32; +pub const ERROR_PIPE_CONNECTED: WIN32_ERROR = 535u32; +pub const ERROR_PIPE_LISTENING: WIN32_ERROR = 536u32; +pub const ERROR_PIPE_LOCAL: WIN32_ERROR = 229u32; +pub const ERROR_PIPE_NOT_CONNECTED: WIN32_ERROR = 233u32; +pub const ERROR_PKINIT_FAILURE: WIN32_ERROR = 1263u32; +pub const ERROR_PLUGPLAY_QUERY_VETOED: WIN32_ERROR = 683u32; +pub const ERROR_PNP_BAD_MPS_TABLE: WIN32_ERROR = 671u32; +pub const ERROR_PNP_INVALID_ID: WIN32_ERROR = 674u32; +pub const ERROR_PNP_IRQ_TRANSLATION_FAILED: WIN32_ERROR = 673u32; +pub const ERROR_PNP_QUERY_REMOVE_DEVICE_TIMEOUT: WIN32_ERROR = 480u32; +pub const ERROR_PNP_QUERY_REMOVE_RELATED_DEVICE_TIMEOUT: WIN32_ERROR = 481u32; +pub const ERROR_PNP_QUERY_REMOVE_UNRELATED_DEVICE_TIMEOUT: WIN32_ERROR = 482u32; +pub const ERROR_PNP_REBOOT_REQUIRED: WIN32_ERROR = 638u32; +pub const ERROR_PNP_RESTART_ENUMERATION: WIN32_ERROR = 636u32; +pub const ERROR_PNP_TRANSLATION_FAILED: WIN32_ERROR = 672u32; +pub const ERROR_POINT_NOT_FOUND: WIN32_ERROR = 1171u32; +pub const ERROR_POLICY_OBJECT_NOT_FOUND: WIN32_ERROR = 8219u32; +pub const ERROR_POLICY_ONLY_IN_DS: WIN32_ERROR = 8220u32; +pub const ERROR_POPUP_ALREADY_ACTIVE: WIN32_ERROR = 1446u32; +pub const ERROR_PORT_MESSAGE_TOO_LONG: WIN32_ERROR = 546u32; +pub const ERROR_PORT_NOT_SET: WIN32_ERROR = 642u32; +pub const ERROR_PORT_UNREACHABLE: WIN32_ERROR = 1234u32; +pub const ERROR_POSSIBLE_DEADLOCK: WIN32_ERROR = 1131u32; +pub const ERROR_POTENTIAL_FILE_FOUND: WIN32_ERROR = 1180u32; +pub const ERROR_PREDEFINED_HANDLE: WIN32_ERROR = 714u32; +pub const ERROR_PRIMARY_TRANSPORT_CONNECT_FAILED: WIN32_ERROR = 746u32; +pub const ERROR_PRINTER_ALREADY_EXISTS: WIN32_ERROR = 1802u32; +pub const ERROR_PRINTER_DELETED: WIN32_ERROR = 1905u32; +pub const ERROR_PRINTER_DRIVER_ALREADY_INSTALLED: WIN32_ERROR = 1795u32; +pub const ERROR_PRINTQ_FULL: WIN32_ERROR = 61u32; +pub const ERROR_PRINT_CANCELLED: WIN32_ERROR = 63u32; +pub const ERROR_PRIVATE_DIALOG_INDEX: WIN32_ERROR = 1415u32; +pub const ERROR_PRIVILEGE_NOT_HELD: WIN32_ERROR = 1314u32; +pub const ERROR_PROCESS_ABORTED: WIN32_ERROR = 1067u32; +pub const ERROR_PROCESS_IN_JOB: WIN32_ERROR = 760u32; +pub const ERROR_PROCESS_IS_PROTECTED: WIN32_ERROR = 1293u32; +pub const ERROR_PROCESS_MODE_ALREADY_BACKGROUND: WIN32_ERROR = 402u32; +pub const ERROR_PROCESS_MODE_NOT_BACKGROUND: WIN32_ERROR = 403u32; +pub const ERROR_PROCESS_NOT_IN_JOB: WIN32_ERROR = 759u32; +pub const ERROR_PROC_NOT_FOUND: WIN32_ERROR = 127u32; +pub const ERROR_PRODUCT_UNINSTALLED: WIN32_ERROR = 1614u32; +pub const ERROR_PRODUCT_VERSION: WIN32_ERROR = 1638u32; +pub const ERROR_PROFILING_AT_LIMIT: WIN32_ERROR = 553u32; +pub const ERROR_PROFILING_NOT_STARTED: WIN32_ERROR = 550u32; +pub const ERROR_PROFILING_NOT_STOPPED: WIN32_ERROR = 551u32; +pub const ERROR_PROMOTION_ACTIVE: WIN32_ERROR = 8221u32; +pub const ERROR_PROTOCOL_UNREACHABLE: WIN32_ERROR = 1233u32; +pub const ERROR_PWD_HISTORY_CONFLICT: WIN32_ERROR = 617u32; +pub const ERROR_PWD_TOO_LONG: WIN32_ERROR = 657u32; +pub const ERROR_PWD_TOO_RECENT: WIN32_ERROR = 616u32; +pub const ERROR_PWD_TOO_SHORT: WIN32_ERROR = 615u32; +pub const ERROR_QUOTA_ACTIVITY: WIN32_ERROR = 810u32; +pub const ERROR_QUOTA_LIST_INCONSISTENT: WIN32_ERROR = 621u32; +pub const ERROR_RANGE_LIST_CONFLICT: WIN32_ERROR = 627u32; +pub const ERROR_RANGE_NOT_FOUND: WIN32_ERROR = 644u32; +pub const ERROR_READ_FAULT: WIN32_ERROR = 30u32; +pub const ERROR_RECEIVE_EXPEDITED: WIN32_ERROR = 708u32; +pub const ERROR_RECEIVE_PARTIAL: WIN32_ERROR = 707u32; +pub const ERROR_RECEIVE_PARTIAL_EXPEDITED: WIN32_ERROR = 709u32; +pub const ERROR_RECOVERY_FAILURE: WIN32_ERROR = 1279u32; +pub const ERROR_REDIRECTOR_HAS_OPEN_HANDLES: WIN32_ERROR = 1794u32; +pub const ERROR_REDIR_PAUSED: WIN32_ERROR = 72u32; +pub const ERROR_REGISTRY_CORRUPT: WIN32_ERROR = 1015u32; +pub const ERROR_REGISTRY_HIVE_RECOVERED: WIN32_ERROR = 685u32; +pub const ERROR_REGISTRY_IO_FAILED: WIN32_ERROR = 1016u32; +pub const ERROR_REGISTRY_QUOTA_LIMIT: WIN32_ERROR = 613u32; +pub const ERROR_REGISTRY_RECOVERED: WIN32_ERROR = 1014u32; +pub const ERROR_REG_NAT_CONSUMPTION: WIN32_ERROR = 1261u32; +pub const ERROR_RELOC_CHAIN_XEEDS_SEGLIM: WIN32_ERROR = 201u32; +pub const ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED: WIN32_ERROR = 1936u32; +pub const ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: WIN32_ERROR = 1220u32; +pub const ERROR_REMOTE_STORAGE_MEDIA_ERROR: WIN32_ERROR = 4352u32; +pub const ERROR_REMOTE_STORAGE_NOT_ACTIVE: WIN32_ERROR = 4351u32; +pub const ERROR_REM_NOT_LIST: WIN32_ERROR = 51u32; +pub const ERROR_REPARSE: WIN32_ERROR = 741u32; +pub const ERROR_REPARSE_ATTRIBUTE_CONFLICT: WIN32_ERROR = 4391u32; +pub const ERROR_REPARSE_OBJECT: WIN32_ERROR = 755u32; +pub const ERROR_REPARSE_POINT_ENCOUNTERED: WIN32_ERROR = 4395u32; +pub const ERROR_REPARSE_TAG_INVALID: WIN32_ERROR = 4393u32; +pub const ERROR_REPARSE_TAG_MISMATCH: WIN32_ERROR = 4394u32; +pub const ERROR_REPLY_MESSAGE_MISMATCH: WIN32_ERROR = 595u32; +pub const ERROR_REQUEST_ABORTED: WIN32_ERROR = 1235u32; +pub const ERROR_REQUEST_OUT_OF_SEQUENCE: WIN32_ERROR = 776u32; +pub const ERROR_REQUEST_PAUSED: WIN32_ERROR = 3050u32; +pub const ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION: WIN32_ERROR = 1459u32; +pub const ERROR_REQ_NOT_ACCEP: WIN32_ERROR = 71u32; +pub const ERROR_RESIDENT_FILE_NOT_SUPPORTED: WIN32_ERROR = 334u32; +pub const ERROR_RESOURCE_CALL_TIMED_OUT: WIN32_ERROR = 5910u32; +pub const ERROR_RESOURCE_DATA_NOT_FOUND: WIN32_ERROR = 1812u32; +pub const ERROR_RESOURCE_LANG_NOT_FOUND: WIN32_ERROR = 1815u32; +pub const ERROR_RESOURCE_NAME_NOT_FOUND: WIN32_ERROR = 1814u32; +pub const ERROR_RESOURCE_REQUIREMENTS_CHANGED: WIN32_ERROR = 756u32; +pub const ERROR_RESOURCE_TYPE_NOT_FOUND: WIN32_ERROR = 1813u32; +pub const ERROR_RESTART_APPLICATION: WIN32_ERROR = 1467u32; +pub const ERROR_RESUME_HIBERNATION: WIN32_ERROR = 727u32; +pub const ERROR_RETRY: WIN32_ERROR = 1237u32; +pub const ERROR_RETURN_ADDRESS_HIJACK_ATTEMPT: WIN32_ERROR = 1662u32; +pub const ERROR_REVISION_MISMATCH: WIN32_ERROR = 1306u32; +pub const ERROR_RING2SEG_MUST_BE_MOVABLE: WIN32_ERROR = 200u32; +pub const ERROR_RING2_STACK_IN_USE: WIN32_ERROR = 207u32; +pub const ERROR_RMODE_APP: WIN32_ERROR = 1153u32; +pub const ERROR_ROWSNOTRELEASED: WIN32_ERROR = 772u32; +pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: WIN32_ERROR = 15403u32; +pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: WIN32_ERROR = 15402u32; +pub const ERROR_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED: WIN32_ERROR = 410u32; +pub const ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET: WIN32_ERROR = 411u32; +pub const ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE: WIN32_ERROR = 412u32; +pub const ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER: WIN32_ERROR = 413u32; +pub const ERROR_RXACT_COMMITTED: WIN32_ERROR = 744u32; +pub const ERROR_RXACT_COMMIT_FAILURE: WIN32_ERROR = 1370u32; +pub const ERROR_RXACT_COMMIT_NECESSARY: WIN32_ERROR = 678u32; +pub const ERROR_RXACT_INVALID_STATE: WIN32_ERROR = 1369u32; +pub const ERROR_RXACT_STATE_CREATED: WIN32_ERROR = 701u32; +pub const ERROR_SAME_DRIVE: WIN32_ERROR = 143u32; +pub const ERROR_SAM_INIT_FAILURE: WIN32_ERROR = 8541u32; +pub const ERROR_SCOPE_NOT_FOUND: WIN32_ERROR = 318u32; +pub const ERROR_SCREEN_ALREADY_LOCKED: WIN32_ERROR = 1440u32; +pub const ERROR_SCRUB_DATA_DISABLED: WIN32_ERROR = 332u32; +pub const ERROR_SECRET_TOO_LONG: WIN32_ERROR = 1382u32; +pub const ERROR_SECTION_DIRECT_MAP_ONLY: WIN32_ERROR = 819u32; +pub const ERROR_SECTOR_NOT_FOUND: WIN32_ERROR = 27u32; +pub const ERROR_SECURITY_DENIES_OPERATION: WIN32_ERROR = 447u32; +pub const ERROR_SECURITY_STREAM_IS_INCONSISTENT: WIN32_ERROR = 306u32; +pub const ERROR_SEEK: WIN32_ERROR = 25u32; +pub const ERROR_SEEK_ON_DEVICE: WIN32_ERROR = 132u32; +pub const ERROR_SEGMENT_NOTIFICATION: WIN32_ERROR = 702u32; +pub const ERROR_SEM_IS_SET: WIN32_ERROR = 102u32; +pub const ERROR_SEM_NOT_FOUND: WIN32_ERROR = 187u32; +pub const ERROR_SEM_OWNER_DIED: WIN32_ERROR = 105u32; +pub const ERROR_SEM_TIMEOUT: WIN32_ERROR = 121u32; +pub const ERROR_SEM_USER_LIMIT: WIN32_ERROR = 106u32; +pub const ERROR_SERIAL_NO_DEVICE: WIN32_ERROR = 1118u32; +pub const ERROR_SERVER_DISABLED: WIN32_ERROR = 1341u32; +pub const ERROR_SERVER_HAS_OPEN_HANDLES: WIN32_ERROR = 1811u32; +pub const ERROR_SERVER_NOT_DISABLED: WIN32_ERROR = 1342u32; +pub const ERROR_SERVER_SHUTDOWN_IN_PROGRESS: WIN32_ERROR = 1255u32; +pub const ERROR_SERVER_SID_MISMATCH: WIN32_ERROR = 628u32; +pub const ERROR_SERVER_TRANSPORT_CONFLICT: WIN32_ERROR = 816u32; +pub const ERROR_SERVICE_ALREADY_RUNNING: WIN32_ERROR = 1056u32; +pub const ERROR_SERVICE_CANNOT_ACCEPT_CTRL: WIN32_ERROR = 1061u32; +pub const ERROR_SERVICE_DATABASE_LOCKED: WIN32_ERROR = 1055u32; +pub const ERROR_SERVICE_DEPENDENCY_DELETED: WIN32_ERROR = 1075u32; +pub const ERROR_SERVICE_DEPENDENCY_FAIL: WIN32_ERROR = 1068u32; +pub const ERROR_SERVICE_DISABLED: WIN32_ERROR = 1058u32; +pub const ERROR_SERVICE_DOES_NOT_EXIST: WIN32_ERROR = 1060u32; +pub const ERROR_SERVICE_EXISTS: WIN32_ERROR = 1073u32; +pub const ERROR_SERVICE_LOGON_FAILED: WIN32_ERROR = 1069u32; +pub const ERROR_SERVICE_MARKED_FOR_DELETE: WIN32_ERROR = 1072u32; +pub const ERROR_SERVICE_NEVER_STARTED: WIN32_ERROR = 1077u32; +pub const ERROR_SERVICE_NOTIFICATION: WIN32_ERROR = 716u32; +pub const ERROR_SERVICE_NOTIFY_CLIENT_LAGGING: WIN32_ERROR = 1294u32; +pub const ERROR_SERVICE_NOT_ACTIVE: WIN32_ERROR = 1062u32; +pub const ERROR_SERVICE_NOT_FOUND: WIN32_ERROR = 1243u32; +pub const ERROR_SERVICE_NOT_IN_EXE: WIN32_ERROR = 1083u32; +pub const ERROR_SERVICE_NO_THREAD: WIN32_ERROR = 1054u32; +pub const ERROR_SERVICE_REQUEST_TIMEOUT: WIN32_ERROR = 1053u32; +pub const ERROR_SERVICE_SPECIFIC_ERROR: WIN32_ERROR = 1066u32; +pub const ERROR_SERVICE_START_HANG: WIN32_ERROR = 1070u32; +pub const ERROR_SESSION_CREDENTIAL_CONFLICT: WIN32_ERROR = 1219u32; +pub const ERROR_SESSION_KEY_TOO_SHORT: WIN32_ERROR = 501u32; +pub const ERROR_SETCOUNT_ON_BAD_LB: WIN32_ERROR = 1433u32; +pub const ERROR_SETMARK_DETECTED: WIN32_ERROR = 1103u32; +pub const ERROR_SET_CONTEXT_DENIED: WIN32_ERROR = 1660u32; +pub const ERROR_SET_NOT_FOUND: WIN32_ERROR = 1170u32; +pub const ERROR_SET_POWER_STATE_FAILED: WIN32_ERROR = 1141u32; +pub const ERROR_SET_POWER_STATE_VETOED: WIN32_ERROR = 1140u32; +pub const ERROR_SHARED_POLICY: WIN32_ERROR = 8218u32; +pub const ERROR_SHARING_BUFFER_EXCEEDED: WIN32_ERROR = 36u32; +pub const ERROR_SHARING_PAUSED: WIN32_ERROR = 70u32; +pub const ERROR_SHARING_VIOLATION: WIN32_ERROR = 32u32; +pub const ERROR_SHORT_NAMES_NOT_ENABLED_ON_VOLUME: WIN32_ERROR = 305u32; +pub const ERROR_SHUTDOWN_DISKS_NOT_IN_MAINTENANCE_MODE: WIN32_ERROR = 1192u32; +pub const ERROR_SHUTDOWN_IN_PROGRESS: WIN32_ERROR = 1115u32; +pub const ERROR_SHUTDOWN_IS_SCHEDULED: WIN32_ERROR = 1190u32; +pub const ERROR_SHUTDOWN_USERS_LOGGED_ON: WIN32_ERROR = 1191u32; +pub const ERROR_SIGNAL_PENDING: WIN32_ERROR = 162u32; +pub const ERROR_SIGNAL_REFUSED: WIN32_ERROR = 156u32; +pub const ERROR_SINGLE_INSTANCE_APP: WIN32_ERROR = 1152u32; +pub const ERROR_SMARTCARD_SUBSYSTEM_FAILURE: WIN32_ERROR = 1264u32; +pub const ERROR_SMB1_NOT_AVAILABLE: WIN32_ERROR = 384u32; +pub const ERROR_SMB_GUEST_LOGON_BLOCKED: WIN32_ERROR = 1272u32; +pub const ERROR_SMR_GARBAGE_COLLECTION_REQUIRED: WIN32_ERROR = 4445u32; +pub const ERROR_SOME_NOT_MAPPED: WIN32_ERROR = 1301u32; +pub const ERROR_SOURCE_ELEMENT_EMPTY: WIN32_ERROR = 1160u32; +pub const ERROR_SPARSE_FILE_NOT_SUPPORTED: WIN32_ERROR = 490u32; +pub const ERROR_SPECIAL_ACCOUNT: WIN32_ERROR = 1371u32; +pub const ERROR_SPECIAL_GROUP: WIN32_ERROR = 1372u32; +pub const ERROR_SPECIAL_USER: WIN32_ERROR = 1373u32; +pub const ERROR_SRC_SRV_DLL_LOAD_FAILED: WIN32_ERROR = 428u32; +pub const ERROR_STACK_BUFFER_OVERRUN: WIN32_ERROR = 1282u32; +pub const ERROR_STACK_OVERFLOW: WIN32_ERROR = 1001u32; +pub const ERROR_STACK_OVERFLOW_READ: WIN32_ERROR = 599u32; +pub const ERROR_STOPPED_ON_SYMLINK: WIN32_ERROR = 681u32; +pub const ERROR_STORAGE_LOST_DATA_PERSISTENCE: WIN32_ERROR = 368u32; +pub const ERROR_STORAGE_RESERVE_ALREADY_EXISTS: WIN32_ERROR = 418u32; +pub const ERROR_STORAGE_RESERVE_DOES_NOT_EXIST: WIN32_ERROR = 417u32; +pub const ERROR_STORAGE_RESERVE_ID_INVALID: WIN32_ERROR = 416u32; +pub const ERROR_STORAGE_RESERVE_NOT_EMPTY: WIN32_ERROR = 419u32; +pub const ERROR_STORAGE_STACK_ACCESS_DENIED: WIN32_ERROR = 472u32; +pub const ERROR_STORAGE_TOPOLOGY_ID_MISMATCH: WIN32_ERROR = 345u32; +pub const ERROR_STRICT_CFG_VIOLATION: WIN32_ERROR = 1657u32; +pub const ERROR_SUBST_TO_JOIN: WIN32_ERROR = 141u32; +pub const ERROR_SUBST_TO_SUBST: WIN32_ERROR = 139u32; +pub const ERROR_SUCCESS: WIN32_ERROR = 0u32; +pub const ERROR_SUCCESS_REBOOT_INITIATED: WIN32_ERROR = 1641u32; +pub const ERROR_SWAPERROR: WIN32_ERROR = 999u32; +pub const ERROR_SYMLINK_CLASS_DISABLED: WIN32_ERROR = 1463u32; +pub const ERROR_SYMLINK_NOT_SUPPORTED: WIN32_ERROR = 1464u32; +pub const ERROR_SYNCHRONIZATION_REQUIRED: WIN32_ERROR = 569u32; +pub const ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED: WIN32_ERROR = 1274u32; +pub const ERROR_SYSTEM_HIVE_TOO_LARGE: WIN32_ERROR = 653u32; +pub const ERROR_SYSTEM_IMAGE_BAD_SIGNATURE: WIN32_ERROR = 637u32; +pub const ERROR_SYSTEM_POWERSTATE_COMPLEX_TRANSITION: WIN32_ERROR = 783u32; +pub const ERROR_SYSTEM_POWERSTATE_TRANSITION: WIN32_ERROR = 782u32; +pub const ERROR_SYSTEM_PROCESS_TERMINATED: WIN32_ERROR = 591u32; +pub const ERROR_SYSTEM_SHUTDOWN: WIN32_ERROR = 641u32; +pub const ERROR_SYSTEM_TRACE: WIN32_ERROR = 150u32; +pub const ERROR_THREAD_1_INACTIVE: WIN32_ERROR = 210u32; +pub const ERROR_THREAD_ALREADY_IN_TASK: WIN32_ERROR = 1552u32; +pub const ERROR_THREAD_MODE_ALREADY_BACKGROUND: WIN32_ERROR = 400u32; +pub const ERROR_THREAD_MODE_NOT_BACKGROUND: WIN32_ERROR = 401u32; +pub const ERROR_THREAD_NOT_IN_PROCESS: WIN32_ERROR = 566u32; +pub const ERROR_THREAD_WAS_SUSPENDED: WIN32_ERROR = 699u32; +pub const ERROR_TIMEOUT: WIN32_ERROR = 1460u32; +pub const ERROR_TIMER_NOT_CANCELED: WIN32_ERROR = 541u32; +pub const ERROR_TIMER_RESOLUTION_NOT_SET: WIN32_ERROR = 607u32; +pub const ERROR_TIMER_RESUME_IGNORED: WIN32_ERROR = 722u32; +pub const ERROR_TIME_SENSITIVE_THREAD: WIN32_ERROR = 422u32; +pub const ERROR_TIME_SKEW: WIN32_ERROR = 1398u32; +pub const ERROR_TLW_WITH_WSCHILD: WIN32_ERROR = 1406u32; +pub const ERROR_TOKEN_ALREADY_IN_USE: WIN32_ERROR = 1375u32; +pub const ERROR_TOO_MANY_CMDS: WIN32_ERROR = 56u32; +pub const ERROR_TOO_MANY_CONTEXT_IDS: WIN32_ERROR = 1384u32; +pub const ERROR_TOO_MANY_DESCRIPTORS: WIN32_ERROR = 331u32; +pub const ERROR_TOO_MANY_LINKS: WIN32_ERROR = 1142u32; +pub const ERROR_TOO_MANY_LUIDS_REQUESTED: WIN32_ERROR = 1333u32; +pub const ERROR_TOO_MANY_MODULES: WIN32_ERROR = 214u32; +pub const ERROR_TOO_MANY_MUXWAITERS: WIN32_ERROR = 152u32; +pub const ERROR_TOO_MANY_NAMES: WIN32_ERROR = 68u32; +pub const ERROR_TOO_MANY_OPEN_FILES: WIN32_ERROR = 4u32; +pub const ERROR_TOO_MANY_POSTS: WIN32_ERROR = 298u32; +pub const ERROR_TOO_MANY_SECRETS: WIN32_ERROR = 1381u32; +pub const ERROR_TOO_MANY_SEMAPHORES: WIN32_ERROR = 100u32; +pub const ERROR_TOO_MANY_SEM_REQUESTS: WIN32_ERROR = 103u32; +pub const ERROR_TOO_MANY_SESS: WIN32_ERROR = 69u32; +pub const ERROR_TOO_MANY_SIDS: WIN32_ERROR = 1389u32; +pub const ERROR_TOO_MANY_TCBS: WIN32_ERROR = 155u32; +pub const ERROR_TOO_MANY_THREADS: WIN32_ERROR = 565u32; +pub const ERROR_TRANSLATION_COMPLETE: WIN32_ERROR = 757u32; +pub const ERROR_TRUSTED_DOMAIN_FAILURE: WIN32_ERROR = 1788u32; +pub const ERROR_TRUSTED_RELATIONSHIP_FAILURE: WIN32_ERROR = 1789u32; +pub const ERROR_TRUST_FAILURE: WIN32_ERROR = 1790u32; +pub const ERROR_UNABLE_TO_LOCK_MEDIA: WIN32_ERROR = 1108u32; +pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT: WIN32_ERROR = 1176u32; +pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT_2: WIN32_ERROR = 1177u32; +pub const ERROR_UNABLE_TO_REMOVE_REPLACED: WIN32_ERROR = 1175u32; +pub const ERROR_UNABLE_TO_UNLOAD_MEDIA: WIN32_ERROR = 1109u32; +pub const ERROR_UNDEFINED_CHARACTER: WIN32_ERROR = 583u32; +pub const ERROR_UNDEFINED_SCOPE: WIN32_ERROR = 319u32; +pub const ERROR_UNEXPECTED_MM_CREATE_ERR: WIN32_ERROR = 556u32; +pub const ERROR_UNEXPECTED_MM_EXTEND_ERR: WIN32_ERROR = 558u32; +pub const ERROR_UNEXPECTED_MM_MAP_ERROR: WIN32_ERROR = 557u32; +pub const ERROR_UNEXPECTED_NTCACHEMANAGER_ERROR: WIN32_ERROR = 443u32; +pub const ERROR_UNEXP_NET_ERR: WIN32_ERROR = 59u32; +pub const ERROR_UNHANDLED_EXCEPTION: WIN32_ERROR = 574u32; +pub const ERROR_UNIDENTIFIED_ERROR: WIN32_ERROR = 1287u32; +pub const ERROR_UNKNOWN_COMPONENT: WIN32_ERROR = 1607u32; +pub const ERROR_UNKNOWN_FEATURE: WIN32_ERROR = 1606u32; +pub const ERROR_UNKNOWN_PATCH: WIN32_ERROR = 1647u32; +pub const ERROR_UNKNOWN_PORT: WIN32_ERROR = 1796u32; +pub const ERROR_UNKNOWN_PRINTER_DRIVER: WIN32_ERROR = 1797u32; +pub const ERROR_UNKNOWN_PRINTPROCESSOR: WIN32_ERROR = 1798u32; +pub const ERROR_UNKNOWN_PRODUCT: WIN32_ERROR = 1605u32; +pub const ERROR_UNKNOWN_PROPERTY: WIN32_ERROR = 1608u32; +pub const ERROR_UNKNOWN_REVISION: WIN32_ERROR = 1305u32; +pub const ERROR_UNRECOGNIZED_MEDIA: WIN32_ERROR = 1785u32; +pub const ERROR_UNRECOGNIZED_VOLUME: WIN32_ERROR = 1005u32; +pub const ERROR_UNSATISFIED_DEPENDENCIES: WIN32_ERROR = 441u32; +pub const ERROR_UNSUPPORTED_COMPRESSION: WIN32_ERROR = 618u32; +pub const ERROR_UNSUPPORTED_TYPE: WIN32_ERROR = 1630u32; +pub const ERROR_UNTRUSTED_MOUNT_POINT: WIN32_ERROR = 448u32; +pub const ERROR_UNWIND: WIN32_ERROR = 542u32; +pub const ERROR_UNWIND_CONSOLIDATE: WIN32_ERROR = 684u32; +pub const ERROR_USER_APC: WIN32_ERROR = 737u32; +pub const ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED: WIN32_ERROR = 1934u32; +pub const ERROR_USER_EXISTS: WIN32_ERROR = 1316u32; +pub const ERROR_USER_MAPPED_FILE: WIN32_ERROR = 1224u32; +pub const ERROR_USER_PROFILE_LOAD: WIN32_ERROR = 500u32; +pub const ERROR_VALIDATE_CONTINUE: WIN32_ERROR = 625u32; +pub const ERROR_VC_DISCONNECTED: WIN32_ERROR = 240u32; +pub const ERROR_VDM_DISALLOWED: WIN32_ERROR = 1286u32; +pub const ERROR_VDM_HARD_ERROR: WIN32_ERROR = 593u32; +pub const ERROR_VERIFIER_STOP: WIN32_ERROR = 537u32; +pub const ERROR_VERSION_PARSE_ERROR: WIN32_ERROR = 777u32; +pub const ERROR_VIRUS_DELETED: WIN32_ERROR = 226u32; +pub const ERROR_VIRUS_INFECTED: WIN32_ERROR = 225u32; +pub const ERROR_VOLSNAP_HIBERNATE_READY: WIN32_ERROR = 761u32; +pub const ERROR_VOLSNAP_PREPARE_HIBERNATE: WIN32_ERROR = 655u32; +pub const ERROR_VOLUME_MOUNTED: WIN32_ERROR = 743u32; +pub const ERROR_VOLUME_NOT_CLUSTER_ALIGNED: WIN32_ERROR = 407u32; +pub const ERROR_VOLUME_NOT_SIS_ENABLED: WIN32_ERROR = 4500u32; +pub const ERROR_VOLUME_NOT_SUPPORTED: WIN32_ERROR = 492u32; +pub const ERROR_VOLUME_NOT_SUPPORT_EFS: WIN32_ERROR = 6014u32; +pub const ERROR_VOLUME_WRITE_ACCESS_DENIED: WIN32_ERROR = 508u32; +pub const ERROR_WAIT_1: WIN32_ERROR = 731u32; +pub const ERROR_WAIT_2: WIN32_ERROR = 732u32; +pub const ERROR_WAIT_3: WIN32_ERROR = 733u32; +pub const ERROR_WAIT_63: WIN32_ERROR = 734u32; +pub const ERROR_WAIT_FOR_OPLOCK: WIN32_ERROR = 765u32; +pub const ERROR_WAIT_NO_CHILDREN: WIN32_ERROR = 128u32; +pub const ERROR_WAKE_SYSTEM: WIN32_ERROR = 730u32; +pub const ERROR_WAKE_SYSTEM_DEBUGGER: WIN32_ERROR = 675u32; +pub const ERROR_WAS_LOCKED: WIN32_ERROR = 717u32; +pub const ERROR_WAS_UNLOCKED: WIN32_ERROR = 715u32; +pub const ERROR_WEAK_WHFBKEY_BLOCKED: WIN32_ERROR = 8651u32; +pub const ERROR_WINDOW_NOT_COMBOBOX: WIN32_ERROR = 1423u32; +pub const ERROR_WINDOW_NOT_DIALOG: WIN32_ERROR = 1420u32; +pub const ERROR_WINDOW_OF_OTHER_THREAD: WIN32_ERROR = 1408u32; +pub const ERROR_WIP_ENCRYPTION_FAILED: WIN32_ERROR = 6023u32; +pub const ERROR_WOF_FILE_RESOURCE_TABLE_CORRUPT: WIN32_ERROR = 4448u32; +pub const ERROR_WOF_WIM_HEADER_CORRUPT: WIN32_ERROR = 4446u32; +pub const ERROR_WOF_WIM_RESOURCE_TABLE_CORRUPT: WIN32_ERROR = 4447u32; +pub const ERROR_WORKING_SET_QUOTA: WIN32_ERROR = 1453u32; +pub const ERROR_WOW_ASSERTION: WIN32_ERROR = 670u32; +pub const ERROR_WRITE_FAULT: WIN32_ERROR = 29u32; +pub const ERROR_WRITE_PROTECT: WIN32_ERROR = 19u32; +pub const ERROR_WRONG_COMPARTMENT: WIN32_ERROR = 1468u32; +pub const ERROR_WRONG_DISK: WIN32_ERROR = 34u32; +pub const ERROR_WRONG_EFS: WIN32_ERROR = 6005u32; +pub const ERROR_WRONG_PASSWORD: WIN32_ERROR = 1323u32; +pub const ERROR_WRONG_TARGET_NAME: WIN32_ERROR = 1396u32; +pub const ERROR_WX86_ERROR: WIN32_ERROR = 540u32; +pub const ERROR_WX86_WARNING: WIN32_ERROR = 539u32; +pub const ERROR_XMLDSIG_ERROR: WIN32_ERROR = 1466u32; +pub const ERROR_XML_PARSE_ERROR: WIN32_ERROR = 1465u32; +pub type EXCEPTION_DISPOSITION = i32; +pub const EXCEPTION_MAXIMUM_PARAMETERS: u32 = 15u32; +#[repr(C)] +pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ContextRecord: *mut CONTEXT, +} +impl ::core::marker::Copy for EXCEPTION_POINTERS {} +impl ::core::clone::Clone for EXCEPTION_POINTERS { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut ::core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], +} +impl ::core::marker::Copy for EXCEPTION_RECORD {} +impl ::core::clone::Clone for EXCEPTION_RECORD { + fn clone(&self) -> Self { + *self + } +} +pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = -1073741571i32; +pub const EXTENDED_STARTUPINFO_PRESENT: PROCESS_CREATION_FLAGS = 524288u32; +pub const E_NOTIMPL: HRESULT = -2147467263i32; +pub const ExceptionCollidedUnwind: EXCEPTION_DISPOSITION = 3i32; +pub const ExceptionContinueExecution: EXCEPTION_DISPOSITION = 0i32; +pub const ExceptionContinueSearch: EXCEPTION_DISPOSITION = 1i32; +pub const ExceptionNestedException: EXCEPTION_DISPOSITION = 2i32; +pub type FACILITY_CODE = u32; +pub const FACILITY_NT_BIT: FACILITY_CODE = 268435456u32; +pub const FALSE: BOOL = 0i32; +pub type FARPROC = ::core::option::Option<unsafe extern "system" fn() -> isize>; +#[repr(C)] +pub struct FD_SET { + pub fd_count: u32, + pub fd_array: [SOCKET; 64], +} +impl ::core::marker::Copy for FD_SET {} +impl ::core::clone::Clone for FD_SET { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct FILETIME { + pub dwLowDateTime: u32, + pub dwHighDateTime: u32, +} +impl ::core::marker::Copy for FILETIME {} +impl ::core::clone::Clone for FILETIME { + fn clone(&self) -> Self { + *self + } +} +pub type FILE_ACCESS_RIGHTS = u32; +pub const FILE_ADD_FILE: FILE_ACCESS_RIGHTS = 2u32; +pub const FILE_ADD_SUBDIRECTORY: FILE_ACCESS_RIGHTS = 4u32; +pub const FILE_ALL_ACCESS: FILE_ACCESS_RIGHTS = 2032127u32; +pub const FILE_APPEND_DATA: FILE_ACCESS_RIGHTS = 4u32; +pub const FILE_ATTRIBUTE_ARCHIVE: FILE_FLAGS_AND_ATTRIBUTES = 32u32; +pub const FILE_ATTRIBUTE_COMPRESSED: FILE_FLAGS_AND_ATTRIBUTES = 2048u32; +pub const FILE_ATTRIBUTE_DEVICE: FILE_FLAGS_AND_ATTRIBUTES = 64u32; +pub const FILE_ATTRIBUTE_DIRECTORY: FILE_FLAGS_AND_ATTRIBUTES = 16u32; +pub const FILE_ATTRIBUTE_EA: FILE_FLAGS_AND_ATTRIBUTES = 262144u32; +pub const FILE_ATTRIBUTE_ENCRYPTED: FILE_FLAGS_AND_ATTRIBUTES = 16384u32; +pub const FILE_ATTRIBUTE_HIDDEN: FILE_FLAGS_AND_ATTRIBUTES = 2u32; +pub const FILE_ATTRIBUTE_INTEGRITY_STREAM: FILE_FLAGS_AND_ATTRIBUTES = 32768u32; +pub const FILE_ATTRIBUTE_NORMAL: FILE_FLAGS_AND_ATTRIBUTES = 128u32; +pub const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: FILE_FLAGS_AND_ATTRIBUTES = 8192u32; +pub const FILE_ATTRIBUTE_NO_SCRUB_DATA: FILE_FLAGS_AND_ATTRIBUTES = 131072u32; +pub const FILE_ATTRIBUTE_OFFLINE: FILE_FLAGS_AND_ATTRIBUTES = 4096u32; +pub const FILE_ATTRIBUTE_PINNED: FILE_FLAGS_AND_ATTRIBUTES = 524288u32; +pub const FILE_ATTRIBUTE_READONLY: FILE_FLAGS_AND_ATTRIBUTES = 1u32; +pub const FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS: FILE_FLAGS_AND_ATTRIBUTES = 4194304u32; +pub const FILE_ATTRIBUTE_RECALL_ON_OPEN: FILE_FLAGS_AND_ATTRIBUTES = 262144u32; +pub const FILE_ATTRIBUTE_REPARSE_POINT: FILE_FLAGS_AND_ATTRIBUTES = 1024u32; +pub const FILE_ATTRIBUTE_SPARSE_FILE: FILE_FLAGS_AND_ATTRIBUTES = 512u32; +pub const FILE_ATTRIBUTE_SYSTEM: FILE_FLAGS_AND_ATTRIBUTES = 4u32; +#[repr(C)] +pub struct FILE_ATTRIBUTE_TAG_INFO { + pub FileAttributes: u32, + pub ReparseTag: u32, +} +impl ::core::marker::Copy for FILE_ATTRIBUTE_TAG_INFO {} +impl ::core::clone::Clone for FILE_ATTRIBUTE_TAG_INFO { + fn clone(&self) -> Self { + *self + } +} +pub const FILE_ATTRIBUTE_TEMPORARY: FILE_FLAGS_AND_ATTRIBUTES = 256u32; +pub const FILE_ATTRIBUTE_UNPINNED: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32; +pub const FILE_ATTRIBUTE_VIRTUAL: FILE_FLAGS_AND_ATTRIBUTES = 65536u32; +#[repr(C)] +pub struct FILE_BASIC_INFO { + pub CreationTime: i64, + pub LastAccessTime: i64, + pub LastWriteTime: i64, + pub ChangeTime: i64, + pub FileAttributes: u32, +} +impl ::core::marker::Copy for FILE_BASIC_INFO {} +impl ::core::clone::Clone for FILE_BASIC_INFO { + fn clone(&self) -> Self { + *self + } +} +pub const FILE_BEGIN: SET_FILE_POINTER_MOVE_METHOD = 0u32; +pub const FILE_COMPLETE_IF_OPLOCKED: NTCREATEFILE_CREATE_OPTIONS = 256u32; +pub const FILE_CONTAINS_EXTENDED_CREATE_INFORMATION: NTCREATEFILE_CREATE_OPTIONS = 268435456u32; +pub const FILE_CREATE: NTCREATEFILE_CREATE_DISPOSITION = 2u32; +pub const FILE_CREATE_PIPE_INSTANCE: FILE_ACCESS_RIGHTS = 4u32; +pub const FILE_CREATE_TREE_CONNECTION: NTCREATEFILE_CREATE_OPTIONS = 128u32; +pub type FILE_CREATION_DISPOSITION = u32; +pub const FILE_CURRENT: SET_FILE_POINTER_MOVE_METHOD = 1u32; +pub const FILE_DELETE_CHILD: FILE_ACCESS_RIGHTS = 64u32; +pub const FILE_DELETE_ON_CLOSE: NTCREATEFILE_CREATE_OPTIONS = 4096u32; +pub const FILE_DIRECTORY_FILE: NTCREATEFILE_CREATE_OPTIONS = 1u32; +pub const FILE_DISALLOW_EXCLUSIVE: NTCREATEFILE_CREATE_OPTIONS = 131072u32; +pub const FILE_DISPOSITION_FLAG_DELETE: FILE_DISPOSITION_INFO_EX_FLAGS = 1u32; +pub const FILE_DISPOSITION_FLAG_DO_NOT_DELETE: FILE_DISPOSITION_INFO_EX_FLAGS = 0u32; +pub const FILE_DISPOSITION_FLAG_FORCE_IMAGE_SECTION_CHECK: FILE_DISPOSITION_INFO_EX_FLAGS = 4u32; +pub const FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE: FILE_DISPOSITION_INFO_EX_FLAGS = 16u32; +pub const FILE_DISPOSITION_FLAG_ON_CLOSE: FILE_DISPOSITION_INFO_EX_FLAGS = 8u32; +pub const FILE_DISPOSITION_FLAG_POSIX_SEMANTICS: FILE_DISPOSITION_INFO_EX_FLAGS = 2u32; +#[repr(C)] +pub struct FILE_DISPOSITION_INFO { + pub DeleteFile: BOOLEAN, +} +impl ::core::marker::Copy for FILE_DISPOSITION_INFO {} +impl ::core::clone::Clone for FILE_DISPOSITION_INFO { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct FILE_DISPOSITION_INFO_EX { + pub Flags: FILE_DISPOSITION_INFO_EX_FLAGS, +} +impl ::core::marker::Copy for FILE_DISPOSITION_INFO_EX {} +impl ::core::clone::Clone for FILE_DISPOSITION_INFO_EX { + fn clone(&self) -> Self { + *self + } +} +pub type FILE_DISPOSITION_INFO_EX_FLAGS = u32; +pub const FILE_END: SET_FILE_POINTER_MOVE_METHOD = 2u32; +#[repr(C)] +pub struct FILE_END_OF_FILE_INFO { + pub EndOfFile: i64, +} +impl ::core::marker::Copy for FILE_END_OF_FILE_INFO {} +impl ::core::clone::Clone for FILE_END_OF_FILE_INFO { + fn clone(&self) -> Self { + *self + } +} +pub const FILE_EXECUTE: FILE_ACCESS_RIGHTS = 32u32; +pub type FILE_FLAGS_AND_ATTRIBUTES = u32; +pub const FILE_FLAG_BACKUP_SEMANTICS: FILE_FLAGS_AND_ATTRIBUTES = 33554432u32; +pub const FILE_FLAG_DELETE_ON_CLOSE: FILE_FLAGS_AND_ATTRIBUTES = 67108864u32; +pub const FILE_FLAG_FIRST_PIPE_INSTANCE: FILE_FLAGS_AND_ATTRIBUTES = 524288u32; +pub const FILE_FLAG_NO_BUFFERING: FILE_FLAGS_AND_ATTRIBUTES = 536870912u32; +pub const FILE_FLAG_OPEN_NO_RECALL: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32; +pub const FILE_FLAG_OPEN_REPARSE_POINT: FILE_FLAGS_AND_ATTRIBUTES = 2097152u32; +pub const FILE_FLAG_OVERLAPPED: FILE_FLAGS_AND_ATTRIBUTES = 1073741824u32; +pub const FILE_FLAG_POSIX_SEMANTICS: FILE_FLAGS_AND_ATTRIBUTES = 16777216u32; +pub const FILE_FLAG_RANDOM_ACCESS: FILE_FLAGS_AND_ATTRIBUTES = 268435456u32; +pub const FILE_FLAG_SEQUENTIAL_SCAN: FILE_FLAGS_AND_ATTRIBUTES = 134217728u32; +pub const FILE_FLAG_SESSION_AWARE: FILE_FLAGS_AND_ATTRIBUTES = 8388608u32; +pub const FILE_FLAG_WRITE_THROUGH: FILE_FLAGS_AND_ATTRIBUTES = 2147483648u32; +pub const FILE_GENERIC_EXECUTE: FILE_ACCESS_RIGHTS = 1179808u32; +pub const FILE_GENERIC_READ: FILE_ACCESS_RIGHTS = 1179785u32; +pub const FILE_GENERIC_WRITE: FILE_ACCESS_RIGHTS = 1179926u32; +#[repr(C)] +pub struct FILE_ID_BOTH_DIR_INFO { + pub NextEntryOffset: u32, + pub FileIndex: u32, + pub CreationTime: i64, + pub LastAccessTime: i64, + pub LastWriteTime: i64, + pub ChangeTime: i64, + pub EndOfFile: i64, + pub AllocationSize: i64, + pub FileAttributes: u32, + pub FileNameLength: u32, + pub EaSize: u32, + pub ShortNameLength: i8, + pub ShortName: [u16; 12], + pub FileId: i64, + pub FileName: [u16; 1], +} +impl ::core::marker::Copy for FILE_ID_BOTH_DIR_INFO {} +impl ::core::clone::Clone for FILE_ID_BOTH_DIR_INFO { + fn clone(&self) -> Self { + *self + } +} +pub type FILE_INFO_BY_HANDLE_CLASS = i32; +pub const FILE_LIST_DIRECTORY: FILE_ACCESS_RIGHTS = 1u32; +pub const FILE_NAME_NORMALIZED: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32; +pub const FILE_NAME_OPENED: GETFINALPATHNAMEBYHANDLE_FLAGS = 8u32; +pub const FILE_NON_DIRECTORY_FILE: NTCREATEFILE_CREATE_OPTIONS = 64u32; +pub const FILE_NO_COMPRESSION: NTCREATEFILE_CREATE_OPTIONS = 32768u32; +pub const FILE_NO_EA_KNOWLEDGE: NTCREATEFILE_CREATE_OPTIONS = 512u32; +pub const FILE_NO_INTERMEDIATE_BUFFERING: NTCREATEFILE_CREATE_OPTIONS = 8u32; +pub const FILE_OPEN: NTCREATEFILE_CREATE_DISPOSITION = 1u32; +pub const FILE_OPEN_BY_FILE_ID: NTCREATEFILE_CREATE_OPTIONS = 8192u32; +pub const FILE_OPEN_FOR_BACKUP_INTENT: NTCREATEFILE_CREATE_OPTIONS = 16384u32; +pub const FILE_OPEN_FOR_FREE_SPACE_QUERY: NTCREATEFILE_CREATE_OPTIONS = 8388608u32; +pub const FILE_OPEN_IF: NTCREATEFILE_CREATE_DISPOSITION = 3u32; +pub const FILE_OPEN_NO_RECALL: NTCREATEFILE_CREATE_OPTIONS = 4194304u32; +pub const FILE_OPEN_REPARSE_POINT: NTCREATEFILE_CREATE_OPTIONS = 2097152u32; +pub const FILE_OPEN_REQUIRING_OPLOCK: NTCREATEFILE_CREATE_OPTIONS = 65536u32; +pub const FILE_OVERWRITE: NTCREATEFILE_CREATE_DISPOSITION = 4u32; +pub const FILE_OVERWRITE_IF: NTCREATEFILE_CREATE_DISPOSITION = 5u32; +pub const FILE_RANDOM_ACCESS: NTCREATEFILE_CREATE_OPTIONS = 2048u32; +pub const FILE_READ_ATTRIBUTES: FILE_ACCESS_RIGHTS = 128u32; +pub const FILE_READ_DATA: FILE_ACCESS_RIGHTS = 1u32; +pub const FILE_READ_EA: FILE_ACCESS_RIGHTS = 8u32; +pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32; +pub const FILE_SEQUENTIAL_ONLY: NTCREATEFILE_CREATE_OPTIONS = 4u32; +pub const FILE_SESSION_AWARE: NTCREATEFILE_CREATE_OPTIONS = 262144u32; +pub const FILE_SHARE_DELETE: FILE_SHARE_MODE = 4u32; +pub type FILE_SHARE_MODE = u32; +pub const FILE_SHARE_NONE: FILE_SHARE_MODE = 0u32; +pub const FILE_SHARE_READ: FILE_SHARE_MODE = 1u32; +pub const FILE_SHARE_WRITE: FILE_SHARE_MODE = 2u32; +#[repr(C)] +pub struct FILE_STANDARD_INFO { + pub AllocationSize: i64, + pub EndOfFile: i64, + pub NumberOfLinks: u32, + pub DeletePending: BOOLEAN, + pub Directory: BOOLEAN, +} +impl ::core::marker::Copy for FILE_STANDARD_INFO {} +impl ::core::clone::Clone for FILE_STANDARD_INFO { + fn clone(&self) -> Self { + *self + } +} +pub const FILE_SUPERSEDE: NTCREATEFILE_CREATE_DISPOSITION = 0u32; +pub const FILE_SYNCHRONOUS_IO_ALERT: NTCREATEFILE_CREATE_OPTIONS = 16u32; +pub const FILE_SYNCHRONOUS_IO_NONALERT: NTCREATEFILE_CREATE_OPTIONS = 32u32; +pub const FILE_TRAVERSE: FILE_ACCESS_RIGHTS = 32u32; +pub type FILE_TYPE = u32; +pub const FILE_TYPE_CHAR: FILE_TYPE = 2u32; +pub const FILE_TYPE_DISK: FILE_TYPE = 1u32; +pub const FILE_TYPE_PIPE: FILE_TYPE = 3u32; +pub const FILE_TYPE_REMOTE: FILE_TYPE = 32768u32; +pub const FILE_TYPE_UNKNOWN: FILE_TYPE = 0u32; +pub const FILE_WRITE_ATTRIBUTES: FILE_ACCESS_RIGHTS = 256u32; +pub const FILE_WRITE_DATA: FILE_ACCESS_RIGHTS = 2u32; +pub const FILE_WRITE_EA: FILE_ACCESS_RIGHTS = 16u32; +pub const FILE_WRITE_THROUGH: NTCREATEFILE_CREATE_OPTIONS = 2u32; +pub const FIONBIO: i32 = -2147195266i32; +#[repr(C)] +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +pub struct FLOATING_SAVE_AREA { + pub ControlWord: u32, + pub StatusWord: u32, + pub TagWord: u32, + pub ErrorOffset: u32, + pub ErrorSelector: u32, + pub DataOffset: u32, + pub DataSelector: u32, + pub RegisterArea: [u8; 80], + pub Cr0NpxState: u32, +} +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +impl ::core::marker::Copy for FLOATING_SAVE_AREA {} +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +impl ::core::clone::Clone for FLOATING_SAVE_AREA { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "x86")] +pub struct FLOATING_SAVE_AREA { + pub ControlWord: u32, + pub StatusWord: u32, + pub TagWord: u32, + pub ErrorOffset: u32, + pub ErrorSelector: u32, + pub DataOffset: u32, + pub DataSelector: u32, + pub RegisterArea: [u8; 80], + pub Spare0: u32, +} +#[cfg(target_arch = "x86")] +impl ::core::marker::Copy for FLOATING_SAVE_AREA {} +#[cfg(target_arch = "x86")] +impl ::core::clone::Clone for FLOATING_SAVE_AREA { + fn clone(&self) -> Self { + *self + } +} +pub const FORMAT_MESSAGE_ALLOCATE_BUFFER: FORMAT_MESSAGE_OPTIONS = 256u32; +pub const FORMAT_MESSAGE_ARGUMENT_ARRAY: FORMAT_MESSAGE_OPTIONS = 8192u32; +pub const FORMAT_MESSAGE_FROM_HMODULE: FORMAT_MESSAGE_OPTIONS = 2048u32; +pub const FORMAT_MESSAGE_FROM_STRING: FORMAT_MESSAGE_OPTIONS = 1024u32; +pub const FORMAT_MESSAGE_FROM_SYSTEM: FORMAT_MESSAGE_OPTIONS = 4096u32; +pub const FORMAT_MESSAGE_IGNORE_INSERTS: FORMAT_MESSAGE_OPTIONS = 512u32; +pub type FORMAT_MESSAGE_OPTIONS = u32; +pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: i32 = 8014i32; +pub const FSCTL_GET_REPARSE_POINT: u32 = 589992u32; +pub const FSCTL_SET_REPARSE_POINT: u32 = 589988u32; +pub const FileAlignmentInfo: FILE_INFO_BY_HANDLE_CLASS = 17i32; +pub const FileAllocationInfo: FILE_INFO_BY_HANDLE_CLASS = 5i32; +pub const FileAttributeTagInfo: FILE_INFO_BY_HANDLE_CLASS = 9i32; +pub const FileBasicInfo: FILE_INFO_BY_HANDLE_CLASS = 0i32; +pub const FileCaseSensitiveInfo: FILE_INFO_BY_HANDLE_CLASS = 23i32; +pub const FileCompressionInfo: FILE_INFO_BY_HANDLE_CLASS = 8i32; +pub const FileDispositionInfo: FILE_INFO_BY_HANDLE_CLASS = 4i32; +pub const FileDispositionInfoEx: FILE_INFO_BY_HANDLE_CLASS = 21i32; +pub const FileEndOfFileInfo: FILE_INFO_BY_HANDLE_CLASS = 6i32; +pub const FileFullDirectoryInfo: FILE_INFO_BY_HANDLE_CLASS = 14i32; +pub const FileFullDirectoryRestartInfo: FILE_INFO_BY_HANDLE_CLASS = 15i32; +pub const FileIdBothDirectoryInfo: FILE_INFO_BY_HANDLE_CLASS = 10i32; +pub const FileIdBothDirectoryRestartInfo: FILE_INFO_BY_HANDLE_CLASS = 11i32; +pub const FileIdExtdDirectoryInfo: FILE_INFO_BY_HANDLE_CLASS = 19i32; +pub const FileIdExtdDirectoryRestartInfo: FILE_INFO_BY_HANDLE_CLASS = 20i32; +pub const FileIdInfo: FILE_INFO_BY_HANDLE_CLASS = 18i32; +pub const FileIoPriorityHintInfo: FILE_INFO_BY_HANDLE_CLASS = 12i32; +pub const FileNameInfo: FILE_INFO_BY_HANDLE_CLASS = 2i32; +pub const FileNormalizedNameInfo: FILE_INFO_BY_HANDLE_CLASS = 24i32; +pub const FileRemoteProtocolInfo: FILE_INFO_BY_HANDLE_CLASS = 13i32; +pub const FileRenameInfo: FILE_INFO_BY_HANDLE_CLASS = 3i32; +pub const FileRenameInfoEx: FILE_INFO_BY_HANDLE_CLASS = 22i32; +pub const FileStandardInfo: FILE_INFO_BY_HANDLE_CLASS = 1i32; +pub const FileStorageInfo: FILE_INFO_BY_HANDLE_CLASS = 16i32; +pub const FileStreamInfo: FILE_INFO_BY_HANDLE_CLASS = 7i32; +pub type FindFileHandle = *mut ::core::ffi::c_void; +pub type GENERIC_ACCESS_RIGHTS = u32; +pub const GENERIC_ALL: GENERIC_ACCESS_RIGHTS = 268435456u32; +pub const GENERIC_EXECUTE: GENERIC_ACCESS_RIGHTS = 536870912u32; +pub const GENERIC_READ: GENERIC_ACCESS_RIGHTS = 2147483648u32; +pub const GENERIC_WRITE: GENERIC_ACCESS_RIGHTS = 1073741824u32; +pub type GETFINALPATHNAMEBYHANDLE_FLAGS = u32; +#[repr(C)] +pub struct GUID { + pub data1: u32, + pub data2: u16, + pub data3: u16, + pub data4: [u8; 8], +} +impl GUID { + pub const fn from_u128(uuid: u128) -> Self { + Self { + data1: (uuid >> 96) as u32, + data2: (uuid >> 80 & 0xffff) as u16, + data3: (uuid >> 64 & 0xffff) as u16, + data4: (uuid as u64).to_be_bytes(), + } + } +} +impl ::core::marker::Copy for GUID {} +impl ::core::clone::Clone for GUID { + fn clone(&self) -> Self { + *self + } +} +pub type HANDLE = *mut ::core::ffi::c_void; +pub type HANDLE_FLAGS = u32; +pub const HANDLE_FLAG_INHERIT: HANDLE_FLAGS = 1u32; +pub const HANDLE_FLAG_PROTECT_FROM_CLOSE: HANDLE_FLAGS = 2u32; +pub const HIGH_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 128u32; +pub type HMODULE = *mut ::core::ffi::c_void; +pub type HRESULT = i32; +pub const IDLE_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 64u32; +#[repr(C)] +pub struct IN6_ADDR { + pub u: IN6_ADDR_0, +} +impl ::core::marker::Copy for IN6_ADDR {} +impl ::core::clone::Clone for IN6_ADDR { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union IN6_ADDR_0 { + pub Byte: [u8; 16], + pub Word: [u16; 8], +} +impl ::core::marker::Copy for IN6_ADDR_0 {} +impl ::core::clone::Clone for IN6_ADDR_0 { + fn clone(&self) -> Self { + *self + } +} +pub const INFINITE: u32 = 4294967295u32; +pub const INHERIT_CALLER_PRIORITY: PROCESS_CREATION_FLAGS = 131072u32; +pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32; +pub const INIT_ONCE_INIT_FAILED: u32 = 4u32; +pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32; +pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(-1i32 as _); +pub const INVALID_SOCKET: SOCKET = -1i32 as _; +#[repr(C)] +pub struct IN_ADDR { + pub S_un: IN_ADDR_0, +} +impl ::core::marker::Copy for IN_ADDR {} +impl ::core::clone::Clone for IN_ADDR { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union IN_ADDR_0 { + pub S_un_b: IN_ADDR_0_0, + pub S_un_w: IN_ADDR_0_1, + pub S_addr: u32, +} +impl ::core::marker::Copy for IN_ADDR_0 {} +impl ::core::clone::Clone for IN_ADDR_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct IN_ADDR_0_0 { + pub s_b1: u8, + pub s_b2: u8, + pub s_b3: u8, + pub s_b4: u8, +} +impl ::core::marker::Copy for IN_ADDR_0_0 {} +impl ::core::clone::Clone for IN_ADDR_0_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct IN_ADDR_0_1 { + pub s_w1: u16, + pub s_w2: u16, +} +impl ::core::marker::Copy for IN_ADDR_0_1 {} +impl ::core::clone::Clone for IN_ADDR_0_1 { + fn clone(&self) -> Self { + *self + } +} +pub const IO_REPARSE_TAG_MOUNT_POINT: u32 = 2684354563u32; +pub const IO_REPARSE_TAG_SYMLINK: u32 = 2684354572u32; +#[repr(C)] +pub struct IO_STATUS_BLOCK { + pub Anonymous: IO_STATUS_BLOCK_0, + pub Information: usize, +} +impl ::core::marker::Copy for IO_STATUS_BLOCK {} +impl ::core::clone::Clone for IO_STATUS_BLOCK { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union IO_STATUS_BLOCK_0 { + pub Status: NTSTATUS, + pub Pointer: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for IO_STATUS_BLOCK_0 {} +impl ::core::clone::Clone for IO_STATUS_BLOCK_0 { + fn clone(&self) -> Self { + *self + } +} +pub type IPPROTO = i32; +pub const IPPROTO_AH: IPPROTO = 51i32; +pub const IPPROTO_CBT: IPPROTO = 7i32; +pub const IPPROTO_DSTOPTS: IPPROTO = 60i32; +pub const IPPROTO_EGP: IPPROTO = 8i32; +pub const IPPROTO_ESP: IPPROTO = 50i32; +pub const IPPROTO_FRAGMENT: IPPROTO = 44i32; +pub const IPPROTO_GGP: IPPROTO = 3i32; +pub const IPPROTO_HOPOPTS: IPPROTO = 0i32; +pub const IPPROTO_ICLFXBM: IPPROTO = 78i32; +pub const IPPROTO_ICMP: IPPROTO = 1i32; +pub const IPPROTO_ICMPV6: IPPROTO = 58i32; +pub const IPPROTO_IDP: IPPROTO = 22i32; +pub const IPPROTO_IGMP: IPPROTO = 2i32; +pub const IPPROTO_IGP: IPPROTO = 9i32; +pub const IPPROTO_IP: IPPROTO = 0i32; +pub const IPPROTO_IPV4: IPPROTO = 4i32; +pub const IPPROTO_IPV6: IPPROTO = 41i32; +pub const IPPROTO_L2TP: IPPROTO = 115i32; +pub const IPPROTO_MAX: IPPROTO = 256i32; +pub const IPPROTO_ND: IPPROTO = 77i32; +pub const IPPROTO_NONE: IPPROTO = 59i32; +pub const IPPROTO_PGM: IPPROTO = 113i32; +pub const IPPROTO_PIM: IPPROTO = 103i32; +pub const IPPROTO_PUP: IPPROTO = 12i32; +pub const IPPROTO_RAW: IPPROTO = 255i32; +pub const IPPROTO_RDP: IPPROTO = 27i32; +pub const IPPROTO_RESERVED_IPSEC: IPPROTO = 258i32; +pub const IPPROTO_RESERVED_IPSECOFFLOAD: IPPROTO = 259i32; +pub const IPPROTO_RESERVED_MAX: IPPROTO = 261i32; +pub const IPPROTO_RESERVED_RAW: IPPROTO = 257i32; +pub const IPPROTO_RESERVED_WNV: IPPROTO = 260i32; +pub const IPPROTO_RM: IPPROTO = 113i32; +pub const IPPROTO_ROUTING: IPPROTO = 43i32; +pub const IPPROTO_SCTP: IPPROTO = 132i32; +pub const IPPROTO_ST: IPPROTO = 5i32; +pub const IPPROTO_TCP: IPPROTO = 6i32; +pub const IPPROTO_UDP: IPPROTO = 17i32; +pub const IPV6_ADD_MEMBERSHIP: i32 = 12i32; +pub const IPV6_DROP_MEMBERSHIP: i32 = 13i32; +#[repr(C)] +pub struct IPV6_MREQ { + pub ipv6mr_multiaddr: IN6_ADDR, + pub ipv6mr_interface: u32, +} +impl ::core::marker::Copy for IPV6_MREQ {} +impl ::core::clone::Clone for IPV6_MREQ { + fn clone(&self) -> Self { + *self + } +} +pub const IPV6_MULTICAST_LOOP: i32 = 11i32; +pub const IPV6_V6ONLY: i32 = 27i32; +pub const IP_ADD_MEMBERSHIP: i32 = 12i32; +pub const IP_DROP_MEMBERSHIP: i32 = 13i32; +#[repr(C)] +pub struct IP_MREQ { + pub imr_multiaddr: IN_ADDR, + pub imr_interface: IN_ADDR, +} +impl ::core::marker::Copy for IP_MREQ {} +impl ::core::clone::Clone for IP_MREQ { + fn clone(&self) -> Self { + *self + } +} +pub const IP_MULTICAST_LOOP: i32 = 11i32; +pub const IP_MULTICAST_TTL: i32 = 10i32; +pub const IP_TTL: i32 = 4i32; +#[repr(C)] +pub struct LINGER { + pub l_onoff: u16, + pub l_linger: u16, +} +impl ::core::marker::Copy for LINGER {} +impl ::core::clone::Clone for LINGER { + fn clone(&self) -> Self { + *self + } +} +pub type LPOVERLAPPED_COMPLETION_ROUTINE = ::core::option::Option< + unsafe extern "system" fn( + dwerrorcode: u32, + dwnumberofbytestransfered: u32, + lpoverlapped: *mut OVERLAPPED, + ) -> (), +>; +pub type LPPROGRESS_ROUTINE = ::core::option::Option< + unsafe extern "system" fn( + totalfilesize: i64, + totalbytestransferred: i64, + streamsize: i64, + streambytestransferred: i64, + dwstreamnumber: u32, + dwcallbackreason: LPPROGRESS_ROUTINE_CALLBACK_REASON, + hsourcefile: HANDLE, + hdestinationfile: HANDLE, + lpdata: *const ::core::ffi::c_void, + ) -> u32, +>; +pub type LPPROGRESS_ROUTINE_CALLBACK_REASON = u32; +pub type LPTHREAD_START_ROUTINE = ::core::option::Option< + unsafe extern "system" fn(lpthreadparameter: *mut ::core::ffi::c_void) -> u32, +>; +pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = ::core::option::Option< + unsafe extern "system" fn( + dwerror: u32, + cbtransferred: u32, + lpoverlapped: *mut OVERLAPPED, + dwflags: u32, + ) -> (), +>; +#[repr(C)] +pub struct M128A { + pub Low: u64, + pub High: i64, +} +impl ::core::marker::Copy for M128A {} +impl ::core::clone::Clone for M128A { + fn clone(&self) -> Self { + *self + } +} +pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: u32 = 16384u32; +pub const MAX_PATH: u32 = 260u32; +pub const MB_COMPOSITE: MULTI_BYTE_TO_WIDE_CHAR_FLAGS = 2u32; +pub const MB_ERR_INVALID_CHARS: MULTI_BYTE_TO_WIDE_CHAR_FLAGS = 8u32; +pub const MB_PRECOMPOSED: MULTI_BYTE_TO_WIDE_CHAR_FLAGS = 1u32; +pub const MB_USEGLYPHCHARS: MULTI_BYTE_TO_WIDE_CHAR_FLAGS = 4u32; +pub const MOVEFILE_COPY_ALLOWED: MOVE_FILE_FLAGS = 2u32; +pub const MOVEFILE_CREATE_HARDLINK: MOVE_FILE_FLAGS = 16u32; +pub const MOVEFILE_DELAY_UNTIL_REBOOT: MOVE_FILE_FLAGS = 4u32; +pub const MOVEFILE_FAIL_IF_NOT_TRACKABLE: MOVE_FILE_FLAGS = 32u32; +pub const MOVEFILE_REPLACE_EXISTING: MOVE_FILE_FLAGS = 1u32; +pub const MOVEFILE_WRITE_THROUGH: MOVE_FILE_FLAGS = 8u32; +pub type MOVE_FILE_FLAGS = u32; +pub const MSG_DONTROUTE: SEND_RECV_FLAGS = 4i32; +pub const MSG_OOB: SEND_RECV_FLAGS = 1i32; +pub const MSG_PEEK: SEND_RECV_FLAGS = 2i32; +pub const MSG_PUSH_IMMEDIATE: SEND_RECV_FLAGS = 32i32; +pub const MSG_WAITALL: SEND_RECV_FLAGS = 8i32; +pub type MULTI_BYTE_TO_WIDE_CHAR_FLAGS = u32; +pub const MaximumFileInfoByHandleClass: FILE_INFO_BY_HANDLE_CLASS = 25i32; +pub type NAMED_PIPE_MODE = u32; +pub const NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 32u32; +pub const NO_ERROR: WIN32_ERROR = 0u32; +pub type NTCREATEFILE_CREATE_DISPOSITION = u32; +pub type NTCREATEFILE_CREATE_OPTIONS = u32; +pub type NTSTATUS = i32; +#[repr(C)] +pub struct OBJECT_ATTRIBUTES { + pub Length: u32, + pub RootDirectory: HANDLE, + pub ObjectName: *mut UNICODE_STRING, + pub Attributes: u32, + pub SecurityDescriptor: *mut ::core::ffi::c_void, + pub SecurityQualityOfService: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for OBJECT_ATTRIBUTES {} +impl ::core::clone::Clone for OBJECT_ATTRIBUTES { + fn clone(&self) -> Self { + *self + } +} +pub const OBJ_DONT_REPARSE: i32 = 4096i32; +pub const OPEN_ALWAYS: FILE_CREATION_DISPOSITION = 4u32; +pub const OPEN_EXISTING: FILE_CREATION_DISPOSITION = 3u32; +#[repr(C)] +pub struct OVERLAPPED { + pub Internal: usize, + pub InternalHigh: usize, + pub Anonymous: OVERLAPPED_0, + pub hEvent: HANDLE, +} +impl ::core::marker::Copy for OVERLAPPED {} +impl ::core::clone::Clone for OVERLAPPED { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union OVERLAPPED_0 { + pub Anonymous: OVERLAPPED_0_0, + pub Pointer: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for OVERLAPPED_0 {} +impl ::core::clone::Clone for OVERLAPPED_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct OVERLAPPED_0_0 { + pub Offset: u32, + pub OffsetHigh: u32, +} +impl ::core::marker::Copy for OVERLAPPED_0_0 {} +impl ::core::clone::Clone for OVERLAPPED_0_0 { + fn clone(&self) -> Self { + *self + } +} +pub type PCSTR = *const u8; +pub type PCWSTR = *const u16; +pub type PIO_APC_ROUTINE = ::core::option::Option< + unsafe extern "system" fn( + apccontext: *const ::core::ffi::c_void, + iostatusblock: *const IO_STATUS_BLOCK, + reserved: u32, + ) -> (), +>; +pub const PIPE_ACCEPT_REMOTE_CLIENTS: NAMED_PIPE_MODE = 0u32; +pub const PIPE_ACCESS_DUPLEX: FILE_FLAGS_AND_ATTRIBUTES = 3u32; +pub const PIPE_ACCESS_INBOUND: FILE_FLAGS_AND_ATTRIBUTES = 1u32; +pub const PIPE_ACCESS_OUTBOUND: FILE_FLAGS_AND_ATTRIBUTES = 2u32; +pub const PIPE_CLIENT_END: NAMED_PIPE_MODE = 0u32; +pub const PIPE_NOWAIT: NAMED_PIPE_MODE = 1u32; +pub const PIPE_READMODE_BYTE: NAMED_PIPE_MODE = 0u32; +pub const PIPE_READMODE_MESSAGE: NAMED_PIPE_MODE = 2u32; +pub const PIPE_REJECT_REMOTE_CLIENTS: NAMED_PIPE_MODE = 8u32; +pub const PIPE_SERVER_END: NAMED_PIPE_MODE = 1u32; +pub const PIPE_TYPE_BYTE: NAMED_PIPE_MODE = 0u32; +pub const PIPE_TYPE_MESSAGE: NAMED_PIPE_MODE = 4u32; +pub const PIPE_WAIT: NAMED_PIPE_MODE = 0u32; +pub type PROCESSOR_ARCHITECTURE = u16; +pub type PROCESS_CREATION_FLAGS = u32; +#[repr(C)] +pub struct PROCESS_INFORMATION { + pub hProcess: HANDLE, + pub hThread: HANDLE, + pub dwProcessId: u32, + pub dwThreadId: u32, +} +impl ::core::marker::Copy for PROCESS_INFORMATION {} +impl ::core::clone::Clone for PROCESS_INFORMATION { + fn clone(&self) -> Self { + *self + } +} +pub const PROCESS_MODE_BACKGROUND_BEGIN: PROCESS_CREATION_FLAGS = 1048576u32; +pub const PROCESS_MODE_BACKGROUND_END: PROCESS_CREATION_FLAGS = 2097152u32; +pub const PROFILE_KERNEL: PROCESS_CREATION_FLAGS = 536870912u32; +pub const PROFILE_SERVER: PROCESS_CREATION_FLAGS = 1073741824u32; +pub const PROFILE_USER: PROCESS_CREATION_FLAGS = 268435456u32; +pub const PROGRESS_CONTINUE: u32 = 0u32; +pub type PSTR = *mut u8; +pub type PVECTORED_EXCEPTION_HANDLER = ::core::option::Option< + unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32, +>; +pub type PWSTR = *mut u16; +pub const READ_CONTROL: FILE_ACCESS_RIGHTS = 131072u32; +pub const REALTIME_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 256u32; +#[repr(C)] +pub struct RTL_CONDITION_VARIABLE { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for RTL_CONDITION_VARIABLE {} +impl ::core::clone::Clone for RTL_CONDITION_VARIABLE { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union RTL_RUN_ONCE { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for RTL_RUN_ONCE {} +impl ::core::clone::Clone for RTL_RUN_ONCE { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct RTL_SRWLOCK { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for RTL_SRWLOCK {} +impl ::core::clone::Clone for RTL_SRWLOCK { + fn clone(&self) -> Self { + *self + } +} +pub const SD_BOTH: WINSOCK_SHUTDOWN_HOW = 2i32; +pub const SD_RECEIVE: WINSOCK_SHUTDOWN_HOW = 0i32; +pub const SD_SEND: WINSOCK_SHUTDOWN_HOW = 1i32; +pub const SECURITY_ANONYMOUS: FILE_FLAGS_AND_ATTRIBUTES = 0u32; +#[repr(C)] +pub struct SECURITY_ATTRIBUTES { + pub nLength: u32, + pub lpSecurityDescriptor: *mut ::core::ffi::c_void, + pub bInheritHandle: BOOL, +} +impl ::core::marker::Copy for SECURITY_ATTRIBUTES {} +impl ::core::clone::Clone for SECURITY_ATTRIBUTES { + fn clone(&self) -> Self { + *self + } +} +pub const SECURITY_CONTEXT_TRACKING: FILE_FLAGS_AND_ATTRIBUTES = 262144u32; +pub const SECURITY_DELEGATION: FILE_FLAGS_AND_ATTRIBUTES = 196608u32; +pub const SECURITY_EFFECTIVE_ONLY: FILE_FLAGS_AND_ATTRIBUTES = 524288u32; +pub const SECURITY_IDENTIFICATION: FILE_FLAGS_AND_ATTRIBUTES = 65536u32; +pub const SECURITY_IMPERSONATION: FILE_FLAGS_AND_ATTRIBUTES = 131072u32; +pub const SECURITY_SQOS_PRESENT: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32; +pub const SECURITY_VALID_SQOS_FLAGS: FILE_FLAGS_AND_ATTRIBUTES = 2031616u32; +pub type SEND_RECV_FLAGS = i32; +pub type SET_FILE_POINTER_MOVE_METHOD = u32; +#[repr(C)] +pub struct SOCKADDR { + pub sa_family: ADDRESS_FAMILY, + pub sa_data: [u8; 14], +} +impl ::core::marker::Copy for SOCKADDR {} +impl ::core::clone::Clone for SOCKADDR { + fn clone(&self) -> Self { + *self + } +} +#[cfg(target_pointer_width = "32")] +pub type SOCKET = u32; +#[cfg(target_pointer_width = "64")] +pub type SOCKET = u64; +pub const SOCKET_ERROR: i32 = -1i32; +pub const SOCK_DGRAM: WINSOCK_SOCKET_TYPE = 2i32; +pub const SOCK_RAW: WINSOCK_SOCKET_TYPE = 3i32; +pub const SOCK_RDM: WINSOCK_SOCKET_TYPE = 4i32; +pub const SOCK_SEQPACKET: WINSOCK_SOCKET_TYPE = 5i32; +pub const SOCK_STREAM: WINSOCK_SOCKET_TYPE = 1i32; +pub const SOL_SOCKET: i32 = 65535i32; +pub const SO_BROADCAST: i32 = 32i32; +pub const SO_ERROR: i32 = 4103i32; +pub const SO_LINGER: i32 = 128i32; +pub const SO_RCVTIMEO: i32 = 4102i32; +pub const SO_SNDTIMEO: i32 = 4101i32; +pub const SPECIFIC_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 65535u32; +pub const STACK_SIZE_PARAM_IS_A_RESERVATION: THREAD_CREATION_FLAGS = 65536u32; +pub const STANDARD_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 2031616u32; +pub const STANDARD_RIGHTS_EXECUTE: FILE_ACCESS_RIGHTS = 131072u32; +pub const STANDARD_RIGHTS_READ: FILE_ACCESS_RIGHTS = 131072u32; +pub const STANDARD_RIGHTS_REQUIRED: FILE_ACCESS_RIGHTS = 983040u32; +pub const STANDARD_RIGHTS_WRITE: FILE_ACCESS_RIGHTS = 131072u32; +pub const STARTF_FORCEOFFFEEDBACK: STARTUPINFOW_FLAGS = 128u32; +pub const STARTF_FORCEONFEEDBACK: STARTUPINFOW_FLAGS = 64u32; +pub const STARTF_PREVENTPINNING: STARTUPINFOW_FLAGS = 8192u32; +pub const STARTF_RUNFULLSCREEN: STARTUPINFOW_FLAGS = 32u32; +pub const STARTF_TITLEISAPPID: STARTUPINFOW_FLAGS = 4096u32; +pub const STARTF_TITLEISLINKNAME: STARTUPINFOW_FLAGS = 2048u32; +pub const STARTF_UNTRUSTEDSOURCE: STARTUPINFOW_FLAGS = 32768u32; +pub const STARTF_USECOUNTCHARS: STARTUPINFOW_FLAGS = 8u32; +pub const STARTF_USEFILLATTRIBUTE: STARTUPINFOW_FLAGS = 16u32; +pub const STARTF_USEHOTKEY: STARTUPINFOW_FLAGS = 512u32; +pub const STARTF_USEPOSITION: STARTUPINFOW_FLAGS = 4u32; +pub const STARTF_USESHOWWINDOW: STARTUPINFOW_FLAGS = 1u32; +pub const STARTF_USESIZE: STARTUPINFOW_FLAGS = 2u32; +pub const STARTF_USESTDHANDLES: STARTUPINFOW_FLAGS = 256u32; +#[repr(C)] +pub struct STARTUPINFOW { + pub cb: u32, + pub lpReserved: PWSTR, + pub lpDesktop: PWSTR, + pub lpTitle: PWSTR, + pub dwX: u32, + pub dwY: u32, + pub dwXSize: u32, + pub dwYSize: u32, + pub dwXCountChars: u32, + pub dwYCountChars: u32, + pub dwFillAttribute: u32, + pub dwFlags: STARTUPINFOW_FLAGS, + pub wShowWindow: u16, + pub cbReserved2: u16, + pub lpReserved2: *mut u8, + pub hStdInput: HANDLE, + pub hStdOutput: HANDLE, + pub hStdError: HANDLE, +} +impl ::core::marker::Copy for STARTUPINFOW {} +impl ::core::clone::Clone for STARTUPINFOW { + fn clone(&self) -> Self { + *self + } +} +pub type STARTUPINFOW_FLAGS = u32; +pub const STATUS_DELETE_PENDING: NTSTATUS = -1073741738i32; +pub const STATUS_END_OF_FILE: NTSTATUS = -1073741807i32; +pub const STATUS_INVALID_PARAMETER: NTSTATUS = -1073741811i32; +pub const STATUS_PENDING: NTSTATUS = 259i32; +pub const STATUS_SUCCESS: NTSTATUS = 0i32; +pub const STD_ERROR_HANDLE: STD_HANDLE = 4294967284u32; +pub type STD_HANDLE = u32; +pub const STD_INPUT_HANDLE: STD_HANDLE = 4294967286u32; +pub const STD_OUTPUT_HANDLE: STD_HANDLE = 4294967285u32; +pub type SYMBOLIC_LINK_FLAGS = u32; +pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: SYMBOLIC_LINK_FLAGS = 2u32; +pub const SYMBOLIC_LINK_FLAG_DIRECTORY: SYMBOLIC_LINK_FLAGS = 1u32; +pub const SYMLINK_FLAG_RELATIVE: u32 = 1u32; +pub const SYNCHRONIZE: FILE_ACCESS_RIGHTS = 1048576u32; +#[repr(C)] +pub struct SYSTEM_INFO { + pub Anonymous: SYSTEM_INFO_0, + pub dwPageSize: u32, + pub lpMinimumApplicationAddress: *mut ::core::ffi::c_void, + pub lpMaximumApplicationAddress: *mut ::core::ffi::c_void, + pub dwActiveProcessorMask: usize, + pub dwNumberOfProcessors: u32, + pub dwProcessorType: u32, + pub dwAllocationGranularity: u32, + pub wProcessorLevel: u16, + pub wProcessorRevision: u16, +} +impl ::core::marker::Copy for SYSTEM_INFO {} +impl ::core::clone::Clone for SYSTEM_INFO { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub union SYSTEM_INFO_0 { + pub dwOemId: u32, + pub Anonymous: SYSTEM_INFO_0_0, +} +impl ::core::marker::Copy for SYSTEM_INFO_0 {} +impl ::core::clone::Clone for SYSTEM_INFO_0 { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct SYSTEM_INFO_0_0 { + pub wProcessorArchitecture: PROCESSOR_ARCHITECTURE, + pub wReserved: u16, +} +impl ::core::marker::Copy for SYSTEM_INFO_0_0 {} +impl ::core::clone::Clone for SYSTEM_INFO_0_0 { + fn clone(&self) -> Self { + *self + } +} +pub const TCP_NODELAY: i32 = 1i32; +pub const THREAD_CREATE_RUN_IMMEDIATELY: THREAD_CREATION_FLAGS = 0u32; +pub const THREAD_CREATE_SUSPENDED: THREAD_CREATION_FLAGS = 4u32; +pub type THREAD_CREATION_FLAGS = u32; +#[repr(C)] +pub struct TIMEVAL { + pub tv_sec: i32, + pub tv_usec: i32, +} +impl ::core::marker::Copy for TIMEVAL {} +impl ::core::clone::Clone for TIMEVAL { + fn clone(&self) -> Self { + *self + } +} +pub const TLS_OUT_OF_INDEXES: u32 = 4294967295u32; +pub type TOKEN_ACCESS_MASK = u32; +pub const TOKEN_ACCESS_PSEUDO_HANDLE: TOKEN_ACCESS_MASK = 24u32; +pub const TOKEN_ACCESS_PSEUDO_HANDLE_WIN8: TOKEN_ACCESS_MASK = 24u32; +pub const TOKEN_ACCESS_SYSTEM_SECURITY: TOKEN_ACCESS_MASK = 16777216u32; +pub const TOKEN_ADJUST_DEFAULT: TOKEN_ACCESS_MASK = 128u32; +pub const TOKEN_ADJUST_GROUPS: TOKEN_ACCESS_MASK = 64u32; +pub const TOKEN_ADJUST_PRIVILEGES: TOKEN_ACCESS_MASK = 32u32; +pub const TOKEN_ADJUST_SESSIONID: TOKEN_ACCESS_MASK = 256u32; +pub const TOKEN_ALL_ACCESS: TOKEN_ACCESS_MASK = 983551u32; +pub const TOKEN_ASSIGN_PRIMARY: TOKEN_ACCESS_MASK = 1u32; +pub const TOKEN_DELETE: TOKEN_ACCESS_MASK = 65536u32; +pub const TOKEN_DUPLICATE: TOKEN_ACCESS_MASK = 2u32; +pub const TOKEN_EXECUTE: TOKEN_ACCESS_MASK = 131072u32; +pub const TOKEN_IMPERSONATE: TOKEN_ACCESS_MASK = 4u32; +pub const TOKEN_QUERY: TOKEN_ACCESS_MASK = 8u32; +pub const TOKEN_QUERY_SOURCE: TOKEN_ACCESS_MASK = 16u32; +pub const TOKEN_READ: TOKEN_ACCESS_MASK = 131080u32; +pub const TOKEN_READ_CONTROL: TOKEN_ACCESS_MASK = 131072u32; +pub const TOKEN_TRUST_CONSTRAINT_MASK: TOKEN_ACCESS_MASK = 131096u32; +pub const TOKEN_WRITE: TOKEN_ACCESS_MASK = 131296u32; +pub const TOKEN_WRITE_DAC: TOKEN_ACCESS_MASK = 262144u32; +pub const TOKEN_WRITE_OWNER: TOKEN_ACCESS_MASK = 524288u32; +pub const TRUE: BOOL = 1i32; +pub const TRUNCATE_EXISTING: FILE_CREATION_DISPOSITION = 5u32; +#[repr(C)] +pub struct UNICODE_STRING { + pub Length: u16, + pub MaximumLength: u16, + pub Buffer: PWSTR, +} +impl ::core::marker::Copy for UNICODE_STRING {} +impl ::core::clone::Clone for UNICODE_STRING { + fn clone(&self) -> Self { + *self + } +} +pub const VOLUME_NAME_DOS: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32; +pub const VOLUME_NAME_GUID: GETFINALPATHNAMEBYHANDLE_FLAGS = 1u32; +pub const VOLUME_NAME_NONE: GETFINALPATHNAMEBYHANDLE_FLAGS = 4u32; +pub const WAIT_ABANDONED: WIN32_ERROR = 128u32; +pub const WAIT_ABANDONED_0: WIN32_ERROR = 128u32; +pub const WAIT_FAILED: WIN32_ERROR = 4294967295u32; +pub const WAIT_IO_COMPLETION: WIN32_ERROR = 192u32; +pub const WAIT_OBJECT_0: WIN32_ERROR = 0u32; +pub const WAIT_TIMEOUT: WIN32_ERROR = 258u32; +pub const WC_ERR_INVALID_CHARS: u32 = 128u32; +pub type WIN32_ERROR = u32; +#[repr(C)] +pub struct WIN32_FIND_DATAW { + pub dwFileAttributes: u32, + pub ftCreationTime: FILETIME, + pub ftLastAccessTime: FILETIME, + pub ftLastWriteTime: FILETIME, + pub nFileSizeHigh: u32, + pub nFileSizeLow: u32, + pub dwReserved0: u32, + pub dwReserved1: u32, + pub cFileName: [u16; 260], + pub cAlternateFileName: [u16; 14], +} +impl ::core::marker::Copy for WIN32_FIND_DATAW {} +impl ::core::clone::Clone for WIN32_FIND_DATAW { + fn clone(&self) -> Self { + *self + } +} +pub type WINSOCK_SHUTDOWN_HOW = i32; +pub type WINSOCK_SOCKET_TYPE = i32; +pub const WRITE_DAC: FILE_ACCESS_RIGHTS = 262144u32; +pub const WRITE_OWNER: FILE_ACCESS_RIGHTS = 524288u32; +pub const WSABASEERR: WSA_ERROR = 10000i32; +#[repr(C)] +pub struct WSABUF { + pub len: u32, + pub buf: PSTR, +} +impl ::core::marker::Copy for WSABUF {} +impl ::core::clone::Clone for WSABUF { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +pub struct WSADATA { + pub wVersion: u16, + pub wHighVersion: u16, + pub iMaxSockets: u16, + pub iMaxUdpDg: u16, + pub lpVendorInfo: PSTR, + pub szDescription: [u8; 257], + pub szSystemStatus: [u8; 129], +} +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +impl ::core::marker::Copy for WSADATA {} +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +impl ::core::clone::Clone for WSADATA { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "x86")] +pub struct WSADATA { + pub wVersion: u16, + pub wHighVersion: u16, + pub szDescription: [u8; 257], + pub szSystemStatus: [u8; 129], + pub iMaxSockets: u16, + pub iMaxUdpDg: u16, + pub lpVendorInfo: PSTR, +} +#[cfg(target_arch = "x86")] +impl ::core::marker::Copy for WSADATA {} +#[cfg(target_arch = "x86")] +impl ::core::clone::Clone for WSADATA { + fn clone(&self) -> Self { + *self + } +} +pub const WSAEACCES: WSA_ERROR = 10013i32; +pub const WSAEADDRINUSE: WSA_ERROR = 10048i32; +pub const WSAEADDRNOTAVAIL: WSA_ERROR = 10049i32; +pub const WSAEAFNOSUPPORT: WSA_ERROR = 10047i32; +pub const WSAEALREADY: WSA_ERROR = 10037i32; +pub const WSAEBADF: WSA_ERROR = 10009i32; +pub const WSAECANCELLED: WSA_ERROR = 10103i32; +pub const WSAECONNABORTED: WSA_ERROR = 10053i32; +pub const WSAECONNREFUSED: WSA_ERROR = 10061i32; +pub const WSAECONNRESET: WSA_ERROR = 10054i32; +pub const WSAEDESTADDRREQ: WSA_ERROR = 10039i32; +pub const WSAEDISCON: WSA_ERROR = 10101i32; +pub const WSAEDQUOT: WSA_ERROR = 10069i32; +pub const WSAEFAULT: WSA_ERROR = 10014i32; +pub const WSAEHOSTDOWN: WSA_ERROR = 10064i32; +pub const WSAEHOSTUNREACH: WSA_ERROR = 10065i32; +pub const WSAEINPROGRESS: WSA_ERROR = 10036i32; +pub const WSAEINTR: WSA_ERROR = 10004i32; +pub const WSAEINVAL: WSA_ERROR = 10022i32; +pub const WSAEINVALIDPROCTABLE: WSA_ERROR = 10104i32; +pub const WSAEINVALIDPROVIDER: WSA_ERROR = 10105i32; +pub const WSAEISCONN: WSA_ERROR = 10056i32; +pub const WSAELOOP: WSA_ERROR = 10062i32; +pub const WSAEMFILE: WSA_ERROR = 10024i32; +pub const WSAEMSGSIZE: WSA_ERROR = 10040i32; +pub const WSAENAMETOOLONG: WSA_ERROR = 10063i32; +pub const WSAENETDOWN: WSA_ERROR = 10050i32; +pub const WSAENETRESET: WSA_ERROR = 10052i32; +pub const WSAENETUNREACH: WSA_ERROR = 10051i32; +pub const WSAENOBUFS: WSA_ERROR = 10055i32; +pub const WSAENOMORE: WSA_ERROR = 10102i32; +pub const WSAENOPROTOOPT: WSA_ERROR = 10042i32; +pub const WSAENOTCONN: WSA_ERROR = 10057i32; +pub const WSAENOTEMPTY: WSA_ERROR = 10066i32; +pub const WSAENOTSOCK: WSA_ERROR = 10038i32; +pub const WSAEOPNOTSUPP: WSA_ERROR = 10045i32; +pub const WSAEPFNOSUPPORT: WSA_ERROR = 10046i32; +pub const WSAEPROCLIM: WSA_ERROR = 10067i32; +pub const WSAEPROTONOSUPPORT: WSA_ERROR = 10043i32; +pub const WSAEPROTOTYPE: WSA_ERROR = 10041i32; +pub const WSAEPROVIDERFAILEDINIT: WSA_ERROR = 10106i32; +pub const WSAEREFUSED: WSA_ERROR = 10112i32; +pub const WSAEREMOTE: WSA_ERROR = 10071i32; +pub const WSAESHUTDOWN: WSA_ERROR = 10058i32; +pub const WSAESOCKTNOSUPPORT: WSA_ERROR = 10044i32; +pub const WSAESTALE: WSA_ERROR = 10070i32; +pub const WSAETIMEDOUT: WSA_ERROR = 10060i32; +pub const WSAETOOMANYREFS: WSA_ERROR = 10059i32; +pub const WSAEUSERS: WSA_ERROR = 10068i32; +pub const WSAEWOULDBLOCK: WSA_ERROR = 10035i32; +pub const WSAHOST_NOT_FOUND: WSA_ERROR = 11001i32; +pub const WSANOTINITIALISED: WSA_ERROR = 10093i32; +pub const WSANO_DATA: WSA_ERROR = 11004i32; +pub const WSANO_RECOVERY: WSA_ERROR = 11003i32; +#[repr(C)] +pub struct WSAPROTOCOLCHAIN { + pub ChainLen: i32, + pub ChainEntries: [u32; 7], +} +impl ::core::marker::Copy for WSAPROTOCOLCHAIN {} +impl ::core::clone::Clone for WSAPROTOCOLCHAIN { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +pub struct WSAPROTOCOL_INFOW { + pub dwServiceFlags1: u32, + pub dwServiceFlags2: u32, + pub dwServiceFlags3: u32, + pub dwServiceFlags4: u32, + pub dwProviderFlags: u32, + pub ProviderId: GUID, + pub dwCatalogEntryId: u32, + pub ProtocolChain: WSAPROTOCOLCHAIN, + pub iVersion: i32, + pub iAddressFamily: i32, + pub iMaxSockAddr: i32, + pub iMinSockAddr: i32, + pub iSocketType: i32, + pub iProtocol: i32, + pub iProtocolMaxOffset: i32, + pub iNetworkByteOrder: i32, + pub iSecurityScheme: i32, + pub dwMessageSize: u32, + pub dwProviderReserved: u32, + pub szProtocol: [u16; 256], +} +impl ::core::marker::Copy for WSAPROTOCOL_INFOW {} +impl ::core::clone::Clone for WSAPROTOCOL_INFOW { + fn clone(&self) -> Self { + *self + } +} +pub const WSASERVICE_NOT_FOUND: WSA_ERROR = 10108i32; +pub const WSASYSCALLFAILURE: WSA_ERROR = 10107i32; +pub const WSASYSNOTREADY: WSA_ERROR = 10091i32; +pub const WSATRY_AGAIN: WSA_ERROR = 11002i32; +pub const WSATYPE_NOT_FOUND: WSA_ERROR = 10109i32; +pub const WSAVERNOTSUPPORTED: WSA_ERROR = 10092i32; +pub type WSA_ERROR = i32; +pub const WSA_E_CANCELLED: WSA_ERROR = 10111i32; +pub const WSA_E_NO_MORE: WSA_ERROR = 10110i32; +pub const WSA_FLAG_NO_HANDLE_INHERIT: u32 = 128u32; +pub const WSA_FLAG_OVERLAPPED: u32 = 1u32; +pub const WSA_INVALID_HANDLE: WSA_ERROR = 6i32; +pub const WSA_INVALID_PARAMETER: WSA_ERROR = 87i32; +pub const WSA_IO_INCOMPLETE: WSA_ERROR = 996i32; +pub const WSA_IO_PENDING: WSA_ERROR = 997i32; +pub const WSA_IPSEC_NAME_POLICY_ERROR: WSA_ERROR = 11033i32; +pub const WSA_NOT_ENOUGH_MEMORY: WSA_ERROR = 8i32; +pub const WSA_OPERATION_ABORTED: WSA_ERROR = 995i32; +pub const WSA_QOS_ADMISSION_FAILURE: WSA_ERROR = 11010i32; +pub const WSA_QOS_BAD_OBJECT: WSA_ERROR = 11013i32; +pub const WSA_QOS_BAD_STYLE: WSA_ERROR = 11012i32; +pub const WSA_QOS_EFILTERCOUNT: WSA_ERROR = 11021i32; +pub const WSA_QOS_EFILTERSTYLE: WSA_ERROR = 11019i32; +pub const WSA_QOS_EFILTERTYPE: WSA_ERROR = 11020i32; +pub const WSA_QOS_EFLOWCOUNT: WSA_ERROR = 11023i32; +pub const WSA_QOS_EFLOWDESC: WSA_ERROR = 11026i32; +pub const WSA_QOS_EFLOWSPEC: WSA_ERROR = 11017i32; +pub const WSA_QOS_EOBJLENGTH: WSA_ERROR = 11022i32; +pub const WSA_QOS_EPOLICYOBJ: WSA_ERROR = 11025i32; +pub const WSA_QOS_EPROVSPECBUF: WSA_ERROR = 11018i32; +pub const WSA_QOS_EPSFILTERSPEC: WSA_ERROR = 11028i32; +pub const WSA_QOS_EPSFLOWSPEC: WSA_ERROR = 11027i32; +pub const WSA_QOS_ESDMODEOBJ: WSA_ERROR = 11029i32; +pub const WSA_QOS_ESERVICETYPE: WSA_ERROR = 11016i32; +pub const WSA_QOS_ESHAPERATEOBJ: WSA_ERROR = 11030i32; +pub const WSA_QOS_EUNKOWNPSOBJ: WSA_ERROR = 11024i32; +pub const WSA_QOS_GENERIC_ERROR: WSA_ERROR = 11015i32; +pub const WSA_QOS_NO_RECEIVERS: WSA_ERROR = 11008i32; +pub const WSA_QOS_NO_SENDERS: WSA_ERROR = 11007i32; +pub const WSA_QOS_POLICY_FAILURE: WSA_ERROR = 11011i32; +pub const WSA_QOS_RECEIVERS: WSA_ERROR = 11005i32; +pub const WSA_QOS_REQUEST_CONFIRMED: WSA_ERROR = 11009i32; +pub const WSA_QOS_RESERVED_PETYPE: WSA_ERROR = 11031i32; +pub const WSA_QOS_SENDERS: WSA_ERROR = 11006i32; +pub const WSA_QOS_TRAFFIC_CTRL_ERROR: WSA_ERROR = 11014i32; +pub const WSA_SECURE_HOST_NOT_FOUND: WSA_ERROR = 11032i32; +pub const WSA_WAIT_EVENT_0: WSA_ERROR = 0i32; +pub const WSA_WAIT_IO_COMPLETION: WSA_ERROR = 192i32; +#[repr(C)] +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +pub struct XSAVE_FORMAT { + pub ControlWord: u16, + pub StatusWord: u16, + pub TagWord: u8, + pub Reserved1: u8, + pub ErrorOpcode: u16, + pub ErrorOffset: u32, + pub ErrorSelector: u16, + pub Reserved2: u16, + pub DataOffset: u32, + pub DataSelector: u16, + pub Reserved3: u16, + pub MxCsr: u32, + pub MxCsr_Mask: u32, + pub FloatRegisters: [M128A; 8], + pub XmmRegisters: [M128A; 16], + pub Reserved4: [u8; 96], +} +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +impl ::core::marker::Copy for XSAVE_FORMAT {} +#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] +impl ::core::clone::Clone for XSAVE_FORMAT { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[cfg(target_arch = "x86")] +pub struct XSAVE_FORMAT { + pub ControlWord: u16, + pub StatusWord: u16, + pub TagWord: u8, + pub Reserved1: u8, + pub ErrorOpcode: u16, + pub ErrorOffset: u32, + pub ErrorSelector: u16, + pub Reserved2: u16, + pub DataOffset: u32, + pub DataSelector: u16, + pub Reserved3: u16, + pub MxCsr: u32, + pub MxCsr_Mask: u32, + pub FloatRegisters: [M128A; 8], + pub XmmRegisters: [M128A; 8], + pub Reserved4: [u8; 224], +} +#[cfg(target_arch = "x86")] +impl ::core::marker::Copy for XSAVE_FORMAT {} +#[cfg(target_arch = "x86")] +impl ::core::clone::Clone for XSAVE_FORMAT { + fn clone(&self) -> Self { + *self + } +} diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs index 7dff81ecb8d..4fe95d41116 100644 --- a/library/std/src/sys/windows/compat.rs +++ b/library/std/src/sys/windows/compat.rs @@ -114,17 +114,20 @@ impl Module { /// (e.g. kernel32 and ntdll). pub unsafe fn new(name: &CStr) -> Option<Self> { // SAFETY: A CStr is always null terminated. - let module = c::GetModuleHandleA(name.as_ptr()); + let module = c::GetModuleHandleA(name.as_ptr().cast::<u8>()); NonNull::new(module).map(Self) } // Try to get the address of a function. pub fn proc_address(self, name: &CStr) -> Option<NonNull<c_void>> { - // SAFETY: - // `self.0` will always be a valid module. - // A CStr is always null terminated. - let proc = unsafe { c::GetProcAddress(self.0.as_ptr(), name.as_ptr()) }; - NonNull::new(proc) + unsafe { + // SAFETY: + // `self.0` will always be a valid module. + // A CStr is always null terminated. + let proc = c::GetProcAddress(self.0.as_ptr(), name.as_ptr().cast::<u8>()); + // SAFETY: `GetProcAddress` returns None on null. + proc.map(|p| NonNull::new_unchecked(p as *mut c_void)) + } } } @@ -199,6 +202,7 @@ macro_rules! compat_fn_optional { )+) => ( $( pub mod $symbol { + #[allow(unused_imports)] use super::*; use crate::ffi::c_void; use crate::mem; diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index d2c597664fa..ce427766d17 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -89,6 +89,12 @@ pub struct FileTimes { accessed: Option<c::FILETIME>, modified: Option<c::FILETIME>, } +impl core::fmt::Debug for c::FILETIME { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let time = ((self.dwHighDateTime as u64) << 32) | self.dwLowDateTime as u64; + f.debug_tuple("FILETIME").field(&time).finish() + } +} #[derive(Debug)] pub struct DirBuilder; @@ -290,6 +296,7 @@ impl File { ptr::null_mut(), ) }; + let handle = unsafe { HandleOrInvalid::from_raw_handle(handle) }; if let Ok(handle) = handle.try_into() { Ok(File { handle: Handle::from_inner(handle) }) } else { @@ -477,7 +484,7 @@ impl File { fn reparse_point( &self, space: &mut Align8<[MaybeUninit<u8>]>, - ) -> io::Result<(c::DWORD, *const c::REPARSE_DATA_BUFFER)> { + ) -> io::Result<(c::DWORD, *mut c::REPARSE_DATA_BUFFER)> { unsafe { let mut bytes = 0; cvt({ @@ -496,32 +503,33 @@ impl File { ) })?; const _: () = assert!(core::mem::align_of::<c::REPARSE_DATA_BUFFER>() <= 8); - Ok((bytes, space.0.as_ptr().cast::<c::REPARSE_DATA_BUFFER>())) + Ok((bytes, space.0.as_mut_ptr().cast::<c::REPARSE_DATA_BUFFER>())) } } fn readlink(&self) -> io::Result<PathBuf> { - let mut space = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]); + let mut space = + Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]); let (_bytes, buf) = self.reparse_point(&mut space)?; unsafe { let (path_buffer, subst_off, subst_len, relative) = match (*buf).ReparseTag { c::IO_REPARSE_TAG_SYMLINK => { - let info: *const c::SYMBOLIC_LINK_REPARSE_BUFFER = - ptr::addr_of!((*buf).rest).cast(); + let info: *mut c::SYMBOLIC_LINK_REPARSE_BUFFER = + ptr::addr_of_mut!((*buf).rest).cast(); assert!(info.is_aligned()); ( - ptr::addr_of!((*info).PathBuffer).cast::<u16>(), + ptr::addr_of_mut!((*info).PathBuffer).cast::<u16>(), (*info).SubstituteNameOffset / 2, (*info).SubstituteNameLength / 2, (*info).Flags & c::SYMLINK_FLAG_RELATIVE != 0, ) } c::IO_REPARSE_TAG_MOUNT_POINT => { - let info: *const c::MOUNT_POINT_REPARSE_BUFFER = - ptr::addr_of!((*buf).rest).cast(); + let info: *mut c::MOUNT_POINT_REPARSE_BUFFER = + ptr::addr_of_mut!((*buf).rest).cast(); assert!(info.is_aligned()); ( - ptr::addr_of!((*info).PathBuffer).cast::<u16>(), + ptr::addr_of_mut!((*info).PathBuffer).cast::<u16>(), (*info).SubstituteNameOffset / 2, (*info).SubstituteNameLength / 2, false, @@ -535,13 +543,20 @@ impl File { } }; let subst_ptr = path_buffer.add(subst_off.into()); - let mut subst = slice::from_raw_parts(subst_ptr, subst_len as usize); + let subst = slice::from_raw_parts_mut(subst_ptr, subst_len as usize); // Absolute paths start with an NT internal namespace prefix `\??\` // We should not let it leak through. if !relative && subst.starts_with(&[92u16, 63u16, 63u16, 92u16]) { - subst = &subst[4..]; + // Turn `\??\` into `\\?\` (a verbatim path). + subst[1] = b'\\' as u16; + // Attempt to convert to a more user-friendly path. + let user = super::args::from_wide_to_user_path( + subst.iter().copied().chain([0]).collect(), + )?; + Ok(PathBuf::from(OsString::from_wide(&user.strip_suffix(&[0]).unwrap_or(&user)))) + } else { + Ok(PathBuf::from(OsString::from_wide(subst))) } - Ok(PathBuf::from(OsString::from_wide(subst))) } } @@ -582,7 +597,11 @@ impl File { )); } cvt(unsafe { - c::SetFileTime(self.as_handle(), None, times.accessed.as_ref(), times.modified.as_ref()) + let accessed = + times.accessed.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null()); + let modified = + times.modified.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null()); + c::SetFileTime(self.as_raw_handle(), ptr::null_mut(), accessed, modified) })?; Ok(()) } @@ -611,9 +630,9 @@ impl File { /// then errors will be `ERROR_NOT_SUPPORTED` or `ERROR_INVALID_PARAMETER`. fn posix_delete(&self) -> io::Result<()> { let mut info = c::FILE_DISPOSITION_INFO_EX { - Flags: c::FILE_DISPOSITION_DELETE - | c::FILE_DISPOSITION_POSIX_SEMANTICS - | c::FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE, + Flags: c::FILE_DISPOSITION_FLAG_DELETE + | c::FILE_DISPOSITION_FLAG_POSIX_SEMANTICS + | c::FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE, }; let size = mem::size_of_val(&info); cvt(unsafe { @@ -784,15 +803,15 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result< // See https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntcreatefile unsafe { let mut handle = ptr::null_mut(); - let mut io_status = c::IO_STATUS_BLOCK::default(); - let name_str = c::UNICODE_STRING::from_ref(name); + let mut io_status = c::IO_STATUS_BLOCK::PENDING; + let mut name_str = c::UNICODE_STRING::from_ref(name); use crate::sync::atomic::{AtomicU32, Ordering}; // The `OBJ_DONT_REPARSE` attribute ensures that we haven't been // tricked into following a symlink. However, it may not be available in // earlier versions of Windows. static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE); - let object = c::OBJECT_ATTRIBUTES { - ObjectName: &name_str, + let mut object = c::OBJECT_ATTRIBUTES { + ObjectName: &mut name_str, RootDirectory: parent.as_raw_handle(), Attributes: ATTRIBUTES.load(Ordering::Relaxed), ..c::OBJECT_ATTRIBUTES::default() @@ -800,7 +819,7 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result< let status = c::NtCreateFile( &mut handle, access, - &object, + &mut object, &mut io_status, crate::ptr::null_mut(), 0, @@ -832,6 +851,7 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result< } impl AsInner<Handle> for File { + #[inline] fn as_inner(&self) -> &Handle { &self.handle } @@ -1132,26 +1152,29 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io &dir, &name, c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY, - )?; - dirlist.push(child_dir); - } else { - for i in 1..=MAX_RETRIES { - let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE); - match result { - Ok(f) => delete(&f)?, - // Already deleted, so skip. - Err(e) if e.kind() == io::ErrorKind::NotFound => break, - // Retry a few times if the file is locked or a delete is already in progress. - Err(e) - if i < MAX_RETRIES - && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) - || e.raw_os_error() - == Some(c::ERROR_SHARING_VIOLATION as _)) => {} - // Otherwise return the error. - Err(e) => return Err(e), - } - thread::yield_now(); + ); + // On success, add the handle to the queue. + // If opening the directory fails we treat it the same as a file + if let Ok(child_dir) = child_dir { + dirlist.push(child_dir); + continue; + } + } + for i in 1..=MAX_RETRIES { + let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE); + match result { + Ok(f) => delete(&f)?, + // Already deleted, so skip. + Err(e) if e.kind() == io::ErrorKind::NotFound => break, + // Retry a few times if the file is locked or a delete is already in progress. + Err(e) + if i < MAX_RETRIES + && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) + || e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _)) => {} + // Otherwise return the error. + Err(e) => return Err(e), } + thread::yield_now(); } } // If there were no more files then delete the directory. @@ -1236,7 +1259,17 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { } pub fn stat(path: &Path) -> io::Result<FileAttr> { - metadata(path, ReparsePoint::Follow) + match metadata(path, ReparsePoint::Follow) { + Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => { + if let Ok(attrs) = lstat(path) { + if !attrs.file_type().is_symlink() { + return Ok(attrs); + } + } + Err(err) + } + result => result, + } } pub fn lstat(path: &Path) -> io::Result<FileAttr> { @@ -1347,7 +1380,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { _dwCallbackReason: c::DWORD, _hSourceFile: c::HANDLE, _hDestinationFile: c::HANDLE, - lpData: c::LPVOID, + lpData: c::LPCVOID, ) -> c::DWORD { if dwStreamNumber == 1 { *(lpData as *mut i64) = StreamBytesTransferred; @@ -1393,24 +1426,41 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> { opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); let f = File::open(junction, &opts)?; let h = f.as_inner().as_raw_handle(); - unsafe { - let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]); + let mut data = + Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]); let data_ptr = data.0.as_mut_ptr(); + let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize); let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>(); // Zero the header to ensure it's fully initialized, including reserved parameters. *db = mem::zeroed(); - let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>(); - let mut i = 0; + let reparse_target_slice = { + let buf_start = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>(); + // Compute offset in bytes and then divide so that we round down + // rather than hit any UB (admittedly this arithmetic should work + // out so that this isn't necessary) + let buf_len_bytes = usize::try_from(data_end.byte_offset_from(buf_start)).unwrap(); + let buf_len_wchars = buf_len_bytes / core::mem::size_of::<c::WCHAR>(); + core::slice::from_raw_parts_mut(buf_start, buf_len_wchars) + }; + // FIXME: this conversion is very hacky - let v = br"\??\"; - let v = v.iter().map(|x| *x as u16); - for c in v.chain(original.as_os_str().encode_wide()) { - *buf.add(i) = c; + let iter = br"\??\" + .iter() + .map(|x| *x as u16) + .chain(original.as_os_str().encode_wide()) + .chain(core::iter::once(0)); + let mut i = 0; + for c in iter { + if i >= reparse_target_slice.len() { + return Err(crate::io::const_io_error!( + crate::io::ErrorKind::InvalidFilename, + "Input filename is too long" + )); + } + reparse_target_slice[i] = c; i += 1; } - *buf.add(i) = 0; - i += 1; (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT; (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD; (*db).ReparseTargetLength = ((i - 1) * 2) as c::WORD; diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index ae33d48c612..84c1fbde32d 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -34,6 +34,7 @@ impl Handle { } impl AsInner<OwnedHandle> for Handle { + #[inline] fn as_inner(&self) -> &OwnedHandle { &self.0 } @@ -143,7 +144,7 @@ impl Handle { let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD; let mut amt = 0; let res = cvt(c::ReadFile( - self.as_handle(), + self.as_raw_handle(), buf.as_ptr() as c::LPVOID, len, &mut amt, @@ -234,7 +235,7 @@ impl Handle { len: usize, offset: Option<u64>, ) -> io::Result<usize> { - let mut io_status = c::IO_STATUS_BLOCK::default(); + let mut io_status = c::IO_STATUS_BLOCK::PENDING; // The length is clamped at u32::MAX. let len = cmp::min(len, c::DWORD::MAX as usize) as c::DWORD; @@ -282,7 +283,7 @@ impl Handle { /// /// If `offset` is `None` then the current file position is used. fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> { - let mut io_status = c::IO_STATUS_BLOCK::default(); + let mut io_status = c::IO_STATUS_BLOCK::PENDING; // The length is clamped at u32::MAX. let len = cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD; @@ -327,7 +328,16 @@ impl<'a> Read for &'a Handle { (**self).read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + (**self).read_buf(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { (**self).read_vectored(bufs) } + + #[inline] + fn is_read_vectored(&self) -> bool { + (**self).is_read_vectored() + } } diff --git a/library/std/src/sys/windows/io.rs b/library/std/src/sys/windows/io.rs index 2cc34c986b9..fc9856caed6 100644 --- a/library/std/src/sys/windows/io.rs +++ b/library/std/src/sys/windows/io.rs @@ -2,8 +2,7 @@ use crate::marker::PhantomData; use crate::mem::size_of; use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle}; use crate::slice; -use crate::sys::{c, Align8}; -use core; +use crate::sys::c; use libc; #[derive(Copy, Clone)] @@ -18,10 +17,7 @@ impl<'a> IoSlice<'a> { pub fn new(buf: &'a [u8]) -> IoSlice<'a> { assert!(buf.len() <= c::ULONG::MAX as usize); IoSlice { - vec: c::WSABUF { - len: buf.len() as c::ULONG, - buf: buf.as_ptr() as *mut u8 as *mut c::CHAR, - }, + vec: c::WSABUF { len: buf.len() as c::ULONG, buf: buf.as_ptr() as *mut u8 }, _p: PhantomData, } } @@ -55,7 +51,7 @@ impl<'a> IoSliceMut<'a> { pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { assert!(buf.len() <= c::ULONG::MAX as usize); IoSliceMut { - vec: c::WSABUF { len: buf.len() as c::ULONG, buf: buf.as_mut_ptr() as *mut c::CHAR }, + vec: c::WSABUF { len: buf.len() as c::ULONG, buf: buf.as_mut_ptr() }, _p: PhantomData, } } @@ -125,22 +121,33 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool { return false; } - const SIZE: usize = size_of::<c::FILE_NAME_INFO>() + c::MAX_PATH * size_of::<c::WCHAR>(); - let mut name_info_bytes = Align8([0u8; SIZE]); + /// Mirrors [`FILE_NAME_INFO`], giving it a fixed length that we can stack + /// allocate + /// + /// [`FILE_NAME_INFO`]: https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_name_info + #[repr(C)] + #[allow(non_snake_case)] + struct FILE_NAME_INFO { + FileNameLength: u32, + FileName: [u16; c::MAX_PATH as usize], + } + let mut name_info = FILE_NAME_INFO { FileNameLength: 0, FileName: [0; c::MAX_PATH as usize] }; + // Safety: buffer length is fixed. let res = c::GetFileInformationByHandleEx( handle, c::FileNameInfo, - name_info_bytes.0.as_mut_ptr() as *mut libc::c_void, - SIZE as u32, + &mut name_info as *mut _ as *mut libc::c_void, + size_of::<FILE_NAME_INFO>() as u32, ); if res == 0 { return false; } - let name_info: &c::FILE_NAME_INFO = &*(name_info_bytes.0.as_ptr() as *const c::FILE_NAME_INFO); - let name_len = name_info.FileNameLength as usize / 2; - // Offset to get the `FileName` field. - let name_ptr = name_info_bytes.0.as_ptr().offset(size_of::<c::DWORD>() as isize).cast::<u16>(); - let s = core::slice::from_raw_parts(name_ptr, name_len); + + // Use `get` because `FileNameLength` can be out of range. + let s = match name_info.FileName.get(..name_info.FileNameLength as usize / 2) { + None => return false, + Some(s) => s, + }; let name = String::from_utf16_lossy(s); // Get the file name only. let name = name.rsplit('\\').next().unwrap_or(&name); diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index 77359abe429..bcc172b0fae 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -68,10 +68,13 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_ALREADY_EXISTS => return AlreadyExists, c::ERROR_FILE_EXISTS => return AlreadyExists, c::ERROR_BROKEN_PIPE => return BrokenPipe, - c::ERROR_FILE_NOT_FOUND => return NotFound, - c::ERROR_PATH_NOT_FOUND => return NotFound, + c::ERROR_FILE_NOT_FOUND + | c::ERROR_PATH_NOT_FOUND + | c::ERROR_INVALID_DRIVE + | c::ERROR_BAD_NETPATH + | c::ERROR_BAD_NET_NAME => return NotFound, c::ERROR_NO_DATA => return BrokenPipe, - c::ERROR_INVALID_NAME => return InvalidFilename, + c::ERROR_INVALID_NAME | c::ERROR_BAD_PATHNAME => return InvalidFilename, c::ERROR_INVALID_PARAMETER => return InvalidInput, c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory, c::ERROR_SEM_TIMEOUT diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index e0701a498fa..2404bbe2b89 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -1,7 +1,7 @@ #![unstable(issue = "none", feature = "windows_net")] use crate::cmp; -use crate::io::{self, IoSlice, IoSliceMut, Read}; +use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut, Read}; use crate::mem; use crate::net::{Shutdown, SocketAddr}; use crate::os::windows::io::{ @@ -214,28 +214,38 @@ impl Socket { Ok(Self(self.0.try_clone()?)) } - fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> { + fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. - let length = cmp::min(buf.len(), i32::MAX as usize) as i32; - let result = - unsafe { c::recv(self.as_raw_socket(), buf.as_mut_ptr() as *mut _, length, flags) }; + let length = cmp::min(buf.capacity(), i32::MAX as usize) as i32; + let result = unsafe { + c::recv(self.as_raw_socket(), buf.as_mut().as_mut_ptr() as *mut _, length, flags) + }; match result { c::SOCKET_ERROR => { let error = unsafe { c::WSAGetLastError() }; if error == c::WSAESHUTDOWN { - Ok(0) + Ok(()) } else { Err(io::Error::from_raw_os_error(error)) } } - _ => Ok(result as usize), + _ => { + unsafe { buf.advance(result as usize) }; + Ok(()) + } } } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { + let mut buf = BorrowedBuf::from(buf); + self.recv_with_flags(buf.unfilled(), 0)?; + Ok(buf.len()) + } + + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { self.recv_with_flags(buf, 0) } @@ -253,7 +263,7 @@ impl Socket { &mut nread, &mut flags, ptr::null_mut(), - ptr::null_mut(), + None, ) }; @@ -277,7 +287,9 @@ impl Socket { } pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { - self.recv_with_flags(buf, c::MSG_PEEK) + let mut buf = BorrowedBuf::from(buf); + self.recv_with_flags(buf.unfilled(), c::MSG_PEEK)?; + Ok(buf.len()) } fn recv_from_with_flags( @@ -335,7 +347,7 @@ impl Socket { &mut nwritten, 0, ptr::null_mut(), - ptr::null_mut(), + None, ) }; cvt(result).map(|_| nwritten as usize) @@ -434,6 +446,7 @@ impl<'a> Read for &'a Socket { } impl AsInner<OwnedSocket> for Socket { + #[inline] fn as_inner(&self) -> &OwnedSocket { &self.0 } diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs index 4bdd8c505ff..2f2b0e56e08 100644 --- a/library/std/src/sys/windows/os_str.rs +++ b/library/std/src/sys/windows/os_str.rs @@ -27,6 +27,7 @@ impl FromInner<Wtf8Buf> for Buf { } impl AsInner<Wtf8> for Buf { + #[inline] fn as_inner(&self) -> &Wtf8 { &self.inner } diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index beeca1917a9..c3573d14c7f 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -220,6 +220,19 @@ fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) { /// /// This path may or may not have a verbatim prefix. pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> { + let path = to_u16s(path)?; + get_long_path(path, true) +} + +/// Get a normalized absolute path that can bypass path length limits. +/// +/// Setting prefer_verbatim to true suggests a stronger preference for verbatim +/// paths even when not strictly necessary. This allows the Windows API to avoid +/// repeating our work. However, if the path may be given back to users or +/// passed to other application then it's preferable to use non-verbatim paths +/// when possible. Non-verbatim paths are better understood by users and handled +/// by more software. +pub(crate) fn get_long_path(mut path: Vec<u16>, prefer_verbatim: bool) -> io::Result<Vec<u16>> { // Normally the MAX_PATH is 260 UTF-16 code units (including the NULL). // However, for APIs such as CreateDirectory[1], the limit is 248. // @@ -243,7 +256,6 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> { // \\?\UNC\ const UNC_PREFIX: &[u16] = &[SEP, SEP, QUERY, SEP, U, N, C, SEP]; - let mut path = to_u16s(path)?; if path.starts_with(VERBATIM_PREFIX) || path.starts_with(NT_PREFIX) || path == &[0] { // Early return for paths that are already verbatim or empty. return Ok(path); @@ -275,29 +287,34 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> { |mut absolute| { path.clear(); - // Secondly, add the verbatim prefix. This is easier here because we know the - // path is now absolute and fully normalized (e.g. `/` has been changed to `\`). - let prefix = match absolute { - // C:\ => \\?\C:\ - [_, COLON, SEP, ..] => VERBATIM_PREFIX, - // \\.\ => \\?\ - [SEP, SEP, DOT, SEP, ..] => { - absolute = &absolute[4..]; - VERBATIM_PREFIX - } - // Leave \\?\ and \??\ as-is. - [SEP, SEP, QUERY, SEP, ..] | [SEP, QUERY, QUERY, SEP, ..] => &[], - // \\ => \\?\UNC\ - [SEP, SEP, ..] => { - absolute = &absolute[2..]; - UNC_PREFIX - } - // Anything else we leave alone. - _ => &[], - }; - - path.reserve_exact(prefix.len() + absolute.len() + 1); - path.extend_from_slice(prefix); + // Only prepend the prefix if needed. + if prefer_verbatim || absolute.len() + 1 >= LEGACY_MAX_PATH { + // Secondly, add the verbatim prefix. This is easier here because we know the + // path is now absolute and fully normalized (e.g. `/` has been changed to `\`). + let prefix = match absolute { + // C:\ => \\?\C:\ + [_, COLON, SEP, ..] => VERBATIM_PREFIX, + // \\.\ => \\?\ + [SEP, SEP, DOT, SEP, ..] => { + absolute = &absolute[4..]; + VERBATIM_PREFIX + } + // Leave \\?\ and \??\ as-is. + [SEP, SEP, QUERY, SEP, ..] | [SEP, QUERY, QUERY, SEP, ..] => &[], + // \\ => \\?\UNC\ + [SEP, SEP, ..] => { + absolute = &absolute[2..]; + UNC_PREFIX + } + // Anything else we leave alone. + _ => &[], + }; + + path.reserve_exact(prefix.len() + absolute.len() + 1); + path.extend_from_slice(prefix); + } else { + path.reserve_exact(absolute.len() + 1); + } path.extend_from_slice(absolute); path.push(0); }, diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index 7b25edaa556..d07147eccc1 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -1,7 +1,7 @@ use crate::os::windows::prelude::*; use crate::ffi::OsStr; -use crate::io::{self, IoSlice, IoSliceMut, Read}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read}; use crate::mem; use crate::path::Path; use crate::ptr; @@ -252,6 +252,28 @@ impl AnonPipe { } } + pub fn read_buf(&self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { + let result = unsafe { + let len = crate::cmp::min(buf.capacity(), c::DWORD::MAX as usize) as c::DWORD; + self.alertable_io_internal(c::ReadFileEx, buf.as_mut().as_mut_ptr() as _, len) + }; + + match result { + // The special treatment of BrokenPipe is to deal with Windows + // pipe semantics, which yields this error when *reading* from + // a pipe after the other end has closed; we interpret that as + // EOF on the pipe. + Err(ref e) if e.kind() == io::ErrorKind::BrokenPipe => Ok(()), + Err(e) => Err(e), + Ok(n) => { + unsafe { + buf.advance(n); + } + Ok(()) + } + } + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.inner.read_vectored(bufs) } @@ -351,7 +373,7 @@ impl AnonPipe { // Asynchronous read of the pipe. // If successful, `callback` will be called once it completes. - let result = io(self.inner.as_handle(), buf, len, &mut overlapped, callback); + let result = io(self.inner.as_handle(), buf, len, &mut overlapped, Some(callback)); if result == c::FALSE { // We can return here because the call failed. // After this we must not return until the I/O completes. diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 10bc949e1f4..df3667c0fd7 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -266,11 +266,7 @@ impl Command { let (program, mut cmd_str) = if is_batch_file { ( command_prompt()?, - args::make_bat_command_line( - &args::to_user_path(program)?, - &self.args, - self.force_quotes_enabled, - )?, + args::make_bat_command_line(&program, &self.args, self.force_quotes_enabled)?, ) } else { let cmd_str = make_command_line(&self.program, &self.args, self.force_quotes_enabled)?; @@ -312,7 +308,7 @@ impl Command { let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?; let mut si = zeroed_startupinfo(); - si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD; + si.cb = mem::size_of::<c::STARTUPINFOW>() as c::DWORD; // If at least one of stdin, stdout or stderr are set (i.e. are non null) // then set the `hStd` fields in `STARTUPINFO`. @@ -336,7 +332,7 @@ impl Command { flags, envp, dirp, - &mut si, + &si, &mut pi, )) }?; @@ -410,7 +406,7 @@ fn resolve_exe<'a>( if has_exe_suffix { // The application name is a path to a `.exe` file. // Let `CreateProcessW` figure out if it exists or not. - return path::maybe_verbatim(Path::new(exe_path)); + return args::to_user_path(Path::new(exe_path)); } let mut path = PathBuf::from(exe_path); @@ -422,7 +418,7 @@ fn resolve_exe<'a>( // It's ok to use `set_extension` here because the intent is to // remove the extension that was just added. path.set_extension(""); - return path::maybe_verbatim(&path); + return args::to_user_path(&path); } } else { ensure_no_nuls(exe_path)?; @@ -510,7 +506,7 @@ where /// Check if a file exists without following symlinks. fn program_exists(path: &Path) -> Option<Vec<u16>> { unsafe { - let path = path::maybe_verbatim(path).ok()?; + let path = args::to_user_path(path).ok()?; // Getting attributes using `GetFileAttributesW` does not follow symlinks // and it will almost always be successful if the link exists. // There are some exceptions for special system files (e.g. the pagefile) @@ -724,8 +720,8 @@ impl From<u32> for ExitCode { } } -fn zeroed_startupinfo() -> c::STARTUPINFO { - c::STARTUPINFO { +fn zeroed_startupinfo() -> c::STARTUPINFOW { + c::STARTUPINFOW { cb: 0, lpReserved: ptr::null_mut(), lpDesktop: ptr::null_mut(), @@ -735,7 +731,7 @@ fn zeroed_startupinfo() -> c::STARTUPINFO { dwXSize: 0, dwYSize: 0, dwXCountChars: 0, - dwYCountCharts: 0, + dwYCountChars: 0, dwFillAttribute: 0, dwFlags: 0, wShowWindow: 0, diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index cdf37cfe911..bca4e38d9f6 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -1,3 +1,4 @@ +use crate::ffi::c_void; use crate::io; use crate::mem; use crate::ptr; @@ -25,8 +26,9 @@ pub fn hashmap_random_keys() -> (u64, u64) { #[inline(never)] fn fallback_rng() -> (u64, u64) { let mut v = (0, 0); - let ret = - unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) }; + let ret = unsafe { + c::RtlGenRandom(&mut v as *mut _ as *mut c_void, mem::size_of_val(&v) as c::ULONG) + }; if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) } } diff --git a/library/std/src/sys/windows/stack_overflow.rs b/library/std/src/sys/windows/stack_overflow.rs index 18a2a36ad25..0caf0a317a4 100644 --- a/library/std/src/sys/windows/stack_overflow.rs +++ b/library/std/src/sys/windows/stack_overflow.rs @@ -18,7 +18,7 @@ impl Handler { } } -extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> c::LONG { +unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> c::LONG { unsafe { let rec = &(*(*ExceptionInfo).ExceptionRecord); let code = rec.ExceptionCode; @@ -34,7 +34,7 @@ extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) - } pub unsafe fn init() { - if c::AddVectoredExceptionHandler(0, vectored_handler).is_null() { + if c::AddVectoredExceptionHandler(0, Some(vectored_handler)).is_null() { panic!("failed to install exception handler"); } // Set the thread stack guarantee for the main thread. diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs index c2cd48470bd..2e3e0859dc1 100644 --- a/library/std/src/sys/windows/stdio.rs +++ b/library/std/src/sys/windows/stdio.rs @@ -169,14 +169,27 @@ fn write( } fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usize> { + debug_assert!(!utf8.is_empty()); + let mut utf16 = [MaybeUninit::<u16>::uninit(); MAX_BUFFER_SIZE / 2]; - let mut len_utf16 = 0; - for (chr, dest) in utf8.encode_utf16().zip(utf16.iter_mut()) { - *dest = MaybeUninit::new(chr); - len_utf16 += 1; - } - // Safety: We've initialized `len_utf16` values. - let utf16: &[u16] = unsafe { MaybeUninit::slice_assume_init_ref(&utf16[..len_utf16]) }; + let utf8 = &utf8[..utf8.floor_char_boundary(utf16.len())]; + + let utf16: &[u16] = unsafe { + // Note that this theoretically checks validity twice in the (most common) case + // where the underlying byte sequence is valid utf-8 (given the check in `write()`). + let result = c::MultiByteToWideChar( + c::CP_UTF8, // CodePage + c::MB_ERR_INVALID_CHARS, // dwFlags + utf8.as_ptr(), // lpMultiByteStr + utf8.len() as c::c_int, // cbMultiByte + utf16.as_mut_ptr() as c::LPWSTR, // lpWideCharStr + utf16.len() as c::c_int, // cchWideChar + ); + assert!(result != 0, "Unexpected error in MultiByteToWideChar"); + + // Safety: MultiByteToWideChar initializes `result` values. + MaybeUninit::slice_assume_init_ref(&utf16[..result as usize]) + }; let mut written = write_u16s(handle, &utf16)?; @@ -189,8 +202,8 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz // a missing surrogate can be produced (and also because of the UTF-8 validation above), // write the missing surrogate out now. // Buffering it would mean we have to lie about the number of bytes written. - let first_char_remaining = utf16[written]; - if first_char_remaining >= 0xDCEE && first_char_remaining <= 0xDFFF { + let first_code_unit_remaining = utf16[written]; + if first_code_unit_remaining >= 0xDCEE && first_code_unit_remaining <= 0xDFFF { // low surrogate // We just hope this works, and give up otherwise let _ = write_u16s(handle, &utf16[written..written + 1]); @@ -212,6 +225,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz } fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result<usize> { + debug_assert!(data.len() < u32::MAX as usize); let mut written = 0; cvt(unsafe { c::WriteConsoleW( @@ -330,7 +344,7 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz // See #38274 and https://stackoverflow.com/questions/43836040/win-api-readconsole. const CTRL_Z: u16 = 0x1A; const CTRL_Z_MASK: c::ULONG = 1 << CTRL_Z; - let mut input_control = c::CONSOLE_READCONSOLE_CONTROL { + let input_control = c::CONSOLE_READCONSOLE_CONTROL { nLength: crate::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG, nInitialChars: 0, dwCtrlWakeupMask: CTRL_Z_MASK, @@ -346,7 +360,7 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz buf.as_mut_ptr() as c::LPVOID, buf.len() as u32, &mut amount, - &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL, + &input_control, ) })?; @@ -365,26 +379,32 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz Ok(amount as usize) } -#[allow(unused)] fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> { - let mut written = 0; - for chr in char::decode_utf16(utf16.iter().cloned()) { - match chr { - Ok(chr) => { - chr.encode_utf8(&mut utf8[written..]); - written += chr.len_utf8(); - } - Err(_) => { - // We can't really do any better than forget all data and return an error. - return Err(io::const_io_error!( - io::ErrorKind::InvalidData, - "Windows stdin in console mode does not support non-UTF-16 input; \ - encountered unpaired surrogate", - )); - } - } + debug_assert!(utf16.len() <= c::c_int::MAX as usize); + debug_assert!(utf8.len() <= c::c_int::MAX as usize); + + let result = unsafe { + c::WideCharToMultiByte( + c::CP_UTF8, // CodePage + c::WC_ERR_INVALID_CHARS, // dwFlags + utf16.as_ptr(), // lpWideCharStr + utf16.len() as c::c_int, // cchWideChar + utf8.as_mut_ptr(), // lpMultiByteStr + utf8.len() as c::c_int, // cbMultiByte + ptr::null(), // lpDefaultChar + ptr::null_mut(), // lpUsedDefaultChar + ) + }; + if result == 0 { + // We can't really do any better than forget all data and return an error. + Err(io::const_io_error!( + io::ErrorKind::InvalidData, + "Windows stdin in console mode does not support non-UTF-16 input; \ + encountered unpaired surrogate", + )) + } else { + Ok(result as usize) } - Ok(written) } impl IncompleteUtf8 { diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index ed58c47e090..18cecb65681 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -2,6 +2,7 @@ use crate::ffi::CStr; use crate::io; use crate::num::NonZeroUsize; use crate::os::windows::io::AsRawHandle; +use crate::os::windows::io::HandleOrNull; use crate::ptr; use crate::sys::c; use crate::sys::handle::Handle; @@ -32,12 +33,12 @@ impl Thread { let ret = c::CreateThread( ptr::null_mut(), stack, - thread_start, + Some(thread_start), p as *mut _, c::STACK_SIZE_PARAM_IS_A_RESERVATION, ptr::null_mut(), ); - + let ret = HandleOrNull::from_raw_handle(ret); return if let Ok(handle) = ret.try_into() { Ok(Thread { handle: Handle::from_inner(handle) }) } else { diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index f1d804ef40c..8752f46ff81 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -91,6 +91,19 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: if stop { return false; } + #[cfg(target_os = "nto")] + if libc::__my_thread_exit as *mut libc::c_void == frame.ip() { + if !hit && start { + use crate::backtrace_rs::SymbolName; + res = bt_fmt.frame().print_raw( + frame.ip(), + Some(SymbolName::new("__my_thread_exit".as_bytes())), + None, + None, + ); + } + return false; + } if !hit && start { res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); } diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 6b24b0e9aa8..e9c727cbbd1 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -44,7 +44,6 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(any(target_os = "l4re", - target_os = "hermit", feature = "restricted-std", all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))] { diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 2c38dfecf97..652c695fc57 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -2,9 +2,8 @@ mod tests; use crate::cmp; -use crate::convert::{TryFrom, TryInto}; use crate::fmt; -use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; use crate::mem; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::ptr; @@ -21,7 +20,7 @@ cfg_if::cfg_if! { target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "watchos", target_os = "openbsd", target_os = "netbsd", target_os = "illumos", - target_os = "solaris", target_os = "haiku", target_os = "l4re"))] { + target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] { use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; } else { @@ -35,7 +34,7 @@ cfg_if::cfg_if! { target_os = "linux", target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "haiku"))] { + target_os = "haiku", target_os = "nto"))] { use libc::MSG_NOSIGNAL; } else { const MSG_NOSIGNAL: c_int = 0x0; @@ -46,7 +45,8 @@ cfg_if::cfg_if! { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "solaris", target_os = "illumos"))] { + target_os = "solaris", target_os = "illumos", + target_os = "nto"))] { use crate::ffi::c_uchar; type IpV4MultiCastType = c_uchar; } else { @@ -239,6 +239,7 @@ impl TcpStream { Ok(TcpStream { inner: sock }) } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -271,6 +272,10 @@ impl TcpStream { self.inner.read(buf) } + pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.inner.read_buf(buf) + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.inner.read_vectored(bufs) } @@ -348,6 +353,7 @@ impl TcpStream { } impl AsInner<Socket> for TcpStream { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } @@ -423,6 +429,7 @@ impl TcpListener { Ok(TcpListener { inner: sock }) } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -513,6 +520,7 @@ impl UdpSocket { Ok(UdpSocket { inner: sock }) } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } diff --git a/library/std/src/sys_common/net/tests.rs b/library/std/src/sys_common/net/tests.rs index ac75d9ebfc8..fc236b8027b 100644 --- a/library/std/src/sys_common/net/tests.rs +++ b/library/std/src/sys_common/net/tests.rs @@ -6,7 +6,7 @@ fn no_lookup_host_duplicates() { let mut addrs = HashMap::new(); let lh = match LookupHost::try_from(("localhost", 0)) { Ok(lh) => lh, - Err(e) => panic!("couldn't resolve `localhost': {e}"), + Err(e) => panic!("couldn't resolve `localhost`: {e}"), }; for sa in lh { *addrs.entry(sa).or_insert(0) += 1; diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs index 2672a2a75b0..204834984a2 100644 --- a/library/std/src/sys_common/thread_local_key.rs +++ b/library/std/src/sys_common/thread_local_key.rs @@ -87,39 +87,20 @@ pub struct StaticKey { dtor: Option<unsafe extern "C" fn(*mut u8)>, } -/// A type for a safely managed OS-based TLS slot. -/// -/// This type allocates an OS TLS key when it is initialized and will deallocate -/// the key when it falls out of scope. When compared with `StaticKey`, this -/// type is entirely safe to use. -/// -/// Implementations will likely, however, contain unsafe code as this type only -/// operates on `*mut u8`, a raw pointer. -/// -/// # Examples -/// -/// ```ignore (cannot-doctest-private-modules) -/// use tls::os::Key; -/// -/// let key = Key::new(None); -/// assert!(key.get().is_null()); -/// key.set(1 as *mut u8); -/// assert!(!key.get().is_null()); -/// -/// drop(key); // deallocate this TLS slot. -/// ``` -pub struct Key { - key: imp::Key, -} - /// Constant initialization value for static TLS keys. /// /// This value specifies no destructor by default. pub const INIT: StaticKey = StaticKey::new(None); -// Define a sentinel value that is unlikely to be returned -// as a TLS key (but it may be returned). +// Define a sentinel value that is likely not to be returned +// as a TLS key. +#[cfg(not(target_os = "nto"))] const KEY_SENTVAL: usize = 0; +// On QNX Neutrino, 0 is always returned when currently not in use. +// Using 0 would mean to always create two keys and remote the first +// one (with value of 0) immediately afterwards. +#[cfg(target_os = "nto")] +const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1; impl StaticKey { #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] @@ -188,39 +169,3 @@ impl StaticKey { } } } - -impl Key { - /// Creates a new managed OS TLS key. - /// - /// This key will be deallocated when the key falls out of scope. - /// - /// The argument provided is an optionally-specified destructor for the - /// value of this TLS key. When a thread exits and the value for this key - /// is non-null the destructor will be invoked. The TLS value will be reset - /// to null before the destructor is invoked. - /// - /// Note that the destructor will not be run when the `Key` goes out of - /// scope. - #[inline] - pub fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key { - Key { key: unsafe { imp::create(dtor) } } - } - - /// See StaticKey::get - #[inline] - pub fn get(&self) -> *mut u8 { - unsafe { imp::get(self.key) } - } - - /// See StaticKey::set - #[inline] - pub fn set(&self, val: *mut u8) { - unsafe { imp::set(self.key, val) } - } -} - -impl Drop for Key { - fn drop(&mut self) { - unsafe { imp::destroy(self.key) } - } -} diff --git a/library/std/src/sys_common/thread_local_key/tests.rs b/library/std/src/sys_common/thread_local_key/tests.rs index 6f32b858f09..6a44c65d918 100644 --- a/library/std/src/sys_common/thread_local_key/tests.rs +++ b/library/std/src/sys_common/thread_local_key/tests.rs @@ -1,24 +1,6 @@ -use super::{Key, StaticKey}; +use super::StaticKey; use core::ptr; -fn assert_sync<T: Sync>() {} -fn assert_send<T: Send>() {} - -#[test] -fn smoke() { - assert_sync::<Key>(); - assert_send::<Key>(); - - let k1 = Key::new(None); - let k2 = Key::new(None); - assert!(k1.get().is_null()); - assert!(k2.get().is_null()); - k1.set(ptr::invalid_mut(1)); - k2.set(ptr::invalid_mut(2)); - assert_eq!(k1.get() as usize, 1); - assert_eq!(k2.get() as usize, 2); -} - #[test] fn statik() { static K1: StaticKey = StaticKey::new(None); diff --git a/library/std/src/sys_common/thread_parking/generic.rs b/library/std/src/sys_common/thread_parking/generic.rs deleted file mode 100644 index 3209bffe353..00000000000 --- a/library/std/src/sys_common/thread_parking/generic.rs +++ /dev/null @@ -1,125 +0,0 @@ -//! Parker implementation based on a Mutex and Condvar. - -use crate::pin::Pin; -use crate::sync::atomic::AtomicUsize; -use crate::sync::atomic::Ordering::SeqCst; -use crate::sync::{Condvar, Mutex}; -use crate::time::Duration; - -const EMPTY: usize = 0; -const PARKED: usize = 1; -const NOTIFIED: usize = 2; - -pub struct Parker { - state: AtomicUsize, - lock: Mutex<()>, - cvar: Condvar, -} - -impl Parker { - /// Construct the generic parker. The UNIX parker implementation - /// requires this to happen in-place. - pub unsafe fn new_in_place(parker: *mut Parker) { - parker.write(Parker { - state: AtomicUsize::new(EMPTY), - lock: Mutex::new(()), - cvar: Condvar::new(), - }); - } - - // This implementation doesn't require `unsafe` and `Pin`, but other implementations do. - pub unsafe fn park(self: Pin<&Self>) { - // If we were previously notified then we consume this notification and - // return quickly. - if self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst).is_ok() { - return; - } - - // Otherwise we need to coordinate going to sleep - let mut m = self.lock.lock().unwrap(); - match self.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { - Ok(_) => {} - Err(NOTIFIED) => { - // We must read here, even though we know it will be `NOTIFIED`. - // This is because `unpark` may have been called again since we read - // `NOTIFIED` in the `compare_exchange` above. We must perform an - // acquire operation that synchronizes with that `unpark` to observe - // any writes it made before the call to unpark. To do that we must - // read from the write it made to `state`. - let old = self.state.swap(EMPTY, SeqCst); - assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); - return; - } // should consume this notification, so prohibit spurious wakeups in next park. - Err(_) => panic!("inconsistent park state"), - } - loop { - m = self.cvar.wait(m).unwrap(); - match self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst) { - Ok(_) => return, // got a notification - Err(_) => {} // spurious wakeup, go back to sleep - } - } - } - - // This implementation doesn't require `unsafe` and `Pin`, but other implementations do. - pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { - // Like `park` above we have a fast path for an already-notified thread, and - // afterwards we start coordinating for a sleep. - // return quickly. - if self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst).is_ok() { - return; - } - let m = self.lock.lock().unwrap(); - match self.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { - Ok(_) => {} - Err(NOTIFIED) => { - // We must read again here, see `park`. - let old = self.state.swap(EMPTY, SeqCst); - assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); - return; - } // should consume this notification, so prohibit spurious wakeups in next park. - Err(_) => panic!("inconsistent park_timeout state"), - } - - // Wait with a timeout, and if we spuriously wake up or otherwise wake up - // from a notification we just want to unconditionally set the state back to - // empty, either consuming a notification or un-flagging ourselves as - // parked. - let (_m, _result) = self.cvar.wait_timeout(m, dur).unwrap(); - match self.state.swap(EMPTY, SeqCst) { - NOTIFIED => {} // got a notification, hurray! - PARKED => {} // no notification, alas - n => panic!("inconsistent park_timeout state: {n}"), - } - } - - // This implementation doesn't require `Pin`, but other implementations do. - pub fn unpark(self: Pin<&Self>) { - // To ensure the unparked thread will observe any writes we made - // before this call, we must perform a release operation that `park` - // can synchronize with. To do that we must write `NOTIFIED` even if - // `state` is already `NOTIFIED`. That is why this must be a swap - // rather than a compare-and-swap that returns if it reads `NOTIFIED` - // on failure. - match self.state.swap(NOTIFIED, SeqCst) { - EMPTY => return, // no one was waiting - NOTIFIED => return, // already unparked - PARKED => {} // gotta go wake someone up - _ => panic!("inconsistent state in unpark"), - } - - // There is a period between when the parked thread sets `state` to - // `PARKED` (or last checked `state` in the case of a spurious wake - // up) and when it actually waits on `cvar`. If we were to notify - // during this period it would be ignored and then when the parked - // thread went to sleep it would never wake up. Fortunately, it has - // `lock` locked at this stage so we can acquire `lock` to wait until - // it is ready to receive the notification. - // - // Releasing `lock` before the call to `notify_one` means that when the - // parked thread wakes it doesn't get woken only to have to wait for us - // to release `lock`. - drop(self.lock.lock().unwrap()); - self.cvar.notify_one() - } -} diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs index e98169597c3..15042fc3bee 100644 --- a/library/std/src/sys_common/thread_parking/id.rs +++ b/library/std/src/sys_common/thread_parking/id.rs @@ -60,7 +60,7 @@ impl Parker { if state == PARKED { // Loop to guard against spurious wakeups. while state == PARKED { - park(self.state.as_mut_ptr().addr()); + park(self.state.as_ptr().addr()); state = self.state.load(Acquire); } @@ -76,10 +76,10 @@ impl Parker { let state = self.state.fetch_sub(1, Acquire).wrapping_sub(1); if state == PARKED { - park_timeout(dur, self.state.as_mut_ptr().addr()); + park_timeout(dur, self.state.as_ptr().addr()); // Swap to ensure that we observe all state changes with acquire // ordering, even if the state has been changed after the timeout - // occured. + // occurred. self.state.swap(EMPTY, Acquire); } } @@ -99,7 +99,7 @@ impl Parker { // and terminated before this call is made. This call then returns an // error or wakes up an unrelated thread. The platform API and // environment does allow this, however. - unpark(tid, self.state.as_mut_ptr().addr()); + unpark(tid, self.state.as_ptr().addr()); } } } diff --git a/library/std/src/sys_common/thread_parking/mod.rs b/library/std/src/sys_common/thread_parking/mod.rs index e8e028bb330..c4d3f9ea2f4 100644 --- a/library/std/src/sys_common/thread_parking/mod.rs +++ b/library/std/src/sys_common/thread_parking/mod.rs @@ -18,10 +18,7 @@ cfg_if::cfg_if! { ))] { mod id; pub use id::Parker; - } else if #[cfg(any(windows, target_family = "unix"))] { - pub use crate::sys::thread_parking::Parker; } else { - mod generic; - pub use generic::Parker; + pub use crate::sys::thread_parking::Parker; } } diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index e202d17e1c2..ff96c35fb0b 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -501,6 +501,7 @@ pub struct Wtf8 { } impl AsInner<[u8]> for Wtf8 { + #[inline] fn as_inner(&self) -> &[u8] { &self.bytes } @@ -594,7 +595,7 @@ impl Wtf8 { } /// Returns the code point at `position` if it is in the ASCII range, - /// or `b'\xFF' otherwise. + /// or `b'\xFF'` otherwise. /// /// # Panics /// diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index cf7c2e05a2e..3b7c31826b9 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -134,10 +134,28 @@ impl<T: 'static> fmt::Debug for LocalKey<T> { /// thread_local! { /// pub static FOO: RefCell<u32> = RefCell::new(1); /// -/// #[allow(unused)] /// static BAR: RefCell<f32> = RefCell::new(1.0); /// } -/// # fn main() {} +/// +/// FOO.with(|foo| assert_eq!(*foo.borrow(), 1)); +/// BAR.with(|bar| assert_eq!(*bar.borrow(), 1.0)); +/// ``` +/// +/// This macro supports a special `const {}` syntax that can be used +/// when the initialization expression can be evaluated as a constant. +/// This can enable a more efficient thread local implementation that +/// can avoid lazy initialization. For types that do not +/// [need to be dropped][crate::mem::needs_drop], this can enable an +/// even more efficient implementation that does not need to +/// track any additional state. +/// +/// ``` +/// use std::cell::Cell; +/// thread_local! { +/// pub static FOO: Cell<u32> = const { Cell::new(1) }; +/// } +/// +/// FOO.with(|foo| assert_eq!(foo.get(), 1)); /// ``` /// /// See [`LocalKey` documentation][`std::thread::LocalKey`] for more @@ -153,220 +171,26 @@ macro_rules! thread_local { () => {}; ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => ( - $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); + $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); $crate::thread_local!($($rest)*); ); ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => ( - $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); + $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); ); // process multiple declarations ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( - $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init); + $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init); $crate::thread_local!($($rest)*); ); // handle a single declaration ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( - $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init); + $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init); ); } -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")] -#[macro_export] -#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)] -#[allow_internal_unsafe] -macro_rules! __thread_local_inner { - // used to generate the `LocalKey` value for const-initialized thread locals - (@key $t:ty, const $init:expr) => {{ - #[cfg_attr(not(windows), inline)] // see comments below - #[deny(unsafe_op_in_unsafe_fn)] - unsafe fn __getit( - _init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { - const INIT_EXPR: $t = $init; - - // wasm without atomics maps directly to `static mut`, and dtors - // aren't implemented because thread dtors aren't really a thing - // on wasm right now - // - // FIXME(#84224) this should come after the `target_thread_local` - // block. - #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] - { - static mut VAL: $t = INIT_EXPR; - unsafe { $crate::option::Option::Some(&VAL) } - } - - // If the platform has support for `#[thread_local]`, use it. - #[cfg(all( - target_thread_local, - not(all(target_family = "wasm", not(target_feature = "atomics"))), - ))] - { - #[thread_local] - static mut VAL: $t = INIT_EXPR; - - // If a dtor isn't needed we can do something "very raw" and - // just get going. - if !$crate::mem::needs_drop::<$t>() { - unsafe { - return $crate::option::Option::Some(&VAL) - } - } - - // 0 == dtor not registered - // 1 == dtor registered, dtor not run - // 2 == dtor registered and is running or has run - #[thread_local] - static mut STATE: $crate::primitive::u8 = 0; - - unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) { - let ptr = ptr as *mut $t; - - unsafe { - $crate::debug_assert_eq!(STATE, 1); - STATE = 2; - $crate::ptr::drop_in_place(ptr); - } - } - - unsafe { - match STATE { - // 0 == we haven't registered a destructor, so do - // so now. - 0 => { - $crate::thread::__FastLocalKeyInner::<$t>::register_dtor( - $crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8, - destroy, - ); - STATE = 1; - $crate::option::Option::Some(&VAL) - } - // 1 == the destructor is registered and the value - // is valid, so return the pointer. - 1 => $crate::option::Option::Some(&VAL), - // otherwise the destructor has already run, so we - // can't give access. - _ => $crate::option::Option::None, - } - } - } - - // On platforms without `#[thread_local]` we fall back to the - // same implementation as below for os thread locals. - #[cfg(all( - not(target_thread_local), - not(all(target_family = "wasm", not(target_feature = "atomics"))), - ))] - { - #[inline] - const fn __init() -> $t { INIT_EXPR } - static __KEY: $crate::thread::__OsLocalKeyInner<$t> = - $crate::thread::__OsLocalKeyInner::new(); - #[allow(unused_unsafe)] - unsafe { - __KEY.get(move || { - if let $crate::option::Option::Some(init) = _init { - if let $crate::option::Option::Some(value) = init.take() { - return value; - } else if $crate::cfg!(debug_assertions) { - $crate::unreachable!("missing initial value"); - } - } - __init() - }) - } - } - } - - unsafe { - $crate::thread::LocalKey::new(__getit) - } - }}; - - // used to generate the `LocalKey` value for `thread_local!` - (@key $t:ty, $init:expr) => { - { - #[inline] - fn __init() -> $t { $init } - - // When reading this function you might ask "why is this inlined - // everywhere other than Windows?", and that's a very reasonable - // question to ask. The short story is that it segfaults rustc if - // this function is inlined. The longer story is that Windows looks - // to not support `extern` references to thread locals across DLL - // boundaries. This appears to at least not be supported in the ABI - // that LLVM implements. - // - // Because of this we never inline on Windows, but we do inline on - // other platforms (where external references to thread locals - // across DLLs are supported). A better fix for this would be to - // inline this function on Windows, but only for "statically linked" - // components. For example if two separately compiled rlibs end up - // getting linked into a DLL then it's fine to inline this function - // across that boundary. It's only not fine to inline this function - // across a DLL boundary. Unfortunately rustc doesn't currently - // have this sort of logic available in an attribute, and it's not - // clear that rustc is even equipped to answer this (it's more of a - // Cargo question kinda). This means that, unfortunately, Windows - // gets the pessimistic path for now where it's never inlined. - // - // The issue of "should enable on Windows sometimes" is #84933 - #[cfg_attr(not(windows), inline)] - unsafe fn __getit( - init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { - #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] - static __KEY: $crate::thread::__StaticLocalKeyInner<$t> = - $crate::thread::__StaticLocalKeyInner::new(); - - #[thread_local] - #[cfg(all( - target_thread_local, - not(all(target_family = "wasm", not(target_feature = "atomics"))), - ))] - static __KEY: $crate::thread::__FastLocalKeyInner<$t> = - $crate::thread::__FastLocalKeyInner::new(); - - #[cfg(all( - not(target_thread_local), - not(all(target_family = "wasm", not(target_feature = "atomics"))), - ))] - static __KEY: $crate::thread::__OsLocalKeyInner<$t> = - $crate::thread::__OsLocalKeyInner::new(); - - // FIXME: remove the #[allow(...)] marker when macros don't - // raise warning for missing/extraneous unsafe blocks anymore. - // See https://github.com/rust-lang/rust/issues/74838. - #[allow(unused_unsafe)] - unsafe { - __KEY.get(move || { - if let $crate::option::Option::Some(init) = init { - if let $crate::option::Option::Some(value) = init.take() { - return value; - } else if $crate::cfg!(debug_assertions) { - $crate::unreachable!("missing default value"); - } - } - __init() - }) - } - } - - unsafe { - $crate::thread::LocalKey::new(__getit) - } - } - }; - ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { - $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = - $crate::__thread_local_inner!(@key $t, $($init)*); - } -} - /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with). #[stable(feature = "thread_local_try_with", since = "1.26.0")] #[non_exhaustive] @@ -779,376 +603,3 @@ impl<T: 'static> LocalKey<RefCell<T>> { self.with(|cell| cell.replace(value)) } } - -mod lazy { - use crate::cell::UnsafeCell; - use crate::hint; - use crate::mem; - - pub struct LazyKeyInner<T> { - inner: UnsafeCell<Option<T>>, - } - - impl<T> LazyKeyInner<T> { - pub const fn new() -> LazyKeyInner<T> { - LazyKeyInner { inner: UnsafeCell::new(None) } - } - - pub unsafe fn get(&self) -> Option<&'static T> { - // SAFETY: The caller must ensure no reference is ever handed out to - // the inner cell nor mutable reference to the Option<T> inside said - // cell. This make it safe to hand a reference, though the lifetime - // of 'static is itself unsafe, making the get method unsafe. - unsafe { (*self.inner.get()).as_ref() } - } - - /// The caller must ensure that no reference is active: this method - /// needs unique access. - pub unsafe fn initialize<F: FnOnce() -> T>(&self, init: F) -> &'static T { - // Execute the initialization up front, *then* move it into our slot, - // just in case initialization fails. - let value = init(); - let ptr = self.inner.get(); - - // SAFETY: - // - // note that this can in theory just be `*ptr = Some(value)`, but due to - // the compiler will currently codegen that pattern with something like: - // - // ptr::drop_in_place(ptr) - // ptr::write(ptr, Some(value)) - // - // Due to this pattern it's possible for the destructor of the value in - // `ptr` (e.g., if this is being recursively initialized) to re-access - // TLS, in which case there will be a `&` and `&mut` pointer to the same - // value (an aliasing violation). To avoid setting the "I'm running a - // destructor" flag we just use `mem::replace` which should sequence the - // operations a little differently and make this safe to call. - // - // The precondition also ensures that we are the only one accessing - // `self` at the moment so replacing is fine. - unsafe { - let _ = mem::replace(&mut *ptr, Some(value)); - } - - // SAFETY: With the call to `mem::replace` it is guaranteed there is - // a `Some` behind `ptr`, not a `None` so `unreachable_unchecked` - // will never be reached. - unsafe { - // After storing `Some` we want to get a reference to the contents of - // what we just stored. While we could use `unwrap` here and it should - // always work it empirically doesn't seem to always get optimized away, - // which means that using something like `try_with` can pull in - // panicking code and cause a large size bloat. - match *ptr { - Some(ref x) => x, - None => hint::unreachable_unchecked(), - } - } - } - - /// The other methods hand out references while taking &self. - /// As such, callers of this method must ensure no `&` and `&mut` are - /// available and used at the same time. - #[allow(unused)] - pub unsafe fn take(&mut self) -> Option<T> { - // SAFETY: See doc comment for this method. - unsafe { (*self.inner.get()).take() } - } - } -} - -/// On some targets like wasm there's no threads, so no need to generate -/// thread locals and we can instead just use plain statics! -#[doc(hidden)] -#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] -pub mod statik { - use super::lazy::LazyKeyInner; - use crate::fmt; - - pub struct Key<T> { - inner: LazyKeyInner<T>, - } - - unsafe impl<T> Sync for Key<T> {} - - impl<T> fmt::Debug for Key<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Key").finish_non_exhaustive() - } - } - - impl<T> Key<T> { - pub const fn new() -> Key<T> { - Key { inner: LazyKeyInner::new() } - } - - pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> { - // SAFETY: The caller must ensure no reference is ever handed out to - // the inner cell nor mutable reference to the Option<T> inside said - // cell. This make it safe to hand a reference, though the lifetime - // of 'static is itself unsafe, making the get method unsafe. - let value = unsafe { - match self.inner.get() { - Some(ref value) => value, - None => self.inner.initialize(init), - } - }; - - Some(value) - } - } -} - -#[doc(hidden)] -#[cfg(all(target_thread_local, not(all(target_family = "wasm", not(target_feature = "atomics"))),))] -pub mod fast { - use super::lazy::LazyKeyInner; - use crate::cell::Cell; - use crate::sys::thread_local_dtor::register_dtor; - use crate::{fmt, mem, panic}; - - #[derive(Copy, Clone)] - enum DtorState { - Unregistered, - Registered, - RunningOrHasRun, - } - - // This data structure has been carefully constructed so that the fast path - // only contains one branch on x86. That optimization is necessary to avoid - // duplicated tls lookups on OSX. - // - // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - pub struct Key<T> { - // If `LazyKeyInner::get` returns `None`, that indicates either: - // * The value has never been initialized - // * The value is being recursively initialized - // * The value has already been destroyed or is being destroyed - // To determine which kind of `None`, check `dtor_state`. - // - // This is very optimizer friendly for the fast path - initialized but - // not yet dropped. - inner: LazyKeyInner<T>, - - // Metadata to keep track of the state of the destructor. Remember that - // this variable is thread-local, not global. - dtor_state: Cell<DtorState>, - } - - impl<T> fmt::Debug for Key<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Key").finish_non_exhaustive() - } - } - - impl<T> Key<T> { - pub const fn new() -> Key<T> { - Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } - } - - // note that this is just a publicly-callable function only for the - // const-initialized form of thread locals, basically a way to call the - // free `register_dtor` function defined elsewhere in std. - pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - unsafe { - register_dtor(a, dtor); - } - } - - pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { - // SAFETY: See the definitions of `LazyKeyInner::get` and - // `try_initialize` for more information. - // - // The caller must ensure no mutable references are ever active to - // the inner cell or the inner T when this is called. - // The `try_initialize` is dependant on the passed `init` function - // for this. - unsafe { - match self.inner.get() { - Some(val) => Some(val), - None => self.try_initialize(init), - } - } - } - - // `try_initialize` is only called once per fast thread local variable, - // except in corner cases where thread_local dtors reference other - // thread_local's, or it is being recursively initialized. - // - // Macos: Inlining this function can cause two `tlv_get_addr` calls to - // be performed for every call to `Key::get`. - // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - #[inline(never)] - unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { - // SAFETY: See comment above (this function doc). - if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } { - // SAFETY: See comment above (this function doc). - Some(unsafe { self.inner.initialize(init) }) - } else { - None - } - } - - // `try_register_dtor` is only called once per fast thread local - // variable, except in corner cases where thread_local dtors reference - // other thread_local's, or it is being recursively initialized. - unsafe fn try_register_dtor(&self) -> bool { - match self.dtor_state.get() { - DtorState::Unregistered => { - // SAFETY: dtor registration happens before initialization. - // Passing `self` as a pointer while using `destroy_value<T>` - // is safe because the function will build a pointer to a - // Key<T>, which is the type of self and so find the correct - // size. - unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::<T>) }; - self.dtor_state.set(DtorState::Registered); - true - } - DtorState::Registered => { - // recursively initialized - true - } - DtorState::RunningOrHasRun => false, - } - } - } - - unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) { - let ptr = ptr as *mut Key<T>; - - // SAFETY: - // - // The pointer `ptr` has been built just above and comes from - // `try_register_dtor` where it is originally a Key<T> coming from `self`, - // making it non-NUL and of the correct type. - // - // Right before we run the user destructor be sure to set the - // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This - // causes future calls to `get` to run `try_initialize_drop` again, - // which will now fail, and return `None`. - // - // Wrap the call in a catch to ensure unwinding is caught in the event - // a panic takes place in a destructor. - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe { - let value = (*ptr).inner.take(); - (*ptr).dtor_state.set(DtorState::RunningOrHasRun); - drop(value); - })) { - rtabort!("thread local panicked on drop"); - } - } -} - -#[doc(hidden)] -#[cfg(all( - not(target_thread_local), - not(all(target_family = "wasm", not(target_feature = "atomics"))), -))] -pub mod os { - use super::lazy::LazyKeyInner; - use crate::cell::Cell; - use crate::sys_common::thread_local_key::StaticKey as OsStaticKey; - use crate::{fmt, marker, panic, ptr}; - - /// Use a regular global static to store this key; the state provided will then be - /// thread-local. - pub struct Key<T> { - // OS-TLS key that we'll use to key off. - os: OsStaticKey, - marker: marker::PhantomData<Cell<T>>, - } - - impl<T> fmt::Debug for Key<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Key").finish_non_exhaustive() - } - } - - unsafe impl<T> Sync for Key<T> {} - - struct Value<T: 'static> { - inner: LazyKeyInner<T>, - key: &'static Key<T>, - } - - impl<T: 'static> Key<T> { - #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] - pub const fn new() -> Key<T> { - Key { os: OsStaticKey::new(Some(destroy_value::<T>)), marker: marker::PhantomData } - } - - /// It is a requirement for the caller to ensure that no mutable - /// reference is active when this method is called. - pub unsafe fn get(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> { - // SAFETY: See the documentation for this method. - let ptr = unsafe { self.os.get() as *mut Value<T> }; - if ptr.addr() > 1 { - // SAFETY: the check ensured the pointer is safe (its destructor - // is not running) + it is coming from a trusted source (self). - if let Some(ref value) = unsafe { (*ptr).inner.get() } { - return Some(value); - } - } - // SAFETY: At this point we are sure we have no value and so - // initializing (or trying to) is safe. - unsafe { self.try_initialize(init) } - } - - // `try_initialize` is only called once per os thread local variable, - // except in corner cases where thread_local dtors reference other - // thread_local's, or it is being recursively initialized. - unsafe fn try_initialize(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> { - // SAFETY: No mutable references are ever handed out meaning getting - // the value is ok. - let ptr = unsafe { self.os.get() as *mut Value<T> }; - if ptr.addr() == 1 { - // destructor is running - return None; - } - - let ptr = if ptr.is_null() { - // If the lookup returned null, we haven't initialized our own - // local copy, so do that now. - let ptr = Box::into_raw(Box::new(Value { inner: LazyKeyInner::new(), key: self })); - // SAFETY: At this point we are sure there is no value inside - // ptr so setting it will not affect anyone else. - unsafe { - self.os.set(ptr as *mut u8); - } - ptr - } else { - // recursive initialization - ptr - }; - - // SAFETY: ptr has been ensured as non-NUL just above an so can be - // dereferenced safely. - unsafe { Some((*ptr).inner.initialize(init)) } - } - } - - unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) { - // SAFETY: - // - // The OS TLS ensures that this key contains a null value when this - // destructor starts to run. We set it back to a sentinel value of 1 to - // ensure that any future calls to `get` for this thread will return - // `None`. - // - // Note that to prevent an infinite loop we reset it back to null right - // before we return from the destructor ourselves. - // - // Wrap the call in a catch to ensure unwinding is caught in the event - // a panic takes place in a destructor. - if let Err(_) = panic::catch_unwind(|| unsafe { - let ptr = Box::from_raw(ptr as *mut Value<T>); - let key = ptr.key; - key.os.set(ptr::invalid_mut(1)); - drop(ptr); - key.os.set(ptr::null_mut()); - }) { - rtabort!("thread local panicked on drop"); - } - } -} diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 489af776798..f712c872708 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -131,7 +131,8 @@ //! //! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. //! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack -//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. +//! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that +//! changes to `RUST_MIN_STACK` may be ignored after program start. //! //! Note that the stack size of the main thread is *not* determined by Rust. //! @@ -192,55 +193,23 @@ pub use scoped::{scope, Scope, ScopedJoinHandle}; #[macro_use] mod local; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::local::{AccessError, LocalKey}; - -// Provide the type used by the thread_local! macro to access TLS keys. This -// needs to be kept in sync with the macro itself (in `local.rs`). -// There are three types: "static", "fast", "OS". The "OS" thread local key -// type is accessed via platform-specific API calls and is slow, while the "fast" -// key type is accessed via code generated via LLVM, where TLS keys are set up -// by the elf linker. "static" is for single-threaded platforms where a global -// static is sufficient. - -#[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(not(test))] -#[cfg(all( - target_thread_local, - not(all(target_family = "wasm", not(target_feature = "atomics"))), -))] -#[doc(hidden)] -pub use self::local::fast::Key as __FastLocalKeyInner; -// when building for tests, use real std's type -#[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(test)] -#[cfg(all( - target_thread_local, - not(all(target_family = "wasm", not(target_feature = "atomics"))), -))] -pub use realstd::thread::__FastLocalKeyInner; - -#[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(not(test))] -#[cfg(all( - not(target_thread_local), - not(all(target_family = "wasm", not(target_feature = "atomics"))), -))] -#[doc(hidden)] -pub use self::local::os::Key as __OsLocalKeyInner; -// when building for tests, use real std's type -#[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(test)] -#[cfg(all( - not(target_thread_local), - not(all(target_family = "wasm", not(target_feature = "atomics"))), -))] -pub use realstd::thread::__OsLocalKeyInner; - -#[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] -#[doc(hidden)] -pub use self::local::statik::Key as __StaticLocalKeyInner; +cfg_if::cfg_if! { + if #[cfg(test)] { + // Avoid duplicating the global state assoicated with thread-locals between this crate and + // realstd. Miri relies on this. + pub use realstd::thread::{local_impl, AccessError, LocalKey}; + } else { + #[stable(feature = "rust1", since = "1.0.0")] + pub use self::local::{AccessError, LocalKey}; + + // Implementation details used by the thread_local!{} macro. + #[doc(hidden)] + #[unstable(feature = "thread_local_internals", issue = "none")] + pub mod local_impl { + pub use crate::sys::common::thread_local::{thread_local_inner, Key}; + } + } +} //////////////////////////////////////////////////////////////////////////////// // Builder @@ -528,7 +497,7 @@ impl Builder { MaybeDangling(mem::MaybeUninit::new(x)) } fn into_inner(self) -> T { - // SAFETY: we are always initiailized. + // SAFETY: we are always initialized. let ret = unsafe { self.0.assume_init_read() }; // Make sure we don't drop. mem::forget(self); @@ -537,7 +506,7 @@ impl Builder { } impl<T> Drop for MaybeDangling<T> { fn drop(&mut self) { - // SAFETY: we are always initiailized. + // SAFETY: we are always initialized. unsafe { self.0.assume_init_drop() }; } } diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 6c9ce6fa0dd..b65e2572cc5 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -375,7 +375,9 @@ fn test_scoped_threads_nll() { // this is mostly a *compilation test* for this exact function: fn foo(x: &u8) { thread::scope(|s| { - s.spawn(|| drop(x)); + s.spawn(|| match x { + _ => (), + }); }); } // let's also run it for good measure diff --git a/library/std/src/time.rs b/library/std/src/time.rs index acf9c29083f..00e2857a137 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -119,7 +119,7 @@ pub use core::time::TryFromFloatSecsError; /// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode -/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get +/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get /// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime /// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html /// @@ -224,7 +224,7 @@ pub struct Instant(time::Instant); /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode /// [gettimeofday]: https://man7.org/linux/man-pages/man2/gettimeofday.2.html /// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime -/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get +/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get /// [GetSystemTimePreciseAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime /// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime /// @@ -352,7 +352,7 @@ impl Instant { self.checked_duration_since(earlier).unwrap_or_default() } - /// Returns the amount of time elapsed since this instant was created. + /// Returns the amount of time elapsed since this instant. /// /// # Panics /// @@ -525,8 +525,8 @@ impl SystemTime { self.0.sub_time(&earlier.0).map_err(SystemTimeError) } - /// Returns the difference between the clock time when this - /// system time was created, and the current clock time. + /// Returns the difference from this system time to the + /// current clock time. /// /// This function may fail as the underlying system clock is susceptible to /// drift and updates (e.g., the system clock could go backwards), so this diff --git a/library/std/src/time/tests.rs b/library/std/src/time/tests.rs index 2e64ae59aff..6ed84806e6d 100644 --- a/library/std/src/time/tests.rs +++ b/library/std/src/time/tests.rs @@ -1,4 +1,5 @@ use super::{Duration, Instant, SystemTime, UNIX_EPOCH}; +use core::fmt::Debug; #[cfg(not(target_arch = "wasm32"))] use test::{black_box, Bencher}; @@ -201,6 +202,32 @@ fn since_epoch() { assert!(a < hundred_twenty_years); } +#[test] +fn big_math() { + // Check that the same result occurs when adding/subtracting each duration one at a time as when + // adding/subtracting them all at once. + #[track_caller] + fn check<T: Eq + Copy + Debug>(start: Option<T>, op: impl Fn(&T, Duration) -> Option<T>) { + const DURATIONS: [Duration; 2] = + [Duration::from_secs(i64::MAX as _), Duration::from_secs(50)]; + if let Some(start) = start { + assert_eq!( + op(&start, DURATIONS.into_iter().sum()), + DURATIONS.into_iter().try_fold(start, |t, d| op(&t, d)) + ) + } + } + + check(SystemTime::UNIX_EPOCH.checked_sub(Duration::from_secs(100)), SystemTime::checked_add); + check(SystemTime::UNIX_EPOCH.checked_add(Duration::from_secs(100)), SystemTime::checked_sub); + + let instant = Instant::now(); + check(instant.checked_sub(Duration::from_secs(100)), Instant::checked_add); + check(instant.checked_sub(Duration::from_secs(i64::MAX as _)), Instant::checked_add); + check(instant.checked_add(Duration::from_secs(100)), Instant::checked_sub); + check(instant.checked_add(Duration::from_secs(i64::MAX as _)), Instant::checked_sub); +} + macro_rules! bench_instant_threaded { ($bench_name:ident, $thread_count:expr) => { #[bench] diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs new file mode 100644 index 00000000000..fce220223a0 --- /dev/null +++ b/library/std/tests/common/mod.rs @@ -0,0 +1,58 @@ +#![allow(unused)] + +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; +use std::thread; +use rand::RngCore; + +/// Copied from `std::test_helpers::test_rng`, since these tests rely on the +/// seed not being the same for every RNG invocation too. +#[track_caller] +pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { + use core::hash::{BuildHasher, Hash, Hasher}; + let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); + core::panic::Location::caller().hash(&mut hasher); + let hc64 = hasher.finish(); + let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>(); + let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap(); + rand::SeedableRng::from_seed(seed) +} + +// Copied from std::sys_common::io +pub struct TempDir(PathBuf); + +impl TempDir { + pub fn join(&self, path: &str) -> PathBuf { + let TempDir(ref p) = *self; + p.join(path) + } + + pub fn path(&self) -> &Path { + let TempDir(ref p) = *self; + p + } +} + +impl Drop for TempDir { + fn drop(&mut self) { + // Gee, seeing how we're testing the fs module I sure hope that we + // at least implement this correctly! + let TempDir(ref p) = *self; + let result = fs::remove_dir_all(p); + // Avoid panicking while panicking as this causes the process to + // immediately abort, without displaying test results. + if !thread::panicking() { + result.unwrap(); + } + } +} + +#[track_caller] // for `test_rng` +pub fn tmpdir() -> TempDir { + let p = env::temp_dir(); + let mut r = test_rng(); + let ret = p.join(&format!("rust-{}", r.next_u32())); + fs::create_dir(&ret).unwrap(); + TempDir(ret) +} diff --git a/library/std/tests/create_dir_all_bare.rs b/library/std/tests/create_dir_all_bare.rs new file mode 100644 index 00000000000..fe789323f97 --- /dev/null +++ b/library/std/tests/create_dir_all_bare.rs @@ -0,0 +1,39 @@ +#![cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))] + +//! Note that this test changes the current directory so +//! should not be in the same process as other tests. +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; + +mod common; + +// On some platforms, setting the current directory will prevent deleting it. +// So this helper ensures the current directory is reset. +struct CurrentDir(PathBuf); +impl CurrentDir { + fn new() -> Self { + Self(env::current_dir().unwrap()) + } + fn set(&self, path: &Path) { + env::set_current_dir(path).unwrap(); + } + fn with(path: &Path, f: impl FnOnce()) { + let current_dir = Self::new(); + current_dir.set(path); + f(); + } +} +impl Drop for CurrentDir { + fn drop(&mut self) { + env::set_current_dir(&self.0).unwrap(); + } +} + +#[test] +fn create_dir_all_bare() { + let tmpdir = common::tmpdir(); + CurrentDir::with(tmpdir.path(), || { + fs::create_dir_all("create-dir-all-bare").unwrap(); + }); +} diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index aae2c49d898..96b4f372b8b 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -3,18 +3,8 @@ use std::ffi::{OsStr, OsString}; use rand::distributions::{Alphanumeric, DistString}; -/// Copied from `std::test_helpers::test_rng`, since these tests rely on the -/// seed not being the same for every RNG invocation too. -#[track_caller] -pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { - use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); - core::panic::Location::caller().hash(&mut hasher); - let hc64 = hasher.finish(); - let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>(); - let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap(); - rand::SeedableRng::from_seed(seed) -} +mod common; +use common::test_rng; #[track_caller] fn make_rand_name() -> OsString { diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index bf3c81fcc98..9ce29a33df6 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -16,7 +16,6 @@ fn arm_linux() { // tidy-alphabetical-start println!("aes: {}", is_arm_feature_detected!("aes")); println!("crc: {}", is_arm_feature_detected!("crc")); - println!("crypto: {}", is_arm_feature_detected!("crypto")); println!("neon: {}", is_arm_feature_detected!("neon")); println!("pmull: {}", is_arm_feature_detected!("pmull")); println!("sha2: {}", is_arm_feature_detected!("sha2")); diff --git a/library/stdarch b/library/stdarch -Subproject a0c30f3e3c75adcd6ee7efc94014ebcead61c50 +Subproject 7e2cdc675b92165c5f8c4c794620252be4605e7 diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml new file mode 100644 index 00000000000..5356ee277cc --- /dev/null +++ b/library/sysroot/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "sysroot" +version = "0.0.0" +edition = "2021" + +# this is a dummy crate to ensure that all required crates appear in the sysroot +[dependencies] +proc_macro = { path = "../proc_macro" } +std = { path = "../std" } +test = { path = "../test" } + +# Forward features to the `std` crate as necessary +[features] +default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"] +backtrace = ["std/backtrace"] +compiler-builtins-c = ["std/compiler-builtins-c"] +compiler-builtins-mem = ["std/compiler-builtins-mem"] +compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"] +compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"] +llvm-libunwind = ["std/llvm-libunwind"] +system-llvm-libunwind = ["std/system-llvm-libunwind"] +panic-unwind = ["std/panic_unwind"] +panic_immediate_abort = ["std/panic_immediate_abort"] +profiler = ["std/profiler"] +std_detect_file_io = ["std/std_detect_file_io"] +std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"] +std_detect_env_override = ["std/std_detect_env_override"] diff --git a/library/sysroot/src/lib.rs b/library/sysroot/src/lib.rs new file mode 100644 index 00000000000..71ceb580a40 --- /dev/null +++ b/library/sysroot/src/lib.rs @@ -0,0 +1 @@ +// This is intentionally empty since this crate is only used to depend on other library crates. diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 61b6f33bce0..91a1abde059 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -7,30 +7,8 @@ edition = "2021" crate-type = ["dylib", "rlib"] [dependencies] -cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } std = { path = "../std" } core = { path = "../core" } -libc = { version = "0.2", default-features = false } panic_unwind = { path = "../panic_unwind" } panic_abort = { path = "../panic_abort" } - -# not actually used but needed to always have proc_macro in the sysroot -proc_macro = { path = "../proc_macro" } - -# Forward features to the `std` crate as necessary -[features] -default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"] -backtrace = ["std/backtrace"] -compiler-builtins-c = ["std/compiler-builtins-c"] -compiler-builtins-mem = ["std/compiler-builtins-mem"] -compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"] -compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"] -llvm-libunwind = ["std/llvm-libunwind"] -system-llvm-libunwind = ["std/system-llvm-libunwind"] -panic-unwind = ["std/panic_unwind"] -panic_immediate_abort = ["std/panic_immediate_abort"] -profiler = ["std/profiler"] -std_detect_file_io = ["std/std_detect_file_io"] -std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"] -std_detect_env_override = ["std/std_detect_env_override"] diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 1ee68c8540b..7eee4ca2361 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -41,6 +41,46 @@ impl<T: Write> Write for OutputLocation<T> { } } +pub struct ConsoleTestDiscoveryState { + pub log_out: Option<File>, + pub tests: usize, + pub benchmarks: usize, + pub ignored: usize, + pub options: Options, +} + +impl ConsoleTestDiscoveryState { + pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestDiscoveryState> { + let log_out = match opts.logfile { + Some(ref path) => Some(File::create(path)?), + None => None, + }; + + Ok(ConsoleTestDiscoveryState { + log_out, + tests: 0, + benchmarks: 0, + ignored: 0, + options: opts.options, + }) + } + + pub fn write_log<F, S>(&mut self, msg: F) -> io::Result<()> + where + S: AsRef<str>, + F: FnOnce() -> S, + { + match self.log_out { + None => Ok(()), + Some(ref mut o) => { + let msg = msg(); + let msg = msg.as_ref(); + o.write_all(msg.as_bytes()) + } + } + } +} + pub struct ConsoleTestState { pub log_out: Option<File>, pub total: usize, @@ -138,53 +178,44 @@ impl ConsoleTestState { // List the tests to console, and optionally to logfile. Filters are honored. pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> { - let mut output = match term::stdout() { + let output = match term::stdout() { None => OutputLocation::Raw(io::stdout().lock()), Some(t) => OutputLocation::Pretty(t), }; - let quiet = opts.format == OutputFormat::Terse; - let mut st = ConsoleTestState::new(opts)?; - - let mut ntest = 0; - let mut nbench = 0; + let mut out: Box<dyn OutputFormatter> = match opts.format { + OutputFormat::Pretty | OutputFormat::Junit => { + Box::new(PrettyFormatter::new(output, false, 0, false, None)) + } + OutputFormat::Terse => Box::new(TerseFormatter::new(output, false, 0, false)), + OutputFormat::Json => Box::new(JsonFormatter::new(output)), + }; + let mut st = ConsoleTestDiscoveryState::new(opts)?; + out.write_discovery_start()?; for test in filter_tests(opts, tests).into_iter() { use crate::TestFn::*; - let TestDescAndFn { desc: TestDesc { name, .. }, testfn } = test; + let TestDescAndFn { desc, testfn } = test; let fntype = match testfn { StaticTestFn(..) | DynTestFn(..) => { - ntest += 1; + st.tests += 1; "test" } StaticBenchFn(..) | DynBenchFn(..) => { - nbench += 1; + st.benchmarks += 1; "benchmark" } }; - writeln!(output, "{name}: {fntype}")?; - st.write_log(|| format!("{fntype} {name}\n"))?; - } + st.ignored += if desc.ignore { 1 } else { 0 }; - fn plural(count: u32, s: &str) -> String { - match count { - 1 => format!("1 {s}"), - n => format!("{n} {s}s"), - } + out.write_test_discovered(&desc, fntype)?; + st.write_log(|| format!("{fntype} {}\n", desc.name))?; } - if !quiet { - if ntest != 0 || nbench != 0 { - writeln!(output)?; - } - - writeln!(output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark"))?; - } - - Ok(()) + out.write_discovery_finish(&st) } // Updates `ConsoleTestState` depending on result of the test execution. diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index 95d2faf2506..47c4e7757e4 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, io, io::prelude::Write}; use super::OutputFormatter; use crate::{ - console::{ConsoleTestState, OutputLocation}, + console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation}, test_result::TestResult, time, types::TestDesc, @@ -18,14 +18,10 @@ impl<T: Write> JsonFormatter<T> { } fn writeln_message(&mut self, s: &str) -> io::Result<()> { - assert!(!s.contains('\n')); - - self.out.write_all(s.as_ref())?; - self.out.write_all(b"\n") - } - - fn write_message(&mut self, s: &str) -> io::Result<()> { - assert!(!s.contains('\n')); + // self.out will take a lock, but that lock is released when write_all returns. This + // results in a race condition and json output may not end with a new line. We avoid this + // by issuing `write_all` calls line-by-line. + assert_eq!(s.chars().last(), Some('\n')); self.out.write_all(s.as_ref()) } @@ -34,47 +30,87 @@ impl<T: Write> JsonFormatter<T> { &mut self, ty: &str, name: &str, - evt: &str, + event: &str, exec_time: Option<&time::TestExecTime>, stdout: Option<Cow<'_, str>>, extra: Option<&str>, ) -> io::Result<()> { // A doc test's name includes a filename which must be escaped for correct json. - self.write_message(&format!( - r#"{{ "type": "{}", "name": "{}", "event": "{}""#, - ty, - EscapedString(name), - evt - ))?; - if let Some(exec_time) = exec_time { - self.write_message(&format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()))?; - } - if let Some(stdout) = stdout { - self.write_message(&format!(r#", "stdout": "{}""#, EscapedString(stdout)))?; - } - if let Some(extra) = extra { - self.write_message(&format!(r#", {extra}"#))?; - } - self.writeln_message(" }") + let name = EscapedString(name); + let exec_time_json = if let Some(exec_time) = exec_time { + format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()) + } else { + String::from("") + }; + let stdout_json = if let Some(stdout) = stdout { + format!(r#", "stdout": "{}""#, EscapedString(stdout)) + } else { + String::from("") + }; + let extra_json = + if let Some(extra) = extra { format!(r#", {extra}"#) } else { String::from("") }; + let newline = "\n"; + + self.writeln_message(&format!( + r#"{{ "type": "{ty}", "name": "{name}", "event": "{event}"{exec_time_json}{stdout_json}{extra_json} }}{newline}"#)) } } impl<T: Write> OutputFormatter for JsonFormatter<T> { + fn write_discovery_start(&mut self) -> io::Result<()> { + self.writeln_message(concat!(r#"{ "type": "suite", "event": "discovery" }"#, "\n")) + } + + fn write_test_discovered(&mut self, desc: &TestDesc, test_type: &str) -> io::Result<()> { + let TestDesc { + name, + ignore, + ignore_message, + source_file, + start_line, + start_col, + end_line, + end_col, + .. + } = desc; + + let name = EscapedString(name.as_slice()); + let ignore_message = ignore_message.unwrap_or(""); + let source_path = EscapedString(source_file); + let newline = "\n"; + + self.writeln_message(&format!( + r#"{{ "type": "{test_type}", "event": "discovered", "name": "{name}", "ignore": {ignore}, "ignore_message": "{ignore_message}", "source_path": "{source_path}", "start_line": {start_line}, "start_col": {start_col}, "end_line": {end_line}, "end_col": {end_col} }}{newline}"# + )) + } + + fn write_discovery_finish(&mut self, state: &ConsoleTestDiscoveryState) -> io::Result<()> { + let ConsoleTestDiscoveryState { tests, benchmarks, ignored, .. } = state; + + let total = tests + benchmarks; + let newline = "\n"; + self.writeln_message(&format!( + r#"{{ "type": "suite", "event": "completed", "tests": {tests}, "benchmarks": {benchmarks}, "total": {total}, "ignored": {ignored} }}{newline}"# + )) + } + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option<u64>) -> io::Result<()> { let shuffle_seed_json = if let Some(shuffle_seed) = shuffle_seed { format!(r#", "shuffle_seed": {shuffle_seed}"#) } else { String::new() }; + let newline = "\n"; self.writeln_message(&format!( - r#"{{ "type": "suite", "event": "started", "test_count": {test_count}{shuffle_seed_json} }}"# - )) + r#"{{ "type": "suite", "event": "started", "test_count": {test_count}{shuffle_seed_json} }}{newline}"# + )) } fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { + let name = EscapedString(desc.name.as_slice()); + let newline = "\n"; self.writeln_message(&format!( - r#"{{ "type": "test", "event": "started", "name": "{}" }}"#, - EscapedString(desc.name.as_slice()) + r#"{{ "type": "test", "event": "started", "name": "{name}" }}{newline}"# )) } @@ -139,53 +175,43 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> { } else { format!(r#", "mib_per_second": {}"#, bs.mb_s) }; + let name = EscapedString(desc.name.as_slice()); - let line = format!( + self.writeln_message(&format!( "{{ \"type\": \"bench\", \ - \"name\": \"{}\", \ - \"median\": {}, \ - \"deviation\": {}{} }}", - EscapedString(desc.name.as_slice()), - median, - deviation, - mbps - ); - - self.writeln_message(&line) + \"name\": \"{name}\", \ + \"median\": {median}, \ + \"deviation\": {deviation}{mbps} }}\n", + )) } } } fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { + let name = EscapedString(desc.name.as_slice()); + let newline = "\n"; self.writeln_message(&format!( - r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#, - EscapedString(desc.name.as_slice()) + r#"{{ "type": "test", "event": "timeout", "name": "{name}" }}{newline}"#, )) } fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> { - self.write_message(&format!( - "{{ \"type\": \"suite\", \ - \"event\": \"{}\", \ - \"passed\": {}, \ - \"failed\": {}, \ - \"ignored\": {}, \ - \"measured\": {}, \ - \"filtered_out\": {}", - if state.failed == 0 { "ok" } else { "failed" }, - state.passed, - state.failed, - state.ignored, - state.measured, - state.filtered_out, - ))?; - - if let Some(ref exec_time) = state.exec_time { - let time_str = format!(", \"exec_time\": {}", exec_time.0.as_secs_f64()); - self.write_message(&time_str)?; - } + let event = if state.failed == 0 { "ok" } else { "failed" }; + let passed = state.passed; + let failed = state.failed; + let ignored = state.ignored; + let measured = state.measured; + let filtered_out = state.filtered_out; + let exec_time_json = if let Some(ref exec_time) = state.exec_time { + format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()) + } else { + String::from("") + }; + let newline = "\n"; - self.writeln_message(" }")?; + self.writeln_message(&format!( + r#"{{ "type": "suite", "event": "{event}", "passed": {passed}, "failed": {failed}, "ignored": {ignored}, "measured": {measured}, "filtered_out": {filtered_out}{exec_time_json} }}{newline}"# + ))?; Ok(state.failed == 0) } diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index 7a40ce33cb7..9f5bf24367e 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -3,7 +3,7 @@ use std::time::Duration; use super::OutputFormatter; use crate::{ - console::{ConsoleTestState, OutputLocation}, + console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation}, test_result::TestResult, time, types::{TestDesc, TestType}, @@ -11,7 +11,7 @@ use crate::{ pub struct JunitFormatter<T> { out: OutputLocation<T>, - results: Vec<(TestDesc, TestResult, Duration)>, + results: Vec<(TestDesc, TestResult, Duration, Vec<u8>)>, } impl<T: Write> JunitFormatter<T> { @@ -26,7 +26,31 @@ impl<T: Write> JunitFormatter<T> { } } +fn str_to_cdata(s: &str) -> String { + // Drop the stdout in a cdata. Unfortunately, you can't put either of `]]>` or + // `<?'` in a CDATA block, so the escaping gets a little weird. + let escaped_output = s.replace("]]>", "]]]]><![CDATA[>"); + let escaped_output = escaped_output.replace("<?", "<]]><![CDATA[?"); + // We also smuggle newlines as 
 so as to keep all the output on one line + let escaped_output = escaped_output.replace("\n", "]]>
<![CDATA["); + // Prune empty CDATA blocks resulting from any escaping + let escaped_output = escaped_output.replace("<![CDATA[]]>", ""); + format!("<![CDATA[{}]]>", escaped_output) +} + impl<T: Write> OutputFormatter for JunitFormatter<T> { + fn write_discovery_start(&mut self) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!")) + } + + fn write_test_discovered(&mut self, _desc: &TestDesc, _test_type: &str) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!")) + } + + fn write_discovery_finish(&mut self, _state: &ConsoleTestDiscoveryState) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!")) + } + fn write_run_start( &mut self, _test_count: usize, @@ -51,14 +75,14 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { desc: &TestDesc, result: &TestResult, exec_time: Option<&time::TestExecTime>, - _stdout: &[u8], + stdout: &[u8], _state: &ConsoleTestState, ) -> io::Result<()> { // Because the testsuite node holds some of the information as attributes, we can't write it // until all of the tests have finished. Instead of writing every result as they come in, we add // them to a Vec and write them all at once when run is complete. let duration = exec_time.map(|t| t.0).unwrap_or_default(); - self.results.push((desc.clone(), result.clone(), duration)); + self.results.push((desc.clone(), result.clone(), duration, stdout.to_vec())); Ok(()) } fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> { @@ -73,7 +97,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { >", state.failed, state.total, state.ignored ))?; - for (desc, result, duration) in std::mem::take(&mut self.results) { + for (desc, result, duration, stdout) in std::mem::take(&mut self.results) { let (class_name, test_name) = parse_class_name(&desc); match result { TestResult::TrIgnored => { /* no-op */ } @@ -86,6 +110,11 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { duration.as_secs_f64() ))?; self.write_message("<failure type=\"assert\"/>")?; + if !stdout.is_empty() { + self.write_message("<system-out>")?; + self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?; + self.write_message("</system-out>")?; + } self.write_message("</testcase>")?; } @@ -98,6 +127,11 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { duration.as_secs_f64() ))?; self.write_message(&format!("<failure message=\"{m}\" type=\"assert\"/>"))?; + if !stdout.is_empty() { + self.write_message("<system-out>")?; + self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?; + self.write_message("</system-out>")?; + } self.write_message("</testcase>")?; } @@ -124,11 +158,19 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> { TestResult::TrOk => { self.write_message(&format!( "<testcase classname=\"{}\" \ - name=\"{}\" time=\"{}\"/>", + name=\"{}\" time=\"{}\"", class_name, test_name, duration.as_secs_f64() ))?; + if stdout.is_empty() || !state.options.display_output { + self.write_message("/>")?; + } else { + self.write_message("><system-out>")?; + self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?; + self.write_message("</system-out>")?; + self.write_message("</testcase>")?; + } } } } diff --git a/library/test/src/formatters/mod.rs b/library/test/src/formatters/mod.rs index cb67b6491a3..bc6ffebc1d3 100644 --- a/library/test/src/formatters/mod.rs +++ b/library/test/src/formatters/mod.rs @@ -1,7 +1,7 @@ use std::{io, io::prelude::Write}; use crate::{ - console::ConsoleTestState, + console::{ConsoleTestDiscoveryState, ConsoleTestState}, test_result::TestResult, time, types::{TestDesc, TestName}, @@ -18,6 +18,10 @@ pub(crate) use self::pretty::PrettyFormatter; pub(crate) use self::terse::TerseFormatter; pub(crate) trait OutputFormatter { + fn write_discovery_start(&mut self) -> io::Result<()>; + fn write_test_discovered(&mut self, desc: &TestDesc, test_type: &str) -> io::Result<()>; + fn write_discovery_finish(&mut self, state: &ConsoleTestDiscoveryState) -> io::Result<()>; + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option<u64>) -> io::Result<()>; fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()>; fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()>; diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 247778e515f..22654a3400b 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -3,7 +3,7 @@ use std::{io, io::prelude::Write}; use super::OutputFormatter; use crate::{ bench::fmt_bench_samples, - console::{ConsoleTestState, OutputLocation}, + console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation}, term, test_result::TestResult, time, @@ -181,6 +181,33 @@ impl<T: Write> PrettyFormatter<T> { } impl<T: Write> OutputFormatter for PrettyFormatter<T> { + fn write_discovery_start(&mut self) -> io::Result<()> { + Ok(()) + } + + fn write_test_discovered(&mut self, desc: &TestDesc, test_type: &str) -> io::Result<()> { + self.write_plain(format!("{}: {test_type}\n", desc.name)) + } + + fn write_discovery_finish(&mut self, state: &ConsoleTestDiscoveryState) -> io::Result<()> { + fn plural(count: usize, s: &str) -> String { + match count { + 1 => format!("1 {s}"), + n => format!("{n} {s}s"), + } + } + + if state.tests != 0 || state.benchmarks != 0 { + self.write_plain("\n")?; + } + + self.write_plain(format!( + "{}, {}\n", + plural(state.tests, "test"), + plural(state.benchmarks, "benchmark") + )) + } + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option<u64>) -> io::Result<()> { let noun = if test_count != 1 { "tests" } else { "test" }; let shuffle_seed_msg = if let Some(shuffle_seed) = shuffle_seed { diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index a431acfbc27..2931ca6ead0 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -3,7 +3,7 @@ use std::{io, io::prelude::Write}; use super::OutputFormatter; use crate::{ bench::fmt_bench_samples, - console::{ConsoleTestState, OutputLocation}, + console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation}, term, test_result::TestResult, time, @@ -167,6 +167,18 @@ impl<T: Write> TerseFormatter<T> { } impl<T: Write> OutputFormatter for TerseFormatter<T> { + fn write_discovery_start(&mut self) -> io::Result<()> { + Ok(()) + } + + fn write_test_discovered(&mut self, desc: &TestDesc, test_type: &str) -> io::Result<()> { + self.write_plain(format!("{}: {test_type}\n", desc.name)) + } + + fn write_discovery_finish(&mut self, _state: &ConsoleTestDiscoveryState) -> io::Result<()> { + Ok(()) + } + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option<u64>) -> io::Result<()> { self.total_test_count = test_count; let noun = if test_count != 1 { "tests" } else { "test" }; diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 69fb529d7f5..e76d6716b94 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -17,7 +17,6 @@ #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] #![feature(internal_output_capture)] -#![feature(is_terminal)] #![feature(staged_api)] #![feature(process_exitcode_internals)] #![feature(panic_can_unwind)] @@ -204,7 +203,7 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn { } /// Invoked when unit tests terminate. Returns `Result::Err` if the test is -/// considered a failure. By default, invokes `report() and checks for a `0` +/// considered a failure. By default, invokes `report()` and checks for a `0` /// result. pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> { let code = result.report().to_i32(); @@ -220,14 +219,14 @@ pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> { struct FilteredTests { tests: Vec<(TestId, TestDescAndFn)>, - benchs: Vec<(TestId, TestDescAndFn)>, + benches: Vec<(TestId, TestDescAndFn)>, next_id: usize, } impl FilteredTests { fn add_bench(&mut self, desc: TestDesc, testfn: TestFn) { let test = TestDescAndFn { desc, testfn }; - self.benchs.push((TestId(self.next_id), test)); + self.benches.push((TestId(self.next_id), test)); self.next_id += 1; } fn add_test(&mut self, desc: TestDesc, testfn: TestFn) { @@ -246,7 +245,7 @@ impl FilteredTests { self.add_test(desc, testfn); } fn total_len(&self) -> usize { - self.tests.len() + self.benchs.len() + self.tests.len() + self.benches.len() } } @@ -291,7 +290,7 @@ where let tests_len = tests.len(); - let mut filtered = FilteredTests { tests: Vec::new(), benchs: Vec::new(), next_id: 0 }; + let mut filtered = FilteredTests { tests: Vec::new(), benches: Vec::new(), next_id: 0 }; for test in filter_tests(opts, tests) { let mut desc = test.desc; @@ -458,7 +457,7 @@ where if opts.bench_benchmarks { // All benchmarks run at the end, in serial. - for (id, b) in filtered.benchs { + for (id, b) in filtered.benches { let event = TestEvent::TeWait(b.desc.clone()); notify_about_test_event(event)?; let join_handle = run_test(opts, false, id, b, run_strategy, tx.clone()); diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 44776fb0a31..c34583e6959 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -63,6 +63,11 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { name: StaticTestName("1"), ignore: true, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -75,6 +80,11 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { name: StaticTestName("2"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -95,6 +105,11 @@ pub fn do_not_run_ignored_tests() { name: StaticTestName("whatever"), ignore: true, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -118,6 +133,11 @@ pub fn ignored_tests_result_in_ignored() { name: StaticTestName("whatever"), ignore: true, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -143,6 +163,11 @@ fn test_should_panic() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::Yes, compile_fail: false, no_run: false, @@ -168,6 +193,11 @@ fn test_should_panic_good_message() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::YesWithMessage("error message"), compile_fail: false, no_run: false, @@ -198,6 +228,11 @@ fn test_should_panic_bad_message() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::YesWithMessage(expected), compile_fail: false, no_run: false, @@ -232,6 +267,11 @@ fn test_should_panic_non_string_message_type() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::YesWithMessage(expected), compile_fail: false, no_run: false, @@ -260,6 +300,11 @@ fn test_should_panic_but_succeeds() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic, compile_fail: false, no_run: false, @@ -288,6 +333,11 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -325,6 +375,11 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -364,6 +419,11 @@ fn typed_test_desc(test_type: TestType) -> TestDesc { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -476,6 +536,11 @@ pub fn exclude_should_panic_option() { name: StaticTestName("3"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::Yes, compile_fail: false, no_run: false, @@ -500,6 +565,11 @@ pub fn exact_filter_match() { name: StaticTestName(name), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -591,6 +661,11 @@ fn sample_tests() -> Vec<TestDescAndFn> { name: DynTestName((*name).clone()), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -720,6 +795,11 @@ pub fn test_bench_no_iter() { name: StaticTestName("f"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -743,6 +823,11 @@ pub fn test_bench_iter() { name: StaticTestName("f"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -759,6 +844,11 @@ fn should_sort_failures_before_printing_them() { name: StaticTestName("a"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -769,6 +859,11 @@ fn should_sort_failures_before_printing_them() { name: StaticTestName("b"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -816,6 +911,11 @@ fn test_dyn_bench_returning_err_fails_when_run_as_test() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 6f2e033095a..e79914dbf4b 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -119,6 +119,11 @@ pub struct TestDesc { pub name: TestName, pub ignore: bool, pub ignore_message: Option<&'static str>, + pub source_file: &'static str, + pub start_line: usize, + pub start_col: usize, + pub end_line: usize, + pub end_col: usize, pub should_panic: options::ShouldPanic, pub compile_fail: bool, pub no_run: bool, diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 3753071d5f0..b655bae9673 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -54,6 +54,22 @@ cfg_if::cfg_if! { } } +// This is the same as musl except that we default to using the system libunwind +// instead of libgcc. +#[cfg(target_env = "ohos")] +cfg_if::cfg_if! { + if #[cfg(all(feature = "llvm-libunwind", feature = "system-llvm-libunwind"))] { + compile_error!("`llvm-libunwind` and `system-llvm-libunwind` cannot be enabled at the same time"); + } else if #[cfg(feature = "llvm-libunwind")] { + #[link(name = "unwind", kind = "static", modifiers = "-bundle")] + extern "C" {} + } else { + #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] + #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] + extern "C" {} + } +} + #[cfg(target_os = "android")] cfg_if::cfg_if! { if #[cfg(feature = "llvm-libunwind")] { @@ -127,3 +143,7 @@ extern "C" {} #[cfg(target_os = "haiku")] #[link(name = "gcc_s")] extern "C" {} + +#[cfg(target_os = "nto")] +#[link(name = "gcc_s")] +extern "C" {} diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 036a35869a5..f6a68073b2f 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -75,6 +75,9 @@ pub const unwinder_private_data_size: usize = 20; #[cfg(all(target_arch = "hexagon", target_os = "linux"))] pub const unwinder_private_data_size: usize = 35; +#[cfg(target_arch = "loongarch64")] +pub const unwinder_private_data_size: usize = 2; + #[repr(C)] pub struct _Unwind_Exception { pub exception_class: _Unwind_Exception_Class, @@ -89,7 +92,7 @@ pub type _Unwind_Exception_Cleanup_Fn = // FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in // the block are reexported in dylib build of std. This is needed when build rustc with -// feature `llvm-libunwind', as no other cdylib will provided those _Unwind_* symbols. +// feature `llvm-libunwind`, as no other cdylib will provided those _Unwind_* symbols. // However the `link` attribute is duplicated multiple times and does not just export symbol, // a better way to manually export symbol would be another attribute like `#[export]`. // See the logic in function rustc_codegen_ssa::src::back::exported_symbols, module |