@bufbuild/protobuf 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/binary-encoding.js +2 -3
- package/dist/cjs/binary-format.d.ts +17 -0
- package/dist/cjs/binary-format.js +1 -1
- package/dist/cjs/codegen-info.d.ts +4 -4
- package/dist/cjs/codegen-info.js +2 -1
- package/dist/cjs/create-descriptor-set.d.ts +7 -1
- package/dist/cjs/create-descriptor-set.js +56 -50
- package/dist/cjs/create-registry-from-desc.d.ts +2 -2
- package/dist/cjs/create-registry-from-desc.js +53 -9
- package/dist/cjs/create-registry.d.ts +3 -2
- package/dist/cjs/create-registry.js +56 -37
- package/dist/cjs/descriptor-set.js +1 -1
- package/dist/cjs/enum.js +1 -1
- package/dist/cjs/extension-accessor.d.ts +35 -0
- package/dist/cjs/extension-accessor.js +108 -0
- package/dist/cjs/extension.d.ts +24 -0
- package/dist/cjs/extension.js +15 -0
- package/dist/cjs/field-list.js +1 -1
- package/dist/cjs/field.js +1 -1
- package/dist/cjs/google/protobuf/any_pb.js +1 -1
- package/dist/cjs/google/protobuf/api_pb.js +1 -1
- package/dist/cjs/google/protobuf/compiler/plugin_pb.js +1 -1
- package/dist/cjs/google/protobuf/descriptor_pb.js +2 -2
- package/dist/cjs/google/protobuf/duration_pb.js +1 -1
- package/dist/cjs/google/protobuf/empty_pb.js +1 -1
- package/dist/cjs/google/protobuf/field_mask_pb.js +1 -1
- package/dist/cjs/google/protobuf/source_context_pb.js +1 -1
- package/dist/cjs/google/protobuf/struct_pb.js +2 -2
- package/dist/cjs/google/protobuf/timestamp_pb.js +1 -1
- package/dist/cjs/google/protobuf/type_pb.js +2 -2
- package/dist/cjs/google/protobuf/wrappers_pb.js +1 -1
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.js +7 -2
- package/dist/cjs/json-format.d.ts +5 -5
- package/dist/cjs/json-format.js +1 -1
- package/dist/cjs/message-type.js +1 -1
- package/dist/cjs/message.js +1 -1
- package/dist/cjs/private/assert.js +1 -1
- package/dist/cjs/private/binary-format-common.d.ts +2 -3
- package/dist/cjs/private/binary-format-common.js +80 -78
- package/dist/cjs/private/binary-format-proto2.js +59 -64
- package/dist/cjs/private/binary-format-proto3.js +44 -40
- package/dist/cjs/private/enum.js +1 -1
- package/dist/cjs/private/extensions.d.ts +34 -0
- package/dist/cjs/private/extensions.js +86 -0
- package/dist/cjs/private/feature-set.d.ts +6 -8
- package/dist/cjs/private/feature-set.js +41 -42
- package/dist/cjs/private/field-list.js +1 -1
- package/dist/cjs/private/field-wrapper.d.ts +2 -2
- package/dist/cjs/private/field-wrapper.js +1 -1
- package/dist/cjs/private/field.js +1 -1
- package/dist/cjs/private/json-format-common.d.ts +3 -3
- package/dist/cjs/private/json-format-common.js +228 -173
- package/dist/cjs/private/json-format-proto2.js +3 -2
- package/dist/cjs/private/json-format-proto3.js +8 -6
- package/dist/cjs/private/message-type.js +1 -1
- package/dist/cjs/private/names.d.ts +2 -2
- package/dist/cjs/private/names.js +3 -2
- package/dist/cjs/private/options-map.js +1 -1
- package/dist/cjs/private/proto-runtime.d.ts +6 -0
- package/dist/cjs/private/proto-runtime.js +5 -1
- package/dist/cjs/private/reify-wkt.js +1 -1
- package/dist/cjs/private/scalars.js +1 -1
- package/dist/cjs/private/text-format.js +1 -1
- package/dist/cjs/private/util-common.js +1 -1
- package/dist/cjs/private/util.js +1 -1
- package/dist/cjs/proto-base64.js +1 -1
- package/dist/cjs/proto-delimited.js +1 -1
- package/dist/cjs/proto-double.js +1 -1
- package/dist/cjs/proto-int64.js +1 -1
- package/dist/cjs/proto2.js +1 -1
- package/dist/cjs/proto3.js +1 -1
- package/dist/cjs/service-type.js +1 -1
- package/dist/cjs/to-plain-message.js +1 -1
- package/dist/cjs/type-registry.d.ts +14 -0
- package/dist/cjs/type-registry.js +1 -1
- package/dist/esm/binary-encoding.js +2 -3
- package/dist/esm/binary-format.d.ts +17 -0
- package/dist/esm/binary-format.js +1 -1
- package/dist/esm/codegen-info.d.ts +4 -4
- package/dist/esm/codegen-info.js +2 -1
- package/dist/esm/create-descriptor-set.d.ts +7 -1
- package/dist/esm/create-descriptor-set.js +57 -51
- package/dist/esm/create-registry-from-desc.d.ts +2 -2
- package/dist/esm/create-registry-from-desc.js +53 -9
- package/dist/esm/create-registry.d.ts +3 -2
- package/dist/esm/create-registry.js +56 -37
- package/dist/esm/descriptor-set.js +1 -1
- package/dist/esm/enum.js +1 -1
- package/dist/esm/extension-accessor.d.ts +35 -0
- package/dist/esm/extension-accessor.js +101 -0
- package/dist/esm/extension.d.ts +24 -0
- package/dist/esm/extension.js +14 -0
- package/dist/esm/field-list.js +1 -1
- package/dist/esm/field.js +1 -1
- package/dist/esm/google/protobuf/any_pb.js +1 -1
- package/dist/esm/google/protobuf/api_pb.js +1 -1
- package/dist/esm/google/protobuf/compiler/plugin_pb.js +1 -1
- package/dist/esm/google/protobuf/descriptor_pb.js +2 -2
- package/dist/esm/google/protobuf/duration_pb.js +1 -1
- package/dist/esm/google/protobuf/empty_pb.js +1 -1
- package/dist/esm/google/protobuf/field_mask_pb.js +1 -1
- package/dist/esm/google/protobuf/source_context_pb.js +1 -1
- package/dist/esm/google/protobuf/struct_pb.js +2 -2
- package/dist/esm/google/protobuf/timestamp_pb.js +1 -1
- package/dist/esm/google/protobuf/type_pb.js +2 -2
- package/dist/esm/google/protobuf/wrappers_pb.js +1 -1
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/json-format.d.ts +5 -5
- package/dist/esm/json-format.js +1 -1
- package/dist/esm/message-type.js +1 -1
- package/dist/esm/message.js +1 -1
- package/dist/esm/private/assert.js +1 -1
- package/dist/esm/private/binary-format-common.d.ts +2 -3
- package/dist/esm/private/binary-format-common.js +80 -77
- package/dist/esm/private/binary-format-proto2.js +59 -64
- package/dist/esm/private/binary-format-proto3.js +44 -40
- package/dist/esm/private/enum.js +1 -1
- package/dist/esm/private/extensions.d.ts +34 -0
- package/dist/esm/private/extensions.js +81 -0
- package/dist/esm/private/feature-set.d.ts +6 -8
- package/dist/esm/private/feature-set.js +40 -41
- package/dist/esm/private/field-list.js +1 -1
- package/dist/esm/private/field-wrapper.d.ts +2 -2
- package/dist/esm/private/field-wrapper.js +1 -1
- package/dist/esm/private/field.js +1 -1
- package/dist/esm/private/json-format-common.d.ts +3 -3
- package/dist/esm/private/json-format-common.js +228 -173
- package/dist/esm/private/json-format-proto2.js +3 -2
- package/dist/esm/private/json-format-proto3.js +8 -6
- package/dist/esm/private/message-type.js +1 -1
- package/dist/esm/private/names.d.ts +2 -2
- package/dist/esm/private/names.js +3 -2
- package/dist/esm/private/options-map.js +1 -1
- package/dist/esm/private/proto-runtime.d.ts +6 -0
- package/dist/esm/private/proto-runtime.js +5 -1
- package/dist/esm/private/reify-wkt.js +1 -1
- package/dist/esm/private/scalars.js +1 -1
- package/dist/esm/private/text-format.js +1 -1
- package/dist/esm/private/util-common.js +1 -1
- package/dist/esm/private/util.js +1 -1
- package/dist/esm/proto-base64.js +1 -1
- package/dist/esm/proto-delimited.js +1 -1
- package/dist/esm/proto-double.js +1 -1
- package/dist/esm/proto-int64.js +1 -1
- package/dist/esm/proto2.js +1 -1
- package/dist/esm/proto3.js +1 -1
- package/dist/esm/service-type.js +1 -1
- package/dist/esm/to-plain-message.js +1 -1
- package/dist/esm/type-registry.d.ts +14 -0
- package/dist/esm/type-registry.js +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright 2021-
|
|
1
|
+
// Copyright 2021-2024 Buf Technologies, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -16,6 +16,8 @@ import { LongType, ScalarType } from "../field.js";
|
|
|
16
16
|
import { assert, assertFloat32, assertInt32, assertUInt32 } from "./assert.js";
|
|
17
17
|
import { protoInt64 } from "../proto-int64.js";
|
|
18
18
|
import { protoBase64 } from "../proto-base64.js";
|
|
19
|
+
import { createExtensionContainer } from "./extensions.js";
|
|
20
|
+
import { getExtension, hasExtension, setExtension, } from "../extension-accessor.js";
|
|
19
21
|
/* eslint-disable no-case-declarations, @typescript-eslint/restrict-plus-operands,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument */
|
|
20
22
|
// Default options for parsing JSON.
|
|
21
23
|
const jsonReadDefaults = {
|
|
@@ -34,171 +36,52 @@ function makeReadOptions(options) {
|
|
|
34
36
|
function makeWriteOptions(options) {
|
|
35
37
|
return options ? Object.assign(Object.assign({}, jsonWriteDefaults), options) : jsonWriteDefaults;
|
|
36
38
|
}
|
|
37
|
-
export function makeJsonFormatCommon(makeWriteField) {
|
|
39
|
+
export function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
|
|
38
40
|
const writeField = makeWriteField(writeEnum, writeScalar);
|
|
39
41
|
return {
|
|
40
42
|
makeReadOptions,
|
|
41
43
|
makeWriteOptions,
|
|
42
44
|
readMessage(type, json, options, message) {
|
|
43
45
|
if (json == null || Array.isArray(json) || typeof json != "object") {
|
|
44
|
-
throw new Error(`cannot decode message ${type.typeName} from JSON: ${
|
|
46
|
+
throw new Error(`cannot decode message ${type.typeName} from JSON: ${debugJsonValue(json)}`);
|
|
45
47
|
}
|
|
46
48
|
message = message !== null && message !== void 0 ? message : new type();
|
|
47
|
-
const oneofSeen =
|
|
49
|
+
const oneofSeen = new Map();
|
|
50
|
+
const registry = options.typeRegistry;
|
|
48
51
|
for (const [jsonKey, jsonValue] of Object.entries(json)) {
|
|
49
52
|
const field = type.fields.findJsonName(jsonKey);
|
|
50
|
-
if (
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
let localName = field.localName;
|
|
57
|
-
let target = message;
|
|
58
|
-
if (field.oneof) {
|
|
59
|
-
if (jsonValue === null && field.kind == "scalar") {
|
|
60
|
-
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second}
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
const seen = oneofSeen[field.oneof.localName];
|
|
64
|
-
if (seen) {
|
|
65
|
-
throw new Error(`cannot decode message ${type.typeName} from JSON: multiple keys for oneof "${field.oneof.name}" present: "${seen}", "${jsonKey}"`);
|
|
66
|
-
}
|
|
67
|
-
oneofSeen[field.oneof.localName] = jsonKey;
|
|
68
|
-
target = target[field.oneof.localName] = { case: localName };
|
|
69
|
-
localName = "value";
|
|
70
|
-
}
|
|
71
|
-
if (field.repeated) {
|
|
72
|
-
if (jsonValue === null) {
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (!Array.isArray(jsonValue)) {
|
|
76
|
-
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`);
|
|
77
|
-
}
|
|
78
|
-
const targetArray = target[localName];
|
|
79
|
-
for (const jsonItem of jsonValue) {
|
|
80
|
-
if (jsonItem === null) {
|
|
81
|
-
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonItem)}`);
|
|
53
|
+
if (field) {
|
|
54
|
+
if (field.oneof) {
|
|
55
|
+
if (jsonValue === null && field.kind == "scalar") {
|
|
56
|
+
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second}
|
|
57
|
+
continue;
|
|
82
58
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
case "message":
|
|
87
|
-
val = field.T.fromJson(jsonItem, options);
|
|
88
|
-
break;
|
|
89
|
-
case "enum":
|
|
90
|
-
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields);
|
|
91
|
-
if (val === undefined)
|
|
92
|
-
continue;
|
|
93
|
-
break;
|
|
94
|
-
case "scalar":
|
|
95
|
-
try {
|
|
96
|
-
val = readScalar(field.T, jsonItem, field.L);
|
|
97
|
-
}
|
|
98
|
-
catch (e) {
|
|
99
|
-
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonItem)}`;
|
|
100
|
-
if (e instanceof Error && e.message.length > 0) {
|
|
101
|
-
m += `: ${e.message}`;
|
|
102
|
-
}
|
|
103
|
-
throw new Error(m);
|
|
104
|
-
}
|
|
105
|
-
break;
|
|
59
|
+
const seen = oneofSeen.get(field.oneof);
|
|
60
|
+
if (seen !== undefined) {
|
|
61
|
+
throw new Error(`cannot decode message ${type.typeName} from JSON: multiple keys for oneof "${field.oneof.name}" present: "${seen}", "${jsonKey}"`);
|
|
106
62
|
}
|
|
107
|
-
|
|
63
|
+
oneofSeen.set(field.oneof, jsonKey);
|
|
108
64
|
}
|
|
65
|
+
readField(message, jsonValue, field, options, type, nullAsZeroValue);
|
|
109
66
|
}
|
|
110
|
-
else
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
case "message":
|
|
125
|
-
val = field.V.T.fromJson(jsonMapValue, options);
|
|
126
|
-
break;
|
|
127
|
-
case "enum":
|
|
128
|
-
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields);
|
|
129
|
-
if (val === undefined)
|
|
130
|
-
continue;
|
|
131
|
-
break;
|
|
132
|
-
case "scalar":
|
|
133
|
-
try {
|
|
134
|
-
val = readScalar(field.V.T, jsonMapValue, LongType.BIGINT);
|
|
135
|
-
}
|
|
136
|
-
catch (e) {
|
|
137
|
-
let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`;
|
|
138
|
-
if (e instanceof Error && e.message.length > 0) {
|
|
139
|
-
m += `: ${e.message}`;
|
|
140
|
-
}
|
|
141
|
-
throw new Error(m);
|
|
142
|
-
}
|
|
143
|
-
break;
|
|
144
|
-
}
|
|
145
|
-
try {
|
|
146
|
-
targetMap[readScalar(field.K, field.K == ScalarType.BOOL
|
|
147
|
-
? jsonMapKey == "true"
|
|
148
|
-
? true
|
|
149
|
-
: jsonMapKey == "false"
|
|
150
|
-
? false
|
|
151
|
-
: jsonMapKey
|
|
152
|
-
: jsonMapKey, LongType.BIGINT).toString()] = val;
|
|
153
|
-
}
|
|
154
|
-
catch (e) {
|
|
155
|
-
let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`;
|
|
156
|
-
if (e instanceof Error && e.message.length > 0) {
|
|
157
|
-
m += `: ${e.message}`;
|
|
158
|
-
}
|
|
159
|
-
throw new Error(m);
|
|
67
|
+
else {
|
|
68
|
+
let found = false;
|
|
69
|
+
if ((registry === null || registry === void 0 ? void 0 : registry.findExtension) &&
|
|
70
|
+
jsonKey.startsWith("[") &&
|
|
71
|
+
jsonKey.endsWith("]")) {
|
|
72
|
+
const ext = registry.findExtension(jsonKey.substring(1, jsonKey.length - 1));
|
|
73
|
+
if (ext && ext.extendee.typeName == type.typeName) {
|
|
74
|
+
found = true;
|
|
75
|
+
const [container, get] = createExtensionContainer(ext);
|
|
76
|
+
readField(container, jsonValue, ext.field, options, ext, true);
|
|
77
|
+
// We pass on the options as BinaryReadOptions/BinaryWriteOptions,
|
|
78
|
+
// so that users can bring their own binary reader and writer factories
|
|
79
|
+
// if necessary.
|
|
80
|
+
setExtension(message, ext, get(), options);
|
|
160
81
|
}
|
|
161
82
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
switch (field.kind) {
|
|
165
|
-
case "message":
|
|
166
|
-
const messageType = field.T;
|
|
167
|
-
if (jsonValue === null &&
|
|
168
|
-
messageType.typeName != "google.protobuf.Value") {
|
|
169
|
-
if (field.oneof) {
|
|
170
|
-
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: null is invalid for oneof field "${jsonKey}"`);
|
|
171
|
-
}
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
if (target[localName] instanceof Message) {
|
|
175
|
-
target[localName].fromJson(jsonValue, options);
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
target[localName] = messageType.fromJson(jsonValue, options);
|
|
179
|
-
if (messageType.fieldWrapper && !field.oneof) {
|
|
180
|
-
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
break;
|
|
184
|
-
case "enum":
|
|
185
|
-
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields);
|
|
186
|
-
if (enumValue !== undefined) {
|
|
187
|
-
target[localName] = enumValue;
|
|
188
|
-
}
|
|
189
|
-
break;
|
|
190
|
-
case "scalar":
|
|
191
|
-
try {
|
|
192
|
-
target[localName] = readScalar(field.T, jsonValue, field.L);
|
|
193
|
-
}
|
|
194
|
-
catch (e) {
|
|
195
|
-
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`;
|
|
196
|
-
if (e instanceof Error && e.message.length > 0) {
|
|
197
|
-
m += `: ${e.message}`;
|
|
198
|
-
}
|
|
199
|
-
throw new Error(m);
|
|
200
|
-
}
|
|
201
|
-
break;
|
|
83
|
+
if (!found && !options.ignoreUnknownFields) {
|
|
84
|
+
throw new Error(`cannot decode message ${type.typeName} from JSON: key "${jsonKey}" is unknown`);
|
|
202
85
|
}
|
|
203
86
|
}
|
|
204
87
|
}
|
|
@@ -231,6 +114,21 @@ export function makeJsonFormatCommon(makeWriteField) {
|
|
|
231
114
|
jsonValue;
|
|
232
115
|
}
|
|
233
116
|
}
|
|
117
|
+
const registry = options.typeRegistry;
|
|
118
|
+
if (registry === null || registry === void 0 ? void 0 : registry.findExtensionFor) {
|
|
119
|
+
for (const uf of type.runtime.bin.listUnknownFields(message)) {
|
|
120
|
+
const ext = registry.findExtensionFor(type.typeName, uf.no);
|
|
121
|
+
if (ext && hasExtension(message, ext)) {
|
|
122
|
+
// We pass on the options as BinaryReadOptions, so that users can bring their own
|
|
123
|
+
// binary reader factory if necessary.
|
|
124
|
+
const value = getExtension(message, ext, options);
|
|
125
|
+
const jsonValue = writeField(ext.field, value, options);
|
|
126
|
+
if (jsonValue !== undefined) {
|
|
127
|
+
json[ext.field.jsonName] = jsonValue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
234
132
|
}
|
|
235
133
|
catch (e) {
|
|
236
134
|
const m = field
|
|
@@ -241,7 +139,7 @@ export function makeJsonFormatCommon(makeWriteField) {
|
|
|
241
139
|
}
|
|
242
140
|
return json;
|
|
243
141
|
},
|
|
244
|
-
readScalar,
|
|
142
|
+
readScalar: (type, json, longType) => readScalar(type, json, longType, nullAsZeroValue), // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
|
|
245
143
|
writeScalar,
|
|
246
144
|
debug: debugJsonValue,
|
|
247
145
|
};
|
|
@@ -259,9 +157,162 @@ function debugJsonValue(json) {
|
|
|
259
157
|
return String(json);
|
|
260
158
|
}
|
|
261
159
|
}
|
|
160
|
+
// Read a JSON value for a field.
|
|
161
|
+
// The "type" argument is only used to provide context in errors.
|
|
162
|
+
// The argument "nullAsZeroValue" applies to singular fields (not repeated, map,
|
|
163
|
+
// or oneof). If the argument is `true`, JSON null is parsed as the fields
|
|
164
|
+
// zero-value. If the argument is false, JSON null sets the field to `undefined`.
|
|
165
|
+
function readField(target, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access
|
|
166
|
+
jsonValue, field, options, type, nullAsZeroValue) {
|
|
167
|
+
let localName = field.localName;
|
|
168
|
+
if (field.oneof) {
|
|
169
|
+
if (jsonValue === null && field.kind == "scalar") {
|
|
170
|
+
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second}
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
target = target[field.oneof.localName] = { case: localName };
|
|
174
|
+
localName = "value";
|
|
175
|
+
}
|
|
176
|
+
if (field.repeated) {
|
|
177
|
+
if (jsonValue === null) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (!Array.isArray(jsonValue)) {
|
|
181
|
+
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`);
|
|
182
|
+
}
|
|
183
|
+
const targetArray = target[localName];
|
|
184
|
+
for (const jsonItem of jsonValue) {
|
|
185
|
+
if (jsonItem === null) {
|
|
186
|
+
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`);
|
|
187
|
+
}
|
|
188
|
+
let val;
|
|
189
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "map" is invalid for repeated fields
|
|
190
|
+
switch (field.kind) {
|
|
191
|
+
case "message":
|
|
192
|
+
val = field.T.fromJson(jsonItem, options);
|
|
193
|
+
break;
|
|
194
|
+
case "enum":
|
|
195
|
+
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields, true);
|
|
196
|
+
if (val === undefined)
|
|
197
|
+
continue;
|
|
198
|
+
break;
|
|
199
|
+
case "scalar":
|
|
200
|
+
try {
|
|
201
|
+
val = readScalar(field.T, jsonItem, field.L, true);
|
|
202
|
+
}
|
|
203
|
+
catch (e) {
|
|
204
|
+
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`;
|
|
205
|
+
if (e instanceof Error && e.message.length > 0) {
|
|
206
|
+
m += `: ${e.message}`;
|
|
207
|
+
}
|
|
208
|
+
throw new Error(m);
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
targetArray.push(val);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else if (field.kind == "map") {
|
|
216
|
+
if (jsonValue === null) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (typeof jsonValue != "object" || Array.isArray(jsonValue)) {
|
|
220
|
+
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`);
|
|
221
|
+
}
|
|
222
|
+
const targetMap = target[localName];
|
|
223
|
+
for (const [jsonMapKey, jsonMapValue] of Object.entries(jsonValue)) {
|
|
224
|
+
if (jsonMapValue === null) {
|
|
225
|
+
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: map value null`);
|
|
226
|
+
}
|
|
227
|
+
let val;
|
|
228
|
+
switch (field.V.kind) {
|
|
229
|
+
case "message":
|
|
230
|
+
val = field.V.T.fromJson(jsonMapValue, options);
|
|
231
|
+
break;
|
|
232
|
+
case "enum":
|
|
233
|
+
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields, true);
|
|
234
|
+
if (val === undefined)
|
|
235
|
+
continue;
|
|
236
|
+
break;
|
|
237
|
+
case "scalar":
|
|
238
|
+
try {
|
|
239
|
+
val = readScalar(field.V.T, jsonMapValue, LongType.BIGINT, true);
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
243
|
+
if (e instanceof Error && e.message.length > 0) {
|
|
244
|
+
m += `: ${e.message}`;
|
|
245
|
+
}
|
|
246
|
+
throw new Error(m);
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
targetMap[readScalar(field.K, field.K == ScalarType.BOOL
|
|
252
|
+
? jsonMapKey == "true"
|
|
253
|
+
? true
|
|
254
|
+
: jsonMapKey == "false"
|
|
255
|
+
? false
|
|
256
|
+
: jsonMapKey
|
|
257
|
+
: jsonMapKey, LongType.BIGINT, true).toString()] = val;
|
|
258
|
+
}
|
|
259
|
+
catch (e) {
|
|
260
|
+
let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
261
|
+
if (e instanceof Error && e.message.length > 0) {
|
|
262
|
+
m += `: ${e.message}`;
|
|
263
|
+
}
|
|
264
|
+
throw new Error(m);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
switch (field.kind) {
|
|
270
|
+
case "message":
|
|
271
|
+
const messageType = field.T;
|
|
272
|
+
if (jsonValue === null &&
|
|
273
|
+
messageType.typeName != "google.protobuf.Value") {
|
|
274
|
+
if (field.oneof) {
|
|
275
|
+
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: null is invalid for oneof field`);
|
|
276
|
+
}
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (target[localName] instanceof Message) {
|
|
280
|
+
target[localName].fromJson(jsonValue, options);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
target[localName] = messageType.fromJson(jsonValue, options);
|
|
284
|
+
if (messageType.fieldWrapper && !field.oneof) {
|
|
285
|
+
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
case "enum":
|
|
290
|
+
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields, nullAsZeroValue);
|
|
291
|
+
if (enumValue !== undefined) {
|
|
292
|
+
target[localName] = enumValue;
|
|
293
|
+
}
|
|
294
|
+
break;
|
|
295
|
+
case "scalar":
|
|
296
|
+
try {
|
|
297
|
+
target[localName] = readScalar(field.T, jsonValue, field.L, nullAsZeroValue);
|
|
298
|
+
}
|
|
299
|
+
catch (e) {
|
|
300
|
+
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
301
|
+
if (e instanceof Error && e.message.length > 0) {
|
|
302
|
+
m += `: ${e.message}`;
|
|
303
|
+
}
|
|
304
|
+
throw new Error(m);
|
|
305
|
+
}
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
262
310
|
// May throw an error. If the error message is non-blank, it should be shown.
|
|
263
311
|
// It is up to the caller to provide context.
|
|
264
|
-
function
|
|
312
|
+
// If the argument "nullAsZeroValue" is `true`, this function returns the zero-value
|
|
313
|
+
// for JSON null. If the argument is `false`, this function returns `undefined`
|
|
314
|
+
// for JSON null.
|
|
315
|
+
function readScalar(type, json, longType, nullAsZeroValue) {
|
|
265
316
|
// every valid case in the switch below returns, and every fall
|
|
266
317
|
// through is regarded as a failure.
|
|
267
318
|
switch (type) {
|
|
@@ -270,7 +321,7 @@ function readScalar(type, json, longType) {
|
|
|
270
321
|
case ScalarType.DOUBLE:
|
|
271
322
|
case ScalarType.FLOAT:
|
|
272
323
|
if (json === null)
|
|
273
|
-
return 0.0;
|
|
324
|
+
return nullAsZeroValue ? 0.0 : undefined;
|
|
274
325
|
if (json === "NaN")
|
|
275
326
|
return Number.NaN;
|
|
276
327
|
if (json === "Infinity")
|
|
@@ -307,7 +358,7 @@ function readScalar(type, json, longType) {
|
|
|
307
358
|
case ScalarType.SINT32:
|
|
308
359
|
case ScalarType.UINT32:
|
|
309
360
|
if (json === null)
|
|
310
|
-
return 0;
|
|
361
|
+
return nullAsZeroValue ? 0 : undefined;
|
|
311
362
|
let int32;
|
|
312
363
|
if (typeof json == "number")
|
|
313
364
|
int32 = json;
|
|
@@ -327,7 +378,7 @@ function readScalar(type, json, longType) {
|
|
|
327
378
|
case ScalarType.SFIXED64:
|
|
328
379
|
case ScalarType.SINT64:
|
|
329
380
|
if (json === null)
|
|
330
|
-
return protoInt64.zero;
|
|
381
|
+
return nullAsZeroValue ? protoInt64.zero : undefined;
|
|
331
382
|
if (typeof json != "number" && typeof json != "string")
|
|
332
383
|
break;
|
|
333
384
|
const long = protoInt64.parse(json);
|
|
@@ -336,7 +387,7 @@ function readScalar(type, json, longType) {
|
|
|
336
387
|
case ScalarType.FIXED64:
|
|
337
388
|
case ScalarType.UINT64:
|
|
338
389
|
if (json === null)
|
|
339
|
-
return protoInt64.zero;
|
|
390
|
+
return nullAsZeroValue ? protoInt64.zero : undefined;
|
|
340
391
|
if (typeof json != "number" && typeof json != "string")
|
|
341
392
|
break;
|
|
342
393
|
const uLong = protoInt64.uParse(json);
|
|
@@ -345,14 +396,14 @@ function readScalar(type, json, longType) {
|
|
|
345
396
|
// bool:
|
|
346
397
|
case ScalarType.BOOL:
|
|
347
398
|
if (json === null)
|
|
348
|
-
return false;
|
|
399
|
+
return nullAsZeroValue ? false : undefined;
|
|
349
400
|
if (typeof json !== "boolean")
|
|
350
401
|
break;
|
|
351
402
|
return json;
|
|
352
403
|
// string:
|
|
353
404
|
case ScalarType.STRING:
|
|
354
405
|
if (json === null)
|
|
355
|
-
return "";
|
|
406
|
+
return nullAsZeroValue ? "" : undefined;
|
|
356
407
|
if (typeof json !== "string") {
|
|
357
408
|
break;
|
|
358
409
|
}
|
|
@@ -368,7 +419,9 @@ function readScalar(type, json, longType) {
|
|
|
368
419
|
// bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
|
|
369
420
|
// Either standard or URL-safe base64 encoding with/without paddings are accepted.
|
|
370
421
|
case ScalarType.BYTES:
|
|
371
|
-
if (json === null
|
|
422
|
+
if (json === null)
|
|
423
|
+
return nullAsZeroValue ? new Uint8Array(0) : undefined;
|
|
424
|
+
if (json === "")
|
|
372
425
|
return new Uint8Array(0);
|
|
373
426
|
if (typeof json !== "string")
|
|
374
427
|
break;
|
|
@@ -376,10 +429,14 @@ function readScalar(type, json, longType) {
|
|
|
376
429
|
}
|
|
377
430
|
throw new Error();
|
|
378
431
|
}
|
|
379
|
-
function
|
|
432
|
+
// If the argument "nullAsZeroValue" is `true`, this function returns the first
|
|
433
|
+
// enum value for JSON null. If the argument is `false`, this function returns
|
|
434
|
+
// `undefined`.
|
|
435
|
+
function readEnum(type, json, ignoreUnknownFields, nullAsZeroValue) {
|
|
380
436
|
if (json === null) {
|
|
381
|
-
// proto3 requires 0 to be default value for all enums
|
|
382
|
-
|
|
437
|
+
// proto3 requires 0 to be default value for all enums (which is required to be the first value).
|
|
438
|
+
// proto2 uses the first value (at least with protoc-gen-go).
|
|
439
|
+
return nullAsZeroValue ? type.values[0].no : undefined;
|
|
383
440
|
}
|
|
384
441
|
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
385
442
|
switch (typeof json) {
|
|
@@ -398,12 +455,12 @@ function readEnum(type, json, ignoreUnknownFields) {
|
|
|
398
455
|
}
|
|
399
456
|
throw new Error(`cannot decode enum ${type.typeName} from JSON: ${debugJsonValue(json)}`);
|
|
400
457
|
}
|
|
401
|
-
function writeEnum(type, value,
|
|
458
|
+
function writeEnum(type, value, emitZeroValue, enumAsInteger) {
|
|
402
459
|
var _a;
|
|
403
460
|
if (value === undefined) {
|
|
404
461
|
return value;
|
|
405
462
|
}
|
|
406
|
-
if (
|
|
463
|
+
if (!emitZeroValue && type.values[0].no === value) {
|
|
407
464
|
// proto3 requires 0 to be default value for all enums
|
|
408
465
|
return undefined;
|
|
409
466
|
}
|
|
@@ -416,7 +473,7 @@ function writeEnum(type, value, emitIntrinsicDefault, enumAsInteger) {
|
|
|
416
473
|
const val = type.findNumber(value);
|
|
417
474
|
return (_a = val === null || val === void 0 ? void 0 : val.name) !== null && _a !== void 0 ? _a : value; // if we don't know the enum value, just return the number
|
|
418
475
|
}
|
|
419
|
-
function writeScalar(type, value,
|
|
476
|
+
function writeScalar(type, value, emitZeroValue) {
|
|
420
477
|
if (value === undefined) {
|
|
421
478
|
return undefined;
|
|
422
479
|
}
|
|
@@ -428,7 +485,7 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
428
485
|
case ScalarType.FIXED32:
|
|
429
486
|
case ScalarType.UINT32:
|
|
430
487
|
assert(typeof value == "number");
|
|
431
|
-
return value != 0 ||
|
|
488
|
+
return value != 0 || emitZeroValue ? value : undefined;
|
|
432
489
|
// float, double: JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity".
|
|
433
490
|
// Either numbers or strings are accepted. Exponent notation is also accepted.
|
|
434
491
|
case ScalarType.FLOAT:
|
|
@@ -441,15 +498,15 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
441
498
|
return "Infinity";
|
|
442
499
|
if (value === Number.NEGATIVE_INFINITY)
|
|
443
500
|
return "-Infinity";
|
|
444
|
-
return value !== 0 ||
|
|
501
|
+
return value !== 0 || emitZeroValue ? value : undefined;
|
|
445
502
|
// string:
|
|
446
503
|
case ScalarType.STRING:
|
|
447
504
|
assert(typeof value == "string");
|
|
448
|
-
return value.length > 0 ||
|
|
505
|
+
return value.length > 0 || emitZeroValue ? value : undefined;
|
|
449
506
|
// bool:
|
|
450
507
|
case ScalarType.BOOL:
|
|
451
508
|
assert(typeof value == "boolean");
|
|
452
|
-
return value ||
|
|
509
|
+
return value || emitZeroValue ? value : undefined;
|
|
453
510
|
// JSON value will be a decimal string. Either numbers or strings are accepted.
|
|
454
511
|
case ScalarType.UINT64:
|
|
455
512
|
case ScalarType.FIXED64:
|
|
@@ -462,14 +519,12 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
462
519
|
// We use implicit conversion with `value != 0` to catch both 0n and "0"
|
|
463
520
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
464
521
|
// @ts-ignore
|
|
465
|
-
return
|
|
466
|
-
? value.toString(10)
|
|
467
|
-
: undefined;
|
|
522
|
+
return emitZeroValue || value != 0 ? value.toString(10) : undefined;
|
|
468
523
|
// bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
|
|
469
524
|
// Either standard or URL-safe base64 encoding with/without paddings are accepted.
|
|
470
525
|
case ScalarType.BYTES:
|
|
471
526
|
assert(value instanceof Uint8Array);
|
|
472
|
-
return
|
|
527
|
+
return emitZeroValue || value.byteLength > 0
|
|
473
528
|
? protoBase64.enc(value)
|
|
474
529
|
: undefined;
|
|
475
530
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright 2021-
|
|
1
|
+
// Copyright 2021-2024 Buf Technologies, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -16,7 +16,8 @@ import { assert } from "./assert.js";
|
|
|
16
16
|
import { makeJsonFormatCommon } from "./json-format-common.js";
|
|
17
17
|
/* eslint-disable no-case-declarations, @typescript-eslint/restrict-plus-operands,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument */
|
|
18
18
|
export function makeJsonFormatProto2() {
|
|
19
|
-
|
|
19
|
+
// TODO field presence: merge this function with proto3. the reading side already switches behavior on the nullAsZeroValue argument.
|
|
20
|
+
return makeJsonFormatCommon(false, (writeEnum, writeScalar) => {
|
|
20
21
|
return function writeField(field, value, options) {
|
|
21
22
|
if (field.kind == "map") {
|
|
22
23
|
const jsonObj = {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright 2021-
|
|
1
|
+
// Copyright 2021-2024 Buf Technologies, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -16,7 +16,8 @@ import { assert } from "./assert.js";
|
|
|
16
16
|
import { makeJsonFormatCommon } from "./json-format-common.js";
|
|
17
17
|
/* eslint-disable no-case-declarations, @typescript-eslint/restrict-plus-operands,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument */
|
|
18
18
|
export function makeJsonFormatProto3() {
|
|
19
|
-
|
|
19
|
+
// TODO field presence: merge this function with proto2. the reading side already switches behavior on the nullAsZeroValue argument.
|
|
20
|
+
return makeJsonFormatCommon(true, (writeEnum, writeScalar) => {
|
|
20
21
|
return function writeField(field, value, options) {
|
|
21
22
|
if (field.kind == "map") {
|
|
22
23
|
const jsonObj = {};
|
|
@@ -63,7 +64,7 @@ export function makeJsonFormatProto3() {
|
|
|
63
64
|
break;
|
|
64
65
|
case "message":
|
|
65
66
|
for (let i = 0; i < value.length; i++) {
|
|
66
|
-
jsonArr.push(
|
|
67
|
+
jsonArr.push(value[i].toJson(options));
|
|
67
68
|
}
|
|
68
69
|
break;
|
|
69
70
|
}
|
|
@@ -72,15 +73,16 @@ export function makeJsonFormatProto3() {
|
|
|
72
73
|
: undefined;
|
|
73
74
|
}
|
|
74
75
|
else {
|
|
76
|
+
if (value === undefined) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
75
79
|
switch (field.kind) {
|
|
76
80
|
case "scalar":
|
|
77
81
|
return writeScalar(field.T, value, !!field.oneof || field.opt || options.emitDefaultValues);
|
|
78
82
|
case "enum":
|
|
79
83
|
return writeEnum(field.T, value, !!field.oneof || field.opt || options.emitDefaultValues, options.enumAsInteger);
|
|
80
84
|
case "message":
|
|
81
|
-
return value
|
|
82
|
-
? wrapField(field.T, value).toJson(options)
|
|
83
|
-
: undefined;
|
|
85
|
+
return wrapField(field.T, value).toJson(options);
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DescEnum, DescEnumValue, DescField, DescMessage, DescService } from "../descriptor-set.js";
|
|
1
|
+
import type { DescEnum, DescEnumValue, DescExtension, DescField, DescMessage, DescService } from "../descriptor-set.js";
|
|
2
2
|
import type { DescMethod, DescOneof } from "../descriptor-set.js";
|
|
3
3
|
/**
|
|
4
4
|
* Returns the name of a protobuf element in generated code.
|
|
@@ -8,7 +8,7 @@ import type { DescMethod, DescOneof } from "../descriptor-set.js";
|
|
|
8
8
|
* the type name. For nested messages and enumerations, the names are joined
|
|
9
9
|
* with an underscore. For methods, the first character is made lowercase.
|
|
10
10
|
*/
|
|
11
|
-
export declare function localName(desc: DescEnum | DescEnumValue | DescMessage | DescOneof | DescField | DescService | DescMethod): string;
|
|
11
|
+
export declare function localName(desc: DescEnum | DescEnumValue | DescMessage | DescExtension | DescOneof | DescField | DescService | DescMethod): string;
|
|
12
12
|
/**
|
|
13
13
|
* Returns the name of a field in generated code.
|
|
14
14
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright 2021-
|
|
1
|
+
// Copyright 2021-2024 Buf Technologies, Inc.
|
|
2
2
|
//
|
|
3
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -27,7 +27,8 @@ export function localName(desc) {
|
|
|
27
27
|
return localOneofName(desc.name);
|
|
28
28
|
case "enum":
|
|
29
29
|
case "message":
|
|
30
|
-
case "service":
|
|
30
|
+
case "service":
|
|
31
|
+
case "extension": {
|
|
31
32
|
const pkg = desc.file.proto.package;
|
|
32
33
|
const offset = pkg === undefined ? 0 : pkg.length + 1;
|
|
33
34
|
const name = desc.typeName.substring(offset).replace(/\./g, "_");
|