/*---------------------------------------------------------------------------
  Copyright 2020-2026, Microsoft Research, Daan Leijen.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the LICENSE file at the root of this distribution.
---------------------------------------------------------------------------*/


/* Asynchronous file operations.

   Currently, this is only supported for the C (with libuv) and NodeJS (`jsnode`) targets.
*/
module async/os/filestd/async/os/file

import std/core/undivstd/core/undiv
import std/num/int32std/num/int32
import std/num/int64std/num/int64
import std/os/pathstd/os/path

import async/asyncasync/async
import async/channelasync/channel
import async/interleaveasync/interleave

import async/api/fileasync/api/uv/file 
  [host=libc|jsnode] async/api/uv/fileasync/api/uv/file  // we only support libuv or nodejs

//-----------------------------------
// path based api (prefixed with `file-`)
//-----------------------------------

// Read the full contents of a file.
pub fun file-read-textstd/async/os/file/file-read-text: (fpath : path) -> <async,exn,fsys,ndet> string( fpathfpath: path : pathstd/os/path/path: V )result: -> <async,exn,fsys,ndet> string : <std/core/types/total: Endetstd/core/types/ndet: X,fsysstd/core/fsys: X,exnstd/core/exn/exn: (E, V) -> V,asyncstd/async/async/async: E> stringstd/core/types/string: V
  withwith: (fd : fd) -> <async,exn,fsys,ndet> string fdfd: fd = fd-openstd/async/os/file/scoped/fd-open: (fpath : path, fmode : filemode, action : (fd : fd) -> <async,exn,fsys,ndet> string) -> <async,exn,fsys,ndet> string(fpathfpath: path, Readstd/async/os/file/Read: filemode)
  fdfd: fd.fd-read-all-textstd/async/os/file/fd-read-all-text: (fd : fd, chunk-len : ? int) -> <async,exn,fsys,ndet> string()

// Emit the full contents of a file to a string channel.
// Tries to read in chunks of `chunk-len` (=-1)
pub fun file-read-text-to-channelstd/async/os/file/file-read-text-to-channel: (fpath : path, ch : channel<string>, chunk-len : ? int) -> <async,exn,fsys,ndet> ()( fpathfpath: path : pathstd/os/path/path: V, chch: channel<string> : channelstd/async/channel/channel: V -> V<stringstd/core/types/string: V>, chunk-lenchunk-len: ? int : intstd/core/types/int: V = -1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
)result: -> <async,exn,fsys,ndet> () : <std/core/types/total: Endetstd/core/types/ndet: X,fsysstd/core/fsys: X,exnstd/core/exn/exn: (E, V) -> V,asyncstd/async/async/async: E> (std/core/types/unit: V)std/core/types/unit: V withwith: (fd : fd) -> <async,exn,fsys,ndet> () fdfd: fd = fd-openstd/async/os/file/scoped/fd-open: (fpath : path, fmode : filemode, action : (fd : fd) -> <async,exn,fsys,ndet> ()) -> <async,exn,fsys,ndet> ()(fpathfpath: path, Readstd/async/os/file/Read: filemode) fdfd: fd.fd-read-text-to-channelstd/async/os/file/fd-read-text-to-channel: (fd : fd, ch : channel<string>, chunk-len : ? int) -> <async,exn,fsys,ndet> ()(chch: channel<string>,chunk-lenchunk-len: int
) // Emit the full contents of a file to a bytes channel. // Tries to read in chunks of `chunk-len` (=-1) pub fun file-read-to-channelstd/async/os/file/file-read-to-channel: (fpath : path, ch : channel<bytes>, chunk-len : ? int) -> <async,exn,fsys,ndet> ()( fpathfpath: path : pathstd/os/path/path: V, chch: channel<bytes> : channelstd/async/channel/channel: V -> V<bytesstd/core/types/bytes: V>, chunk-lenchunk-len: ? int : intstd/core/types/int: V = -1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
)result: -> <async,exn,fsys,ndet> () : <std/core/types/total: Endetstd/core/types/ndet: X,fsysstd/core/fsys: X,exnstd/core/exn/exn: (E, V) -> V,asyncstd/async/async/async: E> (std/core/types/unit: V)std/core/types/unit: V withwith: (fd : fd) -> <async,exn,fsys,ndet> () fdfd: fd = fd-openstd/async/os/file/scoped/fd-open: (fpath : path, fmode : filemode, action : (fd : fd) -> <async,exn,fsys,ndet> ()) -> <async,exn,fsys,ndet> ()(fpathfpath: path, Readstd/async/os/file/Read: filemode) fdfd: fd.fd-read-to-channelstd/async/os/file/fd-read-to-channel: (fd : fd, ch : channel<bytes>, chunk-len : ? int) -> <async,exn,fsys,ndet> ()(chch: channel<bytes>,chunk-lenchunk-len: int
) //----------------------------------- // more primitive file descriptor based api (prefixed with `fd-`) //----------------------------------- // The mode that a (non-seeking) file is opened in. pub type filemodestd/async/os/file/filemode: V // Open for reading, fails if the file does not exist ("r") Readstd/async/os/file/Read: filemode // Open for writing; truncates an existing file, or creates the file if it does not yet exist ("w") Writestd/async/os/file/Write: filemode // Append writes to the end of the file; creates the file if it does not yet exist ("a") Appendstd/async/os/file/Append: filemode // Open for reading and writing; truncates an existing file, or creates the file if it does not yet exist ("w+") ReadWritestd/async/os/file/ReadWrite: filemode abstract struct fdstd/async/os/file/fd: V( fdstd/async/os/file/fd/fd: (fd : fd) -> ssize_t : ssize_tstd/core/types/ssize_t: V, fpathstd/async/os/file/fd/fpath: (fd : fd) -> path : pathstd/os/path/path: V ) pub fun fd/showstd/async/os/file/fd/show: (fd) -> string( Fdstd/async/os/file/Fd: (fd : ssize_t, fpath : path) -> fd(fdfd: ssize_t,fpathfpath: path) : fdstd/async/os/file/fd: V )result: -> total string : stringstd/core/types/string: V fpathfpath: path.showstd/os/path/show: (p : path) -> string ++std/core/types/(++): (x : string, y : string) -> string "(="literal: string
count= 2
++std/core/types/(++): (x : string, y : string) -> string fdfd: ssize_t.intstd/core/int/ssize_t/int: (i : ssize_t) -> int.showstd/core/int/show: (i : int) -> string ++std/core/types/(++): (x : string, y : string) -> string ")"literal: string
count= 1
fun filemode/flagsstd/async/os/file/filemode/flags: (fmode : filemode) -> int32( fmodefmode: filemode : filemodestd/async/os/file/filemode: V )result: -> total int32 : int32std/core/types/int32: V val mm: int = match fmodefmode: filemode Readstd/async/os/file/Read: filemode -> 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
Writestd/async/os/file/Write: filemode -> 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
Appendstd/async/os/file/Append: filemode -> 2literal: int
dec = 2
hex8 = 0x02
bit8 = 0b00000010
ReadWritestd/async/os/file/ReadWrite: filemode -> 3literal: int
dec = 3
hex8 = 0x03
bit8 = 0b00000011
fd-flags-from-filemodestd/async/api/uv/file/fd-flags-from-filemode: (fmode : int32) -> int32(mm: int.int32std/num/int32/int32: (i : int) -> int32
) // Open a file descriptor for a given `path` and file mode `fmode`. pub fun fd-openstd/async/os/file/fd-open: (fpath : path, fmode : filemode) -> <async,exn,fsys> fd( fpathfpath: path : pathstd/os/path/path: V, fmodefmode: filemode : filemodestd/async/os/file/filemode: V )result: -> <async,exn,fsys> fd : <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,fsysstd/core/fsys: X,asyncstd/async/async/async: E> fdstd/async/os/file/fd: V withwith: () -> <async,exn,fsys> fd try-exn-prependstd/core/exn/try-exn-prepend: (pre : string, action : () -> <async,exn,fsys> fd) -> <async,exn,fsys> fd("open "literal: string
count= 5
++std/core/types/(++): (x : string, y : string) -> <async,exn,fsys> string fpathfpath: path.showstd/os/path/show: (p : path) -> <async,exn,fsys> string) Fdstd/async/os/file/Fd: (fd : ssize_t, fpath : path) -> fd(awaitstd/async/async/setup/await: (label : ? string, setup : (evloop : event-loop, resume : (error<ssize_t>) -> ioc ()) -> ioc error<dispose-fn>) -> <async,exn,fsys> ssize_t("fd-open"literal: string
count= 7
, fnfn: (evloop : event-loop, resume : (error<ssize_t>) -> ioc ()) -> ioc error<() -> ioc ()>(evloopevloop: event-loop,resumeresume: (error<ssize_t>) -> ioc ()) fd-open-setupstd/async/api/uv/file/fd-open-setup: (evloop : any, fpath : string, flags : int32, mode : int32, cb : (error<ssize_t>) -> ioc ()) -> ioc error<() -> ioc ()>(evloopevloop: event-loop,fpathfpath: path.stringstd/os/path/string: (p : path) -> ioc string,fmodefmode: filemode.flagsstd/async/os/file/filemode/flags: (fmode : filemode) -> ioc int32,0x666literal: int
dec = 1638
hex16= 0x0666
bit16= 0b0000011001100110
.int32std/num/int32/int32: (i : int) -> ioc int32,resumeresume: (error<ssize_t>) -> ioc ())),fpathfpath: path
) // Close a file descriptor. pub fun fd-closestd/async/os/file/fd-close: (fd) -> <async,exn,fsys> ()( Fdstd/async/os/file/Fd: (fd : ssize_t, fpath : path) -> fd(fdfd: ssize_t) : fdstd/async/os/file/fd: V )result: -> <async,exn,fsys> () : <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,fsysstd/core/fsys: X,asyncstd/async/async/async: E> (std/core/types/unit: V)std/core/types/unit: V awaitstd/async/async/setup/await: (label : ? string, setup : (evloop : event-loop, resume : (error<ssize_t>) -> ioc ()) -> ioc error<dispose-fn>) -> <async,exn,fsys> ssize_t("fd-close"literal: string
count= 8
, fnfn: (evloop : event-loop, resume : (error<ssize_t>) -> ioc ()) -> ioc error<() -> ioc ()>(evloopevloop: event-loop,resumeresume: (error<ssize_t>) -> ioc ()) fd-close-setupstd/async/api/uv/file/fd-close-setup: (evloop : any, fd : ssize_t, cb : (error<ssize_t>) -> ioc ()) -> ioc error<() -> ioc ()>(evloopevloop: event-loop,fdfd: ssize_t,resumeresume: (error<ssize_t>) -> ioc ())) (std/core/types/Unit: ()
)std/core/types/Unit: () // Open a file descriptor for a given `path` and file mode `fmode` and pass it to `action`. // Closes the file descriptor when `action` returns or finalizes. pub fun scoped/fd-openstd/async/os/file/scoped/fd-open: forall<a,e> (fpath : path, fmode : filemode, action : (fd : fd) -> <async,exn,fsys|e> a) -> <async,exn,fsys|e> a( fpathfpath: path : pathstd/os/path/path: V, fmodefmode: filemode : filemodestd/async/os/file/filemode: V, actionaction: (fd : fd) -> <async,exn,fsys|$504> $503 : ( fd : fdstd/async/os/file/fd: V ) -> <exnstd/core/exn/exn: (E, V) -> V,fsysstd/core/fsys: X,asyncstd/async/async/async: E|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V )result: -> <exn,fsys,async|541> 540 : <exnstd/core/exn/exn: (E, V) -> V,fsysstd/core/fsys: X,asyncstd/async/async/async: E|std/core/types/effect-extend: (X, E) -> Eee: E> aa: V val fdfd: fd = fd-openstd/async/os/file/fd-open: (fpath : path, fmode : filemode) -> <async,exn,fsys|$504> fd(fpathfpath: path,fmodefmode: filemode) withwith: () -> <async,exn,fsys|$504> $503 finallystd/core/hnd/finally: (fin : () -> <async,exn,fsys|$504> (), action : () -> <async,exn,fsys|$504> $503) -> <async,exn,fsys|$504> $503 fd-closestd/async/os/file/fd-close: (fd) -> <async,exn,fsys|$504> ()(fdfd: fd) actionaction: (fd : fd) -> <async,exn,fsys|$504> $503(fdfd: fd) pub fun fd-readstd/async/os/file/fd-read: (fd, chunk-len : ? int) -> <async,exn,ndet> bytes( Fdstd/async/os/file/Fd: (fd : ssize_t, fpath : path) -> fd(fdfd: ssize_t,fpathfpath: path) : fdstd/async/os/file/fd: V, chunk-lenchunk-len: ? int : intstd/core/types/int: V = -1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
)result: -> <async,exn,ndet> bytes : <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,ndetstd/core/types/ndet: X,asyncstd/async/async/async: E> bytesstd/core/types/bytes: V withwith: () -> <async,exn,ndet> bytes try-exn-prependstd/core/exn/try-exn-prepend: (pre : string, action : () -> <async,exn,ndet> bytes) -> <async,exn,ndet> bytes("read "literal: string
count= 5
++std/core/types/(++): (x : string, y : string) -> <async,exn,ndet> string fpathfpath: path.showstd/os/path/show: (p : path) -> <async,exn,ndet> string) val lenlen: int = if (chunk-lenchunk-len: int <std/core/int/(<): (x : int, y : int) -> <async,exn,ndet> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
||std/core/types/(||): (x : bool, y : bool) -> <async,exn,ndet> bool chunk-lenchunk-len: int >std/core/int/(>): (x : int, y : int) -> <async,exn,ndet> bool 64000literal: int
dec = 64000
hex32= 0x0000FA00
bit32= 0b00000000000000001111101000000000
) then 64000literal: int
dec = 64000
hex32= 0x0000FA00
bit32= 0b00000000000000001111101000000000
else chunk-lenchunk-len: int if (lenlen: int==std/core/int/(==): (x : int, y : int) -> <async,exn,ndet> bool0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
) then emptystd/core/bytes/empty: bytes else val bufbuf: bytes = unsafe-bytesstd/core/bytes/unsafe-bytes: (len : int) -> <async,exn,ndet> bytes(lenlen: int) val readread: ssize_t = awaitstd/async/async/setup/await: (label : ? string, setup : (evloop : event-loop, resume : (error<ssize_t>) -> ioc ()) -> ioc error<dispose-fn>) -> <async,exn,ndet> ssize_t("fd-read"literal: string
count= 7
, fnfn: (evloop : event-loop, resume : (error<ssize_t>) -> ioc ()) -> ioc error<() -> ioc ()>(evloopevloop: event-loop,resumeresume: (error<ssize_t>) -> ioc ()) fd-read-setupstd/async/api/uv/file/fd-read-setup: (evloop : any, fd : ssize_t, buf : bytes, offset : int64, cb : (error<ssize_t>) -> ioc ()) -> ioc error<() -> ioc ()>(evloopevloop: event-loop,fdfd: ssize_t,bufbuf: bytes,(-1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
).int64std/num/int64/int64: (i : int) -> ioc int64,resumeresume: (error<ssize_t>) -> ioc ())) bufbuf: bytes.adjust-lengthstd/core/bytes/adjust-length: (bs : bytes, newlen : int) -> <async,exn,ndet> bytes(readread: ssize_t.intstd/core/int/ssize_t/int: (i : ssize_t) -> <async,exn,ndet> int
) // note: we must refer to `buf` here to keep it alive during the async operation! // Read the full contents of a file handle. pub fun fd-read-allstd/async/os/file/fd-read-all: (fd : fd, chunk-len : ? int) -> <async,exn,ndet> bytes( fdfd: fd : fdstd/async/os/file/fd: V, chunk-lenchunk-len: ? int : intstd/core/types/int: V = -1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
)result: -> <async,exn,ndet> bytes : <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,ndetstd/core/types/ndet: X,asyncstd/async/async/async: E> bytesstd/core/types/bytes: V fun read-allread-all: (()) -> <async,exn,ndet> list<bytes>((std/core/types/Unit: ())std/core/types/Unit: ())result: -> <async-await,async-cancel,async-ioc,discontinue,exn,ndet> list<bytes> val bsbs: bytes = fd-readstd/async/os/file/fd-read: (fd, chunk-len : ? int) -> <async,exn,ndet> bytes(fdfd: fd,chunk-lenchunk-len: int) if bsbs: bytes.is-emptystd/core/bytes/is-empty: (bs : bytes) -> <async,exn,ndet> bool then [std/core/types/Nil: forall<a> list<a>]std/core/types/Nil: forall<a> list<a> else Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(bsbs: bytes,read-allread-all: (()) -> <async,exn,ndet> list<bytes>(pretend-decreasingstd/core/undiv/pretend-decreasing: (x : ()) -> <async,exn,ndet> ()((std/core/types/Unit: ())std/core/types/Unit: ()))) // a file cannot be infinite so no divergence read-allread-all: (()) -> <async,exn,ndet> list<bytes>((std/core/types/Unit: ())std/core/types/Unit: ()).joinstd/core/bytes/list/join: (bss : list<bytes>) -> <async,exn,ndet> bytes
// Read the full contents of a file handles as a string. pub fun fd-read-all-textstd/async/os/file/fd-read-all-text: (fd : fd, chunk-len : ? int) -> <async,exn,ndet> string( fdfd: fd : fdstd/async/os/file/fd: V, chunk-lenchunk-len: ? int : intstd/core/types/int: V = -1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
)result: -> <async,exn,ndet> string : <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,ndetstd/core/types/ndet: X,asyncstd/async/async/async: E> stringstd/core/types/string: V fd-read-allstd/async/os/file/fd-read-all: (fd : fd, chunk-len : ? int) -> <async,exn,ndet> bytes(fdfd: fd,chunk-lenchunk-len: int).stringstd/core/bytes/string: (bytes : bytes) -> <async,exn,ndet> string
// Read the contents of a file handle to a channel in chunks of `chunk-len` (=64 KiB) when possible. // Emits a final empty `:bytes` on end-of-file. // Note: do not convert byte chunks to a string directly since the may start/end with a partial // utf-8 sequence -- use `fd-read-text-to-channel` instead in such case. pub fun fd-read-to-channelstd/async/os/file/fd-read-to-channel: (fd : fd, ch : channel<bytes>, chunk-len : ? int) -> <async,exn,ndet> ()( fdfd: fd : fdstd/async/os/file/fd: V, chch: channel<bytes> : channelstd/async/channel/channel: V -> V<bytesstd/core/types/bytes: V>, chunk-lenchunk-len: ? int : intstd/core/types/int: V = -1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
)result: -> <async,exn,ndet> () : <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,ndetstd/core/types/ndet: X,asyncstd/async/async/async: E> (std/core/types/unit: V)std/core/types/unit: V fun emit-allemit-all: (()) -> <async,exn,ndet> ()((std/core/types/Unit: ())std/core/types/Unit: ())result: -> <async-await,async-cancel,async-ioc,discontinue,exn,ndet> () val bsbs: bytes = fd-readstd/async/os/file/fd-read: (fd, chunk-len : ? int) -> <async,exn,ndet> bytes(fdfd: fd,chunk-lenchunk-len: int) val eofeof: bool = bsbs: bytes.is-emptystd/core/bytes/is-empty: (bs : bytes) -> <async,exn,ndet> bool chch: channel<bytes>.schedule-emitstd/async/channel/schedule-emit: (ch : channel<bytes>, value : bytes) -> <async,exn,ndet> ()(bsbs: bytes) // continue directly with the next read request if eofeof: bool then (std/core/types/Unit: ())std/core/types/Unit: () else emit-allemit-all: (()) -> <async,exn,ndet> ()(pretend-decreasingstd/core/undiv/pretend-decreasing: (x : ()) -> <async,exn,ndet> ()((std/core/types/Unit: ())std/core/types/Unit: ())) // a file cannot be infinite so no divergence emit-allemit-all: (()) -> <async,exn,ndet> ()((std/core/types/Unit: ())std/core/types/Unit: ()
) // Read the contents of a file handle to a channel as string fragments (of about the `chunk-len` (=64 KiB)). // Emits a final empty string on end-of-file. // Correctly handles partial utf-8 sequences. pub fun fd-read-text-to-channelstd/async/os/file/fd-read-text-to-channel: (fd : fd, ch : channel<string>, chunk-len : ? int) -> <async,exn,ndet> ()( fdfd: fd : fdstd/async/os/file/fd: V, chch: channel<string> : channelstd/async/channel/channel: V -> V<stringstd/core/types/string: V>, chunk-lenchunk-len: ? int : intstd/core/types/int: V = -1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
)result: -> <async,exn,ndet> () : <std/core/types/total: Eexnstd/core/exn/exn: (E, V) -> V,ndetstd/core/types/ndet: X,asyncstd/async/async/async: E> (std/core/types/unit: V)std/core/types/unit: V fun emit-allemit-all: (previous-post : bytes) -> <async,exn,ndet> ()( previous-postprevious-post: bytes : bytesstd/core/types/bytes: V )result: -> <async-await,async-cancel,async-ioc,discontinue,exn,ndet> () : __w-l138-c43: E (std/core/types/unit: V)std/core/types/unit: V val bsbs: bytes = fd-readstd/async/os/file/fd-read: (fd, chunk-len : ? int) -> <async,exn,ndet> bytes(fdfd: fd,chunk-lenchunk-len: int) val eofeof: bool = bsbs: bytes.is-emptystd/core/bytes/is-empty: (bs : bytes) -> <async,exn,ndet> bool if eofeof: bool then if !std/core/types/bool/(!): (b : bool) -> <async,exn,ndet> boolprevious-postprevious-post: bytes.is-emptystd/core/bytes/is-empty: (bs : bytes) -> <async,exn,ndet> bool() then chch: channel<string>.schedule-emitstd/async/channel/schedule-emit: (ch : channel<string>, value : string) -> <async,exn,ndet> ()(previous-postprevious-post: bytes.stringstd/core/bytes/string: (bytes : bytes) -> <async,exn,ndet> string)std/core/types/Unit: () chch: channel<string>.schedule-emitstd/async/channel/schedule-emit: (ch : channel<string>, value : string) -> <async,exn,ndet> ()(""literal: string
count= 0
) else val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)fullfull: string,postpost: bytes)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = bsbs: bytes.partial-stringstd/core/bytes/partial-string: (b : bytes, previous-post : ? bytes) -> <async,exn,ndet> (string, bytes)(previous-postprevious-post: bytes) if !std/core/types/bool/(!): (b : bool) -> <async,exn,ndet> boolfullfull: string.is-emptystd/core/string/is-empty: (s : string) -> <async,exn,ndet> bool() then chch: channel<string>.schedule-emitstd/async/channel/schedule-emit: (ch : channel<string>, value : string) -> <async,exn,ndet> ()(fullfull: string)std/core/types/Unit: () emit-allemit-all: (previous-post : bytes) -> <async,exn,ndet> ()( pretend-decreasingstd/core/undiv/pretend-decreasing: (x : bytes) -> <async,exn,ndet> bytes(postpost: bytes)
) // a file cannot be infinite so no divergence emit-allemit-all: (previous-post : bytes) -> <async,exn,ndet> ()(emptystd/core/bytes/empty: bytes
) //----------------------------------- // Test //----------------------------------- fun test-readstd/async/os/file/test-read: () -> <async,console,exn,fsys,ndet> ()()result: -> <async,console,exn,fsys,ndet> () withwith: (fd : fd) -> <async,console,exn,fsys,ndet> () fdfd: fd = fd-openstd/async/os/file/scoped/fd-open: (fpath : path, fmode : filemode, action : (fd : fd) -> <async,console,exn,fsys,ndet> ()) -> <async,console,exn,fsys,ndet> ()("readme.md"literal: string
count= 9
.pathstd/os/path/path: (s : string) -> <async,console,exn,fsys,ndet> path, Readstd/async/os/file/Read: filemode) printlnstd/core/console/string/println: (s : string) -> <async,console,exn,fsys,ndet> ()("opened"literal: string
count= 6
) val bsbs: bytes = fd-read-allstd/async/os/file/fd-read-all: (fd : fd, chunk-len : ? int) -> <async,console,exn,fsys,ndet> bytes(fdfd: fd,16literal: int
dec = 16
hex8 = 0x10
bit8 = 0b00010000
) printlnstd/core/console/string/println: (s : string) -> <async,console,exn,fsys,ndet> ()("read: "literal: string
count= 6
++std/core/types/(++): (x : string, y : string) -> <async,console,exn,fsys,ndet> string bsbs: bytes.stringstd/core/bytes/string: (bytes : bytes) -> <async,console,exn,fsys,ndet> string) printlnstd/core/console/string/println: (s : string) -> <async,console,exn,fsys,ndet> ()("done"literal: string
count= 4
) fun test-channelstd/async/os/file/test-channel: () -> <pure,async,console,fsys,ndet> ()()result: -> <pure,async,console,fsys,ndet> () val chch: channel<bytes> = channelstd/async/channel/channel: () -> <pure,async,console,fsys,ndet> channel<bytes>() interleavedstd/async/interleave/two/interleaved: (action1 : () -> <pure,async,console,fsys,ndet> (), action2 : () -> <pure,async,console,fsys,ndet> ()) -> <pure,async,console,fsys,ndet> ((), ()) { withwith: (fd : fd) -> <pure,async,console,fsys,ndet> () fdfd: fd = fd-openstd/async/os/file/scoped/fd-open: (fpath : path, fmode : filemode, action : (fd : fd) -> <pure,async,console,fsys,ndet> ()) -> <pure,async,console,fsys,ndet> ()("readme.md"literal: string
count= 9
.pathstd/os/path/path: (s : string) -> <pure,async,console,fsys,ndet> path, Readstd/async/os/file/Read: filemode) printlnstd/core/console/string/println: (s : string) -> <pure,async,console,fsys,ndet> ()("opened"literal: string
count= 6
) fd-read-to-channelstd/async/os/file/fd-read-to-channel: (fd : fd, ch : channel<bytes>, chunk-len : ? int) -> <pure,async,console,fsys,ndet> ()(fdfd: fd,chch: channel<bytes>,16literal: int
dec = 16
hex8 = 0x10
bit8 = 0b00010000
) printlnstd/core/console/string/println: (s : string) -> <pure,async,console,fsys,ndet> ()("done reading"literal: string
count= 12
) } { fun recvrecv: () -> <async,console,div,ndet> ()()result: -> <console,async-await,async-cancel,async-ioc,discontinue,ndet,div> () val bsbs: bytes = chch: channel<bytes>.receivestd/async/channel/receive: (ch : channel<bytes>) -> <async,console,div,ndet> bytes printlnstd/core/console/string/println: (s : string) -> <async,console,div,ndet> ()("recv: "literal: string
count= 6
++std/core/types/(++): (x : string, y : string) -> <async,console,div,ndet> string bsbs: bytes.showstd/core/bytes/show: (bytes : bytes) -> <async,console,div,ndet> string ) // println("recv: " ++ s.count.show ++ ": " ++ s) if !std/core/types/bool/(!): (b : bool) -> <async,console,div,ndet> boolbsbs: bytes.is-emptystd/core/bytes/is-empty: (bs : bytes) -> <async,console,div,ndet> bool then recvrecv: () -> <async,console,div,ndet> ()(
)std/core/types/Unit: () recvrecv: () -> <pure,async,console,fsys,ndet> ()() printlnstd/core/console/string/println: (s : string) -> <pure,async,console,fsys,ndet> ()("done receiving"literal: string
count= 14
) } printlnstd/core/console/string/println: (s : string) -> <pure,async,console,fsys,ndet> ()("program done."literal: string
count= 13
)