ReadExactlyAsync
Completes an incremental byte transfer by awaiting one short operation at a time. Preserves exact partial error identity/counts, validates reported lengths and adds no intermediate byte buffer or implicit flush. Zero length makes no source operation. Source and byte backing loans remain live until task completion.
Module std.io
import std.io;Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.
ReadExactlyAsync
pub async fn ReadExactlyAsync<S>(Source: mut S&, Output: mut byte[], mut Token: CancellationToken) -> Task<Result<void, IoError>>
where S: AsyncReaderCompletes an incremental byte transfer by awaiting one short operation at a time. Preserves exact partial error identity/counts, validates reported lengths and adds no intermediate byte buffer or implicit flush. Zero length makes no source operation. Source and byte backing loans remain live until task completion. S: Concrete mutable AsyncReader stream. Source: Borrowed mutable stream retained by ordinary origin rules. Output: Borrowed mut bytes retained through completion. Token: Owned cancellation observation copied into each awaited step. Return: Task yielding complete success or exact proven transferred-prefix error. Warning: Do not mutate/move borrowed backing or source while work is pending.
Example
module example.exact_async_io;
from std.io import ReadExactlyAsync, WriteAllAsync, IoError;
from std.prelude import Result;
from std.task import Task, CancellationToken, YieldAsync;
struct Stream {
pub ReadCount: usize; pub WriteCount: usize;
pub init() { this.ReadCount = 0; this.WriteCount = 0; }
pub async fn ReadAsync(Output: mut byte[], mut Token: CancellationToken) -> Task<Result<usize, IoError>> {
if Output.Length == 0 || this.ReadCount == 3 { return .Ok { Value = 0 }; }
switch await YieldAsync(move(Token)) { case .Ok => {} case .Err => return .Err { Error = .Failure { Reason = .Cancelled, Transferred = 0 } }; }
Output[0] = 0x61_byte; this.ReadCount += 1; return .Ok { Value = 1 };
}
pub async fn WriteAsync(Input: readonly byte[], mut Token: CancellationToken) -> Task<Result<usize, IoError>> {
if Input.Length == 0 { return .Ok { Value = 0 }; }
switch await YieldAsync(move(Token)) { case .Ok => {} case .Err => return .Err { Error = .Failure { Reason = .Cancelled, Transferred = 0 } }; }
this.WriteCount += 1; return .Ok { Value = 1 };
}
pub async fn FlushAsync(mut Token: CancellationToken) -> Task<Result<void, IoError>> {
if Token.IsCancellationRequested { return .Err { Error = .Failure { Reason = .Cancelled, Transferred = 0 } }; }
return .Ok;
}
}
async fn Main() -> Task<i32> {
var Source = Stream();
var Bytes: byte[3] = [0_byte, 0_byte, 0_byte];
if await ReadExactlyAsync(Source, Bytes) is .Err { Error = _ } { return 1; }
if await WriteAllAsync(Source, Bytes) is .Err { Error = _ } { return 2; }
if await Source.FlushAsync(CancellationToken()) is .Err { Error = _ } { return 3; }
if Source.ReadCount != 3 || Source.WriteCount != 3 || Bytes[2] != 0x61_byte { return 4; }
return 0;
}ReadExactlyAsync
pub fn ReadExactlyAsync<S>(Source: mut S&, Output: mut byte[]) -> Task<Result<void, IoError>>
where S: AsyncReaderSupplies the omitted arguments to ReadExactlyAsync. Note: Defaults: Token = CancellationToken(). S: Same generic argument and constraints as the full operation. Source: Same input, ownership and lifetime contract as the full operation. Output: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.