export module coral.files; import coral; export namespace coral { /** * Platform-generalized identifier for a resource in a [file_store]. */ struct path { /** * Maximum path length. */ static usize const max = u8_max; /** * Common path component separator. */ static char const seperator = '/'; constexpr path() : buffer{0} { this->buffer[max] = max; } template constexpr path(char const(&text)[text_size]) : path{} { static_assert(text_size <= max); for (usize i = 0; i < text_size; i += 1) this->buffer[i] = text[i]; this->buffer[max] = max - text_size; } /** * Returns a weak reference to the [path] as a [slice]. */ constexpr slice as_slice() const { return {this->buffer, this->byte_size()}; } /** * Returns the base pointer of the path name. * * *Note*: the returned buffer pointer is guaranteed to end with a zero terminator. */ char const * begin() const { return reinterpret_cast(this->buffer); } /** * Returns the number of bytes composing the path. */ constexpr usize byte_size() const { return max - this->buffer[max]; } /** * Compares the path to `that`, returning the difference between the two paths or `0` if * they are identical. */ constexpr size compare(path const & that) const { return coral::compare(this->as_slice().as_bytes(), that.as_slice().as_bytes()); } /** * Returns the tail pointer of the path name. */ char const * end() const { return this->buffer + this->byte_size(); } /** * Tests the path against `that` for equality, returning `true` if they are identical, * otherwise `false`. */ constexpr bool equals(path const & that) const { return coral::equals(this->as_slice().as_bytes(), that.as_slice().as_bytes()); } /** * Returns the path hash code. * * *Note:* the returned hash code is not guaranteed to be unique. */ constexpr u64 hash() const { return coral::hash(this->as_slice().as_bytes()); } /** * Returns a new [path] composed of the current path joined with `text`. * * *Note:* should the new path exceed [max] bytes in size, an empty [path] is returned instead. */ constexpr path joined(slice const & text) const { if (text.length > this->buffer[max]) return path{}; path joined_path = *this; for (char const c : text) { joined_path.buffer[joined_path.byte_size()] = c; joined_path.buffer[max] -= 1; } return joined_path; } private: char buffer[max + 1]; }; struct file_reader : public reader { virtual ~file_reader() {} virtual expected seek(u64 offset) = 0; virtual expected tell() = 0; }; struct file_writer : public writer { virtual ~file_writer() {} }; /** * Platform-generalized file system interface. */ struct fs { /** * Descriptor of the various rules that the file-system enforces over access to its files. */ struct access_rules { bool can_read; bool can_write; }; virtual ~fs() {}; /** * Queries the file-system for its global [access_rules], returning them. */ virtual access_rules query_access() = 0; /** * Attempts to read the file in the file system located at `file_path` relative, calling * `then` if it was successfully opened for reading. * * Once `then` returns, access to the file is closed automatically. */ virtual void read_file(path const & file_path, callable const & then) = 0; /** * Attempts to write the file in the file system located at `file_path` relative, calling * `then` if it was successfully opened for writing. * * Once `then` returns, access to the file is closed automatically. */ virtual void write_file(path const & file_path, callable const & then) = 0; }; }