From d23ba6e53197137488f08cbb5e60773cd2de2d6b Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Tue, 14 Jan 2025 13:13:40 +0100 Subject: [PATCH 1/7] feat: add `wasi-0.3.0` draft Followed the example of `wasi-http` and `wasi-clocks` duplicating the package in a subdirectory - Remove `would-block` error code - Replace `wasi:io/error.error` usage by `error-context` - Replace `wasi:io/streams.input-stream` return values by `stream` in return position - Replace `wasi:io/streams.output-stream` return values by `stream` in parameter position - Guests should be able to rely on `stream.new` to construct streams - Merge `read{,via-stream}` into a singular `read`. Both functions take an offset as a parameter and since they now return `stream`, callers can limit the amount of bytes read by using the `stream` directly, therefore functionality of both is identical - Merge `write{,via-stream}` into a singular `write`. Both functions take an offset and `stream` as a parameter. It is assumed that `error-context` returned by writes to the stream and reads from the stream are sufficient for error handling. Signed-off-by: Roman Volosatovs --- wit-0.3.0-draft/deps.lock | 4 + wit-0.3.0-draft/deps.toml | 1 + .../deps/clocks/monotonic-clock.wit | 45 ++ wit-0.3.0-draft/deps/clocks/timezone.wit | 55 ++ wit-0.3.0-draft/deps/clocks/wall-clock.wit | 46 ++ wit-0.3.0-draft/deps/clocks/world.wit | 11 + wit-0.3.0-draft/preopens.wit | 11 + wit-0.3.0-draft/types.wit | 636 ++++++++++++++++++ wit-0.3.0-draft/world.wit | 9 + 9 files changed, 818 insertions(+) create mode 100644 wit-0.3.0-draft/deps.lock create mode 100644 wit-0.3.0-draft/deps.toml create mode 100644 wit-0.3.0-draft/deps/clocks/monotonic-clock.wit create mode 100644 wit-0.3.0-draft/deps/clocks/timezone.wit create mode 100644 wit-0.3.0-draft/deps/clocks/wall-clock.wit create mode 100644 wit-0.3.0-draft/deps/clocks/world.wit create mode 100644 wit-0.3.0-draft/preopens.wit create mode 100644 wit-0.3.0-draft/types.wit create mode 100644 wit-0.3.0-draft/world.wit diff --git a/wit-0.3.0-draft/deps.lock b/wit-0.3.0-draft/deps.lock new file mode 100644 index 0000000..20306c6 --- /dev/null +++ b/wit-0.3.0-draft/deps.lock @@ -0,0 +1,4 @@ +[clocks] +url = "https://github.com/WebAssembly/wasi-clocks/archive/main.tar.gz" +sha256 = "26e315db0d371495f8834edfc0e479042f94152ce677d96d54d3623d0e4ffb1e" +sha512 = "e1c76f499435841316f9287b88d8173558e64f277c321ff390556de8707a0b18dd6c1749bbb17bbbba8d523da246ef6eb05c990ceddb762e03efb2ae30cacc76" diff --git a/wit-0.3.0-draft/deps.toml b/wit-0.3.0-draft/deps.toml new file mode 100644 index 0000000..3f6ad6d --- /dev/null +++ b/wit-0.3.0-draft/deps.toml @@ -0,0 +1 @@ +clocks = "https://github.com/WebAssembly/wasi-clocks/archive/main.tar.gz" diff --git a/wit-0.3.0-draft/deps/clocks/monotonic-clock.wit b/wit-0.3.0-draft/deps/clocks/monotonic-clock.wit new file mode 100644 index 0000000..87ebdaa --- /dev/null +++ b/wit-0.3.0-draft/deps/clocks/monotonic-clock.wit @@ -0,0 +1,45 @@ +package wasi:clocks@0.3.0; +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +@since(version = 0.3.0) +interface monotonic-clock { + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + @since(version = 0.3.0) + type instant = u64; + + /// A duration of time, in nanoseconds. + @since(version = 0.3.0) + type duration = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + @since(version = 0.3.0) + now: func() -> instant; + + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + @since(version = 0.3.0) + resolution: func() -> duration; + + /// Wait until the specified instant has occurred. + @since(version = 0.3.0) + wait-until: func( + when: instant, + ); + + /// Wait for the specified duration has elapsed. + @since(version = 0.3.0) + wait-for: func( + how-long: duration, + ); +} diff --git a/wit-0.3.0-draft/deps/clocks/timezone.wit b/wit-0.3.0-draft/deps/clocks/timezone.wit new file mode 100644 index 0000000..ac91468 --- /dev/null +++ b/wit-0.3.0-draft/deps/clocks/timezone.wit @@ -0,0 +1,55 @@ +package wasi:clocks@0.3.0; + +@unstable(feature = clocks-timezone) +interface timezone { + @unstable(feature = clocks-timezone) + use wall-clock.{datetime}; + + /// Return information needed to display the given `datetime`. This includes + /// the UTC offset, the time zone name, and a flag indicating whether + /// daylight saving time is active. + /// + /// If the timezone cannot be determined for the given `datetime`, return a + /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight + /// saving time. + @unstable(feature = clocks-timezone) + display: func(when: datetime) -> timezone-display; + + /// The same as `display`, but only return the UTC offset. + @unstable(feature = clocks-timezone) + utc-offset: func(when: datetime) -> s32; + + /// Information useful for displaying the timezone of a specific `datetime`. + /// + /// This information may vary within a single `timezone` to reflect daylight + /// saving time adjustments. + @unstable(feature = clocks-timezone) + record timezone-display { + /// The number of seconds difference between UTC time and the local + /// time of the timezone. + /// + /// The returned value will always be less than 86400 which is the + /// number of seconds in a day (24*60*60). + /// + /// In implementations that do not expose an actual time zone, this + /// should return 0. + utc-offset: s32, + + /// The abbreviated name of the timezone to display to a user. The name + /// `UTC` indicates Coordinated Universal Time. Otherwise, this should + /// reference local standards for the name of the time zone. + /// + /// In implementations that do not expose an actual time zone, this + /// should be the string `UTC`. + /// + /// In time zones that do not have an applicable name, a formatted + /// representation of the UTC offset may be returned, such as `-04:00`. + name: string, + + /// Whether daylight saving time is active. + /// + /// In implementations that do not expose an actual time zone, this + /// should return false. + in-daylight-saving-time: bool, + } +} diff --git a/wit-0.3.0-draft/deps/clocks/wall-clock.wit b/wit-0.3.0-draft/deps/clocks/wall-clock.wit new file mode 100644 index 0000000..b7a85ab --- /dev/null +++ b/wit-0.3.0-draft/deps/clocks/wall-clock.wit @@ -0,0 +1,46 @@ +package wasi:clocks@0.3.0; +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +@since(version = 0.3.0) +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + @since(version = 0.3.0) + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + @since(version = 0.3.0) + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + @since(version = 0.3.0) + resolution: func() -> datetime; +} diff --git a/wit-0.3.0-draft/deps/clocks/world.wit b/wit-0.3.0-draft/deps/clocks/world.wit new file mode 100644 index 0000000..f97bcfe --- /dev/null +++ b/wit-0.3.0-draft/deps/clocks/world.wit @@ -0,0 +1,11 @@ +package wasi:clocks@0.3.0; + +@since(version = 0.3.0) +world imports { + @since(version = 0.3.0) + import monotonic-clock; + @since(version = 0.3.0) + import wall-clock; + @unstable(feature = clocks-timezone) + import timezone; +} diff --git a/wit-0.3.0-draft/preopens.wit b/wit-0.3.0-draft/preopens.wit new file mode 100644 index 0000000..9cd1021 --- /dev/null +++ b/wit-0.3.0-draft/preopens.wit @@ -0,0 +1,11 @@ +package wasi:filesystem@0.3.0-draft; + +@since(version = 0.2.0) +interface preopens { + @since(version = 0.2.0) + use types.{descriptor}; + + /// Return the set of preopened directories, and their paths. + @since(version = 0.2.0) + get-directories: func() -> list>; +} diff --git a/wit-0.3.0-draft/types.wit b/wit-0.3.0-draft/types.wit new file mode 100644 index 0000000..89d1f47 --- /dev/null +++ b/wit-0.3.0-draft/types.wit @@ -0,0 +1,636 @@ +package wasi:filesystem@0.3.0-draft; +/// WASI filesystem is a filesystem API primarily intended to let users run WASI +/// programs that access their files on their existing filesystems, without +/// significant overhead. +/// +/// It is intended to be roughly portable between Unix-family platforms and +/// Windows, though it does not hide many of the major differences. +/// +/// Paths are passed as interface-type `string`s, meaning they must consist of +/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain +/// paths which are not accessible by this API. +/// +/// The directory separator in WASI is always the forward-slash (`/`). +/// +/// All paths in WASI are relative paths, and are interpreted relative to a +/// `descriptor` referring to a base directory. If a `path` argument to any WASI +/// function starts with `/`, or if any step of resolving a `path`, including +/// `..` and symbolic link steps, reaches a directory outside of the base +/// directory, or reaches a symlink to an absolute or rooted path in the +/// underlying filesystem, the function fails with `error-code::not-permitted`. +/// +/// For more information about WASI path resolution and sandboxing, see +/// [WASI filesystem path resolution]. +/// +/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md +@since(version = 0.2.0) +interface types { + @since(version = 0.2.0) + use wasi:clocks/wall-clock@0.3.0.{datetime}; + + /// File size or length of a region within a file. + @since(version = 0.2.0) + type filesize = u64; + + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + @since(version = 0.2.0) + enum descriptor-type { + /// The type of the descriptor or file is unknown or is different from + /// any of the other types specified. + unknown, + /// The descriptor refers to a block device inode. + block-device, + /// The descriptor refers to a character device inode. + character-device, + /// The descriptor refers to a directory inode. + directory, + /// The descriptor refers to a named pipe. + fifo, + /// The file refers to a symbolic link inode. + symbolic-link, + /// The descriptor refers to a regular file inode. + regular-file, + /// The descriptor refers to a socket. + socket, + } + + /// Descriptor flags. + /// + /// Note: This was called `fdflags` in earlier versions of WASI. + @since(version = 0.2.0) + flags descriptor-flags { + /// Read mode: Data can be read. + read, + /// Write mode: Data can be written to. + write, + /// Request that writes be performed according to synchronized I/O file + /// integrity completion. The data stored in the file and the file's + /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + file-integrity-sync, + /// Request that writes be performed according to synchronized I/O data + /// integrity completion. Only the data stored in the file is + /// synchronized. This is similar to `O_DSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + data-integrity-sync, + /// Requests that reads be performed at the same level of integrity + /// requested for writes. This is similar to `O_RSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + requested-write-sync, + /// Mutating directories mode: Directory contents may be mutated. + /// + /// When this flag is unset on a descriptor, operations using the + /// descriptor which would create, rename, delete, modify the data or + /// metadata of filesystem objects, or obtain another handle which + /// would permit any of those, shall fail with `error-code::read-only` if + /// they would otherwise succeed. + /// + /// This may only be set on directories. + mutate-directory, + } + + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + @since(version = 0.2.0) + record descriptor-stat { + /// File type. + %type: descriptor-type, + /// Number of hard links to the file. + link-count: link-count, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + size: filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + data-access-timestamp: option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + data-modification-timestamp: option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + status-change-timestamp: option, + } + + /// Flags determining the method of how paths are resolved. + @since(version = 0.2.0) + flags path-flags { + /// As long as the resolved path corresponds to a symbolic link, it is + /// expanded. + symlink-follow, + } + + /// Open flags used by `open-at`. + @since(version = 0.2.0) + flags open-flags { + /// Create file if it does not exist, similar to `O_CREAT` in POSIX. + create, + /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + directory, + /// Fail if file already exists, similar to `O_EXCL` in POSIX. + exclusive, + /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. + truncate, + } + + /// Number of hard links to an inode. + @since(version = 0.2.0) + type link-count = u64; + + /// When setting a timestamp, this gives the value to set it to. + @since(version = 0.2.0) + variant new-timestamp { + /// Leave the timestamp set to its previous value. + no-change, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + now, + /// Set the timestamp to the given value. + timestamp(datetime), + } + + /// A directory entry. + record directory-entry { + /// The type of the file referred to by this directory entry. + %type: descriptor-type, + + /// The name of the object. + name: string, + } + + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + enum error-code { + /// Permission denied, similar to `EACCES` in POSIX. + access, + /// Connection already in progress, similar to `EALREADY` in POSIX. + already, + /// Bad descriptor, similar to `EBADF` in POSIX. + bad-descriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + quota, + /// File exists, similar to `EEXIST` in POSIX. + exist, + /// File too large, similar to `EFBIG` in POSIX. + file-too-large, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + illegal-byte-sequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + in-progress, + /// Interrupted function, similar to `EINTR` in POSIX. + interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + invalid, + /// I/O error, similar to `EIO` in POSIX. + io, + /// Is a directory, similar to `EISDIR` in POSIX. + is-directory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + loop, + /// Too many links, similar to `EMLINK` in POSIX. + too-many-links, + /// Message too large, similar to `EMSGSIZE` in POSIX. + message-size, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + name-too-long, + /// No such device, similar to `ENODEV` in POSIX. + no-device, + /// No such file or directory, similar to `ENOENT` in POSIX. + no-entry, + /// No locks available, similar to `ENOLCK` in POSIX. + no-lock, + /// Not enough space, similar to `ENOMEM` in POSIX. + insufficient-memory, + /// No space left on device, similar to `ENOSPC` in POSIX. + insufficient-space, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + not-directory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + not-empty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + not-recoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + no-tty, + /// No such device or address, similar to `ENXIO` in POSIX. + no-such-device, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + not-permitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + read-only, + /// Invalid seek, similar to `ESPIPE` in POSIX. + invalid-seek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + text-file-busy, + /// Cross-device link, similar to `EXDEV` in POSIX. + cross-device, + } + + /// File or memory access pattern advisory information. + @since(version = 0.2.0) + enum advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + sequential, + /// The application expects to access the specified data in a random + /// order. + random, + /// The application expects to access the specified data in the near + /// future. + will-need, + /// The application expects that it will not access the specified data + /// in the near future. + dont-need, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + no-reuse, + } + + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + @since(version = 0.2.0) + record metadata-hash-value { + /// 64 bits of a 128-bit hash value. + lower: u64, + /// Another 64 bits of a 128-bit hash value. + upper: u64, + } + + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + @since(version = 0.2.0) + resource descriptor { + /// Return a stream for reading from a file, if available. + /// + /// May fail with an error-code describing why the file cannot be read. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// Note: This is similar to `pread` in POSIX. + @since(version = 0.3.0) + read: func( + /// The offset within the file at which to start reading. + offset: filesize, + ) -> result, error-code>; + + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// Note: This is similar to `pwrite` in POSIX. + @since(version = 0.3.0) + write: func( + /// Data to write + data: stream, + /// The offset within the file at which to start writing. + offset: filesize, + ) -> result<_, error-code>; + + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// Note: This is similar to `write` with `O_APPEND` in POSIX. + @since(version = 0.3.0) + append: func(data: stream) -> result<_, error-code>; + + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + @since(version = 0.2.0) + advise: func( + /// The offset within the file to which the advisory applies. + offset: filesize, + /// The length of the region to which the advisory applies. + length: filesize, + /// The advice. + advice: advice + ) -> result<_, error-code>; + + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + @since(version = 0.2.0) + sync-data: func() -> result<_, error-code>; + + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + @since(version = 0.2.0) + get-flags: func() -> result; + + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + @since(version = 0.2.0) + get-type: func() -> result; + + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + @since(version = 0.2.0) + set-size: func(size: filesize) -> result<_, error-code>; + + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + @since(version = 0.2.0) + set-times: func( + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + @since(version = 0.2.0) + read-directory: func() -> result; + + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + @since(version = 0.2.0) + sync: func() -> result<_, error-code>; + + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + @since(version = 0.2.0) + create-directory-at: func( + /// The relative path at which to create the directory. + path: string, + ) -> result<_, error-code>; + + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + @since(version = 0.2.0) + stat: func() -> result; + + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + @since(version = 0.2.0) + stat-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + @since(version = 0.2.0) + set-times-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to operate on. + path: string, + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Create a hard link. + /// + /// Note: This is similar to `linkat` in POSIX. + @since(version = 0.2.0) + link-at: func( + /// Flags determining the method of how the path is resolved. + old-path-flags: path-flags, + /// The relative source path from which to link. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path at which to create the hard link. + new-path: string, + ) -> result<_, error-code>; + + /// Open a file or directory. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + @since(version = 0.2.0) + open-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the object to open. + path: string, + /// The method by which to open the file. + open-flags: open-flags, + /// Flags to use for the resulting descriptor. + %flags: descriptor-flags, + ) -> result; + + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + @since(version = 0.2.0) + readlink-at: func( + /// The relative path of the symbolic link from which to read. + path: string, + ) -> result; + + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + @since(version = 0.2.0) + remove-directory-at: func( + /// The relative path to a directory to remove. + path: string, + ) -> result<_, error-code>; + + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + @since(version = 0.2.0) + rename-at: func( + /// The relative source path of the file or directory to rename. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path to which to rename the file or directory. + new-path: string, + ) -> result<_, error-code>; + + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + @since(version = 0.2.0) + symlink-at: func( + /// The contents of the symbolic link. + old-path: string, + /// The relative destination path at which to create the symbolic link. + new-path: string, + ) -> result<_, error-code>; + + /// Unlink a filesystem object that is not a directory. + /// + /// Return `error-code::is-directory` if the path refers to a directory. + /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + @since(version = 0.2.0) + unlink-file-at: func( + /// The relative path to a file to unlink. + path: string, + ) -> result<_, error-code>; + + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + @since(version = 0.2.0) + is-same-object: func(other: borrow) -> bool; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encouraged to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + @since(version = 0.2.0) + metadata-hash: func() -> result; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + @since(version = 0.2.0) + metadata-hash-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + } + + /// A stream of directory entries. + @since(version = 0.2.0) + resource directory-entry-stream { + /// Read a single directory entry from a `directory-entry-stream`. + @since(version = 0.2.0) + read-directory-entry: func() -> result, error-code>; + } + + /// Attempts to extract a filesystem-related `error-code` from the stream + /// `error-context` provided. + /// + /// Stream operations which return `stream-error::last-operation-failed` + /// have a payload with more information about the operation that failed. + /// This payload can be passed through to this function to see if there's + /// filesystem-related information about the error to return. + /// + /// Note that this function is fallible because not all stream-related + /// errors are filesystem-related errors. + @since(version = 0.3.0) + filesystem-error-code: func(err: error-context) -> option; +} diff --git a/wit-0.3.0-draft/world.wit b/wit-0.3.0-draft/world.wit new file mode 100644 index 0000000..891c889 --- /dev/null +++ b/wit-0.3.0-draft/world.wit @@ -0,0 +1,9 @@ +package wasi:filesystem@0.3.0-draft; + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import types; + @since(version = 0.2.0) + import preopens; +} From a7b76d066229887ed768ea7b3209bbb843269b32 Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Tue, 14 Jan 2025 15:19:50 +0100 Subject: [PATCH 2/7] refactor: avoid introspecting `error-context` This seems to be better aligned with latest specification on error context https://github.com/WebAssembly/component-model/blob/cbdd15d9033446558571824af52a78022aaa3f58/design/mvp/Explainer.md#error-context-type > A consequence of this, however, is that components *must not* depend on the > contents of `error-context` values for behavioral correctness. In particular, > case analysis of the contents of an `error-context` should not determine > *error recovery*; explicit `result` or `variant` types must be used in the > function return type instead (e.g., > `(func (result (tuple (stream u8) (future $my-error)))`). Signed-off-by: Roman Volosatovs --- wit-0.3.0-draft/types.wit | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/wit-0.3.0-draft/types.wit b/wit-0.3.0-draft/types.wit index 89d1f47..662a816 100644 --- a/wit-0.3.0-draft/types.wit +++ b/wit-0.3.0-draft/types.wit @@ -299,12 +299,16 @@ interface types { /// Multiple read, write, and append streams may be active on the same open /// file and they do not interfere with each other. /// + /// This function returns a future, which will resolve to an optional error code, + /// if reading full contents of the file fails. + /// The future resolves to `none` once full contents of the file are read successfully. + /// /// Note: This is similar to `pread` in POSIX. @since(version = 0.3.0) read: func( /// The offset within the file at which to start reading. offset: filesize, - ) -> result, error-code>; + ) -> result, future>>, error-code>; /// Return a stream for writing to a file, if available. /// @@ -314,6 +318,10 @@ interface types { /// extent of the write, with bytes between the previous end and the start of /// the write set to zero. /// + /// This function returns a future, which will resolve to an optional error code, + /// if writing full contents of the stream fails. + /// The future resolves to `none` once full contents of the stream are written successfully. + /// /// Note: This is similar to `pwrite` in POSIX. @since(version = 0.3.0) write: func( @@ -321,15 +329,19 @@ interface types { data: stream, /// The offset within the file at which to start writing. offset: filesize, - ) -> result<_, error-code>; + ) -> result>, error-code>; /// Return a stream for appending to a file, if available. /// /// May fail with an error-code describing why the file cannot be appended. /// + /// This function returns a future, which will resolve to an optional error code, + /// if writing full contents of the stream fails. + /// The future resolves to `none` once full contents of the stream are written successfully. + /// /// Note: This is similar to `write` with `O_APPEND` in POSIX. @since(version = 0.3.0) - append: func(data: stream) -> result<_, error-code>; + append: func(data: stream) -> result>, error-code>; /// Provide file advisory information on a descriptor. /// @@ -620,17 +632,4 @@ interface types { @since(version = 0.2.0) read-directory-entry: func() -> result, error-code>; } - - /// Attempts to extract a filesystem-related `error-code` from the stream - /// `error-context` provided. - /// - /// Stream operations which return `stream-error::last-operation-failed` - /// have a payload with more information about the operation that failed. - /// This payload can be passed through to this function to see if there's - /// filesystem-related information about the error to return. - /// - /// Note that this function is fallible because not all stream-related - /// errors are filesystem-related errors. - @since(version = 0.3.0) - filesystem-error-code: func(err: error-context) -> option; } From 81bd8bbf94e840ef22ff57e69088bd390c8ea8c4 Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Tue, 14 Jan 2025 16:24:23 +0100 Subject: [PATCH 3/7] chore: bump `@since` to `0.3.0` https://github.com/WebAssembly/wasi-filesystem/pull/164#discussion_r1914946117 Signed-off-by: Roman Volosatovs --- wit-0.3.0-draft/preopens.wit | 6 +-- wit-0.3.0-draft/types.wit | 74 ++++++++++++++++++------------------ wit-0.3.0-draft/world.wit | 6 +-- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/wit-0.3.0-draft/preopens.wit b/wit-0.3.0-draft/preopens.wit index 9cd1021..00a9b8e 100644 --- a/wit-0.3.0-draft/preopens.wit +++ b/wit-0.3.0-draft/preopens.wit @@ -1,11 +1,11 @@ package wasi:filesystem@0.3.0-draft; -@since(version = 0.2.0) +@since(version = 0.3.0) interface preopens { - @since(version = 0.2.0) + @since(version = 0.3.0) use types.{descriptor}; /// Return the set of preopened directories, and their paths. - @since(version = 0.2.0) + @since(version = 0.3.0) get-directories: func() -> list>; } diff --git a/wit-0.3.0-draft/types.wit b/wit-0.3.0-draft/types.wit index 662a816..b6d9186 100644 --- a/wit-0.3.0-draft/types.wit +++ b/wit-0.3.0-draft/types.wit @@ -23,19 +23,19 @@ package wasi:filesystem@0.3.0-draft; /// [WASI filesystem path resolution]. /// /// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md -@since(version = 0.2.0) +@since(version = 0.3.0) interface types { - @since(version = 0.2.0) + @since(version = 0.3.0) use wasi:clocks/wall-clock@0.3.0.{datetime}; /// File size or length of a region within a file. - @since(version = 0.2.0) + @since(version = 0.3.0) type filesize = u64; /// The type of a filesystem object referenced by a descriptor. /// /// Note: This was called `filetype` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) enum descriptor-type { /// The type of the descriptor or file is unknown or is different from /// any of the other types specified. @@ -59,7 +59,7 @@ interface types { /// Descriptor flags. /// /// Note: This was called `fdflags` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) flags descriptor-flags { /// Read mode: Data can be read. read, @@ -103,7 +103,7 @@ interface types { /// File attributes. /// /// Note: This was called `filestat` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) record descriptor-stat { /// File type. %type: descriptor-type, @@ -130,7 +130,7 @@ interface types { } /// Flags determining the method of how paths are resolved. - @since(version = 0.2.0) + @since(version = 0.3.0) flags path-flags { /// As long as the resolved path corresponds to a symbolic link, it is /// expanded. @@ -138,7 +138,7 @@ interface types { } /// Open flags used by `open-at`. - @since(version = 0.2.0) + @since(version = 0.3.0) flags open-flags { /// Create file if it does not exist, similar to `O_CREAT` in POSIX. create, @@ -151,11 +151,11 @@ interface types { } /// Number of hard links to an inode. - @since(version = 0.2.0) + @since(version = 0.3.0) type link-count = u64; /// When setting a timestamp, this gives the value to set it to. - @since(version = 0.2.0) + @since(version = 0.3.0) variant new-timestamp { /// Leave the timestamp set to its previous value. no-change, @@ -255,7 +255,7 @@ interface types { } /// File or memory access pattern advisory information. - @since(version = 0.2.0) + @since(version = 0.3.0) enum advice { /// The application has no advice to give on its behavior with respect /// to the specified data. @@ -279,7 +279,7 @@ interface types { /// A 128-bit hash value, split into parts because wasm doesn't have a /// 128-bit integer type. - @since(version = 0.2.0) + @since(version = 0.3.0) record metadata-hash-value { /// 64 bits of a 128-bit hash value. lower: u64, @@ -290,7 +290,7 @@ interface types { /// A descriptor is a reference to a filesystem object, which may be a file, /// directory, named pipe, special file, or other object on which filesystem /// calls may be made. - @since(version = 0.2.0) + @since(version = 0.3.0) resource descriptor { /// Return a stream for reading from a file, if available. /// @@ -346,7 +346,7 @@ interface types { /// Provide file advisory information on a descriptor. /// /// This is similar to `posix_fadvise` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) advise: func( /// The offset within the file to which the advisory applies. offset: filesize, @@ -362,7 +362,7 @@ interface types { /// opened for writing. /// /// Note: This is similar to `fdatasync` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) sync-data: func() -> result<_, error-code>; /// Get flags associated with a descriptor. @@ -371,7 +371,7 @@ interface types { /// /// Note: This returns the value that was the `fs_flags` value returned /// from `fdstat_get` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) get-flags: func() -> result; /// Get the dynamic type of a descriptor. @@ -384,14 +384,14 @@ interface types { /// /// Note: This returns the value that was the `fs_filetype` value returned /// from `fdstat_get` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) get-type: func() -> result; /// Adjust the size of an open file. If this increases the file's size, the /// extra bytes are filled with zeros. /// /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) set-size: func(size: filesize) -> result<_, error-code>; /// Adjust the timestamps of an open file or directory. @@ -399,7 +399,7 @@ interface types { /// Note: This is similar to `futimens` in POSIX. /// /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) set-times: func( /// The desired values of the data access timestamp. data-access-timestamp: new-timestamp, @@ -416,7 +416,7 @@ interface types { /// This always returns a new stream which starts at the beginning of the /// directory. Multiple streams may be active on the same directory, and they /// do not interfere with each other. - @since(version = 0.2.0) + @since(version = 0.3.0) read-directory: func() -> result; /// Synchronize the data and metadata of a file to disk. @@ -425,13 +425,13 @@ interface types { /// opened for writing. /// /// Note: This is similar to `fsync` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) sync: func() -> result<_, error-code>; /// Create a directory. /// /// Note: This is similar to `mkdirat` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) create-directory-at: func( /// The relative path at which to create the directory. path: string, @@ -446,7 +446,7 @@ interface types { /// modified, use `metadata-hash`. /// /// Note: This was called `fd_filestat_get` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) stat: func() -> result; /// Return the attributes of a file or directory. @@ -456,7 +456,7 @@ interface types { /// discussion of alternatives. /// /// Note: This was called `path_filestat_get` in earlier versions of WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) stat-at: func( /// Flags determining the method of how the path is resolved. path-flags: path-flags, @@ -470,7 +470,7 @@ interface types { /// /// Note: This was called `path_filestat_set_times` in earlier versions of /// WASI. - @since(version = 0.2.0) + @since(version = 0.3.0) set-times-at: func( /// Flags determining the method of how the path is resolved. path-flags: path-flags, @@ -485,7 +485,7 @@ interface types { /// Create a hard link. /// /// Note: This is similar to `linkat` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) link-at: func( /// Flags determining the method of how the path is resolved. old-path-flags: path-flags, @@ -509,7 +509,7 @@ interface types { /// `error-code::read-only`. /// /// Note: This is similar to `openat` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) open-at: func( /// Flags determining the method of how the path is resolved. path-flags: path-flags, @@ -527,7 +527,7 @@ interface types { /// filesystem, this function fails with `error-code::not-permitted`. /// /// Note: This is similar to `readlinkat` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) readlink-at: func( /// The relative path of the symbolic link from which to read. path: string, @@ -538,7 +538,7 @@ interface types { /// Return `error-code::not-empty` if the directory is not empty. /// /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) remove-directory-at: func( /// The relative path to a directory to remove. path: string, @@ -547,7 +547,7 @@ interface types { /// Rename a filesystem object. /// /// Note: This is similar to `renameat` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) rename-at: func( /// The relative source path of the file or directory to rename. old-path: string, @@ -563,7 +563,7 @@ interface types { /// `error-code::not-permitted`. /// /// Note: This is similar to `symlinkat` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) symlink-at: func( /// The contents of the symbolic link. old-path: string, @@ -575,7 +575,7 @@ interface types { /// /// Return `error-code::is-directory` if the path refers to a directory. /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. - @since(version = 0.2.0) + @since(version = 0.3.0) unlink-file-at: func( /// The relative path to a file to unlink. path: string, @@ -587,7 +587,7 @@ interface types { /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. /// wasi-filesystem does not expose device and inode numbers, so this function /// may be used instead. - @since(version = 0.2.0) + @since(version = 0.3.0) is-same-object: func(other: borrow) -> bool; /// Return a hash of the metadata associated with a filesystem object referred @@ -609,14 +609,14 @@ interface types { /// computed hash. /// /// However, none of these is required. - @since(version = 0.2.0) + @since(version = 0.3.0) metadata-hash: func() -> result; /// Return a hash of the metadata associated with a filesystem object referred /// to by a directory descriptor and a relative path. /// /// This performs the same hash computation as `metadata-hash`. - @since(version = 0.2.0) + @since(version = 0.3.0) metadata-hash-at: func( /// Flags determining the method of how the path is resolved. path-flags: path-flags, @@ -626,10 +626,10 @@ interface types { } /// A stream of directory entries. - @since(version = 0.2.0) + @since(version = 0.3.0) resource directory-entry-stream { /// Read a single directory entry from a `directory-entry-stream`. - @since(version = 0.2.0) + @since(version = 0.3.0) read-directory-entry: func() -> result, error-code>; } } diff --git a/wit-0.3.0-draft/world.wit b/wit-0.3.0-draft/world.wit index 891c889..0960873 100644 --- a/wit-0.3.0-draft/world.wit +++ b/wit-0.3.0-draft/world.wit @@ -1,9 +1,9 @@ package wasi:filesystem@0.3.0-draft; -@since(version = 0.2.0) +@since(version = 0.3.0) world imports { - @since(version = 0.2.0) + @since(version = 0.3.0) import types; - @since(version = 0.2.0) + @since(version = 0.3.0) import preopens; } From b8a2536f8e71fe5d08198a1d5a74f7ab45f3caf7 Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Wed, 15 Jan 2025 11:54:07 +0100 Subject: [PATCH 4/7] refactor(0.3): simplify error handling Signed-off-by: Roman Volosatovs --- wit-0.3.0-draft/types.wit | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/wit-0.3.0-draft/types.wit b/wit-0.3.0-draft/types.wit index b6d9186..3fafe57 100644 --- a/wit-0.3.0-draft/types.wit +++ b/wit-0.3.0-draft/types.wit @@ -292,23 +292,20 @@ interface types { /// calls may be made. @since(version = 0.3.0) resource descriptor { - /// Return a stream for reading from a file, if available. - /// - /// May fail with an error-code describing why the file cannot be read. + /// Return a stream for reading from a file. /// /// Multiple read, write, and append streams may be active on the same open /// file and they do not interfere with each other. /// - /// This function returns a future, which will resolve to an optional error code, - /// if reading full contents of the file fails. - /// The future resolves to `none` once full contents of the file are read successfully. + /// This function returns a future, which will resolve to an error code if + /// reading full contents of the file fails. /// /// Note: This is similar to `pread` in POSIX. @since(version = 0.3.0) - read: func( + read-via-stream: func( /// The offset within the file at which to start reading. offset: filesize, - ) -> result, future>>, error-code>; + ) -> tuple, future>>; /// Return a stream for writing to a file, if available. /// @@ -318,30 +315,28 @@ interface types { /// extent of the write, with bytes between the previous end and the start of /// the write set to zero. /// - /// This function returns a future, which will resolve to an optional error code, - /// if writing full contents of the stream fails. - /// The future resolves to `none` once full contents of the stream are written successfully. + /// This function returns once either full contents of the stream are + /// written or an error is encountered. /// /// Note: This is similar to `pwrite` in POSIX. @since(version = 0.3.0) - write: func( + write-via-stream: func( /// Data to write data: stream, /// The offset within the file at which to start writing. offset: filesize, - ) -> result>, error-code>; + ) -> result<_, error-code>; /// Return a stream for appending to a file, if available. /// /// May fail with an error-code describing why the file cannot be appended. /// - /// This function returns a future, which will resolve to an optional error code, - /// if writing full contents of the stream fails. - /// The future resolves to `none` once full contents of the stream are written successfully. + /// This function returns once either full contents of the stream are + /// written or an error is encountered. /// /// Note: This is similar to `write` with `O_APPEND` in POSIX. @since(version = 0.3.0) - append: func(data: stream) -> result>, error-code>; + append-via-stream: func(data: stream) -> result<_, error-code>; /// Provide file advisory information on a descriptor. /// From 8e315f4d10e07090ca3c03af03252371a12811c2 Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Wed, 15 Jan 2025 11:58:57 +0100 Subject: [PATCH 5/7] refactor(0.3): asyncify `read-directory` Signed-off-by: Roman Volosatovs --- wit-0.3.0-draft/types.wit | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/wit-0.3.0-draft/types.wit b/wit-0.3.0-draft/types.wit index 3fafe57..05b02fb 100644 --- a/wit-0.3.0-draft/types.wit +++ b/wit-0.3.0-draft/types.wit @@ -411,8 +411,11 @@ interface types { /// This always returns a new stream which starts at the beginning of the /// directory. Multiple streams may be active on the same directory, and they /// do not interfere with each other. + /// + /// This function returns a future, which will resolve to an error code if + /// reading full contents of the directory fails. @since(version = 0.3.0) - read-directory: func() -> result; + read-directory: func() -> tuple, future>>; /// Synchronize the data and metadata of a file to disk. /// @@ -619,12 +622,4 @@ interface types { path: string, ) -> result; } - - /// A stream of directory entries. - @since(version = 0.3.0) - resource directory-entry-stream { - /// Read a single directory entry from a `directory-entry-stream`. - @since(version = 0.3.0) - read-directory-entry: func() -> result, error-code>; - } } From 70fa400184bb3a4fe735d21bfe64b9e2c87885a2 Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Thu, 16 Jan 2025 18:44:31 +0100 Subject: [PATCH 6/7] feat: update wit-deps to 0.5.0 Signed-off-by: Roman Volosatovs --- .github/workflows/main.yml | 4 +++- wit-0.3.0-draft/deps.lock | 1 + wit-0.3.0-draft/deps.toml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d42ff77..db3a344 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,10 +13,12 @@ jobs: - uses: actions/checkout@v4 - name: ensure `./wit/deps` are in sync run: | - curl -Lo 'wit-deps' https://github.com/bytecodealliance/wit-deps/releases/download/v0.3.3/wit-deps-x86_64-unknown-linux-musl + curl -Lo 'wit-deps' https://github.com/bytecodealliance/wit-deps/releases/download/v0.5.0/wit-deps-x86_64-unknown-linux-musl chmod +x wit-deps ./wit-deps lock + ./wit-deps -m wit-0.3.0-draft/deps.toml -l wit-0.3.0-draft/deps.lock -d wit-0.3.0-draft/deps lock git add -N wit/deps + git add -N wit-0.3.0-draft/deps git diff --exit-code - uses: WebAssembly/wit-abi-up-to-date@v22 with: diff --git a/wit-0.3.0-draft/deps.lock b/wit-0.3.0-draft/deps.lock index 20306c6..0386808 100644 --- a/wit-0.3.0-draft/deps.lock +++ b/wit-0.3.0-draft/deps.lock @@ -1,4 +1,5 @@ [clocks] url = "https://github.com/WebAssembly/wasi-clocks/archive/main.tar.gz" +subdir = "wit-0.3.0-draft" sha256 = "26e315db0d371495f8834edfc0e479042f94152ce677d96d54d3623d0e4ffb1e" sha512 = "e1c76f499435841316f9287b88d8173558e64f277c321ff390556de8707a0b18dd6c1749bbb17bbbba8d523da246ef6eb05c990ceddb762e03efb2ae30cacc76" diff --git a/wit-0.3.0-draft/deps.toml b/wit-0.3.0-draft/deps.toml index 3f6ad6d..e004547 100644 --- a/wit-0.3.0-draft/deps.toml +++ b/wit-0.3.0-draft/deps.toml @@ -1 +1 @@ -clocks = "https://github.com/WebAssembly/wasi-clocks/archive/main.tar.gz" +clocks = { url = "https://github.com/WebAssembly/wasi-clocks/archive/main.tar.gz", subdir = "wit-0.3.0-draft" } From 44b42cdf648e32482a7167ed182265be9623a7c3 Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Fri, 17 Jan 2025 10:51:53 +0100 Subject: [PATCH 7/7] drop `-draft` version suffix This ensures that e.g.: ``` wit-bindgen markdown wit-0.3.0-draft -w imports --html-in-md ``` works with wit-bindgen 0.37 refs: https://github.com/WebAssembly/wasi-sockets/commit/3abda6e0bccd1743fa0736c94e5fbb3ec2fb0eaf refs: https://github.com/WebAssembly/wasi-sockets/pull/111#issuecomment-2596214201 Signed-off-by: Roman Volosatovs --- wit-0.3.0-draft/preopens.wit | 2 +- wit-0.3.0-draft/types.wit | 2 +- wit-0.3.0-draft/world.wit | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wit-0.3.0-draft/preopens.wit b/wit-0.3.0-draft/preopens.wit index 00a9b8e..0b29aae 100644 --- a/wit-0.3.0-draft/preopens.wit +++ b/wit-0.3.0-draft/preopens.wit @@ -1,4 +1,4 @@ -package wasi:filesystem@0.3.0-draft; +package wasi:filesystem@0.3.0; @since(version = 0.3.0) interface preopens { diff --git a/wit-0.3.0-draft/types.wit b/wit-0.3.0-draft/types.wit index 05b02fb..ba91568 100644 --- a/wit-0.3.0-draft/types.wit +++ b/wit-0.3.0-draft/types.wit @@ -1,4 +1,4 @@ -package wasi:filesystem@0.3.0-draft; +package wasi:filesystem@0.3.0; /// WASI filesystem is a filesystem API primarily intended to let users run WASI /// programs that access their files on their existing filesystems, without /// significant overhead. diff --git a/wit-0.3.0-draft/world.wit b/wit-0.3.0-draft/world.wit index 0960873..c0ab32a 100644 --- a/wit-0.3.0-draft/world.wit +++ b/wit-0.3.0-draft/world.wit @@ -1,4 +1,4 @@ -package wasi:filesystem@0.3.0-draft; +package wasi:filesystem@0.3.0; @since(version = 0.3.0) world imports {