///|
#borrow(path)
extern "C" fn native_input_open(path : Bytes) -> Int32 = "smithy_input_open"
///|
extern "C" fn native_input_stdin() -> Int32 = "smithy_input_stdin"
///|
#borrow(buffer)
extern "C" fn native_input_read(
fd : Int32,
buffer : Bytes,
size : Int32,
) -> Int32 = "smithy_input_read"
///|
extern "C" fn native_input_close(fd : Int32) -> Bool = "smithy_input_close"
///|
/// Opens `path`, or stdin for "-". Each read gives what the input has now, so
/// a pipe or a FIFO streams as its writer writes.
fn input_source(path : String) -> InputSource raise {
let owned = path != "-"
let name = input_name(path)
guard !path.contains("\u0000") else {
raise CliError("invalid input path", 1)
}
let fd = if owned {
native_input_open(@utf8.encode(path + "\u0000"))
} else {
native_input_stdin()
}
guard fd >= 0 else { raise CliError("could not open \{name}", 1) }
{
read: requested => {
let buffer = Bytes::make(requested, 0)
let count = native_input_read(fd, buffer, requested)
guard count >= 0 && count <= requested else {
raise CliError("could not read \{name}", 1)
}
buffer[:count].to_owned()
},
close: () => {
if owned && !native_input_close(fd) {
raise CliError("could not close \{name}", 1)
}
},
}
}
///|
/// Native reads as data arrives.
fn chunk_source(path : String) -> InputSource raise {
input_source(path)
}