1 // Copyright (c) 2009-2022, Google LLC
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above copyright
9 //       notice, this list of conditions and the following disclaimer in the
10 //       documentation and/or other materials provided with the distribution.
11 //     * Neither the name of Google LLC nor the
12 //       names of its contributors may be used to endorse or promote products
13 //       derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 // ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
19 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include "upbc/upbdev.h"
27 
28 #ifdef _WIN32
29 #ifndef WIN32_LEAN_AND_MEAN
30 #define WIN32_LEAN_AND_MEAN
31 #endif
32 #include <windows.h>
33 #else  // _WIN32
34 #include <unistd.h>
35 #endif  // !_WIN32
36 
37 #include "google/protobuf/compiler/plugin.upb.h"
38 #include "google/protobuf/compiler/plugin.upbdefs.h"
39 #include "upb/base/status.h"
40 #include "upb/json/decode.h"
41 #include "upb/json/encode.h"
42 #include "upb/mem/arena.h"
43 #include "upbc/code_generator_request.h"
44 #include "upbc/code_generator_request.upb.h"
45 #include "upbc/code_generator_request.upbdefs.h"
46 
upbc_JsonDecode(const char * data,size_t size,upb_Arena * arena,upb_Status * status)47 static google_protobuf_compiler_CodeGeneratorResponse* upbc_JsonDecode(
48     const char* data, size_t size, upb_Arena* arena, upb_Status* status) {
49   google_protobuf_compiler_CodeGeneratorResponse* response =
50       google_protobuf_compiler_CodeGeneratorResponse_new(arena);
51 
52   upb_DefPool* s = upb_DefPool_New();
53   const upb_MessageDef* m = google_protobuf_compiler_CodeGeneratorResponse_getmsgdef(s);
54 
55   (void)upb_JsonDecode(data, size, response, m, s, 0, arena, status);
56   if (!upb_Status_IsOk(status)) return NULL;
57 
58   upb_DefPool_Free(s);
59 
60   return response;
61 }
62 
upbc_JsonEncode(const upbc_CodeGeneratorRequest * request,upb_Arena * arena,upb_Status * status)63 static upb_StringView upbc_JsonEncode(const upbc_CodeGeneratorRequest* request,
64                                       upb_Arena* arena, upb_Status* status) {
65   upb_StringView out = {.data = NULL, .size = 0};
66 
67   upb_DefPool* s = upb_DefPool_New();
68   const upb_MessageDef* m = upbc_CodeGeneratorRequest_getmsgdef(s);
69   const int options = upb_JsonEncode_FormatEnumsAsIntegers;
70 
71   out.size = upb_JsonEncode(request, m, s, options, NULL, 0, status);
72   if (!upb_Status_IsOk(status)) goto done;
73 
74   char* data = (char*)upb_Arena_Malloc(arena, out.size + 1);
75 
76   (void)upb_JsonEncode(request, m, s, options, data, out.size + 1, status);
77   if (!upb_Status_IsOk(status)) goto done;
78 
79   out.data = (const char*)data;
80 
81 done:
82   upb_DefPool_Free(s);
83   return out;
84 }
85 
upbdev_ProcessInput(const char * buf,size_t size,upb_Arena * arena,upb_Status * status)86 upb_StringView upbdev_ProcessInput(const char* buf, size_t size,
87                                    upb_Arena* arena, upb_Status* status) {
88   upb_StringView out = {.data = NULL, .size = 0};
89 
90   google_protobuf_compiler_CodeGeneratorRequest* inner_request =
91       google_protobuf_compiler_CodeGeneratorRequest_parse(buf, size, arena);
92 
93   const upbc_CodeGeneratorRequest* outer_request =
94       upbc_MakeCodeGeneratorRequest(inner_request, arena, status);
95   if (upb_Status_IsOk(status))
96     out = upbc_JsonEncode(outer_request, arena, status);
97 
98   return out;
99 }
100 
upbdev_ProcessOutput(const char * buf,size_t size,upb_Arena * arena,upb_Status * status)101 upb_StringView upbdev_ProcessOutput(const char* buf, size_t size,
102                                     upb_Arena* arena, upb_Status* status) {
103   upb_StringView out = {.data = NULL, .size = 0};
104 
105   const google_protobuf_compiler_CodeGeneratorResponse* response =
106       upbc_JsonDecode(buf, size, arena, status);
107   if (!upb_Status_IsOk(status)) return out;
108 
109   out.data = google_protobuf_compiler_CodeGeneratorResponse_serialize(response, arena,
110                                                              &out.size);
111   return out;
112 }
113 
upbdev_ProcessStdout(const char * buf,size_t size,upb_Arena * arena,upb_Status * status)114 void upbdev_ProcessStdout(const char* buf, size_t size, upb_Arena* arena,
115                           upb_Status* status) {
116   const upb_StringView sv = upbdev_ProcessOutput(buf, size, arena, status);
117   if (!upb_Status_IsOk(status)) return;
118 
119   const char* ptr = sv.data;
120   size_t len = sv.size;
121   while (len) {
122     int n = write(1, ptr, len);
123     if (n > 0) {
124       ptr += n;
125       len -= n;
126     }
127   }
128 }
129