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