handle.ha (2286B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 // TODO: Examine the ABI constraints of [[handle]]. Would it be better to make 5 // stream an integer representing an internal handle into a stream table? This 6 // would reduce performance for streams somewhat via the indirect lookup, but 7 // improve the ABI performance for files. 8 9 // An I/O handle is a resource which I/O operations may be performed on. It is 10 // either a [[stream]], which is a userspace I/O abstraction, or a [[file]], 11 // which is backed by a resource on the host OS, such as a file descriptor. 12 export type handle = (file | *stream); 13 14 // Reads up to len(buf) bytes from a [[handle]] into the given buffer, returning 15 // the number of bytes read. 16 export fn read(h: handle, buf: []u8) (size | EOF | error) = { 17 match (h) { 18 case let fd: file => 19 return fd_read(fd, buf); 20 case let st: *stream => 21 return st_read(st, buf); 22 }; 23 }; 24 25 // Writes up to len(buf) bytes to the [[handle]] from the given buffer, 26 // returning the number of bytes written. 27 export fn write(h: handle, buf: const []u8) (size | error) = { 28 match (h) { 29 case let fd: file => 30 return fd_write(fd, buf); 31 case let st: *stream => 32 return st_write(st, buf); 33 case => 34 abort(); 35 }; 36 }; 37 38 // Closes a [[handle]]. No further operations against this handle are permitted 39 // after calling this function. Closing a file handle can fail only under 40 // certain conditions (for example, closing a file twice, or an interrupted 41 // syscall). However, the user should not attempt to close the file again on 42 // failure - at best the user should print a diagnostic message and move on. See 43 // close(2) for details. 44 export fn close(h: handle) (void | error) = { 45 match (h) { 46 case let fd: file => 47 fd_close(fd)?; 48 case let st: *stream => 49 st_close(st)?; 50 }; 51 }; 52 53 // Sets the offset within a [[handle]], returning the new offset. The new offset 54 // is obtained by adding [[off]] to the position specified by [[whence]]. 55 export fn seek(h: handle, off: off, w: whence) (off | error) = { 56 match (h) { 57 case let fd: file => 58 return fd_seek(fd, off, w); 59 case let st: *stream => 60 return st_seek(st, off, w); 61 }; 62 }; 63 64 // Returns the current offset within a [[handle]]. 65 export fn tell(h: handle) (off | error) = { 66 return seek(h, 0, whence::CUR); 67 };