#pragma once
#include <format>
#include <optional>
#include <string>
#include <variant>

namespace util {

	/// An error.
	class Error {
		std::string msg;

		static Error vFormat(const std::string_view formatString, std::format_args args);

	   public:
		explicit Error(const std::string& message) : msg(message) {}

		template <class... Args>
		static constexpr auto format(const std::string_view formatString, Args... args) {
			return vFormat(formatString, std::make_format_args(args...));
		}

		/// Formats a system error.
		static Error systemError();

		const char* message() const { return msg.c_str(); }
	};

	/// An exception which wraps an error.
	class ErrorException : std::exception {
		Error error;
	public:
		explicit ErrorException(const Error& error)
			: error(error) {}

		const char* what() const noexcept override {
			return error.message();
		}
	};

	/// Utility function to throw an error.
	void throwError(const Error& error);

} // namespace util
