move util out of include

This commit is contained in:
Mars 2024-06-20 13:35:59 -04:00
parent 3fde4138de
commit d23c3d3ec1
Signed by: pupbrained
GPG key ID: 874E22DF2F9DFCB5
10 changed files with 14 additions and 18 deletions

32
src/util/macros.h Normal file
View file

@ -0,0 +1,32 @@
#pragma once
/**
* @brief Allows for rust-style function definitions
*/
#define fn auto
/**
* @brief Allows for easy getter creation
*
* @param class_name The class to use
* @param type Type of the getter
* @param name Name of the getter
*/
#define DEFINE_GETTER(class_name, type, name) \
fn class_name::get##name() const->type { return m_##name; }
/**
* @brief Helper for making reflect-cpp impls
*
* @param struct_name The struct name
* @param lower_name The arg name
* @param ... Values of the class to convert
*/
#define DEF_IMPL(struct_name, ...) \
struct struct_name##Impl { \
__VA_ARGS__; \
\
static fn from_class(const struct_name& instance) noexcept -> struct_name##Impl; \
\
[[nodiscard]] fn to_class() const -> struct_name; \
};

119
src/util/numtypes.h Normal file
View file

@ -0,0 +1,119 @@
#pragma once
#include <cstddef>
#include <cstdint>
/**
* @typedef u8
* @brief Represents an 8-bit unsigned integer.
*
* This type alias is used for 8-bit unsigned integers, ranging from 0 to 255.
* It is based on the std::uint8_t type.
*/
using u8 = std::uint8_t;
/**
* @typedef u16
* @brief Represents a 16-bit unsigned integer.
*
* This type alias is used for 16-bit unsigned integers, ranging from 0 to 65,535.
* It is based on the std::uint16_t type.
*/
using u16 = std::uint16_t;
/**
* @typedef u32
* @brief Represents a 32-bit unsigned integer.
*
* This type alias is used for 32-bit unsigned integers, ranging from 0 to 4,294,967,295.
* It is based on the std::uint32_t type.
*/
using u32 = std::uint32_t;
/**
* @typedef u64
* @brief Represents a 64-bit unsigned integer.
*
* This type alias is used for 64-bit unsigned integers, ranging from 0 to
* 18,446,744,073,709,551,615. It is based on the std::uint64_t type.
*/
using u64 = std::uint64_t;
// Type Aliases for Signed Integers
/**
* @typedef i8
* @brief Represents an 8-bit signed integer.
*
* This type alias is used for 8-bit signed integers, ranging from -128 to 127.
* It is based on the std::int8_t type.
*/
using i8 = std::int8_t;
/**
* @typedef i16
* @brief Represents a 16-bit signed integer.
*
* This type alias is used for 16-bit signed integers, ranging from -32,768 to 32,767.
* It is based on the std::int16_t type.
*/
using i16 = std::int16_t;
/**
* @typedef i32
* @brief Represents a 32-bit signed integer.
*
* This type alias is used for 32-bit signed integers, ranging from -2,147,483,648 to 2,147,483,647.
* It is based on the std::int32_t type.
*/
using i32 = std::int32_t;
/**
* @typedef i64
* @brief Represents a 64-bit signed integer.
*
* This type alias is used for 64-bit signed integers, ranging from -9,223,372,036,854,775,808 to
* 9,223,372,036,854,775,807. It is based on the std::int64_t type.
*/
using i64 = std::int64_t;
// Type Aliases for Floating-Point Numbers
/**
* @typedef f32
* @brief Represents a 32-bit floating-point number.
*
* This type alias is used for 32-bit floating-point numbers, which follow the IEEE 754 standard.
* It is based on the float type.
*/
using f32 = float;
/**
* @typedef f64
* @brief Represents a 64-bit floating-point number.
*
* This type alias is used for 64-bit floating-point numbers, which follow the IEEE 754 standard.
* It is based on the double type.
*/
using f64 = double;
// Type Aliases for Size Types
/**
* @typedef usize
* @brief Represents an unsigned size type.
*
* This type alias is used for representing the size of objects in bytes.
* It is based on the std::size_t type, which is the result type of the sizeof operator.
*/
using usize = std::size_t;
/**
* @typedef isize
* @brief Represents a signed size type.
*
* This type alias is used for representing pointer differences.
* It is based on the std::ptrdiff_t type, which is the signed integer type returned when
* subtracting two pointers.
*/
using isize = std::ptrdiff_t;

218
src/util/result.h Normal file
View file

@ -0,0 +1,218 @@
#pragma once
#include <stdexcept>
#include <string>
#include <utility>
#include <variant>
#include "macros.h"
/**
* @class Error
* @brief Represents an error with a message.
*
* This class is used to encapsulate error messages that can be returned from functions.
*/
class Error {
public:
/**
* @brief Constructs an Error with a message.
* @param message The error message.
*/
explicit Error(std::string message) : m_Message(std::move(message)) {}
/**
* @brief Retrieves the error message.
* @return A constant reference to the error message string.
*/
[[nodiscard]] fn message() const -> const std::string& { return m_Message; }
private:
std::string m_Message; ///< The error message.
};
// Primary template for Result with a default type of void
/**
* @class Result
* @brief Represents a result that can either be a value or an error.
*
* This is the primary template for Result, which defaults to handling void results.
*/
template <typename T = void>
class Result;
// Specialization for Result<void>
/**
* @class Result<void>
* @brief Specialization of Result for handling void results.
*
* This class is used when a function either succeeds with no value or fails with an error.
*/
template <>
class Result<void> {
public:
/**
* @brief Constructs a successful Result.
*/
Result() : m_Result(std::monostate {}) {}
/**
* @brief Constructs an error Result.
* @param error The error object.
*/
Result(const Error& error) : m_Result(error) {}
/**
* @brief Constructs an error Result.
* @param error An rvalue reference to the error object.
*/
Result(Error&& error) : m_Result(std::move(error)) {}
/**
* @brief Checks if the Result is successful.
* @return True if the Result is successful, otherwise false.
*/
[[nodiscard]] fn isOk() const -> bool { return std::holds_alternative<std::monostate>(m_Result); }
/**
* @brief Checks if the Result contains an error.
* @return True if the Result contains an error, otherwise false.
*/
[[nodiscard]] fn isErr() const -> bool { return std::holds_alternative<Error>(m_Result); }
/**
* @brief Throws an exception if the Result contains an error.
*
* This function should be called only if the Result is successful.
*/
void value() const {
if (isErr()) {
throw std::logic_error("Attempted to access value of an error Result");
}
}
/**
* @brief Retrieves the error object.
* @return A constant reference to the Error object.
* @throws std::logic_error if the Result is successful.
*/
[[nodiscard]] fn error() const -> const Error& {
if (isOk()) {
throw std::logic_error("Attempted to access error of an ok Result");
}
return std::get<Error>(m_Result);
}
private:
std::variant<std::monostate, Error>
m_Result; ///< The underlying result, which can be either void or an Error.
};
// Primary template for Result
/**
* @class Result
* @brief Represents a result that can either be a value of type T or an error.
*
* This template class is used to handle results that can either be a successful value or an error.
* @tparam T The type of the successful value.
*/
template <typename T>
class Result {
public:
/**
* @brief Constructs a successful Result with a value.
* @param value The value of the Result.
*/
Result(const T& value) : m_Result(value) {}
/**
* @brief Constructs a successful Result with a value.
* @param value An rvalue reference to the value.
*/
Result(T&& value) : m_Result(std::move(value)) {}
/**
* @brief Constructs an error Result.
* @param error The error object.
*/
Result(const Error& error) : m_Result(error) {}
/**
* @brief Constructs an error Result.
* @param error An rvalue reference to the error object.
*/
Result(Error&& error) : m_Result(std::move(error)) {}
/**
* @brief Checks if the Result is successful.
* @return True if the Result is successful, otherwise false.
*/
[[nodiscard]] fn isOk() const -> bool { return std::holds_alternative<T>(m_Result); }
/**
* @brief Checks if the Result contains an error.
* @return True if the Result contains an error, otherwise false.
*/
[[nodiscard]] fn isErr() const -> bool { return std::holds_alternative<Error>(m_Result); }
/**
* @brief Retrieves the value.
* @return A constant reference to the value.
* @throws std::logic_error if the Result contains an error.
*/
fn value() const -> const T& {
if (isErr()) {
throw std::logic_error("Attempted to access value of an error Result");
}
return std::get<T>(m_Result);
}
/**
* @brief Retrieves the error object.
* @return A constant reference to the Error object.
* @throws std::logic_error if the Result is successful.
*/
[[nodiscard]] fn error() const -> const Error& {
if (isOk()) {
throw std::logic_error("Attempted to access error of an ok Result");
}
return std::get<Error>(m_Result);
}
/**
* @brief Retrieves the value or returns a default value.
* @param defaultValue The default value to return if the Result contains an error.
* @return The value if the Result is successful, otherwise the default value.
*/
fn valueOr(const T& defaultValue) const -> T {
return isOk() ? std::get<T>(m_Result) : defaultValue;
}
private:
std::variant<T, Error>
m_Result; ///< The underlying result, which can be either a value of type T or an Error.
};
/**
* @brief Helper function to create a successful Result.
*
* This function deduces the type of the value and creates a successful Result.
* @tparam T The type of the value.
* @param value The value to be stored in the Result.
* @return A Result object containing the value.
*/
template <typename T>
fn Ok(T&& value) {
return Result<std::decay_t<T>>(std::forward<T>(value));
}
/**
* @brief Helper function to create a successful Result<void>.
*
* This function creates a successful Result that does not contain a value.
* @return A Result<void> object indicating success.
*/
inline fn Ok() -> Result<void> { return {}; }