1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#pragma once
#include <forstio/string_literal.h>
#include "schema.h"
#include "crc32.h"
namespace saw {
template<string_literal lit>
struct hash_literal {
static constexpr uint32_t apply(uint32_t seed){
constexpr std::string_view view = lit.view();
return hash<algs::crc32>::update(seed, view);
}
};
template<typename Schema>
struct schema_hash_seed {
static_assert(always_false<Schema>, "Not schema_hashable");
};
template<>
struct schema_hash_seed<schema::SignedInteger> {
using Schema = schema::SignedInteger;
static constexpr uint32_t apply(uint32_t seed){
return hash_literal<Schema::name>::apply(seed);
}
};
template<>
struct schema_hash_seed<schema::UnsignedInteger> {
using Schema = schema::UnsignedInteger;
static constexpr uint32_t apply(uint32_t seed){
return hash_literal<Schema::name>::apply(seed);
}
};
template<>
struct schema_hash_seed<schema::FloatingPoint> {
using Schema = schema::FloatingPoint;
static constexpr uint32_t apply(uint32_t seed){
return hash_literal<Schema::name>::apply(seed);
}
};
template<>
struct schema_hash_seed<schema::String> {
using Schema = schema::String;
static constexpr uint32_t apply(uint32_t seed){
return hash_literal<Schema::name>::apply(seed);
}
};
template<typename P, uint64_t N>
struct schema_hash_seed<schema::Primitive<P,N>> {
using Schema = schema::Primitive<P,N>;
static constexpr uint32_t apply(uint32_t seed){
seed = hash_literal<Schema::name>::apply(seed);
seed = schema_hash_seed<P>::apply(seed);
uint64_t val = N;
std::array<uint8_t,sizeof(uint64_t)> dat{
static_cast<uint8_t>(val >> 0),
static_cast<uint8_t>(val >> 8),
static_cast<uint8_t>(val >> 16),
static_cast<uint8_t>(val >> 24),
static_cast<uint8_t>(val >> 32),
static_cast<uint8_t>(val >> 40),
static_cast<uint8_t>(val >> 48),
static_cast<uint8_t>(val >> 56)
};
seed = hash<algs::crc32>::update(seed, &dat[0], dat.size());
return seed;
}
};
template<typename T, uint64_t N>
struct schema_hash_seed<schema::Array<T,N>> {
using Schema = schema::Array<T,N>;
static constexpr uint32_t apply(uint32_t seed){
seed = hash_literal<Schema::name>::apply(seed);
seed = schema_hash_seed<T>::apply(seed);
uint64_t val = N;
std::array<uint8_t,sizeof(uint64_t)> dat{
static_cast<uint8_t>(val >> 0),
static_cast<uint8_t>(val >> 8),
static_cast<uint8_t>(val >> 16),
static_cast<uint8_t>(val >> 24),
static_cast<uint8_t>(val >> 32),
static_cast<uint8_t>(val >> 40),
static_cast<uint8_t>(val >> 48),
static_cast<uint8_t>(val >> 56)
};
seed = hash<algs::crc32>::update(seed, &dat[0], dat.size());
return seed;
}
};
template<typename... V, string_literal... K>
struct schema_hash_seed<schema::Struct<schema::Member<V,K>...>> {
using Schema = schema::Struct<schema::Member<V,K>...>;
template<uint64_t i>
static constexpr uint32_t apply_ele(uint32_t seed){
using Type = typename parameter_pack_type<i,V...>::type;
constexpr string_literal Lit = parameter_key_pack_type<i,K...>::literal;
using MemberT = typename parameter_pack_type<i,schema::Member<V,K>...>::type;
seed = hash_literal<MemberT::name>::apply(seed);
seed = schema_hash_seed<Type>::apply(seed);
seed = hash_literal<Lit>::apply(seed);
if constexpr ( (i+1) < sizeof...(V) ){
return apply_ele<i+1>(seed);
}
return seed;
}
static constexpr uint32_t apply(uint32_t seed){
seed = hash_literal<Schema::name>::apply(seed);
if constexpr (sizeof...(V) > 0){
seed = apply_ele<0>(seed);
}
return seed;
}
};
template<typename Schema>
struct schema_hash {
static constexpr uint32_t apply() {
constexpr uint32_t seed = 0;
return schema_hash_seed<Schema>::apply(seed);
}
};
}
|