RunProcessWithStreams
Runs an explicit command with borrowed reader/writer stream adapters. Feeds stdin while draining stdout/stderr; selected adapters override standard stream inheritance. Handles short writes without implicit flush or allocation per chunk. Original IoError survives with its channel and partial prefix.
Module std.process
import std.process;Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.
RunProcess
pub fn RunProcess<I, O, E>(Command: readonly ProcessCommand&, Input: mut I&, Output: mut O&, Errors: mut E&, Limit: Timeout, Token: CancellationToken) -> Result<ProcessExit, ProcessStreamError>
where I: Reader where O: Writer where E: WriterRuns an explicit command with borrowed reader/writer stream adapters. Feeds stdin while draining stdout/stderr; selected adapters override standard stream inheritance. Handles short writes without implicit flush or allocation per chunk. Original IoError survives with its channel and partial prefix. I: Concrete mutable input Reader. O: Concrete mutable output Writer. E: Concrete mutable stderr Writer. Command: Explicit command backing, borrowed unmodified through return. Input: Exclusive stdin source; zero successful read means EOF. Output: Exclusive stdout sink; prior delivered bytes survive failure. Errors: Exclusive stderr sink, independent of stdout. Limit: Native execution allowance; callback bodies cannot be preempted. Token: Owned cooperative cancellation observation. Return: Detached child outcome or exact native/channel failure after cleanup. Warning: May allocate/spawn/block. Adapters must return promptly for responsive cancellation and must not wait for another channel in this same operation. No stream view or callback backing escapes; caller retains stream ownership.
Example
module example.process_streams;
from std.process import Arguments, Environment, ProgramInputs, ProcessCommand, RunProcess, ProcessError, ProcessStreamError;
from std.fs import Path;
from std.text import NativeString;
from std.prelude import Result;
from std.io import IoError;
from std.time import Timeout, Seconds;
struct InputStream {
pub Count: usize;
pub init() { this.Count = 0; }
pub fn Read(Output: mut byte[]) -> Result<usize, IoError> {
if this.Count == 3 || Output.Length == 0 { return .Ok { Value = 0 }; }
Output[0] = (0x61_u8 + (this.Count as u8)) as byte;
this.Count += 1; return .Ok { Value = 1 };
}
}
struct OutputStream {
pub Bytes: byte[8]; pub Count: usize; pub Fail: bool;
pub init() { this.Bytes = default(byte[8]); this.Count = 0; this.Fail = false; }
pub fn Write(Input: readonly byte[]) -> Result<usize, IoError> {
if Input.Length == 0 { return .Ok { Value = 0 }; }
if this.Fail && this.Count == 1 { return .Err { Error = .Failure { Reason = .Interrupted, Transferred = 0 } }; }
if this.Count == 8 { return .Err { Error = .OutputFailed }; }
this.Bytes[this.Count] = Input[0]; this.Count += 1; return .Ok { Value = 1 };
}
pub fn Flush() -> Result<void, IoError> { return .Ok; }
}
fn CreateCommand() -> Result<ProcessCommand, ProcessError> {
var Executable = {
// Scoped writable carriers end immediately after explicit payload transfer.
var ExecutableCreation = Path.TryCreate("/bin/sh");
switch ExecutableCreation {
case .Ok { Value = Value: mut Path& } => break move(Value);
case .Err => return .Err { Error = ProcessError { Reason = .OutOfMemory, NativeCode = 0 } };
}
};
var Directory = {
var DirectoryCreation = Path.TryCreate("/");
switch DirectoryCreation {
case .Ok { Value = Value: mut Path& } => break move(Value);
case .Err => return .Err { Error = ProcessError { Reason = .OutOfMemory, NativeCode = 0 } };
}
};
var Values = Arguments();
let CommandArguments: str[3] = ["/bin/sh", "-c", "printf err >&2; /bin/cat; exit 7"];
for Text in CommandArguments {
var Argument = {
var ValueCreation = NativeString.TryCreate(Text);
switch ValueCreation {
case .Ok { Value = Value: mut NativeString& } => break move(Value);
case .Err => return .Err { Error = ProcessError { Reason = .OutOfMemory, NativeCode = 0 } };
}
};
if Values.TryPush(move(Argument)) is .Err { Error = _ } { return .Err { Error = ProcessError { Reason = .OutOfMemory, NativeCode = 0 } }; }
}
return .Ok { Value = ProcessCommand(move(Executable), move(Directory), ProgramInputs(move(Values), Environment())) };
}
fn Main() -> i32 {
// Explicit Linux shell/cat prerequisites; no ambient environment is copied.
var Command = {
var CommandCreation = CreateCommand();
switch CommandCreation {
case .Ok { Value = Value: mut ProcessCommand& } => break move(Value);
case .Err => return 1;
}
};
let Limit = switch Timeout.TryFromDuration(Seconds.Create(2)) { case .Ok { Value = Value } => break Value; case .Err => return 2; };
var Input = InputStream(); var Output = OutputStream(); var Errors = OutputStream();
switch RunProcess(Command, Input, Output, Errors, Limit) {
case .Ok { Value = PatternPayload5138 } => {
switch PatternPayload5138 {
case .Exited { Code = PatternPayload5139 } if (PatternPayload5139 == 7) => {}
default => return 3;
}
}
default => return 3;
}
if Input.Count != 3 || Output.Count != 3 || Errors.Count != 3 { return 4; }
if Output.Bytes[0] != 0x61_byte || Output.Bytes[2] != 0x63_byte || Errors.Bytes[0] != 0x65_byte { return 5; }
Input.Count = 0; Output.Count = 0; Output.Fail = true; Errors.Count = 0;
switch RunProcess(Command, Input, Output, Errors, Limit) {
case .Err { Error = PatternPayload5140 } => {
switch PatternPayload5140 {
case .Output { Error = PatternPayload5141 } => {
switch PatternPayload5141 {
case .Failure { Reason = PatternPayload5142, Transferred = Count } if (PatternPayload5142 is .Interrupted) => {
if Count > 1 || Output.Count != 1 { return 6; }
}
default => return 7;
}
}
default => return 7;
}
}
default => return 7;
}
return 0;
}RunProcess
pub fn RunProcess<I, O, E>(Command: readonly ProcessCommand&, Input: mut I&, Output: mut O&, Errors: mut E&) -> Result<ProcessExit, ProcessStreamError>
where I: Reader where O: Writer where E: WriterSupplies the omitted arguments to RunProcess. Note: Defaults: Limit = .Endless, Token = CancellationToken(). I: Same generic argument and constraints as the full operation. O: Same generic argument and constraints as the full operation. E: Same generic argument and constraints as the full operation. Command: Same input, ownership and lifetime contract as the full operation. Input: Same input, ownership and lifetime contract as the full operation. Output: Same input, ownership and lifetime contract as the full operation. Errors: Same input, ownership and lifetime contract as the full operation. Return: The full synchronous operation's value or typed failure.
RunProcess
pub fn RunProcess<I, O, E>(Command: readonly ProcessCommand&, Input: mut I&, Output: mut O&, Errors: mut E&, mut Limit: Timeout) -> Result<ProcessExit, ProcessStreamError>
where I: Reader where O: Writer where E: WriterSupplies the omitted arguments to RunProcess. Note: Defaults: Token = CancellationToken(). I: Same generic argument and constraints as the full operation. O: Same generic argument and constraints as the full operation. E: Same generic argument and constraints as the full operation. Command: Same input, ownership and lifetime contract as the full operation. Input: Same input, ownership and lifetime contract as the full operation. Output: Same input, ownership and lifetime contract as the full operation. Errors: Same input, ownership and lifetime contract as the full operation. Limit: Same input, ownership and lifetime contract as the full operation. Return: The full synchronous operation's value or typed failure.