Program Listing for File result.hpp

Return to documentation for file (lib/result.hpp)

/* SPDX-License-Identifier: BSD-2-Clause */
#pragma once
#include <frg/variant.hpp>
#include <lib/log.hpp>
#ifdef __KERNEL__
#include <posix/errno.hpp>
#endif
#include <utility>

namespace Gaia {

struct Void {};

template <typename T = Void> class Ok {
public:
  constexpr explicit Ok(T value) : value(std::move(value)) {}

  T value;
};

template <typename T> class Err {
public:
  constexpr explicit Err(T value) : value(value) {}
  T value;
};

template <typename T, typename E> class Result {
public:
  constexpr Result(Ok<T> value) : variant(std::move(value)) {}
  constexpr Result(Err<E> value) : variant(std::move(value)) {}

  constexpr bool is_ok() { return variant.template is<Ok<T>>(); }

  constexpr bool is_err() { return variant.template is<Err<E>>(); }

  constexpr T
  unwrap(const FormatWithLocation &fmt =
             "unwrap failed: cannot unwrap an error type, err: {}") {
    if (is_ok())
      return value().value();
    panic(fmt, error_to_string(error().value()));
  }

  constexpr T unwrap_or(T _value) {
    if (is_ok())
      return value().value();
    return _value;
  }

  constexpr frg::optional<E> error() {
    if (is_err())
      return variant.template get<Err<E>>().value;
    return frg::null_opt;
  }

  constexpr frg::optional<T> value() {
    if (is_ok())
      return std::move(variant.template get<Ok<T>>().value);
    return frg::null_opt;
  }

private:
  frg::variant<Ok<T>, Err<E>> variant;
};

#define TRY(X)                                                                 \
  ({                                                                           \
    auto __ret = (X);                                                          \
    if (__ret.is_err())                                                        \
      return Err(__ret.error().value());                                       \
    __ret.value().value();                                                     \
  })

} // namespace Gaia