OpenSDN source code
src/contrail-common/base/proto.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef ctrlplane_proto_h
6 #define ctrlplane_proto_h
7 
8 #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
9 #define BOOST_MPL_LIMIT_MAP_SIZE 30
10 
11 #include <map>
12 #include <memory>
13 
14 #include <vector>
15 
16 #include <boost/ptr_container/ptr_vector.hpp>
17 #include <boost/function.hpp>
18 #include <boost/type_traits/is_same.hpp>
19 #include <boost/type_traits/is_base_of.hpp>
20 #include <boost/mpl/equal_to.hpp>
21 #include <boost/mpl/for_each.hpp>
22 #include <boost/mpl/greater.hpp>
23 #include <boost/mpl/list.hpp>
24 #include <boost/mpl/map.hpp>
25 #include <boost/mpl/or.hpp>
26 #include <boost/mpl/vector.hpp>
27 #include <boost/mpl/string.hpp>
28 
29 #include "base/compiler.h"
30 #include "base/logging.h"
31 #include "base/parse_object.h"
32 
33 namespace mpl = boost::mpl;
34 
35 class ParseContext {
36 public:
37 
38  ParseContext();
39  ~ParseContext();
40 
42 
43  void Push(ParseObject *data);
44  ParseObject *Pop();
45 
46  void SwapData(ParseObject *obj);
47  void ReleaseData();
48 
49  ParseObject *data();
50 
51  void advance(int delta);
52  int offset() const { return offset_; }
53 
54  void set_lensize(int lensize);
55  int lensize() const;
56  void set_size(size_t length);
57  size_t size() const;
58  void set_total_size();
59  size_t total_size() const;
60 
61  void SetError(int error, int subcode, std::string type, const uint8_t *data,
62  int data_size);
64 private:
65 
67  struct StackFrame;
68  int offset_;
69  std::vector<StackFrame *> stack_;
70 };
71 
73 public:
74  typedef boost::function<void(EncodeContext *, uint8_t *, int, int)> CallbackType;
75 
76  EncodeContext();
78 
79  void Push();
80  void Pop(bool callback);
81  void AddCallback(CallbackType cb, uint8_t *data, int arg);
82 
83  void advance(int delta);
84  int length() const;
85 
86  void SaveOffset(std::string);
88 private:
89  struct StackFrame;
90  boost::ptr_vector<StackFrame> stack_;
92 };
93 
94 template <class C, typename T, T C::* Member>
95 struct Accessor {
96  typedef T C::* member_ptr_t;
97  static void set(C *obj, T value) {
98  obj->*Member = value;
99  }
100  static T get(const C *obj) {
101  return obj->*Member;
102  }
103 };
104 
105 template <class C, std::string C::* Member>
106 struct Accessor<C, std::string, Member> {
107  static void set(C*obj, const uint8_t *data, size_t elem_size) {
108  obj->*Member = std::string((const char *) data, elem_size);
109  }
110  static int size(const C *obj) {
111  return (obj->*Member).size();
112  }
113  static std::string::const_iterator begin(const C *obj) {
114  return (obj->*Member).begin();
115  }
116  static std::string::const_iterator end(const C *obj) {
117  return (obj->*Member).end();
118  }
119 };
120 
121 template <class C, typename T, std::vector<T> C::* Member>
123  static void set(C*obj, const uint8_t *data, size_t elem_size) {
124  obj->*Member = std::vector<T>();
125  size_t size = sizeof(T);
126  for (size_t i = 0; i < elem_size; i += size) {
127  T value = get_value(data, size);
128  data += size;
129  (obj->*Member).push_back(value);
130  }
131  }
132  static int size(const C *obj) {
133  return (obj->*Member).size() * sizeof(T);
134  }
135  static typename std::vector<T>::const_iterator begin(const C *obj) {
136  return (obj->*Member).begin();
137  }
138  static typename std::vector<T>::const_iterator end(const C *obj) {
139  return (obj->*Member).end();
140  }
141 };
142 
143 // Extract the underlying type for pointer types.
144 template <typename T>
145 struct ValueType {
146  typedef T type;
147 };
148 template <typename T>
149 struct ValueType<T *> {
150  typedef T type;
151 };
152 
153 template <typename Obj, typename Col, Col Obj::* Member>
156  typedef Col CollectionType;
157  typedef typename CollectionType::const_iterator iterator;
158  static void insert(Obj *obj, ValueType *element) {
159  (obj->*Member).push_back(element);
160  }
161  static iterator begin(const Obj *obj) {
162  return (obj->*Member).begin();
163  }
164  static iterator end(const Obj *obj) {
165  return (obj->*Member).end();
166  }
167 };
168 
169 // Interface
170 struct ElementBase {
171  static const int kSize = 0;
172  static const int kErrorCode = 0;
173  static const int kErrorSubcode = 0;
174  struct NullCtxInit {
175  void operator()(void *) {
176  }
177  };
178  struct NoMatch {
179  bool match(const void *) {
180  return false;
181  }
182  };
183  static bool Verifier(const void * obj, const uint8_t *data, size_t size,
184  ParseContext *context) {
185  return true;
186  }
187 
188  typedef void SaveOffset; // Save the offset in encode context
189  typedef void ContextType; // push a new context on the stack
190  typedef NullCtxInit ContextInit; // initialize the context data
192  typedef void Setter;
193  typedef void EncodingCallback;
194  typedef void ContextSwap; // swap a context with another one
195  typedef void SizeSetter; // set the size of the element
196 };
197 
198 struct ChoiceBase : public ElementBase {
199  typedef void ContextStorer; // store the context data on pop.
200 };
201 
202 class SequenceBase : public ElementBase {
203 public:
204  static const int kMinOccurs = 1;
205  static const int kMaxOccurs = 1;
206  typedef void ContextStorer; // store the context data on pop.
207 };
208 
209 #include "base/proto_impl.h"
210 
211 template<class Derived>
212 class ProtoElement : public ElementBase {
213 public:
214  typedef void SequenceLength;
215 
216  template <typename T>
217  static void Writer(T *msg, uint8_t *data, size_t size) {
218  typedef typename Derived::Setter setter_t;
219  typedef typename mpl::if_<
220  mpl::equal_to<
221  mpl::int_<Derived::kSize>, mpl::int_<-1> >,
224  >::type writer_t;
225  writer_t writer;
226  writer(data, Derived::kSize, msg);
227  }
228 
229  template <typename T>
230  static int Parse(const uint8_t *data, size_t size, ParseContext *context,
231  T *obj) {
232  typedef typename mpl::if_<
233  mpl::greater<
234  mpl::int_<Derived::kSize>, mpl::int_<0> >,
237  >::type cmp_t;
238 
239  cmp_t cmp;
240  if (!cmp(size)) {
241  PROTO_DEBUG("Error: cmp(size) failed");
242  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
243  TYPE_NAME(Derived), data,
244  Derived::kSize > 0 ? Derived::kSize : context->size());
245  return -1;
246  }
247  if (!Derived::Verifier(obj, data, size, context)) {
248  PROTO_DEBUG(TYPE_NAME(Derived) << " Verifier failed");
249  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
250  TYPE_NAME(Derived), data,
251  Derived::kSize > 0 ? Derived::kSize : context->size());
252  return -1;
253  }
254 
255  typedef typename Derived::ContextInit ctx_init_t;
256  ctx_init_t initializer;
257  initializer(obj);
258 
260  int res = slen(context, data, Derived::kSize, size, obj);
261  if (res < 0) {
262  PROTO_DEBUG(TYPE_NAME(Derived) << ": error: Length Setter failed");
263  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
264  TYPE_NAME(Derived), data, context->lensize());
265  return -1;
266  }
267 
268  typedef typename mpl::if_<boost::is_same<typename Derived::SizeSetter, void>,
269  typename mpl::if_<
270  mpl::equal_to<mpl::int_<Derived::kSize>, mpl::int_<-1> >,
272  typename mpl::if_<
273  mpl::greater<mpl::int_<Derived::kSize>, mpl::int_<0> >,
276  >::type
277  >::type,
279  >::type setter_t;
280 
281  setter_t setter;
282  res = setter(data, size, context, obj);
283  if (res < 0) {
284  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
285  TYPE_NAME(Derived), data,
286  Derived::kSize > 0 ? Derived::kSize : context->size());
287  }
288  return res;
289  }
290 
291  template <typename T>
292  static int Encode(EncodeContext *context, const T *msg, uint8_t *data,
293  size_t size) {
294  typedef typename
295  mpl::if_<boost::is_same<typename Derived::SizeSetter, void>,
296  typename mpl::if_<mpl::equal_to<mpl::int_<Derived::kSize>, mpl::int_<-1> >,
299  typename Derived::SizeSetter
300  >::type size_value_t;
301 
302  int element_size = size_value_t::get(msg);
303  if (data == NULL) {
304  context->advance(element_size);
305  return element_size;
306  }
307  assert(element_size >= 0);
308  if (size < (size_t) element_size) {
309  return -1;
310  }
311 
312  // Setter overrides SequenceLength. Do not register a sequence length
313  // callback if the element has defined a Setter.
314  typename mpl::if_<
315  boost::is_same<typename Derived::Setter, void>,
318  slen(&ProtoElement::SequenceLengthWriteLen, context, data, element_size);
319 
321  cbadd(context, data, element_size);
322 
324 
325  Derived::Writer(msg, data, size);
326 
327  context->advance(element_size);
328  return element_size;
329  }
330 
331 private:
332  static void SequenceLengthWriteLen(EncodeContext *context, uint8_t *data,
333  int offset, int element_size) {
334  int length = context->length() - offset - element_size;
335  put_value(data, element_size, length);
336  }
337 };
338 
339 template <typename Setter, typename T>
340 struct ChoiceSetter {
341  void operator()(T *obj, int &value) {
342  Setter::set(obj, value);
343  }
344 };
345 
346 template <typename T>
347 struct ChoiceSetter<void, T> {
348  void operator()(T* obj, int value) { }
349 };
350 
351 template <class Derived>
352 class ProtoChoice : public ChoiceBase {
353 public:
354  template <typename T>
355  static int Parse(const uint8_t *data, size_t size, ParseContext *context,
356  T *obj) {
357  int advance = Derived::kSize;
358  int value = -1;
359 
360  if (size < (size_t) advance) {
361  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
362  TYPE_NAME(Derived), data, advance);
363  return -1;
364  }
365 
366  value = get_value(data, advance);
367 
368  data += advance;
369  size -= advance;
370  context->advance(advance);
371 
372  typedef typename mpl::if_<
373  boost::is_same<typename Derived::Setter, void>,
376  >::type choice_setter_t;
377 
378  choice_setter_t setter;
379  setter(obj, value);
380 
381  int result = ParseChoice(data, size, value, context, obj);
382  if (result < 0) {
383  PROTO_DEBUG(TYPE_NAME(Derived) << " ParseChoice failed");
384  if (result == -2) {
385  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
386  TYPE_NAME(Derived), data - advance, advance);
387  }
388  return result;
389  }
390  advance += result;
391  return advance;
392  }
393 
394  template <typename T>
395  static int Encode(EncodeContext *context, const T *msg, uint8_t *data,
396  size_t size) {
397  typedef typename Derived::Choice choice_t;
398  int result = 0;
399  ChoiceEncoder<T> encoder(context, msg, data, size, &result);
400  mpl::for_each<choice_t>(encoder);
401  return result;
402  }
403 
404 private:
405  template <typename T>
406  struct ChoiceMatcher {
407  ChoiceMatcher(const uint8_t *data, size_t size, int value,
408  ParseContext *context, T *obj, int *resultp)
410  obj(obj), resultp(resultp), found(false) {
411  }
412  template <typename U>
413  void operator()(U x) {
414  if (found) return;
415  if (U::first::value != -1 && U::first::value != value) {
416  return;
417  }
418  found = true;
420  parser_t;
421  *resultp = parser_t::Parse(data, size, context, obj);
422  }
423  const uint8_t *data;
424  size_t size;
425  int value;
427  T *obj;
428  int *resultp;
429  bool found;
430  };
431  template <typename T>
432  static int ParseChoice(const uint8_t *data, size_t size, int value,
433  ParseContext *context, T *obj) {
434  int result = -2;
435  ChoiceMatcher<T> match(data, size, value, context, obj, &result);
436  mpl::for_each<typename Derived::Choice>(match);
437  return result;
438  }
439 
440  template <typename T>
441  struct ChoiceEncoder {
442  ChoiceEncoder(EncodeContext *context, const T *msg, uint8_t *data, int size,
443  int *resultp)
444  : context(context), msg(msg), data(data), size(size),
445  resultp(resultp), found(false) {
446  }
447  template <typename U, typename CtxType>
448  struct EncoderTrue {
449  int operator()(int opt, EncodeContext *context, const CtxType *msg,
450  uint8_t *data, int size) {
451  if (Derived::kSize) {
452  if (data != NULL) {
453  if (size < Derived::kSize) return -1;
454  put_value(data, Derived::kSize, opt);
455  data += Derived::kSize;
456  size -= Derived::kSize;
457  }
458  context->advance(Derived::kSize);
459  }
460  int result = U::Encode(context, msg, data, size);
461  if (result >= 0) {
462  result += Derived::kSize;
463  }
464  return result;
465  }
466  };
467  template <typename U, typename CtxType>
468  struct EncoderSetter {
469  int operator()(int opt, EncodeContext *context, const CtxType *msg,
470  uint8_t *data, int size) {
471  int value = Derived::Setter::get(msg);
472  if (value == opt || opt == -1) {
473  return EncoderTrue<U, CtxType>()(value, context, msg, data, size);
474  }
475  return 0;
476  }
477  };
478  template <typename U>
479  struct EncoderMatch {
480  int operator()(int opt, EncodeContext *context, const T *msg,
481  uint8_t *data, int size) {
482  typename U::ContextMatch matcher;
483  if (matcher.match(msg)) {
484  return EncoderTrue<U, T>()(opt, context, msg, data, size);
485  }
486  return 0;
487  }
488  };
489  template <typename U>
490  struct EncoderRunTime {
491  int operator()(int opt, EncodeContext *context, const T *msg,
492  uint8_t *data, int size) {
493  if (typeid(*msg) == typeid(typename U::ContextType)) {
494  typedef typename U::ContextType ctx_t;
495  const ctx_t *ctx = static_cast<const ctx_t *>(msg);
496 
497  typedef typename mpl::if_<
498  boost::is_same<typename Derived::Setter, void>,
501  >::type encoder;
502  return encoder()(opt, context, ctx, data, size);
503  }
504  return 0;
505  }
506  };
507  struct EncoderNil {
508  int operator()(int opt, EncodeContext *context, T *msg,
509  uint8_t *data, int size) {
510  return 0;
511  }
512  };
513  template <typename U>
514  void operator()(U x) {
515  if (*resultp < 0 || found) {
516  return;
517  }
518  // The choice element can be determined by:
519  // 1. ContextType of the descendent or
520  // 2. ContextMatch type of the descendent
521  // In the case of ContextType match, the match can be either
522  // performed at compile type (in case of exact match) or at run
523  // type using RTTI.
524  typedef typename mpl::if_<
525  boost::is_same<typename U::second::ContextType, T>,
527  typename mpl::if_<
528  boost::is_same<typename U::second::ContextType, void>,
530  typename mpl::if_<
531  boost::is_base_of<T, typename U::second::ContextType>,
533  EncoderNil
534  >::type
535  >::type
536  >::type choice_t;
537  choice_t choice;
538  int result = choice(U::first::value, context, msg, data, size);
539  if (result < 0) {
540  *resultp = result;
541  } else if (result > 0) {
542  found = true;
543  *resultp += result;
544  }
545  }
546  private:
548  const T *msg;
549  uint8_t *data;
550  int size;
551  int *resultp;
552  bool found;
553  };
554 };
555 
556 template <class Derived>
557 class ProtoSequence : public SequenceBase {
558 public:
559  template <typename T>
560  struct SequenceParser {
561  SequenceParser(const uint8_t *data, size_t size, ParseContext *context,
562  T *obj, int *resultp)
563  : data(data), size(size), context(context), obj(obj),
564  resultp(resultp) {
565  }
566 
567  template <typename U>
568  void operator()(U x) {
569  if (*resultp < 0) {
570  return;
571  }
572  typedef detail::DescendentParser<Derived, U> parser_t;
573  size_t prev_size = context->size();
574  int result = parser_t::Parse(data, size, context, obj);
575  if (result < 0) {
576  *resultp = result;
577  return;
578  }
579 
580  data += result;
581  size -= result;
582  context->advance(result);
583  *resultp += result;
584 
585  if (context->size() != prev_size) {
586  size = context->size();
588  } else {
589  context->set_size(prev_size - result);
590  }
591  }
592 
593  const uint8_t *data;
594  size_t size;
596  T *obj;
597  int *resultp;
598  };
599 
600  template <typename T>
601  static int Parse(const uint8_t *data, size_t size, ParseContext *context,
602  T *obj) {
603  int min = Derived::kMinOccurs;
604  if (min == 0 && size == 0) {
605  return 0;
606  }
607  if (!Derived::Verifier(obj, data, size, context)) {
608  PROTO_DEBUG(TYPE_NAME(Derived) << " Verifier failed");
609  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
610  TYPE_NAME(Derived), data,
611  Derived::kSize > 0 ? Derived::kSize : context->size());
612  return -1;
613  }
614  int lensize = Derived::kSize;
615  int length = size;
616  if (lensize) {
617  if (size < (size_t) lensize) {
618  PROTO_DEBUG("Error: size = " << size << " lensize = " << lensize);
619  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
620  TYPE_NAME(Derived), data, lensize);
621  return -1;
622  }
623  // TODO: options for length (include or exclude length field).
624  length = get_value(data, lensize);
625  assert(length >= 0);
626  size -= lensize;
627  if ((size_t) length > size) {
628  PROTO_DEBUG("Error: length = " << length << " size = " << size);
629  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
630  TYPE_NAME(Derived), data, lensize);
631  return -1;
632  }
633  data += lensize;
634  context->advance(lensize);
635  }
636  int result = lensize;
637  int max = Derived::kMaxOccurs;
638  for (int i = 0; (max == -1 || i < max) && (length > 0); i++) {
639  int sublen = 0;
640  typedef typename Derived::ContextStorer ctx_access_t;
641  typedef typename
643  typedef typename mpl::if_<boost::is_same<typename Derived::ContextSwap, void>,
646  >::type ContextPush;
647  ContextPush pushfn;
648  typedef typename mpl::if_<boost::is_same<child_obj_t, void>,
649  T, child_obj_t>::type ctx_t;
650  ctx_t *child_obj = pushfn(context, obj);
651 
652  SequenceParser<ctx_t> parser(data, length, context, child_obj, &sublen);
653  mpl::for_each<typename Derived::Sequence>(parser);
654  if (sublen < 0) {
655  PROTO_DEBUG(TYPE_NAME(Derived) << ": error: sublen " << sublen);
656  return -1;
657  }
658  if (sublen < (int)(context->size() + context->lensize())) {
659  PROTO_DEBUG(TYPE_NAME(Derived) << ": error: sublen " << sublen
660  << " < " << context->size() << "+" << context->lensize());
661  context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
662  TYPE_NAME(Derived), data,
663  context->size()+context->lensize());
664  return -1;
665  }
666  result += sublen;
667  data += sublen;
668  length -= sublen;
669 
670  typedef typename mpl::if_<boost::is_same<typename Derived::ContextSwap, void>,
673  >::type ContextPop;
674  ContextPop popfn;
675  popfn(context, obj);
676  }
677  return result;
678  }
679 
680  template <typename T>
681  struct SingleEncoder {
682  typedef typename Derived::Sequence sequence_t;
683  int operator()(EncodeContext *context, const T *msg, uint8_t *data,
684  size_t size) {
685  int result = 0;
686  SequenceEncoder<T> encoder(context, msg, data, size, &result);
687  mpl::for_each<sequence_t>(encoder);
688  return result;
689  }
690  };
691 
692  template <typename T>
693  struct ListEncoder {
694  typedef typename Derived::Sequence sequence_t;
695  int operator()(EncodeContext *context, const T *msg, uint8_t *data,
696  size_t size) {
697  typedef typename Derived::ContextStorer ctx_access_t;
698  typedef typename
700  int result = 0;
701 
703  while (iter.HasNext(msg)) {
704  child_obj_t *child_obj = iter.Next();
705  int subres = 0;
706  context->Push();
707  SequenceEncoder<child_obj_t> encoder(context, child_obj,
708  data, size, &subres);
709  mpl::for_each<sequence_t>(encoder);
710  if (subres < 0) {
711  result = subres;
712  break;
713  }
714  result += subres;
715  if (data != NULL) {
716  data += subres;
717  size -= subres;
718  }
719  context->Pop(data != NULL);
720  }
721  return result;
722  }
723  };
724 
725  template <typename T>
726  static int Encode(EncodeContext *context, const T *msg, uint8_t *data,
727  size_t size) {
728  context->Push();
730  if (Derived::kSize > 0) {
731  // context push callback
732  if (data != NULL) {
733  context->AddCallback(&SequenceLengthWriteLen, data, Derived::kSize);
734  data += Derived::kSize;
735  size -= Derived::kSize;
736  }
737  context->advance(Derived::kSize);
738  }
739  typedef typename mpl::if_<
740  mpl::or_<
741  mpl::equal_to<mpl::int_<Derived::kMaxOccurs>,
742  mpl::int_<-1> >,
743  mpl::greater<mpl::int_<Derived::kMaxOccurs>,
744  mpl::int_<1> >
745  >,
747  SingleEncoder<T> >::type encoder_t;
748  encoder_t encoder;
749  int result = encoder(context, msg, data, size);
750  if (result >= 0) {
751  result += Derived::kSize;
752  context->Pop(data != NULL);
753  }
754  return result;
755  }
756 
757 private:
758  template <typename T>
761  size_t size, int *resultp)
762  : context(context), msg(msg), data(data), size(size),
763  resultp(resultp) {
764  }
765  template <typename U>
766  void operator()(U element) {
767  if (*resultp < 0) {
768  return;
769  }
770  int res = U::Encode(context, msg, data, size);
771  if (res < 0) {
772  *resultp = res;
773  } else {
774  *resultp += res;
775  }
776  if (data != NULL) {
777  data += res;
778  size -= res;
779  }
780  }
781 
782  private:
784  const T *msg;
785  uint8_t *data;
786  size_t size;
787  int *resultp;
788  };
789 
790  static void SequenceLengthWriteLen(EncodeContext *context, uint8_t *data,
791  int offset, int arg) {
792  int length = context->length() - Derived::kSize;
793  put_value(data, Derived::kSize, length);
794  }
795 };
796 
797 #endif
boost::function< void(EncodeContext *, uint8_t *, int, int)> CallbackType
void AddCallback(CallbackType cb, uint8_t *data, int arg)
EncodeOffsets & encode_offsets()
boost::ptr_vector< StackFrame > stack_
const ParseErrorContext & error_context()
void set_lensize(int lensize)
void set_size(size_t length)
void SetError(int error, int subcode, std::string type, const uint8_t *data, int data_size)
void Push(ParseObject *data)
ParseErrorContext error_context_
void SwapData(ParseObject *obj)
std::vector< StackFrame * > stack_
static int Encode(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
static int ParseChoice(const uint8_t *data, size_t size, int value, ParseContext *context, T *obj)
static int Parse(const uint8_t *data, size_t size, ParseContext *context, T *obj)
static int Encode(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
static void Writer(T *msg, uint8_t *data, size_t size)
static int Parse(const uint8_t *data, size_t size, ParseContext *context, T *obj)
static void SequenceLengthWriteLen(EncodeContext *context, uint8_t *data, int offset, int element_size)
static void SequenceLengthWriteLen(EncodeContext *context, uint8_t *data, int offset, int arg)
static int Encode(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
static int Parse(const uint8_t *data, size_t size, ParseContext *context, T *obj)
uint8_t type
Definition: load_balance.h:2
#define TYPE_NAME(_type)
Definition: logging.h:31
static void put_value(uint8_t *data, int size, uint64_t value)
Definition: parse_object.h:55
static uint64_t get_value(const uint8_t *data, int size)
Definition: parse_object.h:39
#define PROTO_DEBUG(args...)
Definition: proto_impl.h:13
static std::string::const_iterator begin(const C *obj)
static std::string::const_iterator end(const C *obj)
static void set(C *obj, const uint8_t *data, size_t elem_size)
static void set(C *obj, T value)
static T get(const C *obj)
void operator()(T *obj, int &value)
CollectionType::const_iterator iterator
static iterator begin(const Obj *obj)
ValueType< typename Col::value_type >::type ValueType
static iterator end(const Obj *obj)
static void insert(Obj *obj, ValueType *element)
static const int kErrorSubcode
static bool Verifier(const void *obj, const uint8_t *data, size_t size, ParseContext *context)
int operator()(int opt, EncodeContext *context, const T *msg, uint8_t *data, int size)
int operator()(int opt, EncodeContext *context, T *msg, uint8_t *data, int size)
int operator()(int opt, EncodeContext *context, const T *msg, uint8_t *data, int size)
int operator()(int opt, EncodeContext *context, const CtxType *msg, uint8_t *data, int size)
int operator()(int opt, EncodeContext *context, const CtxType *msg, uint8_t *data, int size)
ChoiceEncoder(EncodeContext *context, const T *msg, uint8_t *data, int size, int *resultp)
ChoiceMatcher(const uint8_t *data, size_t size, int value, ParseContext *context, T *obj, int *resultp)
int operator()(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
SequenceEncoder(EncodeContext *context, const T *msg, uint8_t *data, size_t size, int *resultp)
SequenceParser(const uint8_t *data, size_t size, ParseContext *context, T *obj, int *resultp)
int operator()(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
static void set(C *obj, const uint8_t *data, size_t elem_size)
static std::vector< T >::const_iterator end(const C *obj)
static int size(const C *obj)
static std::vector< T >::const_iterator begin(const C *obj)
ContextAccessor::ValueType ValueType
Definition: proto_impl.h:365
ValueType * Next()
Definition: proto_impl.h:381
bool HasNext(Obj *obj) const
Definition: proto_impl.h:388