IceShard 1
A personal game engine project, with development focused on 2D/2.5D games.
Loading...
Searching...
No Matches
shard.hxx
Go to the documentation of this file.
1
3
4#pragma once
5#include <ice/base.hxx>
6#include <ice/stringid.hxx>
7
8namespace ice
9{
10
18 struct Shard;
19
21 struct ShardID;
22
24 struct ShardPayloadID;
25
28 constexpr auto shardid(ice::Shard shard) noexcept -> ice::ShardID;
29
36 constexpr auto shardid(std::string_view definition) noexcept -> ice::ShardID;
37
39 constexpr auto shard(ice::ShardID id) noexcept -> ice::Shard;
40
48 template<typename T>
49 constexpr auto shard(std::string_view definition, T value);
50
58 template<typename T>
59 constexpr auto shard(ice::ShardID id, T payload) noexcept -> ice::Shard;
60
65 template<typename T>
66 constexpr bool shard_inspect(ice::Shard shard, T& payload) noexcept;
67
71 template<typename T>
72 constexpr auto shard_shatter(ice::Shard shard, T fallback) noexcept -> T;
73
74 constexpr auto operator""_shard(ice::utf8 const* str, size_t size) noexcept -> ice::Shard;
75 constexpr auto operator""_shardid(ice::utf8 const* str, size_t size) noexcept -> ice::ShardID;
76
77
78 // IMPLEMENTATION DETAILS
79
80 namespace detail
81 {
82
83 struct ShardName
84 {
86
88 };
89
96
97 } // namespace detail
98
105
111
112 struct Shard
113 {
116
117 constexpr operator ice::ShardID() const noexcept
118 {
119 return id;
120 }
121 };
122
123 static constexpr ice::Shard Shard_Invalid{ .id = { }, .payload = { } };
124
125 constexpr auto shard_payloadid(std::string_view sv) noexcept -> ice::ShardPayloadID
126 {
127 namespace mm3 = ice::detail::murmur3_hash;
128
129 mm3::mm3_x86_h32 const hash = mm3::cexpr_murmur3_x86_32(
131 );
132 return ice::ShardPayloadID{ hash.h[0] };
133 }
134
135 constexpr auto shardid(std::string_view sv) noexcept -> ice::ShardID
136 {
137 namespace mm3 = ice::detail::murmur3_hash;
138
139 size_t const payload_id_pos = sv.find_first_of('`');
140 if (payload_id_pos == std::string_view::npos)
141 {
142 mm3::mm3_x86_h32 const hash = mm3::cexpr_murmur3_x86_32(sv, ice::build::Constant_ShardName_DefaultSeed);
143
144 return ice::ShardID{
145 .name = { hash.h[0] },
146 .payload = { }
147 };
148 }
149 else
150 {
151 mm3::mm3_x86_h32 const name_hash = mm3::cexpr_murmur3_x86_32(
152 sv.substr(0, payload_id_pos),
154 );
155
156 return ice::ShardID{
157 .name = { name_hash.h[0] },
158 .payload = shard_payloadid(sv.substr(payload_id_pos + 1))
159 };
160 }
161 }
162
163 constexpr auto shardid(ice::Shard shard) noexcept -> ice::ShardID
164 {
165 return shard.id;
166 }
167
168 constexpr auto operator""_shardid(char const* str, size_t size) noexcept -> ice::ShardID
169 {
170 return ice::shardid({ str, size });
171 }
172
174
175 template<typename T>
176 concept AllowedAsShardPayloadID = std::is_trivially_copyable_v<T> && sizeof(T) <= 8;
177
178 template<typename T> requires AllowedAsShardPayloadID<T>
180
181 template<typename T>
183
184
185 namespace detail
186 {
187
188 template<typename T> requires HasShardPayloadID<T>
189 constexpr auto shard_payload(T payload) noexcept -> ice::detail::ShardPayload
190 {
191 if constexpr (sizeof(T) == sizeof(ice::Shard::payload))
192 {
193 return std::bit_cast<ShardPayload>(payload);
194 }
195 else
196 {
197 struct PayloadBitCastHelper
198 {
199 T value;
200 char bytes[sizeof(ice::Shard::payload) - sizeof(T)];
201 } temp{ .value = payload, .bytes = { } };
202
203 return std::bit_cast<ShardPayload>(temp);
204 }
205 }
206
207 template<typename T> requires HasShardPayloadID<T>
208 constexpr auto shard_value(ShardPayload payload) noexcept -> T
209 {
210 if constexpr (sizeof(T) == sizeof(ice::Shard::payload))
211 {
212 return std::bit_cast<T>(payload);
213 }
214 else
215 {
216 struct PayloadBitCastHelper
217 {
218 T value;
219 char bytes[sizeof(ice::Shard::payload) - sizeof(T)];
220 } temp{ std::bit_cast<PayloadBitCastHelper>(payload) };
221
222 return temp.value;
223 }
224 }
225
226 } // namespace detail
227
228 // SHARD CREATION
229
230 constexpr auto shard(ice::ShardID id) noexcept -> ice::Shard
231 {
232 return ice::Shard{ .id = id };
233 }
234
235 template<typename T> requires ice::HasShardPayloadID<T>
236 constexpr auto shard(std::string_view definition, T value) noexcept -> ice::Shard
237 {
238 ice::Shard result{ };
239 ice::ShardID const id = ice::shardid(definition);
240
242 if (id.payload == ice::Constant_ShardPayloadID<T> || id.payload == ice::ShardPayloadID_NotSet)
243 {
244 result.id = id;
246 result.payload = ice::detail::shard_payload(value);
247 }
248 return result;
249 }
250
251 template<typename T> requires ice::HasShardPayloadID<T>
252 constexpr auto shard(ice::ShardID id, T value) noexcept -> ice::Shard
253 {
254 ice::Shard result{ };
255
257 if (id.payload == ice::Constant_ShardPayloadID<T> || id.payload == ice::ShardPayloadID_NotSet)
258 {
259 result.id = id;
261 result.payload = ice::detail::shard_payload(value);
262 }
263 return result;
264 }
265
266 constexpr auto operator""_shard(char const* str, size_t size) noexcept -> ice::Shard
267 {
268 return ice::shard(ice::shardid({ str, size }));
269 }
270
271 template<typename T> requires ice::HasShardPayloadID<T>
272 constexpr auto operator|(ice::Shard shard, T payload) noexcept -> ice::Shard
273 {
274 return ice::shard(shard.id, payload);
275 }
276
277 template<typename T> requires ice::HasShardPayloadID<T>
278 constexpr auto operator|(ice::ShardID shardid, T payload) noexcept -> ice::Shard
279 {
280 return ice::shard(shardid, payload);
281 }
282
283 constexpr auto operator==(ice::ShardID left, ice::ShardID right) noexcept -> bool
284 {
285 if (left.name == right.name)
286 {
287 return left.payload == ice::ShardPayloadID_NotSet
288 || right.payload == ice::ShardPayloadID_NotSet
289 || right.payload == left.payload;
290 }
291 return false;
292 }
293
294 constexpr auto operator==(ice::Shard left, ice::Shard right) noexcept -> bool
295 {
296 return left.id == right.id;
297 }
298
299 constexpr auto operator==(ice::Shard left, ice::ShardID right) noexcept -> bool
300 {
301 return left.id == right;
302 }
303
304 // SHARD INSPECTION
305
306 template<typename T> requires ice::HasShardPayloadID<T>
307 constexpr bool shard_inspect(ice::Shard shard, T& value) noexcept
308 {
309 if (ice::Constant_ShardPayloadID<T> == shard.id.payload)
310 {
311 value = ice::detail::shard_value<T>(shard.payload);
312 return true;
313 }
314 return false;
315 }
316
317 template<typename T> requires ice::HasShardPayloadID<T>
318 constexpr auto shard_shatter(ice::Shard shard, T fallback) noexcept -> T
319 {
320 if (ice::Constant_ShardPayloadID<T> == shard.id.payload)
321 {
322 return ice::detail::shard_value<T>(shard.payload);
323 }
324 return fallback;
325 }
326
327 // COMMON PAYLOAD TYPES
328
329 template<>
331
332 template<>
334
335 template<>
337
338 template<>
340
341 template<>
343
344 template<>
346
347 template<>
349
350 template<>
352
353 template<>
355
356 template<>
358
359 template<>
360 constexpr auto hash(ice::ShardID shardid) noexcept -> ice::u64
361 {
362 return ice::bit_cast<ice::u64>(shardid);
363 }
364
365 constexpr auto hash32(ice::ShardID shardid) noexcept -> ice::u32
366 {
367 return shardid.name.value ^ shardid.payload.value;
368 }
369
370 namespace _validate
371 {
372
373 static constexpr ice::Shard shard_without_payload = "test/shard"_shard;
374 static constexpr ice::Shard shard_with_payload_u32 = "test/shard"_shard | ice::u32{ 42 };
375 static constexpr ice::Shard shard_with_payload_i32 = "test/shard"_shard | ice::i32{ 42 };
376
377 static constexpr ice::Shard shard2_without_payload = "test/shard2"_shard;
378 static constexpr ice::Shard shard2_with_payload_u32 = "test/shard2"_shard | ice::u32{ 42 };
379 static constexpr ice::Shard shard2_with_payload_i32 = "test/shard2"_shard | ice::i32{ 42 };
380
381 static constexpr ice::ShardID shardid_test_1 = "test/shard`ice::u32"_shardid;
383
384 static_assert(shardid_test_1 == shardid_test_1_from_shard, "ShardID creation is not valid!");
385
386 static_assert(shard_without_payload == shard_without_payload, "Assert: Shards are equal to themselfs.");
387 static_assert(shard_with_payload_u32 == shard_with_payload_u32, "Assert: Shards are equal to themselfs.");
388
389 static_assert(shard_without_payload == shard_with_payload_u32, "Assert: Shards without payload are equal to similar Shards with payload.");
390 static_assert(shard_without_payload == shard_with_payload_i32, "Assert: Shards without payload are equal to similar Shards with payload.");
391 static_assert(shard_with_payload_u32 == shard_without_payload, "Assert: Shards without payload are equal to similar Shards with payload.");
392 static_assert(shard_with_payload_i32 == shard_without_payload, "Assert: Shards without payload are equal to similar Shards with payload.");
393
394 static_assert(shard_with_payload_i32 != shard_with_payload_u32, "Assert: Shards with different payloads are not equal.");
395 static_assert(shard_with_payload_u32 != shard_with_payload_i32, "Assert: Shards with different payloads are not equal.");
396
397 static_assert(shard_without_payload != shard2_without_payload, "Assert: Different Shards are not equal.");
398
399 static_assert(shard2_with_payload_u32 != shard_with_payload_u32, "Assert: Different Shards with same payloads are not equal.");
400 static_assert(shard2_with_payload_i32 != shard_with_payload_i32, "Assert: Different Shards with same payloads are not equal.");
401
402 static_assert(shard2_with_payload_u32 != shard_with_payload_i32, "Assert: Different Shards with different payloads are not equal.");
403 static_assert(shard2_with_payload_i32 != shard_with_payload_u32, "Assert: Different Shards with different payloads are not equal.");
404
405 } // namespace detail
406
407
408} // namespace ice
409
410template<>
412 ice::ShardID value,
413 ice::ShardID default_value
414) noexcept -> ice::ShardID
415{
416 return value != ice::Shard_Invalid.id ? value : default_value;
417}
#define ICE_ASSERT_CORE(expression)
Definition assert_core.hxx:43
Definition shard.hxx:176
Definition shard.hxx:182
Definition shard.hxx:371
static constexpr ice::Shard shard2_with_payload_u32
Definition shard.hxx:378
static constexpr ice::ShardID shardid_test_1_from_shard
Definition shard.hxx:382
static constexpr ice::Shard shard2_with_payload_i32
Definition shard.hxx:379
static constexpr ice::Shard shard_with_payload_i32
Definition shard.hxx:375
static constexpr ice::Shard shard_without_payload
Definition shard.hxx:373
static constexpr ice::Shard shard_with_payload_u32
Definition shard.hxx:374
static constexpr ice::ShardID shardid_test_1
Definition shard.hxx:381
static constexpr ice::Shard shard2_without_payload
Definition shard.hxx:377
static constexpr uint32_t Constant_ShardPayloadID_DefaultSeed
The seed used to generate hash values for ice::detail::PayloadID.
Definition constants.hxx:34
static constexpr uint32_t Constant_ShardName_DefaultSeed
The seed used to generate hash values for ice::detail::ShardName.
Definition constants.hxx:31
Definition murmur3.hxx:18
Definition hashmap_details.hxx:13
constexpr auto shard_value(ShardPayload payload) noexcept -> T
Definition shard.hxx:208
constexpr auto shard_payload(T payload) noexcept -> ice::detail::ShardPayload
Definition shard.hxx:189
SPDX-License-Identifier: MIT.
Definition array.hxx:12
constexpr auto shard_payloadid(std::string_view sv) noexcept -> ice::ShardPayloadID
Definition shard.hxx:125
static constexpr ice::ShardPayloadID Constant_ShardPayloadID
Definition shard.hxx:179
constexpr auto operator==(ice::TimeType auto left, TimeType auto right) noexcept
Definition clock_types.hxx:159
std::uint64_t u64
Definition types.hxx:27
std::int32_t i32
Definition types.hxx:21
constexpr bool shard_inspect(ice::Shard shard, T &payload) noexcept
Tries to read the value from the given shard.
Definition shard.hxx:307
constexpr auto value_or_default(T value, U default_value) noexcept -> T=delete
constexpr auto operator|(T left, T right) noexcept -> T
Definition enum_flags.hxx:28
constexpr auto hash32(ice::String value) noexcept -> ice::u32
Definition string.hxx:105
constexpr auto shardid(ice::Shard shard) noexcept -> ice::ShardID
Returns the ice::ShardID value of a shard.
Definition shard.hxx:163
std::uint32_t u32
Definition types.hxx:26
constexpr auto hash(ice::HeapString<> const &value) noexcept -> ice::u64
Definition heap_string.hxx:251
static constexpr ice::Shard Shard_Invalid
Definition shard.hxx:123
static constexpr ice::ShardPayloadID ShardPayloadID_NotSet
Definition shard.hxx:173
constexpr auto shard(ice::ShardID id) noexcept -> ice::Shard
Creates a ice::Shard value from ice::ShardID. Clears the payload ID from the created shard.
Definition shard.hxx:230
char8_t utf8
Definition types.hxx:11
constexpr auto shard_shatter(ice::Shard shard, T fallback) noexcept -> T
Reads the value from the given shard or returns the fallback value.
Definition shard.hxx:318
Definition shard.hxx:113
ice::detail::ShardPayload payload
Definition shard.hxx:115
ice::ShardID id
Definition shard.hxx:114
Definition shard.hxx:107
ice::ShardPayloadID payload
Definition shard.hxx:109
ice::detail::ShardName name
Definition shard.hxx:108
Definition shard.hxx:100
ice::u32 value
Definition shard.hxx:103
ice::StrongValue TypeTag
Definition shard.hxx:101
Type tag to enable utility functions for strongly typed values.
Definition strong_type_value.hxx:11
Definition shard.hxx:84
ice::u32 value
Definition shard.hxx:87
ice::StrongValue TypeTag
Definition shard.hxx:85
Definition shard.hxx:91
ice::StrongValue TypeTag
Definition shard.hxx:92
ice::u64 value
Definition shard.hxx:94