html-to-markdown 2.27.2 → 2.27.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +8 -8
- data/ext/html-to-markdown-rb/native/Cargo.toml +1 -1
- data/lib/html_to_markdown/version.rb +1 -1
- data/rust-vendor/getrandom/.cargo-checksum.json +1 -1
- data/rust-vendor/getrandom/.cargo_vcs_info.json +1 -1
- data/rust-vendor/getrandom/CHANGELOG.md +62 -43
- data/rust-vendor/getrandom/Cargo.lock +49 -56
- data/rust-vendor/getrandom/Cargo.toml +2 -2
- data/rust-vendor/getrandom/Cargo.toml.orig +2 -2
- data/rust-vendor/getrandom/src/backends/efi_rng.rs +8 -10
- data/rust-vendor/getrandom/src/backends/getentropy.rs +13 -4
- data/rust-vendor/getrandom/src/backends/linux_android_with_fallback.rs +10 -25
- data/rust-vendor/getrandom/src/backends/netbsd.rs +17 -25
- data/rust-vendor/getrandom/src/backends/rdrand.rs +15 -9
- data/rust-vendor/getrandom/src/backends/rndr.rs +2 -1
- data/rust-vendor/getrandom/src/backends/vxworks.rs +7 -3
- data/rust-vendor/getrandom/src/backends/windows.rs +21 -5
- data/rust-vendor/getrandom/src/utils/lazy_bool.rs +39 -0
- data/rust-vendor/getrandom/src/utils/lazy_ptr.rs +57 -0
- data/rust-vendor/html-to-markdown-rs/Cargo.toml +2 -2
- data/rust-vendor/html-to-markdown-rs/src/converter/text_node.rs +2 -1
- data/rust-vendor/html-to-markdown-rs/tests/issue_216_217_regressions.rs +82 -0
- data/rust-vendor/quote/.cargo-checksum.json +1 -1
- data/rust-vendor/quote/.cargo_vcs_info.json +1 -1
- data/rust-vendor/quote/.github/workflows/ci.yml +2 -2
- data/rust-vendor/quote/Cargo.lock +21 -21
- data/rust-vendor/quote/Cargo.toml +2 -2
- data/rust-vendor/quote/Cargo.toml.orig +2 -2
- data/rust-vendor/quote/README.md +0 -1
- data/rust-vendor/quote/src/lib.rs +1 -1
- data/rust-vendor/quote/src/to_tokens.rs +7 -0
- data/rust-vendor/quote/tests/ui/not-quotable.stderr +1 -1
- data/rust-vendor/quote/tests/ui/not-repeatable.stderr +3 -11
- data/rust-vendor/r-efi/.cargo-checksum.json +1 -1
- data/rust-vendor/r-efi/.cargo_vcs_info.json +1 -1
- data/rust-vendor/r-efi/AUTHORS +1 -0
- data/rust-vendor/r-efi/Cargo.lock +1 -1
- data/rust-vendor/r-efi/Cargo.toml +1 -3
- data/rust-vendor/r-efi/Cargo.toml.orig +1 -5
- data/rust-vendor/r-efi/NEWS.md +16 -0
- data/rust-vendor/r-efi/src/base.rs +1 -1
- data/rust-vendor/r-efi/src/lib.rs +27 -12
- data/rust-vendor/r-efi/src/protocols/absolute_pointer.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/block_io.rs +8 -8
- data/rust-vendor/r-efi/src/protocols/bus_specific_driver_override.rs +2 -2
- data/rust-vendor/r-efi/src/protocols/debug_support.rs +10 -10
- data/rust-vendor/r-efi/src/protocols/debugport.rs +8 -8
- data/rust-vendor/r-efi/src/protocols/decompress.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/device_path_from_text.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/device_path_to_text.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/device_path_utilities.rs +16 -16
- data/rust-vendor/r-efi/src/protocols/disk_io.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/disk_io2.rs +8 -8
- data/rust-vendor/r-efi/src/protocols/driver_binding.rs +6 -6
- data/rust-vendor/r-efi/src/protocols/driver_diagnostics2.rs +2 -2
- data/rust-vendor/r-efi/src/protocols/driver_family_override.rs +2 -2
- data/rust-vendor/r-efi/src/protocols/file.rs +28 -28
- data/rust-vendor/r-efi/src/protocols/graphics_output.rs +6 -6
- data/rust-vendor/r-efi/src/protocols/hii_database.rs +24 -24
- data/rust-vendor/r-efi/src/protocols/hii_font.rs +8 -8
- data/rust-vendor/r-efi/src/protocols/hii_font_ex.rs +10 -10
- data/rust-vendor/r-efi/src/protocols/hii_string.rs +10 -10
- data/rust-vendor/r-efi/src/protocols/ip4.rs +16 -16
- data/rust-vendor/r-efi/src/protocols/ip6.rs +18 -18
- data/rust-vendor/r-efi/src/protocols/load_file.rs +2 -2
- data/rust-vendor/r-efi/src/protocols/loaded_image.rs +2 -2
- data/rust-vendor/r-efi/src/protocols/managed_network.rs +16 -16
- data/rust-vendor/r-efi/src/protocols/memory_attribute.rs +6 -6
- data/rust-vendor/r-efi/src/protocols/mp_services.rs +15 -15
- data/rust-vendor/r-efi/src/protocols/pci_io.rs +26 -26
- data/rust-vendor/r-efi/src/protocols/platform_driver_override.rs +6 -6
- data/rust-vendor/r-efi/src/protocols/rng.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/service_binding.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/shell.rs +81 -81
- data/rust-vendor/r-efi/src/protocols/shell_dynamic_command.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/simple_file_system.rs +2 -2
- data/rust-vendor/r-efi/src/protocols/simple_network.rs +26 -26
- data/rust-vendor/r-efi/src/protocols/simple_text_input.rs +4 -4
- data/rust-vendor/r-efi/src/protocols/simple_text_input_ex.rs +11 -11
- data/rust-vendor/r-efi/src/protocols/simple_text_output.rs +18 -18
- data/rust-vendor/r-efi/src/protocols/tcp4.rs +20 -20
- data/rust-vendor/r-efi/src/protocols/tcp6.rs +18 -18
- data/rust-vendor/r-efi/src/protocols/timestamp.rs +3 -3
- data/rust-vendor/r-efi/src/protocols/udp4.rs +16 -16
- data/rust-vendor/r-efi/src/protocols/udp6.rs +14 -14
- data/rust-vendor/r-efi/src/system.rs +115 -115
- data/rust-vendor/r-efi/src/vendor/intel/console_control.rs +6 -6
- data/rust-vendor/r-efi-5.3.0/.cargo-checksum.json +1 -0
- data/rust-vendor/r-efi-5.3.0/.cargo_vcs_info.json +6 -0
- data/rust-vendor/r-efi-5.3.0/.github/workflows/publish.yml +39 -0
- data/rust-vendor/r-efi-5.3.0/.github/workflows/rust-tests.yml +125 -0
- data/rust-vendor/r-efi-5.3.0/AUTHORS +74 -0
- data/rust-vendor/r-efi-5.3.0/Cargo.lock +16 -0
- data/rust-vendor/r-efi-5.3.0/Cargo.toml +70 -0
- data/rust-vendor/r-efi-5.3.0/Cargo.toml.orig +51 -0
- data/rust-vendor/r-efi-5.3.0/Makefile +85 -0
- data/rust-vendor/r-efi-5.3.0/NEWS.md +301 -0
- data/rust-vendor/r-efi-5.3.0/README.md +99 -0
- data/rust-vendor/r-efi-5.3.0/examples/freestanding.rs +34 -0
- data/rust-vendor/r-efi-5.3.0/examples/gop-query.rs +188 -0
- data/rust-vendor/r-efi-5.3.0/examples/hello-world.rs +55 -0
- data/rust-vendor/r-efi-5.3.0/src/base.rs +993 -0
- data/rust-vendor/r-efi-5.3.0/src/hii.rs +1300 -0
- data/rust-vendor/r-efi-5.3.0/src/lib.rs +182 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/absolute_pointer.rs +69 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/block_io.rs +70 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/bus_specific_driver_override.rs +32 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/debug_support.rs +835 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/debugport.rs +42 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/decompress.rs +37 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/device_path.rs +82 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/device_path_from_text.rs +26 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/device_path_to_text.rs +30 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/device_path_utilities.rs +63 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/disk_io.rs +40 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/disk_io2.rs +58 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/driver_binding.rs +42 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/driver_diagnostics2.rs +38 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/driver_family_override.rs +23 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/file.rs +183 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/graphics_output.rs +103 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/hii_database.rs +299 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/hii_font.rs +87 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/hii_font_ex.rs +107 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/hii_package_list.rs +14 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/hii_string.rs +71 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/ip4.rs +202 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/ip6.rs +264 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/load_file.rs +26 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/load_file2.rs +15 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/loaded_image.rs +39 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/loaded_image_device_path.rs +13 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/managed_network.rs +147 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/memory_attribute.rs +40 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/mp_services.rs +121 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/pci_io.rs +203 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/platform_driver_override.rs +46 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/rng.rs +83 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/service_binding.rs +20 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/shell.rs +295 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/shell_dynamic_command.rs +33 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/shell_parameters.rs +23 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/simple_file_system.rs +26 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/simple_network.rs +196 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/simple_text_input.rs +38 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/simple_text_input_ex.rs +85 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/simple_text_output.rs +86 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/tcp4.rs +224 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/tcp6.rs +202 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/timestamp.rs +32 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/udp4.rs +151 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols/udp6.rs +137 -0
- data/rust-vendor/r-efi-5.3.0/src/protocols.rs +54 -0
- data/rust-vendor/r-efi-5.3.0/src/system.rs +1130 -0
- data/rust-vendor/r-efi-5.3.0/src/vendor/intel/console_control.rs +37 -0
- data/rust-vendor/r-efi-5.3.0/src/vendor.rs +10 -0
- data/rust-vendor/tokio/.cargo-checksum.json +1 -1
- data/rust-vendor/tokio/.cargo_vcs_info.json +1 -1
- data/rust-vendor/tokio/CHANGELOG.md +94 -0
- data/rust-vendor/tokio/Cargo.lock +1549 -0
- data/rust-vendor/tokio/Cargo.toml +96 -83
- data/rust-vendor/tokio/Cargo.toml.orig +7 -7
- data/rust-vendor/tokio/README.md +1 -1
- data/rust-vendor/tokio/src/fs/open_options.rs +4 -1
- data/rust-vendor/tokio/src/fs/read.rs +4 -1
- data/rust-vendor/tokio/src/fs/write.rs +4 -1
- data/rust-vendor/tokio/src/io/async_write.rs +3 -4
- data/rust-vendor/tokio/src/io/poll_evented.rs +23 -1
- data/rust-vendor/tokio/src/io/stderr.rs +15 -1
- data/rust-vendor/tokio/src/io/stdout.rs +14 -0
- data/rust-vendor/tokio/src/io/util/async_write_ext.rs +2 -2
- data/rust-vendor/tokio/src/io/util/write_buf.rs +11 -2
- data/rust-vendor/tokio/src/lib.rs +12 -28
- data/rust-vendor/tokio/src/macros/select.rs +6 -8
- data/rust-vendor/tokio/src/net/tcp/socket.rs +25 -1
- data/rust-vendor/tokio/src/net/tcp/stream.rs +40 -1
- data/rust-vendor/tokio/src/process/unix/pidfd_reaper.rs +1 -41
- data/rust-vendor/tokio/src/runtime/blocking/pool.rs +18 -14
- data/rust-vendor/tokio/src/runtime/builder.rs +10 -4
- data/rust-vendor/tokio/src/runtime/handle.rs +3 -2
- data/rust-vendor/tokio/src/runtime/io/driver/uring.rs +49 -61
- data/rust-vendor/tokio/src/runtime/io/driver.rs +6 -5
- data/rust-vendor/tokio/src/runtime/mod.rs +20 -1
- data/rust-vendor/tokio/src/runtime/runtime.rs +71 -1
- data/rust-vendor/tokio/src/runtime/scheduler/current_thread/mod.rs +24 -8
- data/rust-vendor/tokio/src/runtime/scheduler/multi_thread/worker.rs +5 -0
- data/rust-vendor/tokio/src/runtime/task/core.rs +1 -0
- data/rust-vendor/tokio/src/runtime/task/join.rs +7 -3
- data/rust-vendor/tokio/src/runtime/task/list.rs +5 -3
- data/rust-vendor/tokio/src/runtime/task/mod.rs +0 -5
- data/rust-vendor/tokio/src/runtime/tests/loom_blocking.rs +39 -1
- data/rust-vendor/tokio/src/signal/mod.rs +6 -17
- data/rust-vendor/tokio/src/signal/registry.rs +1 -1
- data/rust-vendor/tokio/src/signal/unix.rs +24 -44
- data/rust-vendor/tokio/src/signal/windows/sys.rs +52 -64
- data/rust-vendor/tokio/src/signal/windows.rs +35 -23
- data/rust-vendor/tokio/src/sync/mpsc/mod.rs +3 -1
- data/rust-vendor/tokio/src/sync/oneshot.rs +13 -0
- data/rust-vendor/tokio/src/sync/rwlock.rs +4 -5
- data/rust-vendor/tokio/src/sync/tests/loom_oneshot.rs +27 -1
- data/rust-vendor/tokio/src/task/blocking.rs +16 -1
- data/rust-vendor/tokio/src/task/builder.rs +2 -2
- data/rust-vendor/tokio/src/task/mod.rs +1 -1
- data/rust-vendor/tokio/src/task/spawn.rs +8 -3
- data/rust-vendor/tokio/src/task/yield_now.rs +13 -23
- data/rust-vendor/tokio/src/time/clock.rs +62 -0
- data/rust-vendor/tokio/src/util/memchr.rs +32 -4
- data/rust-vendor/tokio/src/util/sharded_list.rs +6 -4
- data/rust-vendor/tokio/tests/fs_link.rs +54 -0
- data/rust-vendor/tokio/tests/io_async_fd_memory_leak.rs +209 -0
- data/rust-vendor/tokio/tests/io_write_buf.rs +56 -0
- data/rust-vendor/tokio/tests/process_issue_7144.rs +8 -0
- data/rust-vendor/tokio/tests/rt_basic.rs +41 -0
- data/rust-vendor/tokio/tests/rt_common_before_park.rs +92 -0
- data/rust-vendor/tokio/tests/rt_metrics.rs +1 -1
- data/rust-vendor/tokio/tests/rt_panic.rs +12 -0
- data/rust-vendor/tokio/tests/rt_shutdown_err.rs +82 -0
- data/rust-vendor/tokio/tests/rt_threaded.rs +49 -1
- data/rust-vendor/tokio/tests/rt_unstable_metrics.rs +32 -0
- data/rust-vendor/tokio/tests/tcp_connect.rs +2 -3
- data/rust-vendor/tokio/tests/tcp_shutdown.rs +1 -3
- data/rust-vendor/tokio/tests/tcp_socket.rs +3 -4
- data/rust-vendor/tokio/tests/tcp_stream.rs +3 -0
- metadata +78 -3
- data/rust-vendor/getrandom/src/utils/lazy.rs +0 -64
|
@@ -16,9 +16,6 @@ use std::task::{Context, Poll};
|
|
|
16
16
|
#[path = "windows/sys.rs"]
|
|
17
17
|
mod imp;
|
|
18
18
|
|
|
19
|
-
#[cfg(windows)]
|
|
20
|
-
pub(crate) use self::imp::{OsExtraData, OsStorage};
|
|
21
|
-
|
|
22
19
|
// For building documentation on Unix machines when the `docsrs` flag is set.
|
|
23
20
|
#[cfg(not(windows))]
|
|
24
21
|
#[path = "windows/stub.rs"]
|
|
@@ -72,7 +69,8 @@ pub struct CtrlC {
|
|
|
72
69
|
impl CtrlC {
|
|
73
70
|
/// Receives the next signal notification event.
|
|
74
71
|
///
|
|
75
|
-
///
|
|
72
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
73
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
76
74
|
///
|
|
77
75
|
/// # Examples
|
|
78
76
|
///
|
|
@@ -93,13 +91,15 @@ impl CtrlC {
|
|
|
93
91
|
/// }
|
|
94
92
|
/// ```
|
|
95
93
|
pub async fn recv(&mut self) -> Option<()> {
|
|
96
|
-
self.inner.recv().await
|
|
94
|
+
self.inner.recv().await;
|
|
95
|
+
Some(())
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
/// Polls to receive the next signal notification event, outside of an
|
|
100
99
|
/// `async` context.
|
|
101
100
|
///
|
|
102
|
-
///
|
|
101
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
102
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
103
103
|
///
|
|
104
104
|
/// # Examples
|
|
105
105
|
///
|
|
@@ -125,7 +125,7 @@ impl CtrlC {
|
|
|
125
125
|
/// }
|
|
126
126
|
/// ```
|
|
127
127
|
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
|
|
128
|
-
self.inner.poll_recv(cx)
|
|
128
|
+
self.inner.poll_recv(cx).map(Some)
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
@@ -149,7 +149,8 @@ pub struct CtrlBreak {
|
|
|
149
149
|
impl CtrlBreak {
|
|
150
150
|
/// Receives the next signal notification event.
|
|
151
151
|
///
|
|
152
|
-
///
|
|
152
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
153
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
153
154
|
///
|
|
154
155
|
/// # Examples
|
|
155
156
|
///
|
|
@@ -169,13 +170,15 @@ impl CtrlBreak {
|
|
|
169
170
|
/// }
|
|
170
171
|
/// ```
|
|
171
172
|
pub async fn recv(&mut self) -> Option<()> {
|
|
172
|
-
self.inner.recv().await
|
|
173
|
+
self.inner.recv().await;
|
|
174
|
+
Some(())
|
|
173
175
|
}
|
|
174
176
|
|
|
175
177
|
/// Polls to receive the next signal notification event, outside of an
|
|
176
178
|
/// `async` context.
|
|
177
179
|
///
|
|
178
|
-
///
|
|
180
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
181
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
179
182
|
///
|
|
180
183
|
/// # Examples
|
|
181
184
|
///
|
|
@@ -201,7 +204,7 @@ impl CtrlBreak {
|
|
|
201
204
|
/// }
|
|
202
205
|
/// ```
|
|
203
206
|
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
|
|
204
|
-
self.inner.poll_recv(cx)
|
|
207
|
+
self.inner.poll_recv(cx).map(Some)
|
|
205
208
|
}
|
|
206
209
|
}
|
|
207
210
|
|
|
@@ -275,7 +278,8 @@ pub struct CtrlClose {
|
|
|
275
278
|
impl CtrlClose {
|
|
276
279
|
/// Receives the next signal notification event.
|
|
277
280
|
///
|
|
278
|
-
///
|
|
281
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
282
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
279
283
|
///
|
|
280
284
|
/// # Examples
|
|
281
285
|
///
|
|
@@ -295,13 +299,15 @@ impl CtrlClose {
|
|
|
295
299
|
/// }
|
|
296
300
|
/// ```
|
|
297
301
|
pub async fn recv(&mut self) -> Option<()> {
|
|
298
|
-
self.inner.recv().await
|
|
302
|
+
self.inner.recv().await;
|
|
303
|
+
Some(())
|
|
299
304
|
}
|
|
300
305
|
|
|
301
306
|
/// Polls to receive the next signal notification event, outside of an
|
|
302
307
|
/// `async` context.
|
|
303
308
|
///
|
|
304
|
-
///
|
|
309
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
310
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
305
311
|
///
|
|
306
312
|
/// # Examples
|
|
307
313
|
///
|
|
@@ -327,7 +333,7 @@ impl CtrlClose {
|
|
|
327
333
|
/// }
|
|
328
334
|
/// ```
|
|
329
335
|
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
|
|
330
|
-
self.inner.poll_recv(cx)
|
|
336
|
+
self.inner.poll_recv(cx).map(Some)
|
|
331
337
|
}
|
|
332
338
|
}
|
|
333
339
|
|
|
@@ -372,7 +378,8 @@ pub struct CtrlShutdown {
|
|
|
372
378
|
impl CtrlShutdown {
|
|
373
379
|
/// Receives the next signal notification event.
|
|
374
380
|
///
|
|
375
|
-
///
|
|
381
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
382
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
376
383
|
///
|
|
377
384
|
/// # Examples
|
|
378
385
|
///
|
|
@@ -392,13 +399,15 @@ impl CtrlShutdown {
|
|
|
392
399
|
/// }
|
|
393
400
|
/// ```
|
|
394
401
|
pub async fn recv(&mut self) -> Option<()> {
|
|
395
|
-
self.inner.recv().await
|
|
402
|
+
self.inner.recv().await;
|
|
403
|
+
Some(())
|
|
396
404
|
}
|
|
397
405
|
|
|
398
406
|
/// Polls to receive the next signal notification event, outside of an
|
|
399
407
|
/// `async` context.
|
|
400
408
|
///
|
|
401
|
-
///
|
|
409
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
410
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
402
411
|
///
|
|
403
412
|
/// # Examples
|
|
404
413
|
///
|
|
@@ -424,7 +433,7 @@ impl CtrlShutdown {
|
|
|
424
433
|
/// }
|
|
425
434
|
/// ```
|
|
426
435
|
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
|
|
427
|
-
self.inner.poll_recv(cx)
|
|
436
|
+
self.inner.poll_recv(cx).map(Some)
|
|
428
437
|
}
|
|
429
438
|
}
|
|
430
439
|
|
|
@@ -469,7 +478,8 @@ pub struct CtrlLogoff {
|
|
|
469
478
|
impl CtrlLogoff {
|
|
470
479
|
/// Receives the next signal notification event.
|
|
471
480
|
///
|
|
472
|
-
///
|
|
481
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
482
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
473
483
|
///
|
|
474
484
|
/// # Examples
|
|
475
485
|
///
|
|
@@ -489,13 +499,15 @@ impl CtrlLogoff {
|
|
|
489
499
|
/// }
|
|
490
500
|
/// ```
|
|
491
501
|
pub async fn recv(&mut self) -> Option<()> {
|
|
492
|
-
self.inner.recv().await
|
|
502
|
+
self.inner.recv().await;
|
|
503
|
+
Some(())
|
|
493
504
|
}
|
|
494
505
|
|
|
495
506
|
/// Polls to receive the next signal notification event, outside of an
|
|
496
507
|
/// `async` context.
|
|
497
508
|
///
|
|
498
|
-
///
|
|
509
|
+
/// Although this returns `Option<()>`, it will never actually return `None`.
|
|
510
|
+
/// This was accidentally exposed and would be a breaking change to be removed.
|
|
499
511
|
///
|
|
500
512
|
/// # Examples
|
|
501
513
|
///
|
|
@@ -521,6 +533,6 @@ impl CtrlLogoff {
|
|
|
521
533
|
/// }
|
|
522
534
|
/// ```
|
|
523
535
|
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
|
|
524
|
-
self.inner.poll_recv(cx)
|
|
536
|
+
self.inner.poll_recv(cx).map(Some)
|
|
525
537
|
}
|
|
526
538
|
}
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
//!
|
|
30
30
|
//! When all [`Sender`] handles have been dropped, it is no longer
|
|
31
31
|
//! possible to send values into the channel. This is considered the termination
|
|
32
|
-
//! event of the stream.
|
|
32
|
+
//! event of the stream. Once all senders have been dropped and any remaining
|
|
33
|
+
//! buffered values have been received, `Receiver::recv` returns `None`
|
|
34
|
+
//! (and `Receiver::poll_recv` returns `Poll::Ready(None)`).
|
|
33
35
|
//!
|
|
34
36
|
//! If the [`Receiver`] handle is dropped, then messages can no longer
|
|
35
37
|
//! be read out of the channel. In this case, all further attempts to send will
|
|
@@ -1391,6 +1391,19 @@ impl<T> Inner<T> {
|
|
|
1391
1391
|
}
|
|
1392
1392
|
}
|
|
1393
1393
|
|
|
1394
|
+
if prev.is_rx_task_set() && !prev.is_complete() {
|
|
1395
|
+
State::unset_rx_task(&self.state);
|
|
1396
|
+
// SAFETY: The sender only accesses `rx_task` (via
|
|
1397
|
+
// `wake_by_ref`) in `complete()` after successfully setting
|
|
1398
|
+
// `VALUE_SENT`. But `set_complete` will not set `VALUE_SENT`
|
|
1399
|
+
// if `CLOSED` is already set (its CAS loop breaks early).
|
|
1400
|
+
// Since `prev` shows that `VALUE_SENT` was not set before we
|
|
1401
|
+
// set `CLOSED`, the sender can no longer set `VALUE_SENT` and
|
|
1402
|
+
// will never access `rx_task`. Therefore, we have exclusive
|
|
1403
|
+
// access here.
|
|
1404
|
+
unsafe { self.rx_task.drop_task() };
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1394
1407
|
prev
|
|
1395
1408
|
}
|
|
1396
1409
|
|
|
@@ -41,11 +41,10 @@ const MAX_READS: u32 = 10;
|
|
|
41
41
|
/// The priority policy of Tokio's read-write lock is _fair_ (or
|
|
42
42
|
/// [_write-preferring_]), in order to ensure that readers cannot starve
|
|
43
43
|
/// writers. Fairness is ensured using a first-in, first-out queue for the tasks
|
|
44
|
-
/// awaiting the lock;
|
|
45
|
-
///
|
|
46
|
-
///
|
|
47
|
-
///
|
|
48
|
-
/// operating system's implementation.
|
|
44
|
+
/// awaiting the lock; a read lock will not be given out until all write lock
|
|
45
|
+
/// requests that were queued before it have been acquired and released. This is
|
|
46
|
+
/// in contrast to the Rust standard library's `std::sync::RwLock`, where the
|
|
47
|
+
/// priority policy is dependent on the operating system's implementation.
|
|
49
48
|
///
|
|
50
49
|
/// The type parameter `T` represents the data that this lock protects. It is
|
|
51
50
|
/// required that `T` satisfies [`Send`] to be shared across threads. The RAII guards
|
|
@@ -3,6 +3,7 @@ use crate::sync::oneshot;
|
|
|
3
3
|
use loom::future::block_on;
|
|
4
4
|
use loom::thread;
|
|
5
5
|
use std::future::poll_fn;
|
|
6
|
+
use std::pin::Pin;
|
|
6
7
|
use std::task::Poll::{Pending, Ready};
|
|
7
8
|
|
|
8
9
|
#[test]
|
|
@@ -87,7 +88,6 @@ fn recv_closed() {
|
|
|
87
88
|
// TODO: Move this into `oneshot` proper.
|
|
88
89
|
|
|
89
90
|
use std::future::Future;
|
|
90
|
-
use std::pin::Pin;
|
|
91
91
|
use std::task::{Context, Poll};
|
|
92
92
|
|
|
93
93
|
struct OnClose<'a> {
|
|
@@ -185,3 +185,29 @@ fn checking_tx_send_ok_not_drop() {
|
|
|
185
185
|
tx_thread_join_handle.join().unwrap();
|
|
186
186
|
});
|
|
187
187
|
}
|
|
188
|
+
|
|
189
|
+
#[test]
|
|
190
|
+
fn drop_rx_after_poll() {
|
|
191
|
+
// Test that rx_task is properly deallocated when the receiver is dropped
|
|
192
|
+
// after being polled (which sets rx_task), while the sender is concurrently
|
|
193
|
+
// trying to send.
|
|
194
|
+
loom::model(|| {
|
|
195
|
+
let (tx, mut rx) = oneshot::channel::<i32>();
|
|
196
|
+
|
|
197
|
+
// Poll once to set rx_task before entering the parallel part of the
|
|
198
|
+
// test.
|
|
199
|
+
let _ = block_on(poll_fn(|cx| {
|
|
200
|
+
let _ = Pin::new(&mut rx).poll(cx);
|
|
201
|
+
Ready(())
|
|
202
|
+
}));
|
|
203
|
+
|
|
204
|
+
// Drop the receiver concurrently with the sender trying to send.
|
|
205
|
+
let rx_thread = thread::spawn(move || {
|
|
206
|
+
drop(rx);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
let _ = tx.send(1);
|
|
210
|
+
|
|
211
|
+
rx_thread.join().unwrap();
|
|
212
|
+
});
|
|
213
|
+
}
|
|
@@ -96,7 +96,7 @@ cfg_rt! {
|
|
|
96
96
|
/// asynchronously. When you run CPU-bound code using `spawn_blocking`, you
|
|
97
97
|
/// should keep this large upper limit in mind. When running many CPU-bound
|
|
98
98
|
/// computations, a semaphore or some other synchronization primitive should be
|
|
99
|
-
/// used to limit the number of
|
|
99
|
+
/// used to limit the number of computations executed in parallel. Specialized
|
|
100
100
|
/// CPU-bound executors, such as [rayon], may also be a good fit.
|
|
101
101
|
///
|
|
102
102
|
/// This function is intended for non-async operations that eventually finish on
|
|
@@ -119,6 +119,21 @@ cfg_rt! {
|
|
|
119
119
|
/// returns. It is possible for a blocking task to be cancelled if it has
|
|
120
120
|
/// not yet started running, but this is not guaranteed.
|
|
121
121
|
///
|
|
122
|
+
/// # When to use `spawn_blocking` vs dedicated threads
|
|
123
|
+
///
|
|
124
|
+
/// `spawn_blocking` is intended for *bounded* blocking work that eventually finishes.
|
|
125
|
+
/// Each call occupies a thread from the runtime's blocking thread pool for the duration
|
|
126
|
+
/// of the task. Long-lived tasks therefore reduce the pool's effective capacity, which
|
|
127
|
+
/// can delay other blocking operations once the pool is saturated and work is queued.
|
|
128
|
+
///
|
|
129
|
+
/// For workloads that run indefinitely or for extended periods (for example,
|
|
130
|
+
/// background workers or persistent processing loops), prefer a dedicated thread created with
|
|
131
|
+
/// [`thread::spawn`].
|
|
132
|
+
///
|
|
133
|
+
/// As a rule of thumb:
|
|
134
|
+
/// - Use `spawn_blocking` for short-lived blocking operations
|
|
135
|
+
/// - Use dedicated threads for long-lived or persistent blocking workloads
|
|
136
|
+
///
|
|
122
137
|
/// Note that if you are using the single threaded runtime, this function will
|
|
123
138
|
/// still spawn additional threads for blocking operations. The current-thread
|
|
124
139
|
/// scheduler's single thread is only used for asynchronous code.
|
|
@@ -20,7 +20,7 @@ use std::{future::Future, io, mem};
|
|
|
20
20
|
/// the task
|
|
21
21
|
///
|
|
22
22
|
/// There are three types of task that can be spawned from a Builder:
|
|
23
|
-
/// - [`spawn_local`] for executing
|
|
23
|
+
/// - [`spawn_local`] for executing not [`Send`] futures
|
|
24
24
|
/// - [`spawn`] for executing [`Send`] futures on the runtime
|
|
25
25
|
/// - [`spawn_blocking`] for executing blocking code in the
|
|
26
26
|
/// blocking thread pool.
|
|
@@ -118,7 +118,7 @@ impl<'a> Builder<'a> {
|
|
|
118
118
|
})
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
/// Spawns `!Send`
|
|
121
|
+
/// Spawns a `!Send` task on the current [`LocalSet`] or [`LocalRuntime`] with
|
|
122
122
|
/// this builder's settings.
|
|
123
123
|
///
|
|
124
124
|
/// The spawned future will be run on the same thread that called `spawn_local`.
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
//! #### `spawn_blocking`
|
|
181
181
|
//!
|
|
182
182
|
//! The `task::spawn_blocking` function is similar to the `task::spawn` function
|
|
183
|
-
//! discussed in the previous section, but rather than spawning
|
|
183
|
+
//! discussed in the previous section, but rather than spawning a
|
|
184
184
|
//! _non-blocking_ future on the Tokio runtime, it instead spawns a
|
|
185
185
|
//! _blocking_ function on a dedicated thread pool for blocking tasks. For
|
|
186
186
|
//! example:
|
|
@@ -6,16 +6,19 @@ use std::future::Future;
|
|
|
6
6
|
|
|
7
7
|
cfg_rt! {
|
|
8
8
|
/// Spawns a new asynchronous task, returning a
|
|
9
|
-
/// [`JoinHandle`]
|
|
9
|
+
/// [`JoinHandle`] for it.
|
|
10
10
|
///
|
|
11
11
|
/// The provided future will start running in the background immediately
|
|
12
12
|
/// when `spawn` is called, even if you don't await the returned
|
|
13
|
-
/// `JoinHandle
|
|
13
|
+
/// [`JoinHandle`].
|
|
14
14
|
///
|
|
15
15
|
/// Spawning a task enables the task to execute concurrently to other tasks. The
|
|
16
16
|
/// spawned task may execute on the current thread, or it may be sent to a
|
|
17
17
|
/// different thread to be executed. The specifics depend on the current
|
|
18
|
-
/// [`Runtime`](crate::runtime::Runtime) configuration.
|
|
18
|
+
/// [`Runtime`](crate::runtime::Runtime) configuration. In a
|
|
19
|
+
/// [running runtime][running-runtime], the task will start immediately in the
|
|
20
|
+
/// background. On a blocked runtime, the user must drive the runtime forward (for
|
|
21
|
+
/// example, by calling [`Runtime::block_on`](crate::runtime::Runtime::block_on)).
|
|
19
22
|
///
|
|
20
23
|
/// It is guaranteed that spawn will not synchronously poll the task being spawned.
|
|
21
24
|
/// This means that calling spawn while holding a lock does not pose a risk of
|
|
@@ -29,6 +32,8 @@ cfg_rt! {
|
|
|
29
32
|
/// the Tokio runtime are always inside its context, but you can also enter the context
|
|
30
33
|
/// using the [`Runtime::enter`](crate::runtime::Runtime::enter()) method.
|
|
31
34
|
///
|
|
35
|
+
/// [running-runtime]: ../runtime/index.html#driving-the-runtime
|
|
36
|
+
///
|
|
32
37
|
/// # Examples
|
|
33
38
|
///
|
|
34
39
|
/// In this example, a server is started and `spawn` is used to start a new task
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
use crate::runtime::context;
|
|
2
2
|
|
|
3
|
-
use std::future::
|
|
4
|
-
use std::
|
|
5
|
-
use std::task::{ready, Context, Poll};
|
|
3
|
+
use std::future::poll_fn;
|
|
4
|
+
use std::task::{ready, Poll};
|
|
6
5
|
|
|
7
6
|
/// Yields execution back to the Tokio runtime.
|
|
8
7
|
///
|
|
@@ -37,28 +36,19 @@ use std::task::{ready, Context, Poll};
|
|
|
37
36
|
/// [`tokio::select!`]: macro@crate::select
|
|
38
37
|
#[cfg_attr(docsrs, doc(cfg(feature = "rt")))]
|
|
39
38
|
pub async fn yield_now() {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
39
|
+
let mut yielded = false;
|
|
40
|
+
poll_fn(|cx| {
|
|
41
|
+
ready!(crate::trace::trace_leaf(cx));
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
|
|
49
|
-
ready!(crate::trace::trace_leaf(cx));
|
|
50
|
-
|
|
51
|
-
if self.yielded {
|
|
52
|
-
return Poll::Ready(());
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
self.yielded = true;
|
|
43
|
+
if yielded {
|
|
44
|
+
return Poll::Ready(());
|
|
45
|
+
}
|
|
56
46
|
|
|
57
|
-
|
|
47
|
+
yielded = true;
|
|
58
48
|
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
}
|
|
49
|
+
context::defer(cx.waker());
|
|
62
50
|
|
|
63
|
-
|
|
51
|
+
Poll::Pending
|
|
52
|
+
})
|
|
53
|
+
.await
|
|
64
54
|
}
|
|
@@ -124,8 +124,39 @@ cfg_test_util! {
|
|
|
124
124
|
/// other timer-backed primitives can cause the runtime to advance the
|
|
125
125
|
/// current time when awaited.
|
|
126
126
|
///
|
|
127
|
+
/// # Preventing auto-advance
|
|
128
|
+
///
|
|
129
|
+
/// In some testing scenarios, you may want to keep the clock paused without
|
|
130
|
+
/// auto-advancing, even while waiting for I/O or other asynchronous operations.
|
|
131
|
+
/// This can be achieved by using [`spawn_blocking`] to wrap your I/O operations.
|
|
132
|
+
///
|
|
133
|
+
/// When a blocking task is running, the clock's auto-advance is temporarily
|
|
134
|
+
/// inhibited. This allows you to wait for I/O to complete while keeping the
|
|
135
|
+
/// paused clock stationary:
|
|
136
|
+
///
|
|
137
|
+
/// ```ignore
|
|
138
|
+
/// use tokio::time::{Duration, Instant};
|
|
139
|
+
/// use tokio::task;
|
|
140
|
+
///
|
|
141
|
+
/// #[tokio::test(start_paused = true)]
|
|
142
|
+
/// async fn test_with_io() {
|
|
143
|
+
/// let start = Instant::now();
|
|
144
|
+
///
|
|
145
|
+
/// // The clock will NOT auto-advance while this blocking task runs
|
|
146
|
+
/// let result = task::spawn_blocking(|| {
|
|
147
|
+
/// // Perform I/O operations here
|
|
148
|
+
/// std::thread::sleep(std::time::Duration::from_millis(10));
|
|
149
|
+
/// 42
|
|
150
|
+
/// }).await.unwrap();
|
|
151
|
+
///
|
|
152
|
+
/// // Time has not advanced
|
|
153
|
+
/// assert_eq!(start.elapsed(), Duration::ZERO);
|
|
154
|
+
/// }
|
|
155
|
+
/// ```
|
|
156
|
+
///
|
|
127
157
|
/// [`Sleep`]: crate::time::Sleep
|
|
128
158
|
/// [`advance`]: crate::time::advance
|
|
159
|
+
/// [`spawn_blocking`]: crate::task::spawn_blocking
|
|
129
160
|
#[track_caller]
|
|
130
161
|
pub fn pause() {
|
|
131
162
|
with_clock(|maybe_clock| {
|
|
@@ -183,6 +214,37 @@ cfg_test_util! {
|
|
|
183
214
|
/// `advance`. However if they don't, the runtime will poll the task again
|
|
184
215
|
/// shortly.
|
|
185
216
|
///
|
|
217
|
+
/// # When to use `sleep` instead
|
|
218
|
+
///
|
|
219
|
+
/// **Important:** `advance` is designed for testing scenarios where you want to
|
|
220
|
+
/// instantly jump forward in time. However, it has limitations that make it
|
|
221
|
+
/// unsuitable for certain use cases:
|
|
222
|
+
///
|
|
223
|
+
/// - **Forcing timeouts:** If you want to reliably trigger a timeout, prefer
|
|
224
|
+
/// using [`sleep`] with auto-advance rather than `advance`. The `advance`
|
|
225
|
+
/// function jumps time forward but doesn't guarantee that all timers will be
|
|
226
|
+
/// processed before your code continues.
|
|
227
|
+
///
|
|
228
|
+
/// - **Simulating freezes:** If you're trying to simulate a scenario where the
|
|
229
|
+
/// program freezes and then resumes, the batch behavior of `advance` may not
|
|
230
|
+
/// produce the expected results. All timers that expire during the advance
|
|
231
|
+
/// complete simultaneously.
|
|
232
|
+
///
|
|
233
|
+
/// For most testing scenarios where you want to wait for a duration to pass
|
|
234
|
+
/// and have all timers fire in order, use [`sleep`] instead:
|
|
235
|
+
///
|
|
236
|
+
/// ```ignore
|
|
237
|
+
/// use tokio::time::{self, Duration};
|
|
238
|
+
///
|
|
239
|
+
/// #[tokio::test(start_paused = true)]
|
|
240
|
+
/// async fn test_timeout_reliable() {
|
|
241
|
+
/// // Use sleep with auto-advance for reliable timeout testing
|
|
242
|
+
/// time::sleep(Duration::from_secs(5)).await;
|
|
243
|
+
/// // All timers that were scheduled to fire within 5 seconds
|
|
244
|
+
/// // have now been processed in order
|
|
245
|
+
/// }
|
|
246
|
+
/// ```
|
|
247
|
+
///
|
|
186
248
|
/// # Panics
|
|
187
249
|
///
|
|
188
250
|
/// Panics if any of the following conditions are met:
|
|
@@ -4,22 +4,50 @@
|
|
|
4
4
|
//! that we only depend on libc on unix.
|
|
5
5
|
|
|
6
6
|
#[cfg(not(all(unix, feature = "libc")))]
|
|
7
|
-
|
|
7
|
+
fn memchr_inner(needle: u8, haystack: &[u8]) -> Option<usize> {
|
|
8
8
|
haystack.iter().position(|val| needle == *val)
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
#[cfg(all(unix, feature = "libc"))]
|
|
12
|
-
|
|
12
|
+
fn memchr_inner(needle: u8, haystack: &[u8]) -> Option<usize> {
|
|
13
13
|
let start = haystack.as_ptr();
|
|
14
14
|
|
|
15
15
|
// SAFETY: `start` is valid for `haystack.len()` bytes.
|
|
16
|
-
let ptr = unsafe { libc::memchr(start.cast(), needle as _, haystack.len()) }
|
|
16
|
+
let ptr = (unsafe { libc::memchr(start.cast(), needle as _, haystack.len()) })
|
|
17
|
+
.cast::<u8>()
|
|
18
|
+
.cast_const();
|
|
17
19
|
|
|
18
20
|
if ptr.is_null() {
|
|
19
21
|
None
|
|
20
22
|
} else {
|
|
21
|
-
|
|
23
|
+
// SAFETY: `ptr` will always be in bounds, since libc guarantees that the ptr will either
|
|
24
|
+
// be to an element inside the array or the ptr will be null
|
|
25
|
+
// since the ptr is in bounds the offset must also always be non null
|
|
26
|
+
// and there can't be more than isize::MAX elements inside an array
|
|
27
|
+
// as rust guarantees that the maximum number of bytes a allocation
|
|
28
|
+
// may occupy is isize::MAX
|
|
29
|
+
unsafe {
|
|
30
|
+
// TODO(MSRV 1.87): When bumping MSRV, switch to `ptr.byte_offset_from_unsigned(start)`.
|
|
31
|
+
Some(usize::try_from(ptr.offset_from(start)).unwrap_unchecked())
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pub(crate) fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
|
|
37
|
+
let index = memchr_inner(needle, haystack)?;
|
|
38
|
+
|
|
39
|
+
// SAFETY: `memchr_inner` returns Some(index) and in that case index must point to an element in haystack
|
|
40
|
+
// or `memchr_inner` None which is guarded by the `?` operator above
|
|
41
|
+
// therefore the index must **always** point to an element in the array
|
|
42
|
+
// and so this indexing operation is safe
|
|
43
|
+
// TODO(MSRV 1.81): When bumping MSRV, switch to `std::hint::assert_unchecked(haystack.get(..=index).is_some());`
|
|
44
|
+
unsafe {
|
|
45
|
+
if haystack.get(..=index).is_none() {
|
|
46
|
+
std::hint::unreachable_unchecked()
|
|
47
|
+
}
|
|
22
48
|
}
|
|
49
|
+
|
|
50
|
+
Some(index)
|
|
23
51
|
}
|
|
24
52
|
|
|
25
53
|
#[cfg(test)]
|
|
@@ -107,10 +107,12 @@ impl<L: ShardedListItem> ShardedList<L, L::Target> {
|
|
|
107
107
|
self.count.load(Ordering::Relaxed)
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
cfg_unstable_metrics! {
|
|
111
|
+
cfg_64bit_metrics! {
|
|
112
|
+
/// Gets the total number of elements added to this list.
|
|
113
|
+
pub(crate) fn added(&self) -> u64 {
|
|
114
|
+
self.added.load(Ordering::Relaxed)
|
|
115
|
+
}
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
|
|
@@ -60,3 +60,57 @@ async fn test_symlink() {
|
|
|
60
60
|
let symlink_meta = fs::symlink_metadata(dst.clone()).await.unwrap();
|
|
61
61
|
assert!(symlink_meta.file_type().is_symlink());
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
#[tokio::test]
|
|
65
|
+
#[cfg_attr(miri, ignore)] // No `linkat` in miri.
|
|
66
|
+
async fn test_hard_link_error_source_not_found() {
|
|
67
|
+
let dir = tempdir().unwrap();
|
|
68
|
+
let src = dir.path().join("nonexistent.txt");
|
|
69
|
+
let dst = dir.path().join("dst.txt");
|
|
70
|
+
|
|
71
|
+
let err = fs::hard_link(&src, &dst).await.unwrap_err();
|
|
72
|
+
assert_eq!(err.kind(), std::io::ErrorKind::NotFound);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
#[tokio::test]
|
|
76
|
+
#[cfg_attr(miri, ignore)] // No `linkat` in miri.
|
|
77
|
+
async fn test_hard_link_error_destination_already_exists() {
|
|
78
|
+
let dir = tempdir().unwrap();
|
|
79
|
+
let src = dir.path().join("src.txt");
|
|
80
|
+
let dst = dir.path().join("dst.txt");
|
|
81
|
+
|
|
82
|
+
// Create source file
|
|
83
|
+
std::fs::write(&src, b"source content").unwrap();
|
|
84
|
+
|
|
85
|
+
// Create destination file
|
|
86
|
+
std::fs::write(&dst, b"destination content").unwrap();
|
|
87
|
+
|
|
88
|
+
// Attempt to create hard link when destination already exists
|
|
89
|
+
let err = fs::hard_link(&src, &dst).await.unwrap_err();
|
|
90
|
+
assert_eq!(err.kind(), std::io::ErrorKind::AlreadyExists);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#[tokio::test]
|
|
94
|
+
#[cfg_attr(miri, ignore)] // No `linkat` in miri.
|
|
95
|
+
async fn test_hard_link_error_source_is_directory() {
|
|
96
|
+
let dir = tempdir().unwrap();
|
|
97
|
+
let src_dir = dir.path().join("src_directory");
|
|
98
|
+
let dst = dir.path().join("dst.txt");
|
|
99
|
+
|
|
100
|
+
// Create source directory
|
|
101
|
+
fs::create_dir(&src_dir).await.unwrap();
|
|
102
|
+
|
|
103
|
+
// Attempt to create hard link from a directory
|
|
104
|
+
// On most systems, hard linking directories is not allowed
|
|
105
|
+
let err = fs::hard_link(&src_dir, &dst).await.unwrap_err();
|
|
106
|
+
|
|
107
|
+
// Different platforms return different error kinds
|
|
108
|
+
#[cfg(unix)]
|
|
109
|
+
assert!(
|
|
110
|
+
err.kind() == std::io::ErrorKind::PermissionDenied
|
|
111
|
+
|| err.kind() == std::io::ErrorKind::Other
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
#[cfg(windows)]
|
|
115
|
+
assert_eq!(err.kind(), std::io::ErrorKind::PermissionDenied);
|
|
116
|
+
}
|