wowlib 0.0.0
Read & write World of Warcraft client files — a C++26 core
Loading...
Searching...
No Matches
convert.hpp
Go to the documentation of this file.
1#pragma once
2
23
24#include <array>
25#include <cstddef>
26
28#include <wowlib/core/error.hpp>
30
31namespace wowlib::formats {
33 template <ClientVersion V>
34 struct VersionTag {};
35
42 template <template <ClientVersion> class E>
43 inline constexpr auto SupportedVersions = nullptr;
44
50 template <template <ClientVersion> class E>
51 inline constexpr auto VersionPivots = nullptr;
52
53 namespace detail {
54 template <std::size_t N>
55 consteval std::size_t indexOf(const std::array<ClientVersion, N>& versions, ClientVersion v) {
56 for (std::size_t i = 0; i < N; ++i)
57 if (versions[i] == v) return i;
58 return N; // not found
59 }
60
61 template <template <ClientVersion> class E, ClientVersion From, ClientVersion To> concept HasConvertStep = requires(
62 const E<From>& src) {
63 { convert_step(src, VersionTag<To>{}) } -> std::same_as<Result<E<To>>>;
64 };
65
69 template <template <ClientVersion> class E>
70 consteval ClientVersion
72 const auto& versions = SupportedVersions<E>;
73 const auto& pivots = VersionPivots<E>;
74 std::size_t i = indexOf(versions, from);
75 const std::size_t j = indexOf(versions, to);
76 const ClientVersion fromCanonical = canonicalVersion(from, pivots, versions);
77 while (i != j) {
78 i = i < j ? i + 1 : i - 1;
79 const ClientVersion c = canonicalVersion(versions[i], pivots, versions);
80 if (c != fromCanonical) return c;
81 }
82 return fromCanonical;
83 }
84 }
85
94 template <template <ClientVersion> class E, ClientVersion From, ClientVersion To>
95 consteval bool hasConvertPath() {
96 constexpr auto& versions = SupportedVersions<E>;
97 constexpr auto& pivots = VersionPivots<E>;
98 static_assert(detail::indexOf(versions, From) < versions.size(), "From is not a supported version of this format");
99 static_assert(detail::indexOf(versions, To) < versions.size(), "To is not a supported version of this format");
100 constexpr ClientVersion fromC = canonicalVersion(From, pivots, versions);
101 constexpr ClientVersion toC = canonicalVersion(To, pivots, versions);
102 if constexpr (fromC == toC) return true;
103 else {
104 constexpr ClientVersion next = detail::nextCanonical<E>(fromC, toC);
106 else return false;
107 }
108 }
109
118 template <ClientVersion To, template <ClientVersion> class E, ClientVersion From> requires(!std::is_same_v<
119 decltype(SupportedVersions<E>), const std::nullptr_t>)
121 constexpr auto& versions = SupportedVersions<E>;
122 constexpr auto& pivots = VersionPivots<E>;
123 static_assert(detail::indexOf(versions, To) < versions.size(), "To is not a supported version of this format");
124 static_assert(From == canonicalVersion(From, pivots, versions),
125 "convert() takes a canonical instantiation — construct entities " "through the public aliases");
126 constexpr ClientVersion toC = canonicalVersion(To, pivots, versions);
127
128 if constexpr (From == toC) return src;
129 else {
130 constexpr ClientVersion next = detail::nextCanonical<E>(From, toC);
132 "no convert_step overload for this canonical version pair — declare "
133 "Result<E<next>> convert_step(const E<From>&, version_tag<next>)") ;
134 auto stepped = convert_step(src, VersionTag<next>{});
135 if (!stepped) return std::unexpected{stepped.error()};
136 return convert<To>(*stepped);
137 }
138 }
139}
Client version identity, the flavor axis that separates a client's CONTENT version from the engine ge...
The error-handling vocabulary: ErrorCode, Error and the Result<T> alias every fallible wowlib operati...
consteval ClientVersion nextCanonical(ClientVersion from, ClientVersion to)
The next CANONICAL version on E's ladder walking from from toward to — the first range boundary cross...
Definition convert.hpp:71
consteval std::size_t indexOf(const std::array< ClientVersion, N > &versions, ClientVersion v)
Definition convert.hpp:55
consteval bool hasConvertPath()
Whether every convert_step along the CANONICAL ladder from from to to exists, i.e.
Definition convert.hpp:95
constexpr auto VersionPivots
The canonicalization pivots of format template E (the assembly's pivot list from its boundaries heade...
Definition convert.hpp:51
constexpr ClientVersion canonicalVersion(ClientVersion v, std::span< const ClientVersion > pivots, std::span< const ClientVersion > grid)
The canonical version v collapses to: the FIRST grid version in v's range.
auto convert(const E< From > &src) -> Result< E< canonicalVersion(To, VersionPivots< E >, SupportedVersions< E >)> >
Convert src to its to - version representation by composing convert_step overloads along the format's...
Definition convert.hpp:120
constexpr auto SupportedVersions
The ordered release list of format template E.
Definition convert.hpp:43
std::expected< T, Error > Result
Every fallible wowlib operation returns Result<T>; bindings translate the error branch into a target-...
Definition error.hpp:100
Tags the target version in convert_step overload signatures.
Definition convert.hpp:34
Version-range canonicalization: the machinery behind collapsing a versioned family's instantiations t...