• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include <iostream>
3 
4 #include "google/protobuf/descriptor.upb.h"
5 #include "google/protobuf/descriptor.upbdefs.h"
6 #include "tests/test_util.h"
7 #include "tests/upb_test.h"
8 #include "upb/pb/decoder.h"
9 #include "upb/pb/encoder.h"
10 #include "upb/port_def.inc"
11 #include "upb/upb.hpp"
12 
13 template <class T>
14 class FillStringHandler {
15  public:
SetHandler(upb_byteshandler * handler)16   static void SetHandler(upb_byteshandler* handler) {
17     upb_byteshandler_setstartstr(handler, &FillStringHandler::StartString,
18                                  NULL);
19     upb_byteshandler_setstring(handler, &FillStringHandler::StringBuf, NULL);
20   }
21 
22  private:
23   // TODO(haberman): add UpbBind/UpbMakeHandler support to BytesHandler so these
24   // can be prettier callbacks.
StartString(void * c,const void * hd,size_t size)25   static void* StartString(void *c, const void *hd, size_t size) {
26     UPB_UNUSED(hd);
27     UPB_UNUSED(size);
28 
29     T* str = static_cast<T*>(c);
30     str->clear();
31     return c;
32   }
33 
StringBuf(void * c,const void * hd,const char * buf,size_t n,const upb_bufhandle * h)34   static size_t StringBuf(void* c, const void* hd, const char* buf, size_t n,
35                           const upb_bufhandle* h) {
36     UPB_UNUSED(hd);
37     UPB_UNUSED(h);
38 
39     T* str = static_cast<T*>(c);
40     try {
41       str->append(buf, n);
42       return n;
43     } catch (const std::exception&) {
44       return 0;
45     }
46   }
47 };
48 
49 class StringSink {
50  public:
51   template <class T>
StringSink(T * target)52   explicit StringSink(T* target) {
53     // TODO(haberman): we need to avoid rebuilding a new handler every time,
54     // but with class globals disallowed for google3 C++ this is tricky.
55     upb_byteshandler_init(&handler_);
56     FillStringHandler<T>::SetHandler(&handler_);
57     input_.Reset(&handler_, target);
58   }
59 
input()60   upb::BytesSink input() { return input_; }
61 
62  private:
63   upb_byteshandler handler_;
64   upb::BytesSink input_;
65 };
66 
test_pb_roundtrip()67 void test_pb_roundtrip() {
68   std::string input(
69       google_protobuf_descriptor_proto_upbdefinit.descriptor.data,
70       google_protobuf_descriptor_proto_upbdefinit.descriptor.size);
71   std::cout << input.size() << "\n";
72   upb::SymbolTable symtab;
73   upb::HandlerCache encoder_cache(upb::pb::EncoderPtr::NewCache());
74   upb::pb::CodeCache decoder_cache(&encoder_cache);
75   upb::Arena arena;
76   upb::Status status;
77   upb::MessageDefPtr md(
78       google_protobuf_FileDescriptorProto_getmsgdef(symtab.ptr()));
79   ASSERT(md);
80   const upb::Handlers *encoder_handlers = encoder_cache.Get(md);
81   ASSERT(encoder_handlers);
82   const upb::pb::DecoderMethodPtr method = decoder_cache.Get(md);
83 
84   std::string output;
85   StringSink string_sink(&output);
86   upb::pb::EncoderPtr encoder =
87       upb::pb::EncoderPtr::Create(&arena, encoder_handlers, string_sink.input());
88   upb::pb::DecoderPtr decoder =
89       upb::pb::DecoderPtr::Create(&arena, method, encoder.input(), &status);
90   bool ok = upb::PutBuffer(input, decoder.input());
91   ASSERT(ok);
92   ASSERT(input == output);
93 }
94 
95 extern "C" {
run_tests(int argc,char * argv[])96 int run_tests(int argc, char *argv[]) {
97   UPB_UNUSED(argc);
98   UPB_UNUSED(argv);
99   test_pb_roundtrip();
100   return 0;
101 }
102 }
103