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