benchmark silo added
[c11concurrency-benchmarks.git] / silo / record / serializer.h
1 #ifndef _NDB_BENCH_SERIALIZER_H_
2 #define _NDB_BENCH_SERIALIZER_H_
3
4 #include <stdint.h>
5 #include "../macros.h"
6 #include "../varint.h"
7
8 typedef uint8_t *(*generic_write_fn)(uint8_t *, const uint8_t *);
9 typedef const uint8_t *(*generic_read_fn)(const uint8_t *, uint8_t *);
10 typedef const uint8_t *(*generic_failsafe_read_fn)(const uint8_t *, size_t, uint8_t *);
11 typedef size_t (*generic_nbytes_fn)(const uint8_t *);
12 typedef size_t (*generic_skip_fn)(const uint8_t *, uint8_t *);
13 typedef size_t (*generic_failsafe_skip_fn)(const uint8_t *, size_t, uint8_t *);
14
15 // wraps a real serializer, exposing generic functions
16 template <typename Serializer>
17 struct generic_serializer {
18   typedef typename Serializer::obj_type obj_type;
19
20   static inline uint8_t *
21   write(uint8_t *buf, const uint8_t *obj)
22   {
23     return Serializer::write(buf, *reinterpret_cast<const obj_type *>(obj));
24   }
25
26   static inline const uint8_t *
27   read(const uint8_t *buf, uint8_t *obj)
28   {
29     return Serializer::read(buf, reinterpret_cast<obj_type *>(obj));
30   }
31
32   // returns nullptr on failure
33   static inline const uint8_t *
34   failsafe_read(const uint8_t *buf, size_t nbytes, uint8_t *obj)
35   {
36     return Serializer::failsafe_read(
37         buf, nbytes, reinterpret_cast<obj_type *>(obj));
38   }
39
40   static inline size_t
41   nbytes(const uint8_t *obj)
42   {
43     return Serializer::nbytes(reinterpret_cast<const obj_type *>(obj));
44   }
45
46   static inline size_t
47   skip(const uint8_t *stream, uint8_t *rawv)
48   {
49     return Serializer::skip(stream, rawv);
50   }
51
52   // returns 0 on failure
53   static inline size_t
54   failsafe_skip(const uint8_t *stream, size_t nbytes, uint8_t *rawv)
55   {
56     return Serializer::failsafe_skip(stream, nbytes, rawv);
57   }
58
59   static inline constexpr size_t
60   max_nbytes()
61   {
62     return Serializer::max_bytes();
63   }
64 };
65
66 template <typename T, bool Compress>
67 struct serializer {
68   typedef T obj_type;
69
70   static inline uint8_t *
71   write(uint8_t *buf, const T &obj)
72   {
73     T *p = (T *) buf;
74     *p = obj;
75     return (uint8_t *) (p + 1);
76   }
77
78   static inline const uint8_t *
79   read(const uint8_t *buf, T *obj)
80   {
81     const T *p = (const T *) buf;
82     *obj = *p;
83     return (const uint8_t *) (p + 1);
84   }
85
86   static inline const uint8_t *
87   failsafe_read(const uint8_t *buf, size_t nbytes, T *obj)
88   {
89     if (unlikely(nbytes < sizeof(T)))
90       return nullptr;
91     return read(buf, obj);
92   }
93
94   static inline size_t
95   nbytes(const T *obj)
96   {
97     return sizeof(*obj);
98   }
99
100   static inline size_t
101   skip(const uint8_t *stream, uint8_t *rawv)
102   {
103     if (rawv)
104       NDB_MEMCPY(rawv, stream, sizeof(T));
105     return sizeof(T);
106   }
107
108   static inline size_t
109   failsafe_skip(const uint8_t *stream, size_t nbytes, uint8_t *rawv)
110   {
111     if (unlikely(nbytes < sizeof(T)))
112       return 0;
113     if (rawv)
114       NDB_MEMCPY(rawv, stream, sizeof(T));
115     return sizeof(T);
116   }
117
118   static inline constexpr size_t
119   max_nbytes()
120   {
121     return sizeof(T);
122   }
123 };
124
125 // serializer<T, True> specializations
126 template <>
127 struct serializer<uint32_t, true> {
128   typedef uint32_t obj_type;
129
130   static inline uint8_t *
131   write(uint8_t *buf, uint32_t obj)
132   {
133     return write_uvint32(buf, obj);
134   }
135
136   static inline const uint8_t *
137   read(const uint8_t *buf, uint32_t *obj)
138   {
139     return read_uvint32(buf, obj);
140   }
141
142   static inline const uint8_t *
143   failsafe_read(const uint8_t *buf, size_t nbytes, uint32_t *obj)
144   {
145     return failsafe_read_uvint32(buf, nbytes, obj);
146   }
147
148   static inline size_t
149   nbytes(const uint32_t *obj)
150   {
151     return size_uvint32(*obj);
152   }
153
154   static inline size_t
155   skip(const uint8_t *stream, uint8_t *rawv)
156   {
157     return skip_uvint32(stream, rawv);
158   }
159
160   static inline size_t
161   failsafe_skip(const uint8_t *stream, size_t nbytes, uint8_t *rawv)
162   {
163     return failsafe_skip_uvint32(stream, nbytes, rawv);
164   }
165
166   static inline constexpr size_t
167   max_nbytes()
168   {
169     return 5;
170   }
171 };
172
173 template <>
174 struct serializer<int32_t, true> {
175   typedef int32_t obj_type;
176
177   static inline uint8_t *
178   write(uint8_t *buf, int32_t obj)
179   {
180     const uint32_t v = encode(obj);
181     return serializer<uint32_t, true>::write(buf, v);
182   }
183
184   static inline const uint8_t *
185   read(const uint8_t *buf, int32_t *obj)
186   {
187     uint32_t v;
188     buf = serializer<uint32_t, true>::read(buf, &v);
189     *obj = decode(v);
190     return buf;
191   }
192
193   static inline const uint8_t *
194   failsafe_read(const uint8_t *buf, size_t nbytes, int32_t *obj)
195   {
196     uint32_t v;
197     buf = serializer<uint32_t, true>::failsafe_read(buf, nbytes, &v);
198     if (unlikely(!buf))
199       return 0;
200     *obj = decode(v);
201     return buf;
202   }
203
204   static inline size_t
205   nbytes(const int32_t *obj)
206   {
207     const uint32_t v = encode(*obj);
208     return serializer<uint32_t, true>::nbytes(&v);
209   }
210
211   static inline size_t
212   skip(const uint8_t *stream, uint8_t *rawv)
213   {
214     return skip_uvint32(stream, rawv);
215   }
216
217   static inline size_t
218   failsafe_skip(const uint8_t *stream, size_t nbytes, uint8_t *rawv)
219   {
220     return failsafe_skip_uvint32(stream, nbytes, rawv);
221   }
222
223   static inline constexpr size_t
224   max_nbytes()
225   {
226     return 5;
227   }
228
229 private:
230   // zig-zag encoding from:
231   // http://code.google.com/p/protobuf/source/browse/trunk/src/google/protobuf/wire_format_lite.h
232
233   static inline ALWAYS_INLINE constexpr uint32_t
234   encode(int32_t value)
235   {
236     return (value << 1) ^ (value >> 31);
237   }
238
239   static inline ALWAYS_INLINE constexpr int32_t
240   decode(uint32_t value)
241   {
242     return (value >> 1) ^ -static_cast<int32_t>(value & 1);
243   }
244 };
245
246 #endif /* _NDB_BENCH_SERIALIZER_H_ */