summaryrefslogtreecommitdiff
path: root/src/io.hh
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@spawned.biz>2026-01-02 22:42:31 +0100
committerJoel Klinghed <the_jk@spawned.biz>2026-01-02 22:42:31 +0100
commit6ed8f5151719fbc14ec0ac6d28a346d1f74cf2ca (patch)
treeebe7588e89e1aa2ae5376acf85f3a3a7b2ec7e10 /src/io.hh
Initial commitHEADmain
Diffstat (limited to 'src/io.hh')
-rw-r--r--src/io.hh109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/io.hh b/src/io.hh
new file mode 100644
index 0000000..90ad52e
--- /dev/null
+++ b/src/io.hh
@@ -0,0 +1,109 @@
+#ifndef IO_HH
+#define IO_HH
+
+#include <cstddef>
+#include <expected>
+#include <memory>
+#include <string>
+#include <utility>
+
+namespace io {
+
+enum class ReadError : uint8_t {
+ Error,
+ Eof,
+ InvalidData, // invalid data read (not used by raw file)
+ MaxTooSmall, // max argument needs to be bigger (not used by raw file)
+};
+
+enum class WriteError : uint8_t {
+ Error,
+};
+
+enum class OpenError : uint8_t {
+ NoSuchFile,
+ NoAccess,
+ Error,
+};
+
+enum class CreateError : uint8_t {
+ Exists,
+ NoAccess,
+ Error,
+};
+
+enum class PipeError : uint8_t {
+ Error,
+};
+
+class Reader {
+ public:
+ virtual ~Reader() = default;
+
+ [[nodiscard]] virtual std::expected<size_t, ReadError> read(void* dst,
+ size_t max) = 0;
+ [[nodiscard]] virtual std::expected<size_t, ReadError> skip(size_t max) = 0;
+
+ [[nodiscard]] std::expected<size_t, ReadError> repeat_read(void* dst,
+ size_t max);
+ [[nodiscard]] std::expected<size_t, ReadError> repeat_skip(size_t max);
+
+ [[nodiscard]]
+ virtual int raw_fd() const = 0;
+
+ protected:
+ Reader() = default;
+
+ Reader(Reader const&) = delete;
+ Reader& operator=(Reader const&) = delete;
+};
+
+class Writer {
+ public:
+ virtual ~Writer() = default;
+
+ [[nodiscard]]
+ virtual std::expected<size_t, WriteError> write(void const* dst,
+ size_t size) = 0;
+
+ // Use this instead of the destructor if you care if the call returned an
+ // error or not. Regardless of returned value, after this method is called
+ // write will always fail.
+ [[nodiscard]]
+ virtual std::expected<void, WriteError> close() = 0;
+
+ [[nodiscard]]
+ virtual int raw_fd() const = 0;
+
+ [[nodiscard]] std::expected<size_t, WriteError> repeat_write(void const* dst,
+ size_t size);
+
+ protected:
+ Writer() = default;
+
+ Writer(Writer const&) = delete;
+ Writer& operator=(Writer const&) = delete;
+};
+
+[[nodiscard]] std::expected<std::unique_ptr<Reader>, OpenError> open(
+ const std::string& file_path);
+[[nodiscard]] std::expected<std::unique_ptr<Reader>, OpenError> openat(
+ int dirfd, const std::string& file_path);
+[[nodiscard]] std::unique_ptr<Reader> memory(std::string data);
+
+[[nodiscard]] std::expected<std::unique_ptr<Writer>, CreateError> create(
+ const std::string& file_path, bool replace_existing);
+[[nodiscard]] std::expected<std::unique_ptr<Writer>, CreateError> createat(
+ int dirfd, const std::string& file_path, bool replace_existing);
+
+[[nodiscard]] std::expected<
+ std::pair<std::unique_ptr<Reader>, std::unique_ptr<Writer>>, PipeError>
+pipe();
+
+// Takes ownership of the fd.
+[[nodiscard]] std::unique_ptr<Reader> reader_from_raw(int fd);
+[[nodiscard]] std::unique_ptr<Writer> writer_from_raw(int fd);
+
+} // namespace io
+
+#endif // IO_HH