123 lines
2.3 KiB
Plaintext
123 lines
2.3 KiB
Plaintext
c :: import "@ffi/c"
|
|
|
|
ReadError :: enum {
|
|
read_failed
|
|
}
|
|
|
|
WriteError :: enum {
|
|
write_failed
|
|
no_progress
|
|
}
|
|
|
|
Io :: struct {
|
|
context ?*mut anyopaque
|
|
vtable @IoVTable
|
|
}
|
|
|
|
IoVTable :: struct {
|
|
read @func(context ?*mut anyopaque, stream ReadStream, buffer []mut u8) usize ! ReadError
|
|
write @func(context ?*mut anyopaque, stream WriteStream, bytes []u8) usize ! WriteError
|
|
}
|
|
|
|
ReadStream :: enum(c_int) {
|
|
stdin = 0
|
|
}
|
|
|
|
WriteStream :: enum(c_int) {
|
|
stdout = 1
|
|
stderr = 2
|
|
}
|
|
|
|
Reader :: struct {
|
|
impl Io
|
|
stream ReadStream
|
|
}
|
|
|
|
Writer :: struct {
|
|
impl Io
|
|
stream WriteStream
|
|
}
|
|
|
|
read func(reader Reader, buffer []mut u8) usize ! ReadError {
|
|
if buffer.len == 0 {
|
|
return 0
|
|
}
|
|
count usize :: try reader.impl.vtable.read(reader.impl.context, reader.stream, buffer)
|
|
if count > buffer.len {
|
|
return .read_failed
|
|
}
|
|
return count
|
|
}
|
|
|
|
write func(writer Writer, bytes []u8) usize ! WriteError {
|
|
if bytes.len == 0 {
|
|
return 0
|
|
}
|
|
count usize :: try writer.impl.vtable.write(writer.impl.context, writer.stream, bytes)
|
|
if count > bytes.len {
|
|
return .write_failed
|
|
}
|
|
return count
|
|
}
|
|
|
|
write_all func(writer Writer, bytes []u8) void ! WriteError {
|
|
offset usize = 0
|
|
while offset < bytes.len {
|
|
count usize :: write(writer, bytes[offset..]) catch |err| {
|
|
return err
|
|
}
|
|
if count == 0 {
|
|
return .no_progress
|
|
}
|
|
offset += count
|
|
}
|
|
return
|
|
}
|
|
|
|
_system_read func(_ ?*mut anyopaque, stream ReadStream, buffer []mut u8) usize ! ReadError {
|
|
request usize = buffer.len
|
|
maximum usize :: usize(max_value(c_long))
|
|
if request > maximum {
|
|
request = maximum
|
|
}
|
|
while true {
|
|
count c_long :: c.read(c_int(stream), buffer.ptr, c_ulong(request))
|
|
if count >= 0 {
|
|
return usize(count)
|
|
}
|
|
if c.__error()^ != 4 {
|
|
return .read_failed
|
|
}
|
|
}
|
|
}
|
|
|
|
_system_write func(_ ?*mut anyopaque, stream WriteStream, bytes []u8) usize ! WriteError {
|
|
fd c_int :: c_int(stream)
|
|
request usize = bytes.len
|
|
maximum usize :: usize(max_value(c_long))
|
|
if request > maximum {
|
|
request = maximum
|
|
}
|
|
while true {
|
|
count c_long :: c.write(fd, bytes.ptr, c_ulong(request))
|
|
if count >= 0 {
|
|
return usize(count)
|
|
}
|
|
if c.__error()^ != 4 {
|
|
return .write_failed
|
|
}
|
|
}
|
|
}
|
|
|
|
_system_vtable IoVTable :: IoVTable {
|
|
read = _system_read,
|
|
write = _system_write,
|
|
}
|
|
|
|
_system func() Io {
|
|
return Io {
|
|
context = none,
|
|
vtable = &_system_vtable,
|
|
}
|
|
}
|