1 /*
2 * serialize.h
3 *
4 * This source file is part of the FoundationDB open source project
5 *
6 * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #ifndef FLOW_SERIALIZE_H
22 #define FLOW_SERIALIZE_H
23 #pragma once
24
25 #include <stdint.h>
26 #include <array>
27 #include <set>
28 #include "flow/Error.h"
29 #include "flow/Arena.h"
30 #include <algorithm>
31
32 // Though similar, is_binary_serializable cannot be replaced by std::is_pod, as doing so would prefer
33 // memcpy over a defined serialize() method on a POD struct. As not all of our structs are packed,
34 // this would both inflate message sizes by transmitting padding, and mean that we're transmitting
35 // undefined bytes over the wire.
36 // A more intelligent SFINAE that does "binarySerialize if POD and no serialize() is defined" could
37 // replace the usage of is_binary_serializable.
38 template <class T>
39 struct is_binary_serializable { enum { value = 0 }; };
40
41 #define BINARY_SERIALIZABLE( T ) template<> struct is_binary_serializable<T> { enum { value = 1 }; };
42
43 BINARY_SERIALIZABLE( int8_t );
44 BINARY_SERIALIZABLE( uint8_t );
45 BINARY_SERIALIZABLE( int16_t );
46 BINARY_SERIALIZABLE( uint16_t );
47 BINARY_SERIALIZABLE( int32_t );
48 BINARY_SERIALIZABLE( uint32_t );
49 BINARY_SERIALIZABLE( int64_t );
50 BINARY_SERIALIZABLE( uint64_t );
51 BINARY_SERIALIZABLE( bool );
52 BINARY_SERIALIZABLE( double );
53
54 template <class Archive, class Item>
55 inline typename Archive::WRITER& operator << (Archive& ar, const Item& item ) {
56 save(ar, const_cast<Item&>(item));
57 return ar;
58 }
59
60 template <class Archive, class Item>
61 inline typename Archive::READER& operator >> (Archive& ar, Item& item ) {
62 load(ar, item);
63 return ar;
64 }
65
66 template <class Archive>
serializer(Archive & ar)67 void serializer(Archive& ar) {}
68
69 template <class Archive, class Item, class... Items>
serializer(Archive & ar,const Item & item,const Items &...items)70 typename Archive::WRITER& serializer(Archive& ar, const Item& item, const Items&... items) {
71 save(ar, item);
72 serializer(ar, items...);
73 return ar;
74 }
75
76 template <class Archive, class Item, class... Items>
serializer(Archive & ar,Item & item,Items &...items)77 typename Archive::READER& serializer(Archive& ar, Item& item, Items&... items) {
78 load(ar, item);
79 serializer(ar, items...);
80 return ar;
81 }
82
83 template <class Archive, class T, class Enable = void>
84 class Serializer {
85 public:
serialize(Archive & ar,T & t)86 static void serialize( Archive& ar, T& t ) {
87 t.serialize(ar);
88 ASSERT( ar.protocolVersion() != 0 );
89 }
90 };
91
92 template <class Ar, class T>
save(Ar & ar,const T & value)93 inline void save( Ar& ar, const T& value ) {
94 Serializer<Ar,T>::serialize(ar, const_cast<T&>(value));
95 }
96
97 template <class Ar, class T>
load(Ar & ar,T & value)98 inline void load( Ar& ar, T& value ) {
99 Serializer<Ar,T>::serialize(ar, value);
100 }
101
102 template <class Archive>
load(Archive & ar,std::string & value)103 inline void load( Archive& ar, std::string& value ) {
104 int32_t length;
105 ar >> length;
106 value.resize(length);
107 ar.serializeBytes( &value[0], (int)value.length() );
108 ASSERT( ar.protocolVersion() != 0 );
109 }
110
111 template <class Archive>
save(Archive & ar,const std::string & value)112 inline void save( Archive& ar, const std::string& value ) {
113 ar << (int32_t)value.length();
114 ar.serializeBytes( (void*)&value[0], (int)value.length() );
115 ASSERT( ar.protocolVersion() != 0 );
116 }
117
118 template <class Archive, class T>
119 class Serializer< Archive, T, typename std::enable_if< is_binary_serializable<T>::value >::type> {
120 public:
serialize(Archive & ar,T & t)121 static void serialize( Archive& ar, T& t ) {
122 ar.serializeBinaryItem(t);
123 }
124 };
125
126 template <class Archive, class T1, class T2>
127 class Serializer< Archive, std::pair<T1,T2>, void > {
128 public:
serialize(Archive & ar,std::pair<T1,T2> & p)129 static void serialize( Archive& ar, std::pair<T1, T2>& p ) {
130 serializer(ar, p.first, p.second);
131 }
132 };
133
134 template <class Archive, class T>
save(Archive & ar,const std::vector<T> & value)135 inline void save( Archive& ar, const std::vector<T>& value ) {
136 ar << (int)value.size();
137 for(auto it = value.begin(); it != value.end(); ++it)
138 ar << *it;
139 ASSERT( ar.protocolVersion() != 0 );
140 }
141 template <class Archive, class T>
load(Archive & ar,std::vector<T> & value)142 inline void load( Archive& ar, std::vector<T>& value ) {
143 int s;
144 ar >> s;
145 value.clear();
146 value.reserve(s);
147 for (int i = 0; i < s; i++) {
148 value.push_back(T());
149 ar >> value[i];
150 }
151 ASSERT( ar.protocolVersion() != 0 );
152 }
153
154 template <class Archive, class T, size_t N>
save(Archive & ar,const std::array<T,N> & value)155 inline void save( Archive& ar, const std::array<T, N>& value ) {
156 for(int ii = 0; ii < N; ++ii)
157 ar << value[ii];
158 ASSERT( ar.protocolVersion() != 0 );
159 }
160 template <class Archive, class T, size_t N>
load(Archive & ar,std::array<T,N> & value)161 inline void load( Archive& ar, std::array<T, N>& value ) {
162 for (int ii = 0; ii < N; ii++) {
163 ar >> value[ii];
164 }
165 ASSERT( ar.protocolVersion() != 0 );
166 }
167
168 template <class Archive, class T>
save(Archive & ar,const std::set<T> & value)169 inline void save( Archive& ar, const std::set<T>& value ) {
170 ar << (int)value.size();
171 for(auto it = value.begin(); it != value.end(); ++it)
172 ar << *it;
173 ASSERT( ar.protocolVersion() != 0 );
174 }
175 template <class Archive, class T>
load(Archive & ar,std::set<T> & value)176 inline void load( Archive& ar, std::set<T>& value ) {
177 int s;
178 ar >> s;
179 value.clear();
180 T currentValue;
181 for (int i = 0; i < s; i++) {
182 ar >> currentValue;
183 value.insert(currentValue);
184 }
185 ASSERT( ar.protocolVersion() != 0 );
186 }
187
188 template <class Archive, class K, class V>
save(Archive & ar,const std::map<K,V> & value)189 inline void save( Archive& ar, const std::map<K, V>& value ) {
190 ar << (int)value.size();
191 for (const auto &it : value) {
192 ar << it.first << it.second;
193 }
194 ASSERT( ar.protocolVersion() != 0 );
195 }
196 template <class Archive, class K, class V>
load(Archive & ar,std::map<K,V> & value)197 inline void load( Archive& ar, std::map<K, V>& value ) {
198 int s;
199 ar >> s;
200 value.clear();
201 for (int i = 0; i < s; ++i) {
202 std::pair<K, V> p;
203 ar >> p.first >> p.second;
204 value.emplace(p);
205 }
206 ASSERT( ar.protocolVersion() != 0 );
207 }
208
209 #pragma intrinsic (memcpy)
210
211 #if VALGRIND
valgrindCheck(const void * data,int bytes,const char * context)212 static bool valgrindCheck( const void* data, int bytes, const char* context ) {
213 auto first= VALGRIND_CHECK_MEM_IS_DEFINED( data, bytes );
214 if (first) {
215 int und=0;
216 for(int b=0; b<bytes; b++)
217 if (VALGRIND_CHECK_MEM_IS_DEFINED( (uint8_t*)data+b, 1 ))
218 und++;
219 TraceEvent(SevError, "UndefinedData").detail("In", context).detail("Size", bytes).detail("Undefined", und).detail("FirstAt", (int64_t)first-(int64_t)data);
220 return false;
221 }
222 return true;
223
224 }
225 #else
valgrindCheck(const void * data,int bytes,const char * context)226 static inline bool valgrindCheck( const void* data, int bytes, const char* context ) { return true; }
227 #endif
228
229 extern const uint64_t currentProtocolVersion;
230 extern const uint64_t minValidProtocolVersion;
231 extern const uint64_t compatibleProtocolVersionMask;
232
233 struct _IncludeVersion {
234 uint64_t v;
_IncludeVersion_IncludeVersion235 explicit _IncludeVersion( uint64_t defaultVersion ) : v(defaultVersion) {
236 ASSERT( defaultVersion >= minValidProtocolVersion );
237 }
238 template <class Ar>
write_IncludeVersion239 void write( Ar& ar ) {
240 ar.setProtocolVersion(v);
241 ar << v;
242 }
243 template <class Ar>
read_IncludeVersion244 void read( Ar& ar ) {
245 ar >> v;
246 if (v < minValidProtocolVersion) {
247 auto err = incompatible_protocol_version();
248 TraceEvent(SevError, "InvalidSerializationVersion").error(err).detailf("Version", "%llx", v);
249 throw err;
250 }
251 if (v > currentProtocolVersion) {
252 // For now, no forward compatibility whatsoever is supported. In the future, this check may be weakened for
253 // particular data structures (e.g. to support mismatches between client and server versions when the client
254 // must deserialize zookeeper and database structures)
255 auto err = incompatible_protocol_version();
256 TraceEvent(SevError, "FutureProtocolVersion").error(err).detailf("Version", "%llx", v);
257 throw err;
258 }
259 ar.setProtocolVersion(v);
260 }
261 };
262 struct _AssumeVersion {
263 uint64_t v;
_AssumeVersion_AssumeVersion264 explicit _AssumeVersion( uint64_t version ) : v(version) {
265 ASSERT( version >= minValidProtocolVersion );
266 }
write_AssumeVersion267 template <class Ar> void write( Ar& ar ) { ar.setProtocolVersion(v); }
read_AssumeVersion268 template <class Ar> void read( Ar& ar ) { ar.setProtocolVersion(v); }
269 };
270 struct _Unversioned {
write_Unversioned271 template <class Ar> void write( Ar& ar ) { ar.setProtocolVersion(0); }
read_Unversioned272 template <class Ar> void read( Ar& ar ) { ar.setProtocolVersion(0); }
273 };
274
275 // These functions return valid options to the VersionOptions parameter of the constructor of each archive type
276 inline _IncludeVersion IncludeVersion( uint64_t defaultVersion = currentProtocolVersion ) { return _IncludeVersion(defaultVersion); }
AssumeVersion(uint64_t version)277 inline _AssumeVersion AssumeVersion( uint64_t version ) { return _AssumeVersion(version); }
Unversioned()278 inline _Unversioned Unversioned() { return _Unversioned(); }
279
280 //static uint64_t size_limits[] = { 0ULL, 255ULL, 65535ULL, 16777215ULL, 4294967295ULL, 1099511627775ULL, 281474976710655ULL, 72057594037927935ULL, 18446744073709551615ULL };
281
282 class BinaryWriter : NonCopyable {
283 public:
284 static const int isDeserializing = 0;
285 typedef BinaryWriter WRITER;
286
serializeBytes(StringRef bytes)287 void serializeBytes( StringRef bytes ) {
288 serializeBytes(bytes.begin(), bytes.size());
289 }
serializeBytes(const void * data,int bytes)290 void serializeBytes(const void* data, int bytes) {
291 valgrindCheck( data, bytes, "serializeBytes" );
292 void* p = writeBytes(bytes);
293 memcpy(p, data, bytes);
294 }
295 template <class T>
serializeBinaryItem(const T & t)296 void serializeBinaryItem( const T& t ) {
297 *(T*)writeBytes(sizeof(T)) = t;
298 }
getData()299 void* getData() { return data; }
getLength()300 int getLength() { return size; }
toValue()301 Standalone<StringRef> toValue() { return Standalone<StringRef>( StringRef(data,size), arena ); }
302 template <class VersionOptions>
BinaryWriter(VersionOptions vo)303 explicit BinaryWriter( VersionOptions vo ) : data(NULL), size(0), allocated(0) { vo.write(*this); }
BinaryWriter(BinaryWriter && rhs)304 BinaryWriter( BinaryWriter&& rhs ) : arena(std::move(rhs.arena)), data(rhs.data), size(rhs.size), allocated(rhs.allocated), m_protocolVersion(rhs.m_protocolVersion) {
305 rhs.size = 0;
306 rhs.allocated = 0;
307 rhs.data = 0;
308 }
309 void operator=( BinaryWriter&& r) {
310 arena = std::move(r.arena);
311 data = r.data;
312 size = r.size;
313 allocated = r.allocated;
314 m_protocolVersion = r.m_protocolVersion;
315 r.size = 0;
316 r.allocated = 0;
317 r.data = 0;
318 }
319
320 template <class T, class VersionOptions>
toValue(T const & t,VersionOptions vo)321 static Standalone<StringRef> toValue( T const& t, VersionOptions vo ) {
322 BinaryWriter wr(vo);
323 wr << t;
324 return wr.toValue();
325 }
326
bytesNeeded(uint64_t val)327 static int bytesNeeded( uint64_t val ) {
328 int n;
329 for( n=1; n<8 && (val>>(n*8)); ++n );
330 return n;
331 }
332
serializeAsTuple(StringRef str)333 void serializeAsTuple( StringRef str ) {
334 size_t last_pos = 0;
335
336 serializeBytes(LiteralStringRef("\x01"));
337
338 for (size_t pos = 0; pos < str.size(); ++pos) {
339 if (str[pos] == '\x00') {
340 serializeBytes(str.substr(last_pos,pos - last_pos));
341 serializeBytes(LiteralStringRef("\x00\xff"));
342 last_pos = pos + 1;
343 }
344 }
345 serializeBytes(str.substr(last_pos,str.size() - last_pos));
346 serializeBytes(LiteralStringRef("\x00"));
347 }
348
serializeAsTuple(bool t)349 void serializeAsTuple( bool t ) {
350 if(!t) {
351 void* p = writeBytes(1);
352 ((uint8_t*)p)[0] = (uint8_t)20;
353 } else {
354 void* p = writeBytes(2);
355 ((uint8_t*)p)[0] = (uint8_t)21;
356 ((uint8_t*)p)[1] = (uint8_t)1;
357 }
358 }
359
serializeAsTuple(uint64_t t)360 void serializeAsTuple( uint64_t t ) {
361 if(t == 0) {
362 void* p = writeBytes(1);
363 ((uint8_t*)p)[0] = (uint8_t)20;
364 return;
365 }
366
367
368 //int n = ( std::lower_bound(size_limits, size_limits+9, t) - size_limits );
369 //ASSERT( n <= 8 );
370 int n = bytesNeeded(t);
371 void* p = writeBytes(n+1);
372 ((uint8_t*)p)[0] = (uint8_t)(20+n);
373 uint64_t x = bigEndian64(t);
374 memcpy((uint8_t*)p+1, (uint8_t*)&x+(8-n), n);
375 }
376
serializeAsTuple(int64_t t)377 void serializeAsTuple( int64_t t ) {
378 if(t == 0) {
379 void* p = writeBytes(1);
380 ((uint8_t*)p)[0] = (uint8_t)20;
381 } else if(t > 0) {
382 //int n = ( std::lower_bound(size_limits, size_limits+9, t) - size_limits );
383 //ASSERT( n <= 9 );
384 int n = bytesNeeded(t);
385
386 void* p = writeBytes(n+1);
387 ((uint8_t*)p)[0] = (uint8_t)(20+n);
388 uint64_t x = bigEndian64((uint64_t)t);
389 memcpy((uint8_t*)p+1, (uint8_t*)&x+(8-n), n);
390 } else {
391 //int n = ( std::lower_bound(size_limits, size_limits+9, -t) - size_limits );
392 //ASSERT( n <= 9 );
393 int n = bytesNeeded(-t);
394
395 void* p = writeBytes(n+1);
396 ((uint8_t*)p)[0] = (uint8_t)(20-n);
397 uint64_t x = bigEndian64(t-1);
398 memcpy((uint8_t*)p+1, (uint8_t*)&x+(8-n), n);
399 }
400 }
401
protocolVersion()402 uint64_t protocolVersion() const { return m_protocolVersion; }
setProtocolVersion(uint64_t pv)403 void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
404 private:
405 Arena arena;
406 uint8_t* data;
407 int size, allocated;
408 uint64_t m_protocolVersion;
409
writeBytes(int s)410 void* writeBytes(int s) {
411 int p = size;
412 size += s;
413 if (size > allocated) {
414 if(size <= 512-sizeof(ArenaBlock)) {
415 allocated = 512-sizeof(ArenaBlock);
416 } else if(size <= 4096-sizeof(ArenaBlock)) {
417 allocated = 4096-sizeof(ArenaBlock);
418 } else {
419 allocated = std::max(allocated*2, size);
420 }
421 Arena newArena;
422 uint8_t* newData = new ( newArena ) uint8_t[ allocated ];
423 memcpy(newData, data, p);
424 arena = newArena;
425 data = newData;
426 }
427 return data+p;
428 }
429 };
430
431 // A known-length memory segment and an unknown-length memory segment which can be written to as a whole.
432 struct SplitBuffer {
433 void write(const void* data, int length);
434 void write(const void* data, int length, int offset);
435 void writeAndShrink(const void* data, int length);
436 uint8_t *begin, *next;
437 int first_length;
438 };
439
440 // A writer that can serialize to a SplitBuffer
441 class OverWriter {
442 public:
443 typedef OverWriter WRITER;
444
445 template <class VersionOptions>
OverWriter(SplitBuffer buf,VersionOptions vo)446 explicit OverWriter(SplitBuffer buf, VersionOptions vo) : buf(buf), len(std::numeric_limits<int>::max()) { vo.write(*this); }
447
448 template <class VersionOptions>
OverWriter(void * ptr,int len,VersionOptions vo)449 explicit OverWriter(void *ptr, int len, VersionOptions vo) : len(len) {
450 buf.begin = (uint8_t *)ptr;
451 buf.first_length = len;
452 vo.write(*this);
453 }
454
serializeBytes(StringRef bytes)455 void serializeBytes( StringRef bytes ) {
456 serializeBytes(bytes.begin(), bytes.size());
457 }
serializeBytes(const void * data,int bytes)458 void serializeBytes(const void* data, int bytes) {
459 valgrindCheck( data, bytes, "serializeBytes" );
460 writeBytes(data, bytes);
461 }
462 template <class T>
serializeBinaryItem(const T & t)463 void serializeBinaryItem( const T& t ) {
464 writeBytes(&t, sizeof(T));
465 }
466
protocolVersion()467 uint64_t protocolVersion() const { return m_protocolVersion; }
setProtocolVersion(uint64_t pv)468 void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
469
470 private:
471 int len;
472 SplitBuffer buf;
473 uint64_t m_protocolVersion;
474
writeBytes(const void * data,int wlen)475 void writeBytes(const void *data, int wlen) {
476 ASSERT(wlen <= len);
477 buf.writeAndShrink(data, wlen);
478 len -= wlen;
479 }
480 };
481
482
483 class ArenaReader {
484 public:
485 static const int isDeserializing = 1;
486 typedef ArenaReader READER;
487
readBytes(int bytes)488 const void* readBytes( int bytes ) {
489 const char* b = begin;
490 const char* e = b + bytes;
491 ASSERT( e <= end );
492 begin = e;
493 return b;
494 }
495
peekBytes(int bytes)496 const void* peekBytes( int bytes ) {
497 ASSERT( begin + bytes <= end );
498 return begin;
499 }
500
serializeBytes(void * data,int bytes)501 void serializeBytes(void* data, int bytes) {
502 memcpy(data, readBytes(bytes), bytes);
503 }
504
arenaRead(int bytes)505 const uint8_t* arenaRead( int bytes ) {
506 return (const uint8_t*)readBytes(bytes);
507 }
508
509 template <class T>
serializeBinaryItem(T & t)510 void serializeBinaryItem( T& t ) {
511 t = *(T*)readBytes(sizeof(T));
512 }
513
514 template <class VersionOptions>
ArenaReader(Arena const & arena,const StringRef & input,VersionOptions vo)515 ArenaReader( Arena const& arena, const StringRef& input, VersionOptions vo ) : m_pool(arena), check(NULL) {
516 begin = (const char*)input.begin();
517 end = begin + input.size();
518 vo.read(*this);
519 }
520
arena()521 Arena& arena() { return m_pool; }
522
protocolVersion()523 uint64_t protocolVersion() const { return m_protocolVersion; }
setProtocolVersion(uint64_t pv)524 void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
525
empty()526 bool empty() const { return begin == end; }
527
checkpoint()528 void checkpoint() {
529 check = begin;
530 }
531
rewind()532 void rewind() {
533 ASSERT(check != NULL);
534 begin = check;
535 check = NULL;
536 }
537
538 private:
539 const char *begin, *end, *check;
540 Arena m_pool;
541 uint64_t m_protocolVersion;
542 };
543
544 class BinaryReader {
545 public:
546 static const int isDeserializing = 1;
547 typedef BinaryReader READER;
548
readBytes(int bytes)549 const void* readBytes( int bytes ) {
550 const char* b = begin;
551 const char* e = b + bytes;
552 ASSERT( e <= end );
553 begin = e;
554 return b;
555 }
556
peekBytes(int bytes)557 const void* peekBytes( int bytes ) {
558 ASSERT( begin + bytes <= end );
559 return begin;
560 }
561
serializeBytes(void * data,int bytes)562 void serializeBytes(void* data, int bytes) {
563 memcpy(data, readBytes(bytes), bytes);
564 }
565
566 template <class T>
serializeBinaryItem(T & t)567 void serializeBinaryItem( T& t ) {
568 t = *(T*)readBytes(sizeof(T));
569 }
570
arenaRead(int bytes)571 const uint8_t* arenaRead( int bytes ) {
572 // Reads and returns the next bytes.
573 // The returned pointer has the lifetime of this.arena()
574 // Could be implemented zero-copy if [begin,end) was in this.arena() already; for now is a copy
575 if (!bytes) return NULL;
576 uint8_t* dat = new (arena()) uint8_t[ bytes ];
577 serializeBytes( dat, bytes );
578 return dat;
579 }
580
581 template <class VersionOptions>
BinaryReader(const void * data,int length,VersionOptions vo)582 BinaryReader( const void* data, int length, VersionOptions vo ) {
583 begin = (const char*)data;
584 end = begin + length;
585 check = nullptr;
586 vo.read(*this);
587 }
588 template <class VersionOptions>
BinaryReader(const StringRef & s,VersionOptions vo)589 BinaryReader( const StringRef& s, VersionOptions vo ) { begin = (const char*)s.begin(); end = begin + s.size(); vo.read(*this); }
590 template <class VersionOptions>
BinaryReader(const std::string & v,VersionOptions vo)591 BinaryReader( const std::string& v, VersionOptions vo ) { begin = v.c_str(); end = begin + v.size(); vo.read(*this); }
592
arena()593 Arena& arena() { return m_pool; }
594
595 template <class T, class VersionOptions>
fromStringRef(StringRef sr,VersionOptions vo)596 static T fromStringRef( StringRef sr, VersionOptions vo ) {
597 T t;
598 BinaryReader r(sr, vo);
599 r >> t;
600 return t;
601 }
602
protocolVersion()603 uint64_t protocolVersion() const { return m_protocolVersion; }
setProtocolVersion(uint64_t pv)604 void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
605
assertEnd()606 void assertEnd() { ASSERT( begin == end ); }
607
empty()608 bool empty() const { return begin == end; }
609
checkpoint()610 void checkpoint() {
611 check = begin;
612 }
613
rewind()614 void rewind() {
615 ASSERT(check != nullptr);
616 begin = check;
617 check = nullptr;
618 }
619
620
621 private:
622 const char *begin, *end, *check;
623 Arena m_pool;
624 uint64_t m_protocolVersion;
625 };
626
627 struct SendBuffer {
628 int bytes_written, bytes_sent;
629 uint8_t const* data;
630 SendBuffer* next;
631 };
632
633 struct PacketBuffer : SendBuffer, FastAllocated<PacketBuffer> {
634 int reference_count;
635 enum { DATA_SIZE = 4096 - 28 }; //28 is the size of the PacketBuffer fields
636 uint8_t data[ DATA_SIZE ];
637
PacketBufferPacketBuffer638 PacketBuffer() : reference_count(1) {
639 next = 0;
640 bytes_written = bytes_sent = 0;
641 ((SendBuffer*)this)->data = data;
642 static_assert( sizeof(PacketBuffer) == 4096, "PacketBuffer size mismatch" );
643 }
nextPacketBufferPacketBuffer644 PacketBuffer* nextPacketBuffer() { return (PacketBuffer*)next; }
addrefPacketBuffer645 void addref() { ++reference_count; }
delrefPacketBuffer646 void delref() { if (!--reference_count) delete this; }
bytes_unwrittenPacketBuffer647 int bytes_unwritten() const { return DATA_SIZE-bytes_written; }
648 };
649
650 struct PacketWriter {
651 static const int isDeserializing = 0;
652 typedef PacketWriter WRITER;
653
654 PacketBuffer* buffer;
655 struct ReliablePacket *reliable; // NULL if this is unreliable; otherwise the last entry in the ReliablePacket::cont chain
656 int length;
657 uint64_t m_protocolVersion;
658
659 // reliable is NULL if this is an unreliable packet, or points to a ReliablePacket. PacketWriter is responsible
660 // for filling in reliable->buffer, ->cont, ->begin, and ->end, but not ->prev or ->next.
661 template <class VersionOptions>
PacketWriterPacketWriter662 PacketWriter(PacketBuffer* buf, ReliablePacket* reliable, VersionOptions vo) { init(buf, reliable); vo.read(*this); }
663
serializeBytesPacketWriter664 void serializeBytes(const void* data, int bytes) {
665 if (bytes <= buffer->bytes_unwritten()) {
666 memcpy(buffer->data + buffer->bytes_written, data, bytes);
667 buffer->bytes_written += bytes;
668 } else {
669 serializeBytesAcrossBoundary(data, bytes);
670 }
671 }
672 void serializeBytesAcrossBoundary(const void* data, int bytes);
673 void writeAhead( int bytes, struct SplitBuffer* );
674 void nextBuffer();
675 PacketBuffer* finish();
sizePacketWriter676 int size() { return length; }
677
serializeBytesPacketWriter678 void serializeBytes( StringRef bytes ) {
679 serializeBytes(bytes.begin(), bytes.size());
680 }
681 template <class T>
serializeBinaryItemPacketWriter682 void serializeBinaryItem( const T& t ) {
683 if (sizeof(T) <= buffer->bytes_unwritten()) {
684 *(T*)(buffer->data + buffer->bytes_written) = t;
685 buffer->bytes_written += sizeof(T);
686 } else {
687 serializeBytesAcrossBoundary(&t, sizeof(T));
688 }
689 }
protocolVersionPacketWriter690 uint64_t protocolVersion() const { return m_protocolVersion; }
setProtocolVersionPacketWriter691 void setProtocolVersion(uint64_t pv) { m_protocolVersion = pv; }
692 private:
693 void init( PacketBuffer* buf, ReliablePacket* reliable );
694 };
695
696 struct ISerializeSource {
697 virtual void serializePacketWriter( PacketWriter& ) const = 0;
698 virtual void serializeBinaryWriter( BinaryWriter& ) const = 0;
699 };
700
701 template <class T>
702 struct MakeSerializeSource : ISerializeSource {
serializePacketWriterMakeSerializeSource703 virtual void serializePacketWriter( PacketWriter& w ) const { ((T const*)this)->serialize(w); }
serializeBinaryWriterMakeSerializeSource704 virtual void serializeBinaryWriter( BinaryWriter& w ) const { ((T const*)this)->serialize(w); }
705 };
706
707 template <class T>
708 struct SerializeSource : MakeSerializeSource<SerializeSource<T>> {
709 T const& value;
SerializeSourceSerializeSource710 SerializeSource(T const& value) : value(value) {}
serializeSerializeSource711 template <class Ar> void serialize(Ar& ar) const { ar << value; }
712 };
713
714 template <class T>
715 struct SerializeBoolAnd : MakeSerializeSource<SerializeBoolAnd<T>> {
716 bool b;
717 T const& value;
SerializeBoolAndSerializeBoolAnd718 SerializeBoolAnd( bool b, T const& value ) : b(b), value(value) {}
serializeSerializeBoolAnd719 template <class Ar> void serialize(Ar& ar) const { ar << b << value; }
720 };
721
722 struct SerializeSourceRaw : MakeSerializeSource<SerializeSourceRaw> {
723 StringRef data;
SerializeSourceRawSerializeSourceRaw724 SerializeSourceRaw(StringRef data) : data(data) {}
serializeSerializeSourceRaw725 template <class Ar> void serialize(Ar& ar) const { ar.serializeBytes(data); }
726 };
727
728 #endif
729