hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 817e5c0d2bbc5fa608d2a77914e634b323c4443e
parent 71293168373230f176f164931d60b40dacc634dc
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri,  1 Apr 2022 14:11:18 +0200

io: add readv, writev

Implements: https://todo.sr.ht/~sircmpwn/hare/319
Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Aio/+freebsd/vector.ha | 41+++++++++++++++++++++++++++++++++++++++++
Aio/+linux/vector.ha | 41+++++++++++++++++++++++++++++++++++++++++
Mrt/+freebsd/syscalls.ha | 10++++++++++
Mrt/+linux/syscalls.ha | 8++++----
Mscripts/gen-stdlib | 2++
Mstdlib.mk | 4++++
6 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/io/+freebsd/vector.ha b/io/+freebsd/vector.ha @@ -0,0 +1,41 @@ +// License: MPL-2.0 +// (c) 2021 Drew DeVault <sir@cmpwn.com> +use errors; +use rt; + +export type vector = rt::iovec; + +// Creates a vector for use with [[writev]] and [[readv]]. +export fn mkvector(buf: []u8) vector = vector { + iov_base = buf: *[*]u8, + iov_len = len(buf), +}; + +// Performs a vectored read on the given file. A read is performed on each of +// the vectors, prepared with [[mkvector]], in order, and the total number of +// bytes read is returned. Note that an under-read is considered an error. +export fn readv(fd: file, vectors: vector...) (size | EOF | error) = { + match (rt::readv(fd, vectors: *[*]rt::iovec, len(vectors): int)) { + case let err: rt::errno => + return errors::errno(err); + case let n: size => + switch (n) { + case 0 => + return EOF; + case => + return n; + }; + }; +}; + +// Performs a vectored write on the given file. Each of the vectors, prepared +// with [[mkvector]], are written to the file in order, and the total number of +// bytes written is returned. Note that an under-write is considered an error. +export fn writev(fd: file, vectors: vector...) (size | error) = { + match (rt::writev(fd, vectors: *[*]rt::iovec, len(vectors): int)) { + case let err: rt::errno => + return errors::errno(err); + case let n: size => + return n; + }; +}; diff --git a/io/+linux/vector.ha b/io/+linux/vector.ha @@ -0,0 +1,41 @@ +// License: MPL-2.0 +// (c) 2021 Drew DeVault <sir@cmpwn.com> +use errors; +use rt; + +export type vector = rt::iovec; + +// Creates a vector for use with [[writev]] and [[readv]]. +export fn mkvector(buf: []u8) vector = vector { + iov_base = buf: *[*]u8, + iov_len = len(buf), +}; + +// Performs a vectored read on the given file. A read is performed on each of +// the vectors, prepared with [[mkvector]], in order, and the total number of +// bytes read is returned. Note that an under-read is considered an error. +export fn readv(fd: file, vectors: vector...) (size | EOF | error) = { + match (rt::readv(fd, vectors: *[*]rt::iovec, len(vectors): int)) { + case let err: rt::errno => + return errors::errno(err); + case let n: size => + switch (n) { + case 0 => + return EOF; + case => + return n; + }; + }; +}; + +// Performs a vectored write on the given file. Each of the vectors, prepared +// with [[mkvector]], are written to the file in order, and the total number of +// bytes written is returned. Note that an under-write is considered an error. +export fn writev(fd: file, vectors: vector...) (size | error) = { + match (rt::writev(fd, vectors: *[*]rt::iovec, len(vectors): int)) { + case let err: rt::errno => + return errors::errno(err); + case let n: size => + return n; + }; +}; diff --git a/rt/+freebsd/syscalls.ha b/rt/+freebsd/syscalls.ha @@ -53,6 +53,16 @@ export fn write(fd: int, buf: *const void, count: size) (size | errno) = { fd: u64, buf: uintptr: u64, count: u64))?: size; }; +export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = { + return wrap_return(syscall3(SYS_readv, + fd: u64, iov: uintptr: u64, iovcnt: u64))?: size; +}; + +export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = { + return wrap_return(syscall3(SYS_writev, + fd: u64, iov: uintptr: u64, iovcnt: u64))?: size; +}; + export fn close(fd: int) (void | errno) = { wrap_return(syscall1(SYS_close, fd: u64))?; }; diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha @@ -628,14 +628,14 @@ export fn getpeername(sockfd: int, addr: nullable *sockaddr, addrlen: nullable * sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int; }; -export fn readv(fd: int, iov: *const iovec, iovcnt: int) (int | errno) = { +export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = { return wrap_return(syscall3(SYS_readv, - fd: u64, iov: uintptr: u64, iovcnt: u64))?: int; + fd: u64, iov: uintptr: u64, iovcnt: u64))?: size; }; -export fn writev(fd: int, iov: *const iovec, iovcnt: int) (int | errno) = { +export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = { return wrap_return(syscall3(SYS_writev, - fd: u64, iov: uintptr: u64, iovcnt: u64))?: int; + fd: u64, iov: uintptr: u64, iovcnt: u64))?: size; }; export fn sendmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = { diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -709,6 +709,7 @@ gensrcs_io() { println+linux.ha \ +linux/file.ha \ +linux/mmap.ha \ + +linux/vector.ha \ copy.ha \ drain.ha \ empty.ha \ @@ -725,6 +726,7 @@ gensrcs_io() { println+freebsd.ha \ +freebsd/file.ha \ +freebsd/mmap.ha \ + +freebsd/vector.ha \ copy.ha \ drain.ha \ empty.ha \ diff --git a/stdlib.mk b/stdlib.mk @@ -1222,6 +1222,7 @@ stdlib_io_linux_srcs= \ $(STDLIB)/io/println+linux.ha \ $(STDLIB)/io/+linux/file.ha \ $(STDLIB)/io/+linux/mmap.ha \ + $(STDLIB)/io/+linux/vector.ha \ $(STDLIB)/io/copy.ha \ $(STDLIB)/io/drain.ha \ $(STDLIB)/io/empty.ha \ @@ -1239,6 +1240,7 @@ stdlib_io_freebsd_srcs= \ $(STDLIB)/io/println+freebsd.ha \ $(STDLIB)/io/+freebsd/file.ha \ $(STDLIB)/io/+freebsd/mmap.ha \ + $(STDLIB)/io/+freebsd/vector.ha \ $(STDLIB)/io/copy.ha \ $(STDLIB)/io/drain.ha \ $(STDLIB)/io/empty.ha \ @@ -3114,6 +3116,7 @@ testlib_io_linux_srcs= \ $(STDLIB)/io/println+linux.ha \ $(STDLIB)/io/+linux/file.ha \ $(STDLIB)/io/+linux/mmap.ha \ + $(STDLIB)/io/+linux/vector.ha \ $(STDLIB)/io/copy.ha \ $(STDLIB)/io/drain.ha \ $(STDLIB)/io/empty.ha \ @@ -3134,6 +3137,7 @@ testlib_io_freebsd_srcs= \ $(STDLIB)/io/println+freebsd.ha \ $(STDLIB)/io/+freebsd/file.ha \ $(STDLIB)/io/+freebsd/mmap.ha \ + $(STDLIB)/io/+freebsd/vector.ha \ $(STDLIB)/io/copy.ha \ $(STDLIB)/io/drain.ha \ $(STDLIB)/io/empty.ha \