Skip to main content

base_scheduler/
pipe_writer.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use crate::{Cancellation, OperationResult};
5use std::{
6    future::Future,
7    io::{self, IoSlice},
8};
9
10/// Sequential, non-positional output to an adopted pipe, bound to its creating scheduler and owning its descriptor.
11///
12/// Each operation performs one possibly partial transfer in pipe order; the unwritten suffix remains the caller's responsibility. Borrowed storage is accessed only synchronously within each poll, so dropping or forgetting a pending future leaves no backend access to it. Cancellation ends the current wait without rolling back transferred bytes; successful progress wins concurrent cancellation.
13///
14/// Writing after every read end has closed fails with `BrokenPipe` (`EPIPE`). The process must ignore `SIGPIPE`, as Rust executables do by default, for that error to be observable instead of terminating the process.
15pub trait PipeWriter: Send {
16    /// Make one possibly partial borrowed transfer. An empty buffer completes with zero after checking that the handle is open and cancellation has not been requested.
17    fn write(
18        &mut self,
19        buffer: &[u8],
20        cancellation: &Cancellation,
21    ) -> impl Future<Output = OperationResult<usize>> + Send;
22
23    /// Gather one possibly partial transfer from borrowed ranges. Short progress does not advance the caller's slices.
24    fn write_vectored(
25        &mut self,
26        buffers: &[IoSlice<'_>],
27        cancellation: &Cancellation,
28    ) -> impl Future<Output = OperationResult<usize>> + Send;
29
30    /// Stop output, retire backend registration and close the descriptor, reporting the close result. There is no buffered output to flush. Readers observe end of file once no other write ends remain. Later operations fail with `BrokenPipe`; repeating `close` succeeds without further effect. Dropping the writer also closes the descriptor, without awaiting retirement. Unlike socket and file handles, a pipe handle owns its descriptor. After backend shutdown, `close` can report the shutdown error; the descriptor is closed regardless.
31    fn close(&mut self) -> impl Future<Output = io::Result<()>> + Send;
32}