summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2018-12-19 12:24:54 -0800
committerGitHub <noreply@github.com>2018-12-19 12:24:54 -0800
commit161258a2adeaffd4e2cd5ab4ea370224e618ec95 (patch)
tree7b4172b89d9d88f2922100f8dca2768aa04fb13f
parent2c0e0054a85651ff20067ec504844a4611097041 (diff)
parent18563bee4c9822a1ee42bb1d93024981777eea41 (diff)
Merge pull request #142 from TeBoring/json-any-encoding
Add support for encoding Any in json
-rw-r--r--tools/dump_cinit.lua1
-rw-r--r--upb/def.h4
-rw-r--r--upb/json/parser.c8
-rw-r--r--upb/json/parser.rl8
-rw-r--r--upb/json/printer.c55
5 files changed, 67 insertions, 9 deletions
diff --git a/tools/dump_cinit.lua b/tools/dump_cinit.lua
index 93ee12e..34d9dd1 100644
--- a/tools/dump_cinit.lua
+++ b/tools/dump_cinit.lua
@@ -350,6 +350,7 @@ end
local function well_known_type(m)
local type_map = {}
+ type_map["google.protobuf.Any"] = "UPB_WELLKNOWN_ANY"
type_map["google.protobuf.Duration"] = "UPB_WELLKNOWN_DURATION"
type_map["google.protobuf.Timestamp"] = "UPB_WELLKNOWN_TIMESTAMP"
type_map["google.protobuf.Value"] = "UPB_WELLKNOWN_VALUE"
diff --git a/upb/def.h b/upb/def.h
index c9ed1cf..98b458a 100644
--- a/upb/def.h
+++ b/upb/def.h
@@ -689,6 +689,10 @@ typedef upb_strtable_iter upb_msg_oneof_iter;
#define UPB_MAPENTRY_KEY 1
#define UPB_MAPENTRY_VALUE 2
+/* Well-known field tag numbers for Any messages. */
+#define UPB_ANY_TYPE 1
+#define UPB_ANY_VALUE 2
+
/* Well-known field tag numbers for timestamp messages. */
#define UPB_DURATION_SECONDS 1
#define UPB_DURATION_NANOS 2
diff --git a/upb/json/parser.c b/upb/json/parser.c
index 83590a1..08056d3 100644
--- a/upb/json/parser.c
+++ b/upb/json/parser.c
@@ -1301,15 +1301,15 @@ static bool end_stringval_nontop(upb_json_parser *p) {
return true;
}
- if (p->top->is_any) {
- return end_any_stringval(p);
- }
-
if (p->top->f == NULL) {
multipart_end(p);
return true;
}
+ if (p->top->is_any) {
+ return end_any_stringval(p);
+ }
+
switch (upb_fielddef_type(p->top->f)) {
case UPB_TYPE_BYTES:
if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
diff --git a/upb/json/parser.rl b/upb/json/parser.rl
index a7bdb3f..e584515 100644
--- a/upb/json/parser.rl
+++ b/upb/json/parser.rl
@@ -1299,15 +1299,15 @@ static bool end_stringval_nontop(upb_json_parser *p) {
return true;
}
- if (p->top->is_any) {
- return end_any_stringval(p);
- }
-
if (p->top->f == NULL) {
multipart_end(p);
return true;
}
+ if (p->top->is_any) {
+ return end_any_stringval(p);
+ }
+
switch (upb_fielddef_type(p->top->f)) {
case UPB_TYPE_BYTES:
if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
diff --git a/upb/json/printer.c b/upb/json/printer.c
index fe306d4..5ed79a0 100644
--- a/upb/json/printer.c
+++ b/upb/json/printer.c
@@ -69,6 +69,15 @@ strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
return ret;
}
+/* Convert a null-terminated const char* to a string piece. */
+strpc *newstrpc_str(upb_handlers *h, const char * str) {
+ strpc * ret = upb_gmalloc(sizeof(*ret));
+ ret->ptr = upb_gstrdup(str);
+ ret->len = strlen(str);
+ upb_handlers_addcleanup(h, ret, freestrpc);
+ return ret;
+}
+
/* ------------ JSON string printing: values, maps, arrays ------------------ */
static void print_data(
@@ -920,6 +929,49 @@ static bool printer_endmsg_noframe(
return true;
}
+static void *scalar_startstr_onlykey(
+ void *closure, const void *handler_data, size_t size_hint) {
+ upb_json_printer *p = closure;
+ UPB_UNUSED(size_hint);
+ CHK(putkey(closure, handler_data));
+ return p;
+}
+
+/* Set up handlers for an Any submessage. */
+void printer_sethandlers_any(const void *closure, upb_handlers *h) {
+ const upb_msgdef *md = upb_handlers_msgdef(h);
+
+ const upb_fielddef* type_field = upb_msgdef_itof(md, UPB_ANY_TYPE);
+ const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_ANY_VALUE);
+
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+
+ /* type_url's json name is "@type" */
+ upb_handlerattr type_name_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr value_name_attr = UPB_HANDLERATTR_INITIALIZER;
+ strpc *type_url_json_name = newstrpc_str(h, "@type");
+ strpc *value_json_name = newstrpc_str(h, "value");
+
+ upb_handlerattr_sethandlerdata(&type_name_attr, type_url_json_name);
+ upb_handlerattr_sethandlerdata(&value_name_attr, value_json_name);
+
+ /* Set up handlers. */
+ upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
+ upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
+
+ upb_handlers_setstartstr(h, type_field, scalar_startstr, &type_name_attr);
+ upb_handlers_setstring(h, type_field, scalar_str, &empty_attr);
+ upb_handlers_setendstr(h, type_field, scalar_endstr, &empty_attr);
+
+ /* This is not the full and correct JSON encoding for the Any value field. It
+ * requires further processing by the wrapper code based on the type URL.
+ */
+ upb_handlers_setstartstr(h, value_field, scalar_startstr_onlykey,
+ &value_name_attr);
+
+ UPB_UNUSED(closure);
+}
+
/* Set up handlers for a duration submessage. */
void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
@@ -1074,7 +1126,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
case UPB_WELLKNOWN_UNSPECIFIED:
break;
case UPB_WELLKNOWN_ANY:
- break;
+ printer_sethandlers_any(closure, h);
+ return;
case UPB_WELLKNOWN_DURATION:
printer_sethandlers_duration(closure, h);
return;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback