2022-07-30 12:24:03 -04:00
|
|
|
#pragma once
|
|
|
|
|
2022-11-28 12:09:39 -05:00
|
|
|
#include "../DefaultInclude.hpp"
|
2022-07-30 12:24:03 -04:00
|
|
|
#include <string_view>
|
2023-01-27 18:25:19 -05:00
|
|
|
#include <json.hpp>
|
2022-12-11 13:44:38 -05:00
|
|
|
#include <tuple>
|
2022-12-12 11:44:17 -05:00
|
|
|
#include "../utils/Result.hpp"
|
2022-07-30 12:24:03 -04:00
|
|
|
|
|
|
|
namespace geode {
|
2022-12-08 17:28:05 -05:00
|
|
|
enum class VersionCompare {
|
|
|
|
LessEq,
|
|
|
|
Exact,
|
|
|
|
MoreEq,
|
|
|
|
};
|
|
|
|
|
2022-07-30 12:24:03 -04:00
|
|
|
/**
|
2022-12-12 08:45:27 -05:00
|
|
|
* A version label, like v1.0.0-alpha or v2.3.4-prerelease. Purely semantic,
|
|
|
|
* and not used in comparisons; so for example v1.0.0-alpha == v1.0.0.
|
|
|
|
*/
|
|
|
|
enum class VersionTag {
|
|
|
|
Alpha,
|
|
|
|
Beta,
|
|
|
|
Prerelease,
|
|
|
|
};
|
|
|
|
GEODE_DLL std::optional<VersionTag> versionTagFromString(std::string const& str);
|
|
|
|
GEODE_DLL std::string versionTagToSuffixString(VersionTag tag);
|
|
|
|
GEODE_DLL std::string versionTagToString(VersionTag tag);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class representing version information. Not strictly semver, notably in
|
|
|
|
* regard to identifiers; identifiers are restricted to a few common ones,
|
|
|
|
* and are purely semantic, i.e. not used in comparisons. See VersionTag
|
|
|
|
* for details
|
2022-07-30 12:24:03 -04:00
|
|
|
* @class VersionInfo
|
|
|
|
*/
|
2022-12-08 17:28:05 -05:00
|
|
|
class GEODE_DLL VersionInfo final {
|
2022-07-30 12:24:03 -04:00
|
|
|
protected:
|
2022-12-12 08:45:27 -05:00
|
|
|
size_t m_major = 1;
|
|
|
|
size_t m_minor = 0;
|
|
|
|
size_t m_patch = 0;
|
|
|
|
std::optional<VersionTag> m_tag;
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-07-30 12:24:03 -04:00
|
|
|
public:
|
2022-12-08 15:04:02 -05:00
|
|
|
constexpr VersionInfo() = default;
|
2022-12-12 08:45:27 -05:00
|
|
|
constexpr VersionInfo(size_t major, size_t minor, size_t patch) {
|
|
|
|
m_major = major;
|
|
|
|
m_minor = minor;
|
|
|
|
m_patch = patch;
|
|
|
|
}
|
|
|
|
constexpr VersionInfo(
|
|
|
|
size_t major, size_t minor, size_t patch,
|
|
|
|
std::optional<VersionTag> tag
|
|
|
|
) {
|
2022-07-30 12:24:03 -04:00
|
|
|
m_major = major;
|
|
|
|
m_minor = minor;
|
|
|
|
m_patch = patch;
|
2022-12-12 08:45:27 -05:00
|
|
|
m_tag = tag;
|
2022-07-30 12:24:03 -04:00
|
|
|
}
|
2022-12-12 11:44:17 -05:00
|
|
|
|
|
|
|
static Result<VersionInfo> parse(std::string const& string);
|
2022-07-30 12:24:03 -04:00
|
|
|
|
2022-12-12 08:45:27 -05:00
|
|
|
constexpr size_t getMajor() const {
|
2022-12-08 15:04:02 -05:00
|
|
|
return m_major;
|
|
|
|
}
|
2022-07-30 12:24:03 -04:00
|
|
|
|
2022-12-12 08:45:27 -05:00
|
|
|
constexpr size_t getMinor() const {
|
2022-12-08 15:04:02 -05:00
|
|
|
return m_minor;
|
|
|
|
}
|
2022-07-30 12:24:03 -04:00
|
|
|
|
2022-12-12 08:45:27 -05:00
|
|
|
constexpr size_t getPatch() const {
|
2022-12-08 15:04:02 -05:00
|
|
|
return m_patch;
|
|
|
|
}
|
|
|
|
|
2022-12-12 08:45:27 -05:00
|
|
|
constexpr std::optional<VersionTag> getTag() const {
|
|
|
|
return m_tag;
|
|
|
|
}
|
|
|
|
|
2022-12-11 14:01:52 -05:00
|
|
|
// Apple clang does not support operator<=>! Yippee!
|
|
|
|
|
|
|
|
constexpr bool operator==(VersionInfo const& other) const {
|
|
|
|
return std::tie(m_major, m_minor, m_patch) ==
|
|
|
|
std::tie(other.m_major, other.m_minor, other.m_patch);
|
|
|
|
}
|
|
|
|
constexpr bool operator<(VersionInfo const& other) const {
|
|
|
|
return std::tie(m_major, m_minor, m_patch) <
|
|
|
|
std::tie(other.m_major, other.m_minor, other.m_patch);
|
|
|
|
}
|
|
|
|
constexpr bool operator<=(VersionInfo const& other) const {
|
|
|
|
return std::tie(m_major, m_minor, m_patch) <=
|
|
|
|
std::tie(other.m_major, other.m_minor, other.m_patch);
|
|
|
|
}
|
|
|
|
constexpr bool operator>(VersionInfo const& other) const {
|
|
|
|
return std::tie(m_major, m_minor, m_patch) >
|
|
|
|
std::tie(other.m_major, other.m_minor, other.m_patch);
|
|
|
|
}
|
|
|
|
constexpr bool operator>=(VersionInfo const& other) const {
|
|
|
|
return std::tie(m_major, m_minor, m_patch) >=
|
2022-12-08 15:04:02 -05:00
|
|
|
std::tie(other.m_major, other.m_minor, other.m_patch);
|
|
|
|
}
|
2022-07-30 12:24:03 -04:00
|
|
|
|
2022-12-12 08:45:27 -05:00
|
|
|
std::string toString(bool includeTag = true) const;
|
2022-07-30 12:24:03 -04:00
|
|
|
};
|
2022-12-08 17:28:05 -05:00
|
|
|
GEODE_DLL std::ostream& operator<<(std::ostream& stream, VersionInfo const& version);
|
2022-11-22 17:35:08 -05:00
|
|
|
|
2022-12-08 17:28:05 -05:00
|
|
|
class GEODE_DLL ComparableVersionInfo final {
|
|
|
|
protected:
|
|
|
|
VersionInfo m_version;
|
|
|
|
VersionCompare m_compare = VersionCompare::Exact;
|
|
|
|
|
|
|
|
public:
|
|
|
|
constexpr ComparableVersionInfo() = default;
|
|
|
|
constexpr ComparableVersionInfo(
|
|
|
|
VersionInfo const& version,
|
|
|
|
VersionCompare const& compare
|
|
|
|
) : m_version(version), m_compare(compare) {}
|
2022-12-12 11:44:17 -05:00
|
|
|
|
|
|
|
static Result<ComparableVersionInfo> parse(std::string const& string);
|
2022-12-08 17:28:05 -05:00
|
|
|
|
|
|
|
constexpr bool compare(VersionInfo const& version) const {
|
2023-01-31 07:48:34 -05:00
|
|
|
// opposing major versions never match
|
|
|
|
if (m_version.getMajor() != version.getMajor()) {
|
|
|
|
return false;
|
|
|
|
}
|
2023-02-09 10:45:06 -05:00
|
|
|
|
2022-12-08 17:28:05 -05:00
|
|
|
switch (m_compare) {
|
2023-02-09 10:45:06 -05:00
|
|
|
case VersionCompare::LessEq:
|
|
|
|
return m_version <= version;
|
|
|
|
case VersionCompare::MoreEq:
|
|
|
|
return m_version >= version;
|
|
|
|
default:
|
|
|
|
return m_version == version;
|
2022-12-08 17:28:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string toString() const;
|
|
|
|
};
|
|
|
|
GEODE_DLL std::ostream& operator<<(std::ostream& stream, ComparableVersionInfo const& version);
|
2022-07-30 12:24:03 -04:00
|
|
|
}
|
2023-01-27 18:25:19 -05:00
|
|
|
|
|
|
|
template <class V>
|
|
|
|
requires std::is_same_v<V, geode::VersionInfo> || std::is_same_v<V, geode::ComparableVersionInfo>
|
|
|
|
struct json::Serialize<V> {
|
|
|
|
static json::Value to_json(V const& info) {
|
|
|
|
return info.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
static V from_json(json::Value const& json) {
|
|
|
|
auto ver = V::parse(json.as_string());
|
|
|
|
if (!ver) {
|
|
|
|
throw json::JsonException(
|
|
|
|
"Invalid version format: " + ver.unwrapErr()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return ver.unwrap();
|
|
|
|
}
|
|
|
|
};
|