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