summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/alloc/benches/btree/map.rs1
-rw-r--r--library/alloc/benches/vec.rs2
-rw-r--r--library/alloc/benches/vec_deque.rs146
-rw-r--r--library/alloc/src/alloc.rs8
-rw-r--r--library/alloc/src/borrow.rs13
-rw-r--r--library/alloc/src/boxed.rs131
-rw-r--r--library/alloc/src/boxed/thin.rs10
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs81
-rw-r--r--library/alloc/src/collections/binary_heap/tests.rs19
-rw-r--r--library/alloc/src/collections/btree/map.rs192
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs86
-rw-r--r--library/alloc/src/collections/btree/mod.rs1
-rw-r--r--library/alloc/src/collections/btree/navigate.rs12
-rw-r--r--library/alloc/src/collections/btree/set.rs75
-rw-r--r--library/alloc/src/collections/btree/set/tests.rs1
-rw-r--r--library/alloc/src/collections/linked_list.rs397
-rw-r--r--library/alloc/src/collections/vec_deque/drain.rs40
-rw-r--r--library/alloc/src/collections/vec_deque/into_iter.rs189
-rw-r--r--library/alloc/src/collections/vec_deque/iter.rs33
-rw-r--r--library/alloc/src/collections/vec_deque/iter_mut.rs32
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs170
-rw-r--r--library/alloc/src/collections/vec_deque/spec_from_iter.rs2
-rw-r--r--library/alloc/src/collections/vec_deque/tests.rs42
-rw-r--r--library/alloc/src/fmt.rs10
-rw-r--r--library/alloc/src/lib.rs49
-rw-r--r--library/alloc/src/macros.rs2
-rw-r--r--library/alloc/src/raw_vec.rs1
-rw-r--r--library/alloc/src/rc.rs48
-rw-r--r--library/alloc/src/rc/tests.rs15
-rw-r--r--library/alloc/src/str.rs10
-rw-r--r--library/alloc/src/string.rs32
-rw-r--r--library/alloc/src/sync.rs64
-rw-r--r--library/alloc/src/task.rs3
-rw-r--r--library/alloc/src/tests.rs24
-rw-r--r--library/alloc/src/vec/cow.rs1
-rw-r--r--library/alloc/src/vec/drain.rs8
-rw-r--r--library/alloc/src/vec/drain_filter.rs8
-rw-r--r--library/alloc/src/vec/in_place_collect.rs2
-rw-r--r--library/alloc/src/vec/into_iter.rs35
-rw-r--r--library/alloc/src/vec/mod.rs36
-rw-r--r--library/alloc/src/vec/splice.rs2
-rw-r--r--library/alloc/tests/boxed.rs17
-rw-r--r--library/alloc/tests/const_fns.rs19
-rw-r--r--library/alloc/tests/lib.rs8
-rw-r--r--library/alloc/tests/slice.rs42
-rw-r--r--library/alloc/tests/str.rs26
-rw-r--r--library/alloc/tests/vec.rs24
-rw-r--r--library/alloc/tests/vec_deque.rs37
m---------library/backtrace0
-rw-r--r--library/core/benches/array.rs10
-rw-r--r--library/core/benches/lib.rs1
-rw-r--r--library/core/benches/num/flt2dec/strategy/grisu.rs27
-rw-r--r--library/core/benches/tuple.rs22
-rw-r--r--library/core/src/alloc/layout.rs15
-rw-r--r--library/core/src/alloc/mod.rs7
-rw-r--r--library/core/src/any.rs5
-rw-r--r--library/core/src/array/ascii.rs47
-rw-r--r--library/core/src/array/equality.rs73
-rw-r--r--library/core/src/array/iter.rs33
-rw-r--r--library/core/src/array/mod.rs30
-rw-r--r--library/core/src/ascii.rs75
-rw-r--r--library/core/src/ascii/ascii_char.rs565
-rw-r--r--library/core/src/bool.rs15
-rw-r--r--library/core/src/borrow.rs17
-rw-r--r--library/core/src/cell.rs137
-rw-r--r--library/core/src/cell/lazy.rs134
-rw-r--r--library/core/src/cell/once.rs53
-rw-r--r--library/core/src/char/convert.rs12
-rw-r--r--library/core/src/char/methods.rs76
-rw-r--r--library/core/src/char/mod.rs251
-rw-r--r--library/core/src/clone.rs23
-rw-r--r--library/core/src/cmp.rs219
-rw-r--r--library/core/src/cmp/bytewise.rs83
-rw-r--r--library/core/src/convert/mod.rs54
-rw-r--r--library/core/src/convert/num.rs50
-rw-r--r--library/core/src/default.rs4
-rw-r--r--library/core/src/error.rs4
-rw-r--r--library/core/src/escape.rs99
-rw-r--r--library/core/src/ffi/c_str.rs34
-rw-r--r--library/core/src/ffi/mod.rs10
-rw-r--r--library/core/src/fmt/builders.rs14
-rw-r--r--library/core/src/fmt/mod.rs366
-rw-r--r--library/core/src/fmt/rt.rs212
-rw-r--r--library/core/src/fmt/rt/v1.rs63
-rw-r--r--library/core/src/future/into_future.rs1
-rw-r--r--library/core/src/future/mod.rs12
-rw-r--r--library/core/src/hash/mod.rs95
-rw-r--r--library/core/src/hash/sip.rs17
-rw-r--r--library/core/src/hint.rs16
-rw-r--r--library/core/src/internal_macros.rs71
-rw-r--r--library/core/src/intrinsics.rs334
-rw-r--r--library/core/src/intrinsics/mir.rs40
-rw-r--r--library/core/src/iter/adapters/by_ref_sized.rs5
-rw-r--r--library/core/src/iter/adapters/chain.rs75
-rw-r--r--library/core/src/iter/adapters/cloned.rs14
-rw-r--r--library/core/src/iter/adapters/copied.rs19
-rw-r--r--library/core/src/iter/adapters/cycle.rs26
-rw-r--r--library/core/src/iter/adapters/enumerate.rs36
-rw-r--r--library/core/src/iter/adapters/flatten.rs107
-rw-r--r--library/core/src/iter/adapters/fuse.rs15
-rw-r--r--library/core/src/iter/adapters/rev.rs19
-rw-r--r--library/core/src/iter/adapters/skip.rs54
-rw-r--r--library/core/src/iter/adapters/take.rs34
-rw-r--r--library/core/src/iter/mod.rs1
-rw-r--r--library/core/src/iter/range.rs45
-rw-r--r--library/core/src/iter/sources/empty.rs3
-rw-r--r--library/core/src/iter/sources/repeat.rs5
-rw-r--r--library/core/src/iter/sources/repeat_n.rs8
-rw-r--r--library/core/src/iter/sources/repeat_with.rs1
-rw-r--r--library/core/src/iter/traits/accum.rs40
-rw-r--r--library/core/src/iter/traits/collect.rs3
-rw-r--r--library/core/src/iter/traits/double_ended.rs26
-rw-r--r--library/core/src/iter/traits/iterator.rs141
-rw-r--r--library/core/src/lib.rs65
-rw-r--r--library/core/src/macros/mod.rs9
-rw-r--r--library/core/src/macros/panic.md2
-rw-r--r--library/core/src/marker.rs238
-rw-r--r--library/core/src/mem/manually_drop.rs6
-rw-r--r--library/core/src/mem/maybe_uninit.rs30
-rw-r--r--library/core/src/mem/mod.rs62
-rw-r--r--library/core/src/mem/transmutability.rs10
-rw-r--r--library/core/src/net/display_buffer.rs (renamed from library/std/src/net/display_buffer.rs)0
-rw-r--r--library/core/src/net/ip_addr.rs2070
-rw-r--r--library/core/src/net/mod.rs24
-rw-r--r--library/core/src/net/parser.rs (renamed from library/std/src/net/parser.rs)6
-rw-r--r--library/core/src/net/socket_addr.rs691
-rw-r--r--library/core/src/num/dec2flt/common.rs179
-rw-r--r--library/core/src/num/dec2flt/decimal.rs65
-rw-r--r--library/core/src/num/dec2flt/float.rs4
-rw-r--r--library/core/src/num/dec2flt/lemire.rs2
-rw-r--r--library/core/src/num/dec2flt/mod.rs18
-rw-r--r--library/core/src/num/dec2flt/number.rs1
-rw-r--r--library/core/src/num/dec2flt/parse.rs224
-rw-r--r--library/core/src/num/error.rs6
-rw-r--r--library/core/src/num/f32.rs38
-rw-r--r--library/core/src/num/f64.rs38
-rw-r--r--library/core/src/num/flt2dec/strategy/grisu.rs16
-rw-r--r--library/core/src/num/int_macros.rs93
-rw-r--r--library/core/src/num/mod.rs473
-rw-r--r--library/core/src/num/nonzero.rs129
-rw-r--r--library/core/src/num/shells/u16.rs2
-rw-r--r--library/core/src/num/uint_macros.rs53
-rw-r--r--library/core/src/num/wrapping.rs168
-rw-r--r--library/core/src/ops/arith.rs78
-rw-r--r--library/core/src/ops/bit.rs69
-rw-r--r--library/core/src/ops/control_flow.rs9
-rw-r--r--library/core/src/ops/deref.rs8
-rw-r--r--library/core/src/ops/drop.rs68
-rw-r--r--library/core/src/ops/function.rs25
-rw-r--r--library/core/src/ops/index.rs5
-rw-r--r--library/core/src/ops/index_range.rs15
-rw-r--r--library/core/src/ops/range.rs3
-rw-r--r--library/core/src/ops/try_trait.rs26
-rw-r--r--library/core/src/option.rs352
-rw-r--r--library/core/src/panic.rs16
-rw-r--r--library/core/src/panic/panic_info.rs8
-rw-r--r--library/core/src/panic/unwind_safe.rs2
-rw-r--r--library/core/src/panicking.rs21
-rw-r--r--library/core/src/pin.rs35
-rw-r--r--library/core/src/primitive_docs.rs86
-rw-r--r--library/core/src/ptr/alignment.rs18
-rw-r--r--library/core/src/ptr/const_ptr.rs51
-rw-r--r--library/core/src/ptr/mod.rs262
-rw-r--r--library/core/src/ptr/mut_ptr.rs65
-rw-r--r--library/core/src/ptr/non_null.rs43
-rw-r--r--library/core/src/ptr/unique.rs14
-rw-r--r--library/core/src/result.rs187
-rw-r--r--library/core/src/slice/ascii.rs79
-rw-r--r--library/core/src/slice/cmp.rs27
-rw-r--r--library/core/src/slice/index.rs41
-rw-r--r--library/core/src/slice/iter.rs46
-rw-r--r--library/core/src/slice/iter/macros.rs97
-rw-r--r--library/core/src/slice/memchr.rs14
-rw-r--r--library/core/src/slice/mod.rs137
-rw-r--r--library/core/src/slice/sort.rs31
-rw-r--r--library/core/src/str/iter.rs4
-rw-r--r--library/core/src/str/mod.rs46
-rw-r--r--library/core/src/str/pattern.rs10
-rw-r--r--library/core/src/str/traits.rs98
-rw-r--r--library/core/src/sync/atomic.rs223
-rw-r--r--library/core/src/sync/exclusive.rs3
-rw-r--r--library/core/src/task/poll.rs10
-rw-r--r--library/core/src/task/ready.rs4
-rw-r--r--library/core/src/time.rs26
-rw-r--r--library/core/src/tuple.rs76
-rw-r--r--library/core/src/unicode/unicode_data.rs2577
-rw-r--r--library/core/tests/array.rs19
-rw-r--r--library/core/tests/asserting.rs6
-rw-r--r--library/core/tests/atomic.rs2
-rw-r--r--library/core/tests/bool.rs2
-rw-r--r--library/core/tests/cell.rs2
-rw-r--r--library/core/tests/char.rs2
-rw-r--r--library/core/tests/clone.rs1
-rw-r--r--library/core/tests/cmp.rs6
-rw-r--r--library/core/tests/convert.rs2
-rw-r--r--library/core/tests/fmt/mod.rs8
-rw-r--r--library/core/tests/hash/mod.rs24
-rw-r--r--library/core/tests/hash/sip.rs4
-rw-r--r--library/core/tests/iter/adapters/chain.rs41
-rw-r--r--library/core/tests/iter/adapters/enumerate.rs15
-rw-r--r--library/core/tests/iter/adapters/flatten.rs46
-rw-r--r--library/core/tests/iter/adapters/mod.rs2
-rw-r--r--library/core/tests/iter/adapters/skip.rs14
-rw-r--r--library/core/tests/iter/adapters/take.rs15
-rw-r--r--library/core/tests/iter/range.rs19
-rw-r--r--library/core/tests/iter/traits/iterator.rs18
-rw-r--r--library/core/tests/lazy.rs4
-rw-r--r--library/core/tests/lib.rs15
-rw-r--r--library/core/tests/mem.rs190
-rw-r--r--library/core/tests/net/ip_addr.rs1035
-rw-r--r--library/core/tests/net/mod.rs13
-rw-r--r--library/core/tests/net/parser.rs (renamed from library/std/src/net/parser/tests.rs)4
-rw-r--r--library/core/tests/net/socket_addr.rs233
-rw-r--r--library/core/tests/nonzero.rs20
-rw-r--r--library/core/tests/num/const_from.rs2
-rw-r--r--library/core/tests/num/dec2flt/mod.rs11
-rw-r--r--library/core/tests/num/dec2flt/parse.rs2
-rw-r--r--library/core/tests/num/ieee754.rs1
-rw-r--r--library/core/tests/num/int_macros.rs26
-rw-r--r--library/core/tests/num/mod.rs58
-rw-r--r--library/core/tests/num/uint_macros.rs26
-rw-r--r--library/core/tests/option.rs24
-rw-r--r--library/core/tests/slice.rs21
-rw-r--r--library/core/tests/time.rs12
-rw-r--r--library/panic_abort/src/android.rs4
-rw-r--r--library/panic_abort/src/lib.rs2
-rw-r--r--library/panic_unwind/src/emcc.rs2
-rw-r--r--library/panic_unwind/src/gcc.rs4
-rw-r--r--library/panic_unwind/src/lib.rs4
-rw-r--r--library/panic_unwind/src/seh.rs2
-rw-r--r--library/portable-simd/.github/workflows/ci.yml4
-rw-r--r--library/portable-simd/README.md34
-rw-r--r--library/portable-simd/crates/core_simd/Cargo.toml9
-rw-r--r--library/portable-simd/crates/core_simd/examples/README.md13
-rw-r--r--library/portable-simd/crates/core_simd/examples/dot_product.rs169
-rw-r--r--library/portable-simd/crates/core_simd/src/alias.rs227
-rw-r--r--library/portable-simd/crates/core_simd/src/cast.rs55
-rw-r--r--library/portable-simd/crates/core_simd/src/elements.rs4
-rw-r--r--library/portable-simd/crates/core_simd/src/elements/const_ptr.rs141
-rw-r--r--library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs136
-rw-r--r--library/portable-simd/crates/core_simd/src/eq.rs38
-rw-r--r--library/portable-simd/crates/core_simd/src/fmt.rs50
-rw-r--r--library/portable-simd/crates/core_simd/src/intrinsics.rs16
-rw-r--r--library/portable-simd/crates/core_simd/src/lane_count.rs36
-rw-r--r--library/portable-simd/crates/core_simd/src/lib.rs8
-rw-r--r--library/portable-simd/crates/core_simd/src/masks.rs67
-rw-r--r--library/portable-simd/crates/core_simd/src/masks/bitmask.rs4
-rw-r--r--library/portable-simd/crates/core_simd/src/masks/full_masks.rs6
-rw-r--r--library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs4
-rw-r--r--library/portable-simd/crates/core_simd/src/mod.rs6
-rw-r--r--library/portable-simd/crates/core_simd/src/ops/deref.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/ord.rs102
-rw-r--r--library/portable-simd/crates/core_simd/src/swizzle.rs72
-rw-r--r--library/portable-simd/crates/core_simd/src/swizzle_dyn.rs157
-rw-r--r--library/portable-simd/crates/core_simd/src/vector.rs667
-rw-r--r--library/portable-simd/crates/core_simd/src/vector/float.rs24
-rw-r--r--library/portable-simd/crates/core_simd/src/vector/int.rs63
-rw-r--r--library/portable-simd/crates/core_simd/src/vector/ptr.rs51
-rw-r--r--library/portable-simd/crates/core_simd/src/vector/uint.rs63
-rw-r--r--library/portable-simd/crates/core_simd/tests/autoderef.rs2
-rw-r--r--library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs2
-rw-r--r--library/portable-simd/crates/core_simd/tests/masks.rs59
-rw-r--r--library/portable-simd/crates/core_simd/tests/ops_macros.rs14
-rw-r--r--library/portable-simd/crates/core_simd/tests/pointers.rs111
-rw-r--r--library/portable-simd/crates/core_simd/tests/round.rs2
-rw-r--r--library/portable-simd/crates/core_simd/tests/swizzle.rs16
-rw-r--r--library/portable-simd/crates/core_simd/tests/swizzle_dyn.rs74
-rw-r--r--library/portable-simd/crates/core_simd/tests/to_bytes.rs2
-rw-r--r--library/portable-simd/crates/core_simd/tests/try_from_slice.rs25
-rw-r--r--library/portable-simd/crates/test_helpers/Cargo.toml3
-rw-r--r--library/portable-simd/crates/test_helpers/src/array.rs2
-rw-r--r--library/portable-simd/crates/test_helpers/src/biteq.rs20
-rw-r--r--library/portable-simd/crates/test_helpers/src/lib.rs346
-rw-r--r--library/proc_macro/src/bridge/fxhash.rs2
-rw-r--r--library/proc_macro/src/bridge/mod.rs10
-rw-r--r--library/proc_macro/src/lib.rs14
-rw-r--r--library/std/Cargo.toml14
-rw-r--r--library/std/build.rs5
-rw-r--r--library/std/src/alloc.rs8
-rw-r--r--library/std/src/ascii.rs3
-rw-r--r--library/std/src/collections/hash/map.rs7
-rw-r--r--library/std/src/collections/hash/set.rs8
-rw-r--r--library/std/src/collections/mod.rs11
-rw-r--r--library/std/src/env.rs18
-rw-r--r--library/std/src/f32.rs36
-rw-r--r--library/std/src/f32/tests.rs16
-rw-r--r--library/std/src/f64.rs36
-rw-r--r--library/std/src/f64/tests.rs16
-rw-r--r--library/std/src/ffi/os_str.rs1
-rw-r--r--library/std/src/fs.rs82
-rw-r--r--library/std/src/fs/tests.rs42
-rw-r--r--library/std/src/io/buffered/bufwriter.rs2
-rw-r--r--library/std/src/io/buffered/tests.rs13
-rw-r--r--library/std/src/io/copy.rs2
-rw-r--r--library/std/src/io/cursor.rs2
-rw-r--r--library/std/src/io/error.rs13
-rw-r--r--library/std/src/io/impls.rs56
-rw-r--r--library/std/src/io/mod.rs50
-rw-r--r--library/std/src/io/readbuf/tests.rs2
-rw-r--r--library/std/src/io/stdio.rs27
-rw-r--r--library/std/src/io/tests.rs2
-rw-r--r--library/std/src/keyword_docs.rs10
-rw-r--r--library/std/src/lib.rs35
-rw-r--r--library/std/src/net/ip_addr.rs2075
-rw-r--r--library/std/src/net/ip_addr/tests.rs1035
-rw-r--r--library/std/src/net/mod.rs6
-rw-r--r--library/std/src/net/socket_addr.rs689
-rw-r--r--library/std/src/net/tcp.rs14
-rw-r--r--library/std/src/net/tcp/tests.rs33
-rw-r--r--library/std/src/net/udp.rs1
-rw-r--r--library/std/src/net/udp/tests.rs5
-rw-r--r--library/std/src/os/android/net.rs4
-rw-r--r--library/std/src/os/fd/owned.rs15
-rw-r--r--library/std/src/os/fd/raw.rs12
-rw-r--r--library/std/src/os/fuchsia/raw.rs6
-rw-r--r--library/std/src/os/hermit/io/mod.rs13
-rw-r--r--library/std/src/os/hermit/io/net.rs46
-rw-r--r--library/std/src/os/hermit/mod.rs5
-rw-r--r--library/std/src/os/linux/net.rs4
-rw-r--r--library/std/src/os/linux/process.rs2
-rw-r--r--library/std/src/os/linux/raw.rs1
-rw-r--r--library/std/src/os/mod.rs16
-rw-r--r--library/std/src/os/net/linux_ext/addr.rs6
-rw-r--r--library/std/src/os/net/linux_ext/mod.rs2
-rw-r--r--library/std/src/os/nto/fs.rs92
-rw-r--r--library/std/src/os/nto/mod.rs4
-rw-r--r--library/std/src/os/nto/raw.rs40
-rw-r--r--library/std/src/os/unix/fs.rs32
-rw-r--r--library/std/src/os/unix/fs/tests.rs57
-rw-r--r--library/std/src/os/unix/mod.rs7
-rw-r--r--library/std/src/os/unix/net/addr.rs4
-rw-r--r--library/std/src/os/unix/net/ancillary.rs141
-rw-r--r--library/std/src/os/unix/net/datagram.rs51
-rw-r--r--library/std/src/os/unix/net/listener.rs3
-rw-r--r--library/std/src/os/unix/net/stream.rs39
-rw-r--r--library/std/src/os/unix/net/tests.rs3
-rw-r--r--library/std/src/os/unix/process.rs26
-rw-r--r--library/std/src/os/unix/ucred.rs3
-rw-r--r--library/std/src/os/vita/fs.rs95
-rw-r--r--library/std/src/os/vita/mod.rs6
-rw-r--r--library/std/src/os/vita/raw.rs70
-rw-r--r--library/std/src/os/windows/io/handle.rs58
-rw-r--r--library/std/src/os/windows/io/raw.rs17
-rw-r--r--library/std/src/os/windows/io/socket.rs77
-rw-r--r--library/std/src/panic.rs7
-rw-r--r--library/std/src/panicking.rs34
-rw-r--r--library/std/src/path.rs74
-rw-r--r--library/std/src/personality/dwarf/eh.rs5
-rw-r--r--library/std/src/personality/gcc.rs14
-rw-r--r--library/std/src/prelude/mod.rs6
-rw-r--r--library/std/src/prelude/v1.rs8
-rw-r--r--library/std/src/primitive_docs.rs86
-rw-r--r--library/std/src/process.rs98
-rw-r--r--library/std/src/process/tests.rs34
-rw-r--r--library/std/src/sync/lazy_lock.rs146
-rw-r--r--library/std/src/sync/mod.rs11
-rw-r--r--library/std/src/sync/mpmc/array.rs107
-rw-r--r--library/std/src/sync/mpmc/list.rs12
-rw-r--r--library/std/src/sync/mpmc/mod.rs4
-rw-r--r--library/std/src/sync/mpsc/sync_tests.rs13
-rw-r--r--library/std/src/sync/mutex.rs24
-rw-r--r--library/std/src/sync/once.rs16
-rw-r--r--library/std/src/sync/once_lock.rs62
-rw-r--r--library/std/src/sync/once_lock/tests.rs2
-rw-r--r--library/std/src/sync/remutex.rs4
-rw-r--r--library/std/src/sys/common/alloc.rs1
-rw-r--r--library/std/src/sys/common/mod.rs1
-rw-r--r--library/std/src/sys/common/thread_local/fast_local.rs247
-rw-r--r--library/std/src/sys/common/thread_local/mod.rs103
-rw-r--r--library/std/src/sys/common/thread_local/os_local.rs190
-rw-r--r--library/std/src/sys/common/thread_local/static_local.rs109
-rw-r--r--library/std/src/sys/hermit/args.rs2
-rw-r--r--library/std/src/sys/hermit/fd.rs78
-rw-r--r--library/std/src/sys/hermit/fs.rs62
-rw-r--r--library/std/src/sys/hermit/futex.rs6
-rw-r--r--library/std/src/sys/hermit/mod.rs101
-rw-r--r--library/std/src/sys/hermit/net.rs652
-rw-r--r--library/std/src/sys/hermit/os.rs2
-rw-r--r--library/std/src/sys/hermit/time.rs110
-rw-r--r--library/std/src/sys/itron/thread.rs2
-rw-r--r--library/std/src/sys/itron/thread_parking.rs37
-rw-r--r--library/std/src/sys/itron/wait_flag.rs72
-rw-r--r--library/std/src/sys/mod.rs26
-rw-r--r--library/std/src/sys/sgx/abi/entry.S10
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/alloc.rs1
-rw-r--r--library/std/src/sys/sgx/fd.rs7
-rw-r--r--library/std/src/sys/sgx/net.rs9
-rw-r--r--library/std/src/sys/sgx/waitqueue/mod.rs16
-rw-r--r--library/std/src/sys/solid/mod.rs4
-rw-r--r--library/std/src/sys/solid/net.rs25
-rw-r--r--library/std/src/sys/solid/time.rs4
-rw-r--r--library/std/src/sys/unix/alloc.rs3
-rw-r--r--library/std/src/sys/unix/args.rs5
-rw-r--r--library/std/src/sys/unix/env.rs22
-rw-r--r--library/std/src/sys/unix/fd.rs227
-rw-r--r--library/std/src/sys/unix/fs.rs145
-rw-r--r--library/std/src/sys/unix/futex.rs2
-rw-r--r--library/std/src/sys/unix/kernel_copy.rs62
-rw-r--r--library/std/src/sys/unix/kernel_copy/tests.rs42
-rw-r--r--library/std/src/sys/unix/l4re.rs5
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs11
-rw-r--r--library/std/src/sys/unix/mod.rs19
-rw-r--r--library/std/src/sys/unix/net.rs43
-rw-r--r--library/std/src/sys/unix/os.rs26
-rw-r--r--library/std/src/sys/unix/os_str.rs1
-rw-r--r--library/std/src/sys/unix/pipe.rs7
-rw-r--r--library/std/src/sys/unix/process/mod.rs2
-rw-r--r--library/std/src/sys/unix/process/process_fuchsia.rs2
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs76
-rw-r--r--library/std/src/sys/unix/process/process_vxworks.rs2
-rw-r--r--library/std/src/sys/unix/rand.rs6
-rw-r--r--library/std/src/sys/unix/stdio.rs6
-rw-r--r--library/std/src/sys/unix/thread.rs34
-rw-r--r--library/std/src/sys/unix/thread_parking/pthread.rs9
-rw-r--r--library/std/src/sys/unix/time.rs110
-rw-r--r--library/std/src/sys/unsupported/io.rs2
-rw-r--r--library/std/src/sys/unsupported/mod.rs1
-rw-r--r--library/std/src/sys/unsupported/net.rs6
-rw-r--r--library/std/src/sys/unsupported/once.rs11
-rw-r--r--library/std/src/sys/unsupported/pipe.rs6
-rw-r--r--library/std/src/sys/unsupported/thread_parking.rs11
-rw-r--r--library/std/src/sys/wasi/fd.rs21
-rw-r--r--library/std/src/sys/wasi/fs.rs4
-rw-r--r--library/std/src/sys/wasi/mod.rs11
-rw-r--r--library/std/src/sys/wasi/net.rs13
-rw-r--r--library/std/src/sys/wasm/mod.rs2
-rw-r--r--library/std/src/sys/windows/args.rs35
-rw-r--r--library/std/src/sys/windows/c.rs1309
-rw-r--r--library/std/src/sys/windows/c/errors.rs1883
-rw-r--r--library/std/src/sys/windows/c/windows_sys.lst2590
-rw-r--r--library/std/src/sys/windows/c/windows_sys.rs4276
-rw-r--r--library/std/src/sys/windows/compat.rs16
-rw-r--r--library/std/src/sys/windows/fs.rs154
-rw-r--r--library/std/src/sys/windows/handle.rs16
-rw-r--r--library/std/src/sys/windows/io.rs39
-rw-r--r--library/std/src/sys/windows/mod.rs9
-rw-r--r--library/std/src/sys/windows/net.rs33
-rw-r--r--library/std/src/sys/windows/os_str.rs1
-rw-r--r--library/std/src/sys/windows/path.rs65
-rw-r--r--library/std/src/sys/windows/pipe.rs26
-rw-r--r--library/std/src/sys/windows/process.rs22
-rw-r--r--library/std/src/sys/windows/rand.rs123
-rw-r--r--library/std/src/sys/windows/stack_overflow.rs4
-rw-r--r--library/std/src/sys/windows/stdio.rs78
-rw-r--r--library/std/src/sys/windows/thread.rs5
-rw-r--r--library/std/src/sys_common/backtrace.rs13
-rw-r--r--library/std/src/sys_common/mod.rs1
-rw-r--r--library/std/src/sys_common/net.rs18
-rw-r--r--library/std/src/sys_common/net/tests.rs2
-rw-r--r--library/std/src/sys_common/once/futex.rs11
-rw-r--r--library/std/src/sys_common/once/queue.rs11
-rw-r--r--library/std/src/sys_common/thread_local_key.rs71
-rw-r--r--library/std/src/sys_common/thread_local_key/tests.rs20
-rw-r--r--library/std/src/sys_common/thread_parking/generic.rs125
-rw-r--r--library/std/src/sys_common/thread_parking/id.rs8
-rw-r--r--library/std/src/sys_common/thread_parking/mod.rs9
-rw-r--r--library/std/src/sys_common/thread_parking/wait_flag.rs102
-rw-r--r--library/std/src/sys_common/wtf8.rs3
-rw-r--r--library/std/src/thread/local.rs597
-rw-r--r--library/std/src/thread/mod.rs79
-rw-r--r--library/std/src/thread/tests.rs4
-rw-r--r--library/std/src/time.rs10
-rw-r--r--library/std/src/time/tests.rs27
-rw-r--r--library/std/tests/common/mod.rs58
-rw-r--r--library/std/tests/create_dir_all_bare.rs39
-rw-r--r--library/std/tests/env.rs14
-rw-r--r--library/std/tests/run-time-detect.rs1
m---------library/stdarch0
-rw-r--r--library/sysroot/Cargo.toml27
-rw-r--r--library/sysroot/src/lib.rs1
-rw-r--r--library/test/Cargo.toml22
-rw-r--r--library/test/src/console.rs83
-rw-r--r--library/test/src/formatters/json.rs154
-rw-r--r--library/test/src/formatters/junit.rs54
-rw-r--r--library/test/src/formatters/mod.rs6
-rw-r--r--library/test/src/formatters/pretty.rs29
-rw-r--r--library/test/src/formatters/terse.rs14
-rw-r--r--library/test/src/lib.rs13
-rw-r--r--library/test/src/tests.rs100
-rw-r--r--library/test/src/types.rs5
-rw-r--r--library/unwind/src/lib.rs20
-rw-r--r--library/unwind/src/libunwind.rs5
482 files changed, 26300 insertions, 16012 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/benches/vec_deque.rs b/library/alloc/benches/vec_deque.rs
index 7c78561ebf1..313a97ed1ff 100644
--- a/library/alloc/benches/vec_deque.rs
+++ b/library/alloc/benches/vec_deque.rs
@@ -1,4 +1,8 @@
-use std::collections::VecDeque;
+use core::iter::Iterator;
+use std::{
+ collections::{vec_deque, VecDeque},
+ mem,
+};
use test::{black_box, Bencher};
#[bench]
@@ -53,6 +57,146 @@ fn bench_try_fold(b: &mut Bencher) {
b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b))))
}
+/// does the memory bookkeeping to reuse the buffer of the Vec between iterations.
+/// `setup` must not modify its argument's length or capacity. `g` must not move out of its argument.
+fn into_iter_helper<
+ T: Copy,
+ F: FnOnce(&mut VecDeque<T>),
+ G: FnOnce(&mut vec_deque::IntoIter<T>),
+>(
+ v: &mut Vec<T>,
+ setup: F,
+ g: G,
+) {
+ let ptr = v.as_mut_ptr();
+ let len = v.len();
+ // ensure that the vec is full, to make sure that any wrapping from the deque doesn't
+ // access uninitialized memory.
+ assert_eq!(v.len(), v.capacity());
+
+ let mut deque = VecDeque::from(mem::take(v));
+ setup(&mut deque);
+
+ let mut it = deque.into_iter();
+ g(&mut it);
+
+ mem::forget(it);
+
+ // SAFETY: the provided functions are not allowed to modify the allocation, so the buffer is still alive.
+ // len and capacity are accurate due to the above assertion.
+ // All the elements in the buffer are still valid, because of `T: Copy` which implies `T: !Drop`.
+ mem::forget(mem::replace(v, unsafe { Vec::from_raw_parts(ptr, len, len) }));
+}
+
+#[bench]
+fn bench_into_iter(b: &mut Bencher) {
+ let len = 1024;
+ // we reuse this allocation for every run
+ let mut vec: Vec<usize> = (0..len).collect();
+ vec.shrink_to_fit();
+
+ b.iter(|| {
+ let mut sum = 0;
+ into_iter_helper(
+ &mut vec,
+ |_| {},
+ |it| {
+ for i in it {
+ sum += i;
+ }
+ },
+ );
+ black_box(sum);
+
+ let mut sum = 0;
+ // rotating a full deque doesn't move any memory.
+ into_iter_helper(
+ &mut vec,
+ |d| d.rotate_left(len / 2),
+ |it| {
+ for i in it {
+ sum += i;
+ }
+ },
+ );
+ black_box(sum);
+ });
+}
+
+#[bench]
+fn bench_into_iter_fold(b: &mut Bencher) {
+ let len = 1024;
+
+ // because `fold` takes ownership of the iterator,
+ // we can't prevent it from dropping the memory,
+ // so we have to bite the bullet and reallocate
+ // for every iteration.
+ b.iter(|| {
+ let deque: VecDeque<usize> = (0..len).collect();
+ assert_eq!(deque.len(), deque.capacity());
+ let sum = deque.into_iter().fold(0, |a, b| a + b);
+ black_box(sum);
+
+ // rotating a full deque doesn't move any memory.
+ let mut deque: VecDeque<usize> = (0..len).collect();
+ assert_eq!(deque.len(), deque.capacity());
+ deque.rotate_left(len / 2);
+ let sum = deque.into_iter().fold(0, |a, b| a + b);
+ black_box(sum);
+ });
+}
+
+#[bench]
+fn bench_into_iter_try_fold(b: &mut Bencher) {
+ let len = 1024;
+ // we reuse this allocation for every run
+ let mut vec: Vec<usize> = (0..len).collect();
+ vec.shrink_to_fit();
+
+ // Iterator::any uses Iterator::try_fold under the hood
+ b.iter(|| {
+ let mut b = false;
+ into_iter_helper(&mut vec, |_| {}, |it| b = it.any(|i| i == len - 1));
+ black_box(b);
+
+ into_iter_helper(&mut vec, |d| d.rotate_left(len / 2), |it| b = it.any(|i| i == len - 1));
+ black_box(b);
+ });
+}
+
+#[bench]
+fn bench_into_iter_next_chunk(b: &mut Bencher) {
+ let len = 1024;
+ // we reuse this allocation for every run
+ let mut vec: Vec<usize> = (0..len).collect();
+ vec.shrink_to_fit();
+
+ b.iter(|| {
+ let mut buf = [0; 64];
+ into_iter_helper(
+ &mut vec,
+ |_| {},
+ |it| {
+ while let Ok(a) = it.next_chunk() {
+ buf = a;
+ }
+ },
+ );
+ black_box(buf);
+
+ into_iter_helper(
+ &mut vec,
+ |d| d.rotate_left(len / 2),
+ |it| {
+ while let Ok(a) = it.next_chunk() {
+ buf = a;
+ }
+ },
+ );
+ black_box(buf);
+ });
+}
+
#[bench]
fn bench_from_array_1000(b: &mut Bencher) {
const N: usize = 1000;
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 e54880e8652..d9e274df0f5 100644
--- a/library/alloc/src/collections/vec_deque/into_iter.rs
+++ b/library/alloc/src/collections/vec_deque/into_iter.rs
@@ -1,5 +1,6 @@
-use core::fmt;
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<
@@ -52,6 +52,127 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
let len = self.inner.len();
(len, Some(len))
}
+
+ #[inline]
+ fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
+ let len = self.inner.len;
+ let rem = if len < n {
+ self.inner.clear();
+ n - len
+ } else {
+ self.inner.drain(..n);
+ 0
+ };
+ NonZeroUsize::new(rem).map_or(Ok(()), Err)
+ }
+
+ #[inline]
+ fn count(self) -> usize {
+ self.inner.len
+ }
+
+ fn try_fold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
+ where
+ F: FnMut(B, Self::Item) -> R,
+ R: Try<Output = B>,
+ {
+ struct Guard<'a, T, A: Allocator> {
+ deque: &'a mut VecDeque<T, A>,
+ // `consumed <= deque.len` always holds.
+ consumed: usize,
+ }
+
+ impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> {
+ fn drop(&mut self) {
+ self.deque.len -= self.consumed;
+ self.deque.head = self.deque.to_physical_idx(self.consumed);
+ }
+ }
+
+ let mut guard = Guard { deque: &mut self.inner, consumed: 0 };
+
+ let (head, tail) = guard.deque.as_slices();
+
+ init = head
+ .iter()
+ .map(|elem| {
+ guard.consumed += 1;
+ // SAFETY: Because we incremented `guard.consumed`, the
+ // deque effectively forgot the element, so we can take
+ // ownership
+ unsafe { ptr::read(elem) }
+ })
+ .try_fold(init, &mut f)?;
+
+ tail.iter()
+ .map(|elem| {
+ guard.consumed += 1;
+ // SAFETY: Same as above.
+ unsafe { ptr::read(elem) }
+ })
+ .try_fold(init, &mut f)
+ }
+
+ #[inline]
+ fn fold<B, F>(mut self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ match self.try_fold(init, |b, item| Ok::<B, !>(f(b, item))) {
+ Ok(b) => b,
+ Err(e) => match e {},
+ }
+ }
+
+ #[inline]
+ fn last(mut self) -> Option<Self::Item> {
+ self.inner.pop_back()
+ }
+
+ fn next_chunk<const N: usize>(
+ &mut self,
+ ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
+ let mut raw_arr = MaybeUninit::uninit_array();
+ let raw_arr_ptr = raw_arr.as_mut_ptr().cast();
+ let (head, tail) = self.inner.as_slices();
+
+ if head.len() >= N {
+ // SAFETY: By manually adjusting the head and length of the deque, we effectively
+ // make it forget the first `N` elements, so taking ownership of them is safe.
+ unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, N) };
+ self.inner.head = self.inner.to_physical_idx(N);
+ self.inner.len -= N;
+ // SAFETY: We initialized the entire array with items from `head`
+ return Ok(unsafe { raw_arr.transpose().assume_init() });
+ }
+
+ // SAFETY: Same argument as above.
+ unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, head.len()) };
+ let remaining = N - head.len();
+
+ if tail.len() >= remaining {
+ // SAFETY: Same argument as above.
+ unsafe {
+ ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), remaining)
+ };
+ self.inner.head = self.inner.to_physical_idx(N);
+ self.inner.len -= N;
+ // SAFETY: We initialized the entire array with items from `head` and `tail`
+ Ok(unsafe { raw_arr.transpose().assume_init() })
+ } else {
+ // SAFETY: Same argument as above.
+ unsafe {
+ ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), tail.len())
+ };
+ let init = head.len() + tail.len();
+ // We completely drained all the deques elements.
+ self.inner.head = 0;
+ self.inner.len = 0;
+ // SAFETY: We copied all elements from both slices to the beginning of the array, so
+ // the given range is initialized.
+ Err(unsafe { array::IntoIter::new_unchecked(raw_arr, 0..init) })
+ }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -60,10 +181,74 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
fn next_back(&mut self) -> Option<T> {
self.inner.pop_back()
}
+
+ #[inline]
+ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
+ let len = self.inner.len;
+ let rem = if len < n {
+ self.inner.clear();
+ 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
+ where
+ F: FnMut(B, Self::Item) -> R,
+ R: Try<Output = B>,
+ {
+ struct Guard<'a, T, A: Allocator> {
+ deque: &'a mut VecDeque<T, A>,
+ // `consumed <= deque.len` always holds.
+ consumed: usize,
+ }
+
+ impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> {
+ fn drop(&mut self) {
+ self.deque.len -= self.consumed;
+ }
+ }
+
+ let mut guard = Guard { deque: &mut self.inner, consumed: 0 };
+
+ let (head, tail) = guard.deque.as_slices();
+
+ init = tail
+ .iter()
+ .map(|elem| {
+ guard.consumed += 1;
+ // SAFETY: See `try_fold`'s safety comment.
+ unsafe { ptr::read(elem) }
+ })
+ .try_rfold(init, &mut f)?;
+
+ head.iter()
+ .map(|elem| {
+ guard.consumed += 1;
+ // SAFETY: Same as above.
+ unsafe { ptr::read(elem) }
+ })
+ .try_rfold(init, &mut f)
+ }
+
+ #[inline]
+ fn rfold<B, F>(mut self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ match self.try_rfold(init, |b, item| Ok::<B, !>(f(b, item))) {
+ Ok(b) => b,
+ Err(e) => match e {},
+ }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
+ #[inline]
fn is_empty(&self) -> bool {
self.inner.is_empty()
}
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/array.rs b/library/core/benches/array.rs
index 845c6076294..d8cc44d05c4 100644
--- a/library/core/benches/array.rs
+++ b/library/core/benches/array.rs
@@ -11,9 +11,9 @@ macro_rules! map_array {
};
}
-map_array!(map_8byte_8byte_8, 0u64, 1u64, 800);
-map_array!(map_8byte_8byte_64, 0u64, 1u64, 6400);
-map_array!(map_8byte_8byte_256, 0u64, 1u64, 25600);
+map_array!(map_8byte_8byte_8, 0u64, 1u64, 80);
+map_array!(map_8byte_8byte_64, 0u64, 1u64, 640);
+map_array!(map_8byte_8byte_256, 0u64, 1u64, 2560);
-map_array!(map_8byte_256byte_256, 0u64, [0u64; 4], 25600);
-map_array!(map_256byte_8byte_256, [0u64; 4], 0u64, 25600);
+map_array!(map_8byte_256byte_256, 0u64, [0u64; 4], 2560);
+map_array!(map_256byte_8byte_256, [0u64; 4], 0u64, 2560);
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 f290e5baf9d..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 {
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]&lt;T&gt; 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 5a76e866923..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.
///
@@ -216,18 +216,16 @@ 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* in any way.
+/// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the
+/// 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 5a0b8594104..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,
@@ -3502,8 +3576,10 @@ pub trait Iterator {
}
}
- /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
- /// of another.
+ /// [Lexicographically](Ord#lexicographical-comparison) compares the [`PartialOrd`] elements of
+ /// this [`Iterator`] with those of another. The comparison works like short-circuit
+ /// evaluation, returning a result without comparing the remaining elements.
+ /// As soon as an order can be determined, the evaluation stops and a result is returned.
///
/// # Examples
///
@@ -3513,10 +3589,27 @@ pub trait Iterator {
/// assert_eq!([1.].iter().partial_cmp([1.].iter()), Some(Ordering::Equal));
/// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
/// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater));
+ /// ```
///
+ /// For floating-point numbers, NaN does not have a total order and will result
+ /// in `None` when compared:
+ ///
+ /// ```
/// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None);
/// ```
+ ///
+ /// The results are determined by the order of evaluation.
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!([1.0, f64::NAN].iter().partial_cmp([2.0, f64::NAN].iter()), Some(Ordering::Less));
+ /// assert_eq!([2.0, f64::NAN].iter().partial_cmp([1.0, f64::NAN].iter()), Some(Ordering::Greater));
+ /// assert_eq!([f64::NAN, 1.0].iter().partial_cmp([f64::NAN, 2.0].iter()), None);
+ /// ```
+ ///
#[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,
@@ -3555,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,
@@ -3588,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,
@@ -3613,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,
@@ -3635,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
@@ -3645,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,
@@ -3666,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,
@@ -3687,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,
@@ -3708,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,
@@ -3729,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,
@@ -3760,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,
@@ -3788,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,
@@ -3834,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,
@@ -3849,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,
@@ -3907,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 07a7d45c7eb..47a3e78b4d5 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,6 +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]
+#[rustc_coinductive]
pub trait Sized {
// Empty.
}
@@ -213,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
@@ -323,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
@@ -400,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
@@ -425,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
@@ -590,14 +688,14 @@ 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>,
/// }
/// ```
///
-/// This also in turn requires the annotation `T: 'a`, indicating
+/// This also in turn infers the lifetime bound `T: 'a`, indicating
/// that any references in `T` are valid over the lifetime `'a`.
///
/// When initializing a `Slice` you simply provide the value
@@ -606,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>,
@@ -668,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
///
@@ -685,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>;
@@ -731,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
}
@@ -773,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.
///
@@ -822,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"]
@@ -838,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.
///
@@ -857,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.
@@ -876,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!("(&minus;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> &minus; 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 d29ae35614c..ba5e6ddc752 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -437,7 +437,8 @@ impl<Idx> RangeInclusive<Idx> {
/// ```
#[stable(feature = "inclusive_range_methods", since = "1.27.0")]
#[inline]
- pub fn into_inner(self) -> (Idx, Idx) {
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+ pub const fn into_inner(self) -> (Idx, Idx) {
(self.start, self.end)
}
}
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 16eb726f6f6..5ee1b5e4afc 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -23,8 +23,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "Follow the rabbit";
/// let ptr: *const u8 = s.as_ptr();
@@ -63,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
///
@@ -134,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)]
@@ -163,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"
)]
@@ -266,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)
}
@@ -323,8 +321,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let ptr: *const u8 = &10u8 as *const u8;
///
@@ -384,8 +380,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// #![feature(ptr_as_uninit)]
///
@@ -449,8 +443,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
/// let ptr: *const u8 = s.as_ptr();
@@ -526,8 +518,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements
/// let data = [1u8, 2, 3, 4, 5];
@@ -908,8 +898,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
/// let ptr: *const u8 = s.as_ptr();
@@ -928,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)`).
@@ -993,8 +989,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
///
@@ -1072,8 +1066,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements
/// let data = [1u8, 2, 3, 4, 5];
@@ -1152,8 +1144,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements (backwards)
/// let data = [1u8, 2, 3, 4, 5];
@@ -1205,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
@@ -1246,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
@@ -1359,7 +1349,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
/// ```
/// #![feature(pointer_is_aligned)]
/// #![feature(pointer_byte_offsets)]
@@ -1482,7 +1471,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
/// ```
/// #![feature(pointer_is_aligned)]
/// #![feature(pointer_byte_offsets)]
@@ -1670,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 0a2f63e3ec6..5edd291fb76 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -22,8 +22,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let mut s = [1, 2, 3];
/// let ptr: *mut u32 = s.as_mut_ptr();
@@ -62,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
///
@@ -140,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)]
@@ -169,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"
)]
@@ -272,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)
}
@@ -332,8 +330,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let ptr: *mut u8 = &mut 10u8 as *mut u8;
///
@@ -396,8 +392,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// #![feature(ptr_as_uninit)]
///
@@ -461,8 +455,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let mut s = [1, 2, 3];
/// let ptr: *mut u32 = s.as_mut_ptr();
@@ -481,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.
@@ -539,8 +541,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements
/// let mut data = [1u8, 2, 3, 4, 5];
@@ -660,8 +660,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let mut s = [1, 2, 3];
/// let ptr: *mut u32 = s.as_mut_ptr();
@@ -1010,8 +1008,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
/// let ptr: *const u8 = s.as_ptr();
@@ -1030,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) }
+ 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)`).
@@ -1095,8 +1099,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
///
@@ -1174,8 +1176,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements
/// let data = [1u8, 2, 3, 4, 5];
@@ -1254,8 +1254,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements (backwards)
/// let data = [1u8, 2, 3, 4, 5];
@@ -1307,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
@@ -1348,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
@@ -1627,7 +1625,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
/// ```
/// #![feature(pointer_is_aligned)]
/// #![feature(pointer_byte_offsets)]
@@ -1752,7 +1749,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
/// ```
/// #![feature(pointer_is_aligned)]
/// #![feature(pointer_byte_offsets)]
@@ -2058,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 7596e9cc005..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};
@@ -525,8 +524,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<i32, &str> = Ok(-3);
/// assert_eq!(x.is_ok(), true);
@@ -547,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);
///
@@ -560,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,
@@ -572,8 +567,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<i32, &str> = Ok(-3);
/// assert_eq!(x.is_err(), false);
@@ -594,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, "!"));
@@ -608,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,
@@ -627,8 +619,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(x.ok(), Some(2));
@@ -638,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,
}
}
@@ -658,8 +642,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(x.err(), None);
@@ -669,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),
}
}
@@ -693,8 +669,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(x.as_ref(), Ok(&2));
@@ -716,8 +690,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// fn mutate(r: &mut Result<i32, i32>) {
/// match r.as_mut() {
@@ -812,8 +784,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let k = 21;
///
@@ -841,8 +811,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// fn stringify(x: u32) -> String { format!("error code: {x}") }
///
@@ -924,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
@@ -950,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
@@ -968,8 +938,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(7);
/// assert_eq!(x.iter().next(), Some(&7));
@@ -989,8 +957,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let mut x: Result<u32, &str> = Ok(7);
/// match x.iter_mut().next() {
@@ -1031,8 +997,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```should_panic
/// let x: Result<u32, &str> = Err("emergency failure");
/// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
@@ -1160,8 +1124,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```should_panic
/// let x: Result<u32, &str> = Ok(10);
/// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`
@@ -1222,8 +1184,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// # #![feature(never_type)]
/// # #![feature(unwrap_infallible)]
@@ -1259,8 +1219,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// # #![feature(never_type)]
/// # #![feature(unwrap_infallible)]
@@ -1298,8 +1256,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// let y: Result<&str, &str> = Err("late error");
@@ -1318,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),
}
}
@@ -1383,8 +1331,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// let y: Result<u32, &str> = Err("late error");
@@ -1403,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,
}
}
@@ -1426,8 +1364,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }
/// fn err(x: u32) -> Result<u32, u32> { Err(x) }
@@ -1456,8 +1392,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let default = 2;
/// let x: Result<u32, &str> = Ok(9);
@@ -1467,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,
}
}
@@ -1487,8 +1414,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// fn count(x: &str) -> usize { x.len() }
///
@@ -1567,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> {
@@ -1752,8 +1615,6 @@ impl<T, E> Result<Result<T, E>, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// #![feature(result_flattening)]
/// let x: Result<Result<&'static str, u32>, u32> = Ok(Ok("hello"));
@@ -1807,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 {
@@ -1842,8 +1702,6 @@ impl<T, E> IntoIterator for Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(5);
/// let v: Vec<u32> = x.into_iter().collect();
@@ -2076,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>;
@@ -2096,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 {
@@ -2118,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 6ea16bf6430..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);
@@ -1596,7 +1595,8 @@ impl<T> [T] {
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_slice_split_at_not_mut", issue = "101158")]
+ #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_allow_const_fn_unstable(slice_split_at_unchecked)]
#[inline]
#[track_caller]
#[must_use]
@@ -1695,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.
@@ -2381,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
@@ -2393,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
@@ -2456,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
@@ -2473,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
@@ -2542,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
@@ -2557,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
@@ -2730,8 +2736,10 @@ impl<T> [T] {
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index`. Additionally, this reordering is
/// unstable (i.e. any number of equal elements may end up at position `index`), in-place
- /// (i.e. does not allocate), and *O*(*n*) worst-case. This function is also/ known as "kth
- /// element" in other libraries. It returns a triplet of the following from the reordered slice:
+ /// (i.e. does not allocate), and *O*(*n*) on average. The worst-case performance is *O*(*n* log *n*).
+ /// This function is also known as "kth element" in other libraries.
+ ///
+ /// It returns a triplet of the following from the reordered slice:
/// the subslice prior to `index`, the element at `index`, and the subslice after `index`;
/// accordingly, the values in those two subslices will respectively all be less-than-or-equal-to
/// and greater-than-or-equal-to the value of the element at `index`.
@@ -2777,8 +2785,11 @@ impl<T> [T] {
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index` using the comparator function.
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
- /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function
- /// is also known as "kth element" in other libraries. It returns a triplet of the following from
+ /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) on average.
+ /// The worst-case performance is *O*(*n* log *n*). This function is also known as
+ /// "kth element" in other libraries.
+ ///
+ /// It returns a triplet of the following from
/// the slice reordered according to the provided comparator function: the subslice prior to
/// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in
/// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to
@@ -2829,8 +2840,11 @@ impl<T> [T] {
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index` using the key extraction function.
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
- /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function
- /// is also known as "kth element" in other libraries. It returns a triplet of the following from
+ /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) on average.
+ /// The worst-case performance is *O*(*n* log *n*).
+ /// This function is also known as "kth element" in other libraries.
+ ///
+ /// It returns a triplet of the following from
/// the slice reordered according to the provided key extraction function: the subslice prior to
/// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in
/// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to
@@ -2947,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
// +---+---+---+---+---+---+
@@ -3465,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;
@@ -3808,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.
@@ -4248,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 {
@@ -4390,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 {
&[]
@@ -4399,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 []
@@ -4444,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..91ee2903aab 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -791,8 +791,8 @@ pub struct CharArrayRefSearcher<'a, 'b, const N: usize>(
/// # Examples
///
/// ```
-/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
-/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(['o', 'l']), Some(2));
+/// assert_eq!("Hello world".find(['h', 'w']), Some(6));
/// ```
impl<'a, const N: usize> Pattern<'a> for [char; N] {
pattern_methods!(CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher);
@@ -811,8 +811,8 @@ unsafe impl<'a, const N: usize> ReverseSearcher<'a> for CharArraySearcher<'a, N>
/// # Examples
///
/// ```
-/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
-/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(&['o', 'l']), Some(2));
+/// assert_eq!("Hello world".find(&['h', 'w']), Some(6));
/// ```
impl<'a, 'b, const N: usize> Pattern<'a> for &'b [char; N] {
pattern_methods!(CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher);
@@ -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 adf521d9b94..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.85" }
+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 286ad68fd13..2a6b1a5ec73 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())
@@ -334,6 +334,10 @@ impl File {
///
/// See the [`OpenOptions::open`] method for more details.
///
+ /// If you only need to read the entire file contents,
+ /// consider [`std::fs::read()`][self::read] or
+ /// [`std::fs::read_to_string()`][self::read_to_string] instead.
+ ///
/// # Errors
///
/// This function will return an error if `path` does not already exist.
@@ -343,9 +347,12 @@ impl File {
///
/// ```no_run
/// use std::fs::File;
+ /// use std::io::Read;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::open("foo.txt")?;
+ /// let mut data = vec![];
+ /// f.read_to_end(&mut data)?;
/// Ok(())
/// }
/// ```
@@ -361,16 +368,20 @@ impl File {
///
/// Depending on the platform, this function may fail if the
/// full directory path does not exist.
- ///
/// See the [`OpenOptions::open`] function for more details.
///
+ /// See also [`std::fs::write()`][self::write] for a simple function to
+ /// create a file with a given data.
+ ///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
+ /// use std::io::Write;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create("foo.txt")?;
+ /// f.write_all(&1234_u32.to_be_bytes())?;
/// Ok(())
/// }
/// ```
@@ -397,9 +408,11 @@ impl File {
/// #![feature(file_create_new)]
///
/// use std::fs::File;
+ /// use std::io::Write;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create_new("foo.txt")?;
+ /// f.write_all("Hello, world!".as_bytes())?;
/// Ok(())
/// }
/// ```
@@ -426,9 +439,11 @@ impl File {
///
/// ```no_run
/// use std::fs::File;
+ /// use std::io::Write;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::options().append(true).open("example.log")?;
+ /// writeln!(&mut f, "new line")?;
/// Ok(())
/// }
/// ```
@@ -694,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
}
@@ -717,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")]
@@ -746,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")]
@@ -802,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")]
@@ -966,6 +986,9 @@ impl OpenOptions {
/// In order for the file to be created, [`OpenOptions::write`] or
/// [`OpenOptions::append`] access must be used.
///
+ /// See also [`std::fs::write()`][self::write] for a simple function to
+ /// create a file with a given data.
+ ///
/// # Examples
///
/// ```no_run
@@ -1065,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
}
@@ -1330,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
}
@@ -1582,6 +1608,7 @@ impl FileType {
}
impl AsInner<fs_imp::FileType> for FileType {
+ #[inline]
fn as_inner(&self) -> &fs_imp::FileType {
&self.0
}
@@ -1594,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
}
@@ -1748,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
}
@@ -1917,7 +1946,7 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
/// On success, the total number of bytes copied is returned and it is equal to
/// the length of the `to` file as reported by `metadata`.
///
-/// If you’re wanting to copy the contents of one file to another and you’re
+/// If you want to copy the contents of one file to another and you’re
/// working with [`File`]s, see the [`io::copy()`] function.
///
/// # Platform-specific behavior
@@ -2262,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
///
@@ -2483,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
}
@@ -2493,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/copy.rs b/library/std/src/io/copy.rs
index 38b98afffa1..1d9d93f5b64 100644
--- a/library/std/src/io/copy.rs
+++ b/library/std/src/io/copy.rs
@@ -10,7 +10,7 @@ use crate::mem::MaybeUninit;
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
-/// If you’re wanting to copy the contents of one file to another and you’re
+/// If you want to copy the contents of one file to another and you’re
/// working with filesystem paths, see the [`fs::copy`] function.
///
/// [`fs::copy`]: crate::fs::copy
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 4a15305301d..a6bc468b092 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -1,8 +1,21 @@
-use crate::cell::Cell;
-use crate::fmt;
+use crate::cell::UnsafeCell;
+use crate::mem::ManuallyDrop;
use crate::ops::Deref;
use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::sync::OnceLock;
+use crate::sync::Once;
+use crate::{fmt, ptr};
+
+use super::once::ExclusiveState;
+
+// We use the state of a Once as discriminant value. Upon creation, the state is
+// "incomplete" and `f` contains the initialization closure. In the first call to
+// `call_once`, `f` is taken and run. If it succeeds, `value` is set and the state
+// is changed to "complete". If it panics, the Once is poisoned, so none of the
+// two fields is initialized.
+union Data<T, F> {
+ value: ManuallyDrop<T>,
+ f: ManuallyDrop<F>,
+}
/// A value which is initialized on the first access.
///
@@ -13,7 +26,7 @@ use crate::sync::OnceLock;
/// # Examples
///
/// ```
-/// #![feature(once_cell)]
+/// #![feature(lazy_cell)]
///
/// use std::collections::HashMap;
///
@@ -41,18 +54,55 @@ use crate::sync::OnceLock;
/// // Some("Hoyten")
/// }
/// ```
-#[unstable(feature = "once_cell", issue = "74465")]
+#[unstable(feature = "lazy_cell", issue = "109736")]
pub struct LazyLock<T, F = fn() -> T> {
- cell: OnceLock<T>,
- init: Cell<Option<F>>,
+ once: Once,
+ data: UnsafeCell<Data<T, F>>,
}
+
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 { cell: OnceLock::new(), init: Cell::new(Some(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
@@ -62,7 +112,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
/// # Examples
///
/// ```
- /// #![feature(once_cell)]
+ /// #![feature(lazy_cell)]
///
/// use std::sync::LazyLock;
///
@@ -72,16 +122,56 @@ 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.cell.get_or_init(|| match this.init.take() {
- Some(f) => f(),
- None => panic!("Lazy instance has previously been poisoned"),
- })
+ this.once.call_once(|| {
+ // SAFETY: `call_once` only runs this closure once, ever.
+ let data = unsafe { &mut *this.data.get() };
+ let f = unsafe { ManuallyDrop::take(&mut data.f) };
+ let value = f();
+ data.value = ManuallyDrop::new(value);
+ });
+
+ // SAFETY:
+ // There are four possible scenarios:
+ // * the closure was called and initialized `value`.
+ // * the closure was called and panicked, so this point is never reached.
+ // * the closure was not called, but a previous call initialized `value`.
+ // * the closure was not called because the Once is poisoned, so this point
+ // is never reached.
+ // So `value` has definitely been initialized and will not be modified again.
+ unsafe { &*(*this.data.get()).value }
+ }
+}
+
+impl<T, F> LazyLock<T, F> {
+ /// Get the inner value if it has already been initialized.
+ fn get(&self) -> Option<&T> {
+ if self.once.is_completed() {
+ // SAFETY:
+ // The closure has been run successfully, so `value` has been initialized
+ // and will not be modified again.
+ Some(unsafe { &*(*self.data.get()).value })
+ } else {
+ None
+ }
+ }
+}
+
+#[unstable(feature = "lazy_cell", issue = "109736")]
+impl<T, F> Drop for LazyLock<T, F> {
+ fn drop(&mut self) {
+ match self.once.state() {
+ ExclusiveState::Incomplete => unsafe { ManuallyDrop::drop(&mut self.data.get_mut().f) },
+ ExclusiveState::Complete => unsafe {
+ ManuallyDrop::drop(&mut self.data.get_mut().value)
+ },
+ ExclusiveState::Poisoned => {}
+ }
}
}
-#[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;
@@ -91,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]
@@ -100,26 +190,26 @@ 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 {
- f.debug_struct("Lazy").field("cell", &self.cell).finish_non_exhaustive()
+ match self.get() {
+ Some(v) => f.debug_tuple("LazyLock").field(v).finish(),
+ None => f.write_str("LazyLock(Uninit)"),
+ }
}
}
// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
// to not impl `Sync` for `F`
-// we do create a `&mut Option<F>` in `force`, but this is
-// properly synchronized, so it only happens once
-// so it also does not contribute to this impl.
-#[unstable(feature = "once_cell", issue = "74465")]
-unsafe impl<T, F: Send> Sync for LazyLock<T, F> where OnceLock<T>: Sync {}
+#[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")]
-impl<T, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> where OnceLock<T>: RefUnwindSafe {}
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T, F: UnwindSafe> UnwindSafe for LazyLock<T, F> where OnceLock<T>: UnwindSafe {}
+#[unstable(feature = "lazy_cell", issue = "109736")]
+impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
+#[unstable(feature = "lazy_cell", issue = "109736")]
+impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}
#[cfg(test)]
mod tests;
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index ba20bab87a4..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};
@@ -186,7 +189,7 @@ mod condvar;
mod lazy_lock;
mod mpmc;
mod mutex;
-mod once;
+pub(crate) mod once;
mod once_lock;
mod poison;
mod remutex;
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.rs b/library/std/src/sync/once.rs
index 0f25417d6b5..1b17c31089f 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -43,6 +43,12 @@ pub struct OnceState {
pub(crate) inner: sys::OnceState,
}
+pub(crate) enum ExclusiveState {
+ Incomplete,
+ Poisoned,
+ Complete,
+}
+
/// Initialization value for static [`Once`] values.
///
/// # Examples
@@ -248,6 +254,16 @@ impl Once {
pub fn is_completed(&self) -> bool {
self.inner.is_completed()
}
+
+ /// Returns the current state of the `Once` instance.
+ ///
+ /// Since this takes a mutable reference, no initialization can currently
+ /// be running, so the state must be either "incomplete", "poisoned" or
+ /// "complete".
+ #[inline]
+ pub(crate) fn state(&mut self) -> ExclusiveState {
+ self.inner.state()
+ }
}
#[stable(feature = "std_debug", since = "1.16.0")]
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/itron/thread_parking.rs b/library/std/src/sys/itron/thread_parking.rs
new file mode 100644
index 00000000000..fe9934439d1
--- /dev/null
+++ b/library/std/src/sys/itron/thread_parking.rs
@@ -0,0 +1,37 @@
+use super::abi;
+use super::error::expect_success_aborting;
+use super::time::with_tmos;
+use crate::time::Duration;
+
+pub type ThreadId = abi::ID;
+
+pub use super::task::current_task_id_aborting as current;
+
+pub fn park(_hint: usize) {
+ match unsafe { abi::slp_tsk() } {
+ abi::E_OK | abi::E_RLWAI => {}
+ err => {
+ expect_success_aborting(err, &"slp_tsk");
+ }
+ }
+}
+
+pub fn park_timeout(dur: Duration, _hint: usize) {
+ match with_tmos(dur, |tmo| unsafe { abi::tslp_tsk(tmo) }) {
+ abi::E_OK | abi::E_RLWAI | abi::E_TMOUT => {}
+ err => {
+ expect_success_aborting(err, &"tslp_tsk");
+ }
+ }
+}
+
+pub fn unpark(id: ThreadId, _hint: usize) {
+ match unsafe { abi::wup_tsk(id) } {
+ // It is allowed to try to wake up a destroyed or unrelated task, so we ignore all
+ // errors that could result from that situation.
+ abi::E_OK | abi::E_NOEXS | abi::E_OBJ | abi::E_QOVR => {}
+ err => {
+ expect_success_aborting(err, &"wup_tsk");
+ }
+ }
+}
diff --git a/library/std/src/sys/itron/wait_flag.rs b/library/std/src/sys/itron/wait_flag.rs
deleted file mode 100644
index e432edd2077..00000000000
--- a/library/std/src/sys/itron/wait_flag.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use crate::mem::MaybeUninit;
-use crate::time::Duration;
-
-use super::{
- abi,
- error::{expect_success, fail},
- time::with_tmos,
-};
-
-const CLEAR: abi::FLGPTN = 0;
-const RAISED: abi::FLGPTN = 1;
-
-/// A thread parking primitive that is not susceptible to race conditions,
-/// but provides no atomic ordering guarantees and allows only one `raise` per wait.
-pub struct WaitFlag {
- flag: abi::ID,
-}
-
-impl WaitFlag {
- /// Creates a new wait flag.
- pub fn new() -> WaitFlag {
- let flag = expect_success(
- unsafe {
- abi::acre_flg(&abi::T_CFLG {
- flgatr: abi::TA_FIFO | abi::TA_WSGL | abi::TA_CLR,
- iflgptn: CLEAR,
- })
- },
- &"acre_flg",
- );
-
- WaitFlag { flag }
- }
-
- /// Wait for the wait flag to be raised.
- pub fn wait(&self) {
- let mut token = MaybeUninit::uninit();
- expect_success(
- unsafe { abi::wai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr()) },
- &"wai_flg",
- );
- }
-
- /// Wait for the wait flag to be raised or the timeout to occur.
- ///
- /// Returns whether the flag was raised (`true`) or the operation timed out (`false`).
- pub fn wait_timeout(&self, dur: Duration) -> bool {
- let mut token = MaybeUninit::uninit();
- let res = with_tmos(dur, |tmout| unsafe {
- abi::twai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr(), tmout)
- });
-
- match res {
- abi::E_OK => true,
- abi::E_TMOUT => false,
- error => fail(error, &"twai_flg"),
- }
- }
-
- /// Raise the wait flag.
- ///
- /// Calls to this function should be balanced with the number of successful waits.
- pub fn raise(&self) {
- expect_success(unsafe { abi::set_flg(self.flag, RAISED) }, &"set_flg");
- }
-}
-
-impl Drop for WaitFlag {
- fn drop(&mut self) {
- expect_success(unsafe { abi::del_flg(self.flag) }, &"del_flg");
- }
-}
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/mod.rs b/library/std/src/sys/solid/mod.rs
index 5867979a2a7..923d27fd936 100644
--- a/library/std/src/sys/solid/mod.rs
+++ b/library/std/src/sys/solid/mod.rs
@@ -13,9 +13,9 @@ mod itron {
pub(super) mod spin;
pub(super) mod task;
pub mod thread;
+ pub mod thread_parking;
pub(super) mod time;
use super::unsupported;
- pub mod wait_flag;
}
pub mod alloc;
@@ -43,8 +43,8 @@ pub use self::itron::thread;
pub mod memchr;
pub mod thread_local_dtor;
pub mod thread_local_key;
+pub use self::itron::thread_parking;
pub mod time;
-pub use self::itron::wait_flag;
mod rwlock;
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 dbaa3c33e2e..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 {
@@ -284,9 +466,23 @@ impl<'a> Read for &'a FileDesc {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
+
+ 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
}
@@ -311,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/once.rs b/library/std/src/sys/unsupported/once.rs
index b4bb4975f41..11fde1888ba 100644
--- a/library/std/src/sys/unsupported/once.rs
+++ b/library/std/src/sys/unsupported/once.rs
@@ -1,5 +1,6 @@
use crate::cell::Cell;
use crate::sync as public;
+use crate::sync::once::ExclusiveState;
pub struct Once {
state: Cell<State>,
@@ -44,6 +45,16 @@ impl Once {
self.state.get() == State::Complete
}
+ #[inline]
+ pub(crate) fn state(&mut self) -> ExclusiveState {
+ match self.state.get() {
+ State::Incomplete => ExclusiveState::Incomplete,
+ State::Poisoned => ExclusiveState::Poisoned,
+ State::Complete => ExclusiveState::Complete,
+ _ => unreachable!("invalid Once state"),
+ }
+ }
+
#[cold]
#[track_caller]
pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) {
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 81461de4f72..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,69 +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
}
-// "RNG\0"
-pub const BCRYPT_RNG_ALGORITHM: &[u16] = &[b'R' as u16, b'N' as u16, b'G' as u16, 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 {
@@ -332,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)]
@@ -541,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,
@@ -557,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,
@@ -597,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],
@@ -702,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,
@@ -744,527 +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" {
- // 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 fn BCryptOpenAlgorithmProvider(
- phalgorithm: *mut BCRYPT_ALG_HANDLE,
- pszAlgId: LPCWSTR,
- pszimplementation: LPCWSTR,
- dwflags: ULONG,
- ) -> NTSTATUS;
- pub fn BCryptCloseAlgorithmProvider(hAlgorithm: BCRYPT_ALG_HANDLE, 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,
@@ -1274,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 b5a49489d3f..bca4e38d9f6 100644
--- a/library/std/src/sys/windows/rand.rs
+++ b/library/std/src/sys/windows/rand.rs
@@ -1,106 +1,41 @@
-//! # Random key generation
-//!
-//! This module wraps the RNG provided by the OS. There are a few different
-//! ways to interface with the OS RNG so it's worth exploring each of the options.
-//! Note that at the time of writing these all go through the (undocumented)
-//! `bcryptPrimitives.dll` but they use different route to get there.
-//!
-//! Originally we were using [`RtlGenRandom`], however that function is
-//! deprecated and warns it "may be altered or unavailable in subsequent versions".
-//!
-//! So we switched to [`BCryptGenRandom`] with the `BCRYPT_USE_SYSTEM_PREFERRED_RNG`
-//! flag to query and find the system configured RNG. However, this change caused a small
-//! but significant number of users to experience panics caused by a failure of
-//! this function. See [#94098].
-//!
-//! The current version falls back to using `BCryptOpenAlgorithmProvider` if
-//! `BCRYPT_USE_SYSTEM_PREFERRED_RNG` fails for any reason.
-//!
-//! [#94098]: https://github.com/rust-lang/rust/issues/94098
-//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
-//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+use crate::ffi::c_void;
+use crate::io;
use crate::mem;
use crate::ptr;
use crate::sys::c;
-/// Generates high quality secure random keys for use by [`HashMap`].
-///
-/// This is used to seed the default [`RandomState`].
-///
-/// [`HashMap`]: crate::collections::HashMap
-/// [`RandomState`]: crate::collections::hash_map::RandomState
pub fn hashmap_random_keys() -> (u64, u64) {
- Rng::SYSTEM.gen_random_keys().unwrap_or_else(fallback_rng)
+ let mut v = (0, 0);
+ let ret = unsafe {
+ c::BCryptGenRandom(
+ ptr::null_mut(),
+ &mut v as *mut _ as *mut u8,
+ mem::size_of_val(&v) as c::ULONG,
+ c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
+ )
+ };
+ if c::nt_success(ret) { v } else { fallback_rng() }
}
-struct Rng {
- algorithm: c::BCRYPT_ALG_HANDLE,
- flags: u32,
-}
-impl Rng {
- const SYSTEM: Self = unsafe { Self::new(ptr::null_mut(), c::BCRYPT_USE_SYSTEM_PREFERRED_RNG) };
-
- /// Create the RNG from an existing algorithm handle.
- ///
- /// # Safety
- ///
- /// The handle must either be null or a valid algorithm handle.
- const unsafe fn new(algorithm: c::BCRYPT_ALG_HANDLE, flags: u32) -> Self {
- Self { algorithm, flags }
- }
-
- /// Open a handle to the RNG algorithm.
- fn open() -> Result<Self, c::NTSTATUS> {
- use crate::sync::atomic::AtomicPtr;
- use crate::sync::atomic::Ordering::{Acquire, Release};
-
- // An atomic is used so we don't need to reopen the handle every time.
- static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(ptr::null_mut());
-
- let mut handle = HANDLE.load(Acquire);
- if handle.is_null() {
- let status = unsafe {
- c::BCryptOpenAlgorithmProvider(
- &mut handle,
- c::BCRYPT_RNG_ALGORITHM.as_ptr(),
- ptr::null(),
- 0,
- )
- };
- if c::nt_success(status) {
- // If another thread opens a handle first then use that handle instead.
- let result = HANDLE.compare_exchange(ptr::null_mut(), handle, Release, Acquire);
- if let Err(previous_handle) = result {
- // Close our handle and return the previous one.
- unsafe { c::BCryptCloseAlgorithmProvider(handle, 0) };
- handle = previous_handle;
- }
- Ok(unsafe { Self::new(handle, 0) })
- } else {
- Err(status)
- }
- } else {
- Ok(unsafe { Self::new(handle, 0) })
- }
- }
+/// Generate random numbers using the fallback RNG function (RtlGenRandom)
+///
+/// This is necessary because of a failure to load the SysWOW64 variant of the
+/// bcryptprimitives.dll library from code that lives in bcrypt.dll
+/// See <https://bugzilla.mozilla.org/show_bug.cgi?id=1788004#c9>
+#[cfg(not(target_vendor = "uwp"))]
+#[inline(never)]
+fn fallback_rng() -> (u64, u64) {
+ let mut v = (0, 0);
+ let ret = unsafe {
+ c::RtlGenRandom(&mut v as *mut _ as *mut c_void, mem::size_of_val(&v) as c::ULONG)
+ };
- fn gen_random_keys(self) -> Result<(u64, u64), c::NTSTATUS> {
- let mut v = (0, 0);
- let status = unsafe {
- let size = mem::size_of_val(&v).try_into().unwrap();
- c::BCryptGenRandom(self.algorithm, ptr::addr_of_mut!(v).cast(), size, self.flags)
- };
- if c::nt_success(status) { Ok(v) } else { Err(status) }
- }
+ if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) }
}
-/// Generate random numbers using the fallback RNG function
+/// We can't use RtlGenRandom with UWP, so there is no fallback
+#[cfg(target_vendor = "uwp")]
#[inline(never)]
-fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
- match Rng::open().and_then(|rng| rng.gen_random_keys()) {
- Ok(keys) => keys,
- Err(status) => {
- panic!("RNG broken: {rng_status:#x}, fallback RNG broken: {status:#x}")
- }
- }
+fn fallback_rng() -> (u64, u64) {
+ panic!("fallback RNG broken: RtlGenRandom() not supported on UWP");
}
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/once/futex.rs b/library/std/src/sys_common/once/futex.rs
index 5c7e6c01371..42db5fad4b4 100644
--- a/library/std/src/sys_common/once/futex.rs
+++ b/library/std/src/sys_common/once/futex.rs
@@ -4,6 +4,7 @@ use crate::sync::atomic::{
AtomicU32,
Ordering::{Acquire, Relaxed, Release},
};
+use crate::sync::once::ExclusiveState;
use crate::sys::futex::{futex_wait, futex_wake_all};
// On some platforms, the OS is very nice and handles the waiter queue for us.
@@ -78,6 +79,16 @@ impl Once {
self.state.load(Acquire) == COMPLETE
}
+ #[inline]
+ pub(crate) fn state(&mut self) -> ExclusiveState {
+ match *self.state.get_mut() {
+ INCOMPLETE => ExclusiveState::Incomplete,
+ POISONED => ExclusiveState::Poisoned,
+ COMPLETE => ExclusiveState::Complete,
+ _ => unreachable!("invalid Once state"),
+ }
+ }
+
// This uses FnMut to match the API of the generic implementation. As this
// implementation is quite light-weight, it is generic over the closure and
// so avoids the cost of dynamic dispatch.
diff --git a/library/std/src/sys_common/once/queue.rs b/library/std/src/sys_common/once/queue.rs
index d953a674592..def0bcd6fac 100644
--- a/library/std/src/sys_common/once/queue.rs
+++ b/library/std/src/sys_common/once/queue.rs
@@ -60,6 +60,7 @@ use crate::fmt;
use crate::ptr;
use crate::sync as public;
use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
+use crate::sync::once::ExclusiveState;
use crate::thread::{self, Thread};
type Masked = ();
@@ -121,6 +122,16 @@ impl Once {
self.state_and_queue.load(Ordering::Acquire).addr() == COMPLETE
}
+ #[inline]
+ pub(crate) fn state(&mut self) -> ExclusiveState {
+ match self.state_and_queue.get_mut().addr() {
+ INCOMPLETE => ExclusiveState::Incomplete,
+ POISONED => ExclusiveState::Poisoned,
+ COMPLETE => ExclusiveState::Complete,
+ _ => unreachable!("invalid Once state"),
+ }
+ }
+
// This is a non-generic function to reduce the monomorphization cost of
// using `call_once` (this isn't exactly a trivial or small implementation).
//
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 0ead6633c35..c4d3f9ea2f4 100644
--- a/library/std/src/sys_common/thread_parking/mod.rs
+++ b/library/std/src/sys_common/thread_parking/mod.rs
@@ -14,16 +14,11 @@ cfg_if::cfg_if! {
} else if #[cfg(any(
target_os = "netbsd",
all(target_vendor = "fortanix", target_env = "sgx"),
+ target_os = "solid_asp3",
))] {
mod id;
pub use id::Parker;
- } else if #[cfg(target_os = "solid_asp3")] {
- mod wait_flag;
- pub use wait_flag::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/thread_parking/wait_flag.rs b/library/std/src/sys_common/thread_parking/wait_flag.rs
deleted file mode 100644
index d0f8899a94e..00000000000
--- a/library/std/src/sys_common/thread_parking/wait_flag.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-//! A wait-flag-based thread parker.
-//!
-//! Some operating systems provide low-level parking primitives like wait counts,
-//! event flags or semaphores which are not susceptible to race conditions (meaning
-//! the wakeup can occur before the wait operation). To implement the `std` thread
-//! parker on top of these primitives, we only have to ensure that parking is fast
-//! when the thread token is available, the atomic ordering guarantees are maintained
-//! and spurious wakeups are minimized.
-//!
-//! To achieve this, this parker uses an atomic variable with three states: `EMPTY`,
-//! `PARKED` and `NOTIFIED`:
-//! * `EMPTY` means the token has not been made available, but the thread is not
-//! currently waiting on it.
-//! * `PARKED` means the token is not available and the thread is parked.
-//! * `NOTIFIED` means the token is available.
-//!
-//! `park` and `park_timeout` change the state from `EMPTY` to `PARKED` and from
-//! `NOTIFIED` to `EMPTY`. If the state was `NOTIFIED`, the thread was unparked and
-//! execution can continue without calling into the OS. If the state was `EMPTY`,
-//! the token is not available and the thread waits on the primitive (here called
-//! "wait flag").
-//!
-//! `unpark` changes the state to `NOTIFIED`. If the state was `PARKED`, the thread
-//! is or will be sleeping on the wait flag, so we raise it.
-
-use crate::pin::Pin;
-use crate::sync::atomic::AtomicI8;
-use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sys::wait_flag::WaitFlag;
-use crate::time::Duration;
-
-const EMPTY: i8 = 0;
-const PARKED: i8 = -1;
-const NOTIFIED: i8 = 1;
-
-pub struct Parker {
- state: AtomicI8,
- wait_flag: WaitFlag,
-}
-
-impl Parker {
- /// Construct a parker for the current thread. The UNIX parker
- /// implementation requires this to happen in-place.
- pub unsafe fn new_in_place(parker: *mut Parker) {
- parker.write(Parker { state: AtomicI8::new(EMPTY), wait_flag: WaitFlag::new() })
- }
-
- // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
- pub unsafe fn park(self: Pin<&Self>) {
- match self.state.fetch_sub(1, Acquire) {
- // NOTIFIED => EMPTY
- NOTIFIED => return,
- // EMPTY => PARKED
- EMPTY => (),
- _ => panic!("inconsistent park state"),
- }
-
- // Avoid waking up from spurious wakeups (these are quite likely, see below).
- loop {
- self.wait_flag.wait();
-
- match self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed) {
- Ok(_) => return,
- Err(PARKED) => (),
- Err(_) => panic!("inconsistent park state"),
- }
- }
- }
-
- // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
- pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
- match self.state.fetch_sub(1, Acquire) {
- NOTIFIED => return,
- EMPTY => (),
- _ => panic!("inconsistent park state"),
- }
-
- self.wait_flag.wait_timeout(dur);
-
- // Either a wakeup or a timeout occurred. Wakeups may be spurious, as there can be
- // a race condition when `unpark` is performed between receiving the timeout and
- // resetting the state, resulting in the eventflag being set unnecessarily. `park`
- // is protected against this by looping until the token is actually given, but
- // here we cannot easily tell.
-
- // Use `swap` to provide acquire ordering.
- match self.state.swap(EMPTY, Acquire) {
- NOTIFIED => (),
- PARKED => (),
- _ => panic!("inconsistent park state"),
- }
- }
-
- // This implementation doesn't require `Pin`, but other implementations do.
- pub fn unpark(self: Pin<&Self>) {
- let state = self.state.swap(NOTIFIED, Release);
-
- if state == PARKED {
- self.wait_flag.raise();
- }
- }
-}
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 692ff0cbca6..f712c872708 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -124,12 +124,15 @@
//!
//! ## Stack size
//!
-//! The default stack size is platform-dependent and subject to change. Currently it is 2MB on all
-//! Tier-1 platforms. There are two ways to manually specify the stack size for spawned threads:
+//! The default stack size is platform-dependent and subject to change.
+//! Currently, it is 2 MiB on all Tier-1 platforms.
+//!
+//! There are two ways to manually specify the stack size for spawned threads:
//!
//! * 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.
//!
@@ -190,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
@@ -526,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);
@@ -535,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 &#xa so as to keep all the output on one line
+ let escaped_output = escaped_output.replace("\n", "]]>&#xA;<![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