@bufbuild/protobuf 1.7.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/create-descriptor-set.d.ts +6 -0
- package/dist/cjs/create-descriptor-set.js +2 -2
- package/dist/cjs/google/protobuf/descriptor_pb.js +1 -1
- package/dist/cjs/google/protobuf/struct_pb.js +1 -1
- package/dist/cjs/google/protobuf/type_pb.js +1 -1
- package/dist/cjs/private/feature-set.d.ts +4 -6
- package/dist/cjs/private/feature-set.js +17 -13
- package/dist/cjs/private/json-format-common.d.ts +3 -3
- package/dist/cjs/private/json-format-common.js +45 -36
- package/dist/cjs/private/json-format-proto2.js +2 -2
- package/dist/cjs/private/json-format-proto3.js +2 -2
- package/dist/esm/create-descriptor-set.d.ts +6 -0
- package/dist/esm/create-descriptor-set.js +3 -3
- package/dist/esm/google/protobuf/descriptor_pb.js +1 -1
- package/dist/esm/google/protobuf/struct_pb.js +1 -1
- package/dist/esm/google/protobuf/type_pb.js +1 -1
- package/dist/esm/private/feature-set.d.ts +4 -6
- package/dist/esm/private/feature-set.js +16 -12
- package/dist/esm/private/json-format-common.d.ts +3 -3
- package/dist/esm/private/json-format-common.js +45 -36
- package/dist/esm/private/json-format-proto2.js +2 -2
- package/dist/esm/private/json-format-proto3.js +2 -2
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FeatureSetDefaults, FileDescriptorProto, FileDescriptorSet } from "./google/protobuf/descriptor_pb.js";
|
|
2
2
|
import type { DescriptorSet } from "./descriptor-set.js";
|
|
3
|
+
import type { BinaryReadOptions, BinaryWriteOptions } from "./binary-format.js";
|
|
3
4
|
/**
|
|
4
5
|
* Create a DescriptorSet, a convenient interface for working with a set of
|
|
5
6
|
* google.protobuf.FileDescriptorProto.
|
|
@@ -26,5 +27,10 @@ interface CreateDescriptorSetOptions {
|
|
|
26
27
|
* `--experimental_edition_defaults_out`.
|
|
27
28
|
*/
|
|
28
29
|
featureSetDefaults?: FeatureSetDefaults;
|
|
30
|
+
/**
|
|
31
|
+
* Internally, data is serialized when features are resolved. The
|
|
32
|
+
* serialization options given here will be used for feature resolution.
|
|
33
|
+
*/
|
|
34
|
+
serializationOptions?: Partial<BinaryReadOptions & BinaryWriteOptions>;
|
|
29
35
|
}
|
|
30
36
|
export {};
|
|
@@ -44,11 +44,11 @@ function createDescriptorSet(input, options) {
|
|
|
44
44
|
: input;
|
|
45
45
|
const resolverByEdition = new Map();
|
|
46
46
|
const files = fileDescriptors.map((proto) => {
|
|
47
|
-
var _a
|
|
47
|
+
var _a;
|
|
48
48
|
const edition = (_a = proto.edition) !== null && _a !== void 0 ? _a : parseFileSyntax(proto.syntax, proto.edition).edition;
|
|
49
49
|
let resolveFeatures = resolverByEdition.get(edition);
|
|
50
50
|
if (resolveFeatures === undefined) {
|
|
51
|
-
resolveFeatures = (0, feature_set_js_1.createFeatureResolver)(
|
|
51
|
+
resolveFeatures = (0, feature_set_js_1.createFeatureResolver)(edition, options === null || options === void 0 ? void 0 : options.featureSetDefaults, options === null || options === void 0 ? void 0 : options.serializationOptions);
|
|
52
52
|
resolverByEdition.set(edition, resolveFeatures);
|
|
53
53
|
}
|
|
54
54
|
return newFile(proto, cart, resolveFeatures);
|
|
@@ -21,7 +21,7 @@ exports.GeneratedCodeInfo_Annotation_Semantic = exports.GeneratedCodeInfo_Annota
|
|
|
21
21
|
// The messages in this file describe the definitions found in .proto files.
|
|
22
22
|
// A valid .proto file can be translated directly to a FileDescriptorProto
|
|
23
23
|
// without any other information (e.g. without reading its imports).
|
|
24
|
-
// @generated by protoc-gen-es v1.7.
|
|
24
|
+
// @generated by protoc-gen-es v1.7.1 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts"
|
|
25
25
|
// @generated from file google/protobuf/descriptor.proto (package google.protobuf, syntax proto2)
|
|
26
26
|
/* eslint-disable */
|
|
27
27
|
const proto2_js_1 = require("../../proto2.js");
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.ListValue = exports.Value = exports.Struct = exports.NullValue = void 0;
|
|
17
|
-
// @generated by protoc-gen-es v1.7.
|
|
17
|
+
// @generated by protoc-gen-es v1.7.1 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts"
|
|
18
18
|
// @generated from file google/protobuf/struct.proto (package google.protobuf, syntax proto3)
|
|
19
19
|
/* eslint-disable */
|
|
20
20
|
const proto3_js_1 = require("../../proto3.js");
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.Option = exports.EnumValue = exports.Enum = exports.Field_Cardinality = exports.Field_Kind = exports.Field = exports.Type = exports.Syntax = void 0;
|
|
17
|
-
// @generated by protoc-gen-es v1.7.
|
|
17
|
+
// @generated by protoc-gen-es v1.7.1 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts"
|
|
18
18
|
// @generated from file google/protobuf/type.proto (package google.protobuf, syntax proto3)
|
|
19
19
|
/* eslint-disable */
|
|
20
20
|
const proto3_js_1 = require("../../proto3.js");
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { Edition, FeatureSet, FeatureSetDefaults } from "../google/protobuf/descriptor_pb.js";
|
|
2
|
-
|
|
3
|
-
* Static edition feature defaults supported by @bufbuild/protobuf.
|
|
4
|
-
*/
|
|
5
|
-
export declare const featureSetDefaults: FeatureSetDefaults;
|
|
2
|
+
import type { BinaryReadOptions, BinaryWriteOptions } from "../binary-format.js";
|
|
6
3
|
/**
|
|
7
4
|
* A merged google.protobuf.FeaturesSet, with all fields guaranteed to be set.
|
|
8
5
|
*/
|
|
@@ -16,6 +13,7 @@ export type MergedFeatureSet = FeatureSet & Required<FeatureSet>;
|
|
|
16
13
|
*/
|
|
17
14
|
export type FeatureResolverFn = (a?: FeatureSet, b?: FeatureSet) => MergedFeatureSet;
|
|
18
15
|
/**
|
|
19
|
-
* Create an edition feature resolver with the given feature set defaults
|
|
16
|
+
* Create an edition feature resolver with the given feature set defaults, or
|
|
17
|
+
* the feature set defaults supported by @bufbuild/protobuf.
|
|
20
18
|
*/
|
|
21
|
-
export declare function createFeatureResolver(
|
|
19
|
+
export declare function createFeatureResolver(edition: Edition, compiledFeatureSetDefaults?: FeatureSetDefaults, serializationOptions?: Partial<BinaryReadOptions & BinaryWriteOptions>): FeatureResolverFn;
|
|
@@ -13,24 +13,28 @@
|
|
|
13
13
|
// See the License for the specific language governing permissions and
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.createFeatureResolver =
|
|
16
|
+
exports.createFeatureResolver = void 0;
|
|
17
17
|
const descriptor_pb_js_1 = require("../google/protobuf/descriptor_pb.js");
|
|
18
18
|
const proto_base64_js_1 = require("../proto-base64.js");
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Return the edition feature defaults supported by @bufbuild/protobuf.
|
|
21
21
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
function getFeatureSetDefaults(options) {
|
|
23
|
+
return descriptor_pb_js_1.FeatureSetDefaults.fromBinary(proto_base64_js_1.protoBase64.dec(
|
|
24
|
+
/*upstream-inject-feature-defaults-start*/ "ChESDAgBEAIYAiABKAEwAhjmBwoREgwIAhABGAEgAigBMAEY5wcKERIMCAEQARgBIAIoATABGOgHIOYHKOgH" /*upstream-inject-feature-defaults-end*/), options);
|
|
25
|
+
}
|
|
24
26
|
/**
|
|
25
|
-
* Create an edition feature resolver with the given feature set defaults
|
|
27
|
+
* Create an edition feature resolver with the given feature set defaults, or
|
|
28
|
+
* the feature set defaults supported by @bufbuild/protobuf.
|
|
26
29
|
*/
|
|
27
|
-
function createFeatureResolver(compiledFeatureSetDefaults,
|
|
30
|
+
function createFeatureResolver(edition, compiledFeatureSetDefaults, serializationOptions) {
|
|
28
31
|
var _a, _b;
|
|
29
|
-
const
|
|
30
|
-
const
|
|
32
|
+
const fds = compiledFeatureSetDefaults !== null && compiledFeatureSetDefaults !== void 0 ? compiledFeatureSetDefaults : getFeatureSetDefaults(serializationOptions);
|
|
33
|
+
const min = fds.minimumEdition;
|
|
34
|
+
const max = fds.maximumEdition;
|
|
31
35
|
if (min === undefined ||
|
|
32
36
|
max === undefined ||
|
|
33
|
-
|
|
37
|
+
fds.defaults.some((d) => d.edition === undefined)) {
|
|
34
38
|
throw new Error("Invalid FeatureSetDefaults");
|
|
35
39
|
}
|
|
36
40
|
if (edition < min) {
|
|
@@ -40,7 +44,7 @@ function createFeatureResolver(compiledFeatureSetDefaults, edition) {
|
|
|
40
44
|
throw new Error(`Edition ${descriptor_pb_js_1.Edition[edition]} is later than the maximum supported edition ${descriptor_pb_js_1.Edition[max]}`);
|
|
41
45
|
}
|
|
42
46
|
let highestMatch = undefined;
|
|
43
|
-
for (const c of
|
|
47
|
+
for (const c of fds.defaults) {
|
|
44
48
|
const e = (_a = c.edition) !== null && _a !== void 0 ? _a : 0;
|
|
45
49
|
if (e > edition) {
|
|
46
50
|
continue;
|
|
@@ -56,12 +60,12 @@ function createFeatureResolver(compiledFeatureSetDefaults, edition) {
|
|
|
56
60
|
if (highestMatch === undefined) {
|
|
57
61
|
throw new Error(`No valid default found for edition ${descriptor_pb_js_1.Edition[edition]}`);
|
|
58
62
|
}
|
|
59
|
-
const
|
|
63
|
+
const featureSetBin = highestMatch.f.toBinary(serializationOptions);
|
|
60
64
|
return (...rest) => {
|
|
61
|
-
const f = descriptor_pb_js_1.FeatureSet.fromBinary(
|
|
65
|
+
const f = descriptor_pb_js_1.FeatureSet.fromBinary(featureSetBin, serializationOptions);
|
|
62
66
|
for (const c of rest) {
|
|
63
67
|
if (c !== undefined) {
|
|
64
|
-
f.fromBinary(c.toBinary());
|
|
68
|
+
f.fromBinary(c.toBinary(serializationOptions), serializationOptions);
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
71
|
if (!validateMergedFeatures(f)) {
|
|
@@ -3,7 +3,7 @@ import type { FieldInfo } from "../field.js";
|
|
|
3
3
|
import { ScalarType } from "../field.js";
|
|
4
4
|
import type { EnumType } from "../enum.js";
|
|
5
5
|
type JsonFormatWriteFieldFn = (field: FieldInfo, value: any, options: JsonWriteOptions) => JsonValue | undefined;
|
|
6
|
-
export declare function makeJsonFormatCommon(makeWriteField: (writeEnumFn: typeof writeEnum, writeScalarFn: typeof writeScalar) => JsonFormatWriteFieldFn): JsonFormat;
|
|
7
|
-
declare function writeEnum(type: EnumType, value: number | undefined,
|
|
8
|
-
declare function writeScalar(type: ScalarType, value: any,
|
|
6
|
+
export declare function makeJsonFormatCommon(nullAsZeroValue: boolean, makeWriteField: (writeEnumFn: typeof writeEnum, writeScalarFn: typeof writeScalar) => JsonFormatWriteFieldFn): JsonFormat;
|
|
7
|
+
declare function writeEnum(type: EnumType, value: number | undefined, emitZeroValue: boolean, enumAsInteger: boolean): JsonValue | undefined;
|
|
8
|
+
declare function writeScalar(type: ScalarType, value: any, emitZeroValue: boolean): JsonValue | undefined;
|
|
9
9
|
export {};
|
|
@@ -39,7 +39,7 @@ function makeReadOptions(options) {
|
|
|
39
39
|
function makeWriteOptions(options) {
|
|
40
40
|
return options ? Object.assign(Object.assign({}, jsonWriteDefaults), options) : jsonWriteDefaults;
|
|
41
41
|
}
|
|
42
|
-
function makeJsonFormatCommon(makeWriteField) {
|
|
42
|
+
function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
|
|
43
43
|
const writeField = makeWriteField(writeEnum, writeScalar);
|
|
44
44
|
return {
|
|
45
45
|
makeReadOptions,
|
|
@@ -65,7 +65,7 @@ function makeJsonFormatCommon(makeWriteField) {
|
|
|
65
65
|
}
|
|
66
66
|
oneofSeen.set(field.oneof, jsonKey);
|
|
67
67
|
}
|
|
68
|
-
readField(message, jsonValue, field, options, type);
|
|
68
|
+
readField(message, jsonValue, field, options, type, nullAsZeroValue);
|
|
69
69
|
}
|
|
70
70
|
else {
|
|
71
71
|
let found = false;
|
|
@@ -76,7 +76,7 @@ function makeJsonFormatCommon(makeWriteField) {
|
|
|
76
76
|
if (ext && ext.extendee.typeName == type.typeName) {
|
|
77
77
|
found = true;
|
|
78
78
|
const [container, get] = (0, extensions_js_1.createExtensionContainer)(ext);
|
|
79
|
-
readField(container, jsonValue, ext.field, options, ext);
|
|
79
|
+
readField(container, jsonValue, ext.field, options, ext, true);
|
|
80
80
|
// We pass on the options as BinaryReadOptions/BinaryWriteOptions,
|
|
81
81
|
// so that users can bring their own binary reader and writer factories
|
|
82
82
|
// if necessary.
|
|
@@ -142,7 +142,7 @@ function makeJsonFormatCommon(makeWriteField) {
|
|
|
142
142
|
}
|
|
143
143
|
return json;
|
|
144
144
|
},
|
|
145
|
-
readScalar,
|
|
145
|
+
readScalar: (type, json, longType) => readScalar(type, json, longType, nullAsZeroValue), // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
|
|
146
146
|
writeScalar,
|
|
147
147
|
debug: debugJsonValue,
|
|
148
148
|
};
|
|
@@ -163,8 +163,11 @@ function debugJsonValue(json) {
|
|
|
163
163
|
}
|
|
164
164
|
// Read a JSON value for a field.
|
|
165
165
|
// The "type" argument is only used to provide context in errors.
|
|
166
|
+
// The argument "nullAsZeroValue" applies to singular fields (not repeated, map,
|
|
167
|
+
// or oneof). If the argument is `true`, JSON null is parsed as the fields
|
|
168
|
+
// zero-value. If the argument is false, JSON null sets the field to `undefined`.
|
|
166
169
|
function readField(target, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access
|
|
167
|
-
jsonValue, field, options, type) {
|
|
170
|
+
jsonValue, field, options, type, nullAsZeroValue) {
|
|
168
171
|
let localName = field.localName;
|
|
169
172
|
if (field.oneof) {
|
|
170
173
|
if (jsonValue === null && field.kind == "scalar") {
|
|
@@ -193,13 +196,13 @@ jsonValue, field, options, type) {
|
|
|
193
196
|
val = field.T.fromJson(jsonItem, options);
|
|
194
197
|
break;
|
|
195
198
|
case "enum":
|
|
196
|
-
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields);
|
|
199
|
+
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields, true);
|
|
197
200
|
if (val === undefined)
|
|
198
201
|
continue;
|
|
199
202
|
break;
|
|
200
203
|
case "scalar":
|
|
201
204
|
try {
|
|
202
|
-
val = readScalar(field.T, jsonItem, field.L);
|
|
205
|
+
val = readScalar(field.T, jsonItem, field.L, true);
|
|
203
206
|
}
|
|
204
207
|
catch (e) {
|
|
205
208
|
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`;
|
|
@@ -231,13 +234,13 @@ jsonValue, field, options, type) {
|
|
|
231
234
|
val = field.V.T.fromJson(jsonMapValue, options);
|
|
232
235
|
break;
|
|
233
236
|
case "enum":
|
|
234
|
-
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields);
|
|
237
|
+
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields, true);
|
|
235
238
|
if (val === undefined)
|
|
236
239
|
continue;
|
|
237
240
|
break;
|
|
238
241
|
case "scalar":
|
|
239
242
|
try {
|
|
240
|
-
val = readScalar(field.V.T, jsonMapValue, field_js_1.LongType.BIGINT);
|
|
243
|
+
val = readScalar(field.V.T, jsonMapValue, field_js_1.LongType.BIGINT, true);
|
|
241
244
|
}
|
|
242
245
|
catch (e) {
|
|
243
246
|
let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
@@ -255,7 +258,7 @@ jsonValue, field, options, type) {
|
|
|
255
258
|
: jsonMapKey == "false"
|
|
256
259
|
? false
|
|
257
260
|
: jsonMapKey
|
|
258
|
-
: jsonMapKey, field_js_1.LongType.BIGINT).toString()] = val;
|
|
261
|
+
: jsonMapKey, field_js_1.LongType.BIGINT, true).toString()] = val;
|
|
259
262
|
}
|
|
260
263
|
catch (e) {
|
|
261
264
|
let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
@@ -288,14 +291,14 @@ jsonValue, field, options, type) {
|
|
|
288
291
|
}
|
|
289
292
|
break;
|
|
290
293
|
case "enum":
|
|
291
|
-
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields);
|
|
294
|
+
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields, nullAsZeroValue);
|
|
292
295
|
if (enumValue !== undefined) {
|
|
293
296
|
target[localName] = enumValue;
|
|
294
297
|
}
|
|
295
298
|
break;
|
|
296
299
|
case "scalar":
|
|
297
300
|
try {
|
|
298
|
-
target[localName] = readScalar(field.T, jsonValue, field.L);
|
|
301
|
+
target[localName] = readScalar(field.T, jsonValue, field.L, nullAsZeroValue);
|
|
299
302
|
}
|
|
300
303
|
catch (e) {
|
|
301
304
|
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
@@ -310,7 +313,10 @@ jsonValue, field, options, type) {
|
|
|
310
313
|
}
|
|
311
314
|
// May throw an error. If the error message is non-blank, it should be shown.
|
|
312
315
|
// It is up to the caller to provide context.
|
|
313
|
-
function
|
|
316
|
+
// If the argument "nullAsZeroValue" is `true`, this function returns the zero-value
|
|
317
|
+
// for JSON null. If the argument is `false`, this function returns `undefined`
|
|
318
|
+
// for JSON null.
|
|
319
|
+
function readScalar(type, json, longType, nullAsZeroValue) {
|
|
314
320
|
// every valid case in the switch below returns, and every fall
|
|
315
321
|
// through is regarded as a failure.
|
|
316
322
|
switch (type) {
|
|
@@ -319,7 +325,7 @@ function readScalar(type, json, longType) {
|
|
|
319
325
|
case field_js_1.ScalarType.DOUBLE:
|
|
320
326
|
case field_js_1.ScalarType.FLOAT:
|
|
321
327
|
if (json === null)
|
|
322
|
-
return 0.0
|
|
328
|
+
return nullAsZeroValue ? 0.0 : undefined;
|
|
323
329
|
if (json === "NaN")
|
|
324
330
|
return Number.NaN;
|
|
325
331
|
if (json === "Infinity")
|
|
@@ -356,7 +362,7 @@ function readScalar(type, json, longType) {
|
|
|
356
362
|
case field_js_1.ScalarType.SINT32:
|
|
357
363
|
case field_js_1.ScalarType.UINT32:
|
|
358
364
|
if (json === null)
|
|
359
|
-
return
|
|
365
|
+
return nullAsZeroValue ? 0 : undefined;
|
|
360
366
|
let int32;
|
|
361
367
|
if (typeof json == "number")
|
|
362
368
|
int32 = json;
|
|
@@ -376,7 +382,7 @@ function readScalar(type, json, longType) {
|
|
|
376
382
|
case field_js_1.ScalarType.SFIXED64:
|
|
377
383
|
case field_js_1.ScalarType.SINT64:
|
|
378
384
|
if (json === null)
|
|
379
|
-
return proto_int64_js_1.protoInt64.zero
|
|
385
|
+
return nullAsZeroValue ? proto_int64_js_1.protoInt64.zero : undefined;
|
|
380
386
|
if (typeof json != "number" && typeof json != "string")
|
|
381
387
|
break;
|
|
382
388
|
const long = proto_int64_js_1.protoInt64.parse(json);
|
|
@@ -385,7 +391,7 @@ function readScalar(type, json, longType) {
|
|
|
385
391
|
case field_js_1.ScalarType.FIXED64:
|
|
386
392
|
case field_js_1.ScalarType.UINT64:
|
|
387
393
|
if (json === null)
|
|
388
|
-
return proto_int64_js_1.protoInt64.zero
|
|
394
|
+
return nullAsZeroValue ? proto_int64_js_1.protoInt64.zero : undefined;
|
|
389
395
|
if (typeof json != "number" && typeof json != "string")
|
|
390
396
|
break;
|
|
391
397
|
const uLong = proto_int64_js_1.protoInt64.uParse(json);
|
|
@@ -394,14 +400,14 @@ function readScalar(type, json, longType) {
|
|
|
394
400
|
// bool:
|
|
395
401
|
case field_js_1.ScalarType.BOOL:
|
|
396
402
|
if (json === null)
|
|
397
|
-
return
|
|
403
|
+
return nullAsZeroValue ? false : undefined;
|
|
398
404
|
if (typeof json !== "boolean")
|
|
399
405
|
break;
|
|
400
406
|
return json;
|
|
401
407
|
// string:
|
|
402
408
|
case field_js_1.ScalarType.STRING:
|
|
403
409
|
if (json === null)
|
|
404
|
-
return ""
|
|
410
|
+
return nullAsZeroValue ? "" : undefined;
|
|
405
411
|
if (typeof json !== "string") {
|
|
406
412
|
break;
|
|
407
413
|
}
|
|
@@ -417,19 +423,24 @@ function readScalar(type, json, longType) {
|
|
|
417
423
|
// bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
|
|
418
424
|
// Either standard or URL-safe base64 encoding with/without paddings are accepted.
|
|
419
425
|
case field_js_1.ScalarType.BYTES:
|
|
420
|
-
if (json === null
|
|
421
|
-
return new Uint8Array(0)
|
|
426
|
+
if (json === null)
|
|
427
|
+
return nullAsZeroValue ? new Uint8Array(0) : undefined;
|
|
428
|
+
if (json === "")
|
|
429
|
+
return new Uint8Array(0);
|
|
422
430
|
if (typeof json !== "string")
|
|
423
431
|
break;
|
|
424
432
|
return proto_base64_js_1.protoBase64.dec(json);
|
|
425
433
|
}
|
|
426
434
|
throw new Error();
|
|
427
435
|
}
|
|
428
|
-
function
|
|
436
|
+
// If the argument "nullAsZeroValue" is `true`, this function returns the first
|
|
437
|
+
// enum value for JSON null. If the argument is `false`, this function returns
|
|
438
|
+
// `undefined`.
|
|
439
|
+
function readEnum(type, json, ignoreUnknownFields, nullAsZeroValue) {
|
|
429
440
|
if (json === null) {
|
|
430
|
-
// proto3 requires 0 to be default value for all enums
|
|
431
|
-
//
|
|
432
|
-
return 0;
|
|
441
|
+
// proto3 requires 0 to be default value for all enums (which is required to be the first value).
|
|
442
|
+
// proto2 uses the first value (at least with protoc-gen-go).
|
|
443
|
+
return nullAsZeroValue ? type.values[0].no : undefined;
|
|
433
444
|
}
|
|
434
445
|
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
435
446
|
switch (typeof json) {
|
|
@@ -448,12 +459,12 @@ function readEnum(type, json, ignoreUnknownFields) {
|
|
|
448
459
|
}
|
|
449
460
|
throw new Error(`cannot decode enum ${type.typeName} from JSON: ${debugJsonValue(json)}`);
|
|
450
461
|
}
|
|
451
|
-
function writeEnum(type, value,
|
|
462
|
+
function writeEnum(type, value, emitZeroValue, enumAsInteger) {
|
|
452
463
|
var _a;
|
|
453
464
|
if (value === undefined) {
|
|
454
465
|
return value;
|
|
455
466
|
}
|
|
456
|
-
if (
|
|
467
|
+
if (!emitZeroValue && type.values[0].no === value) {
|
|
457
468
|
// proto3 requires 0 to be default value for all enums
|
|
458
469
|
return undefined;
|
|
459
470
|
}
|
|
@@ -466,7 +477,7 @@ function writeEnum(type, value, emitIntrinsicDefault, enumAsInteger) {
|
|
|
466
477
|
const val = type.findNumber(value);
|
|
467
478
|
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
|
|
468
479
|
}
|
|
469
|
-
function writeScalar(type, value,
|
|
480
|
+
function writeScalar(type, value, emitZeroValue) {
|
|
470
481
|
if (value === undefined) {
|
|
471
482
|
return undefined;
|
|
472
483
|
}
|
|
@@ -478,7 +489,7 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
478
489
|
case field_js_1.ScalarType.FIXED32:
|
|
479
490
|
case field_js_1.ScalarType.UINT32:
|
|
480
491
|
(0, assert_js_1.assert)(typeof value == "number");
|
|
481
|
-
return value != 0 ||
|
|
492
|
+
return value != 0 || emitZeroValue ? value : undefined;
|
|
482
493
|
// float, double: JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity".
|
|
483
494
|
// Either numbers or strings are accepted. Exponent notation is also accepted.
|
|
484
495
|
case field_js_1.ScalarType.FLOAT:
|
|
@@ -491,15 +502,15 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
491
502
|
return "Infinity";
|
|
492
503
|
if (value === Number.NEGATIVE_INFINITY)
|
|
493
504
|
return "-Infinity";
|
|
494
|
-
return value !== 0 ||
|
|
505
|
+
return value !== 0 || emitZeroValue ? value : undefined;
|
|
495
506
|
// string:
|
|
496
507
|
case field_js_1.ScalarType.STRING:
|
|
497
508
|
(0, assert_js_1.assert)(typeof value == "string");
|
|
498
|
-
return value.length > 0 ||
|
|
509
|
+
return value.length > 0 || emitZeroValue ? value : undefined;
|
|
499
510
|
// bool:
|
|
500
511
|
case field_js_1.ScalarType.BOOL:
|
|
501
512
|
(0, assert_js_1.assert)(typeof value == "boolean");
|
|
502
|
-
return value ||
|
|
513
|
+
return value || emitZeroValue ? value : undefined;
|
|
503
514
|
// JSON value will be a decimal string. Either numbers or strings are accepted.
|
|
504
515
|
case field_js_1.ScalarType.UINT64:
|
|
505
516
|
case field_js_1.ScalarType.FIXED64:
|
|
@@ -512,14 +523,12 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
512
523
|
// We use implicit conversion with `value != 0` to catch both 0n and "0"
|
|
513
524
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
514
525
|
// @ts-ignore
|
|
515
|
-
return
|
|
516
|
-
? value.toString(10)
|
|
517
|
-
: undefined;
|
|
526
|
+
return emitZeroValue || value != 0 ? value.toString(10) : undefined;
|
|
518
527
|
// bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
|
|
519
528
|
// Either standard or URL-safe base64 encoding with/without paddings are accepted.
|
|
520
529
|
case field_js_1.ScalarType.BYTES:
|
|
521
530
|
(0, assert_js_1.assert)(value instanceof Uint8Array);
|
|
522
|
-
return
|
|
531
|
+
return emitZeroValue || value.byteLength > 0
|
|
523
532
|
? proto_base64_js_1.protoBase64.enc(value)
|
|
524
533
|
: undefined;
|
|
525
534
|
}
|
|
@@ -19,8 +19,8 @@ const assert_js_1 = require("./assert.js");
|
|
|
19
19
|
const json_format_common_js_1 = require("./json-format-common.js");
|
|
20
20
|
/* 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 */
|
|
21
21
|
function makeJsonFormatProto2() {
|
|
22
|
-
// TODO field presence: merge this function with
|
|
23
|
-
return (0, json_format_common_js_1.makeJsonFormatCommon)((writeEnum, writeScalar) => {
|
|
22
|
+
// TODO field presence: merge this function with proto3. the reading side already switches behavior on the nullAsZeroValue argument.
|
|
23
|
+
return (0, json_format_common_js_1.makeJsonFormatCommon)(false, (writeEnum, writeScalar) => {
|
|
24
24
|
return function writeField(field, value, options) {
|
|
25
25
|
if (field.kind == "map") {
|
|
26
26
|
const jsonObj = {};
|
|
@@ -19,8 +19,8 @@ const assert_js_1 = require("./assert.js");
|
|
|
19
19
|
const json_format_common_js_1 = require("./json-format-common.js");
|
|
20
20
|
/* 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 */
|
|
21
21
|
function makeJsonFormatProto3() {
|
|
22
|
-
// TODO field presence: merge this function with proto2
|
|
23
|
-
return (0, json_format_common_js_1.makeJsonFormatCommon)((writeEnum, writeScalar) => {
|
|
22
|
+
// TODO field presence: merge this function with proto2. the reading side already switches behavior on the nullAsZeroValue argument.
|
|
23
|
+
return (0, json_format_common_js_1.makeJsonFormatCommon)(true, (writeEnum, writeScalar) => {
|
|
24
24
|
return function writeField(field, value, options) {
|
|
25
25
|
if (field.kind == "map") {
|
|
26
26
|
const jsonObj = {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FeatureSetDefaults, FileDescriptorProto, FileDescriptorSet } from "./google/protobuf/descriptor_pb.js";
|
|
2
2
|
import type { DescriptorSet } from "./descriptor-set.js";
|
|
3
|
+
import type { BinaryReadOptions, BinaryWriteOptions } from "./binary-format.js";
|
|
3
4
|
/**
|
|
4
5
|
* Create a DescriptorSet, a convenient interface for working with a set of
|
|
5
6
|
* google.protobuf.FileDescriptorProto.
|
|
@@ -26,5 +27,10 @@ interface CreateDescriptorSetOptions {
|
|
|
26
27
|
* `--experimental_edition_defaults_out`.
|
|
27
28
|
*/
|
|
28
29
|
featureSetDefaults?: FeatureSetDefaults;
|
|
30
|
+
/**
|
|
31
|
+
* Internally, data is serialized when features are resolved. The
|
|
32
|
+
* serialization options given here will be used for feature resolution.
|
|
33
|
+
*/
|
|
34
|
+
serializationOptions?: Partial<BinaryReadOptions & BinaryWriteOptions>;
|
|
29
35
|
}
|
|
30
36
|
export {};
|
|
@@ -17,7 +17,7 @@ import { LongType, ScalarType } from "./field.js";
|
|
|
17
17
|
import { MethodIdempotency, MethodKind } from "./service-type.js";
|
|
18
18
|
import { fieldJsonName, findEnumSharedPrefix } from "./private/names.js";
|
|
19
19
|
import { parseTextFormatEnumValue, parseTextFormatScalarValue, } from "./private/text-format.js";
|
|
20
|
-
import { createFeatureResolver
|
|
20
|
+
import { createFeatureResolver } from "./private/feature-set.js";
|
|
21
21
|
/**
|
|
22
22
|
* Create a DescriptorSet, a convenient interface for working with a set of
|
|
23
23
|
* google.protobuf.FileDescriptorProto.
|
|
@@ -41,11 +41,11 @@ export function createDescriptorSet(input, options) {
|
|
|
41
41
|
: input;
|
|
42
42
|
const resolverByEdition = new Map();
|
|
43
43
|
const files = fileDescriptors.map((proto) => {
|
|
44
|
-
var _a
|
|
44
|
+
var _a;
|
|
45
45
|
const edition = (_a = proto.edition) !== null && _a !== void 0 ? _a : parseFileSyntax(proto.syntax, proto.edition).edition;
|
|
46
46
|
let resolveFeatures = resolverByEdition.get(edition);
|
|
47
47
|
if (resolveFeatures === undefined) {
|
|
48
|
-
resolveFeatures = createFeatureResolver(
|
|
48
|
+
resolveFeatures = createFeatureResolver(edition, options === null || options === void 0 ? void 0 : options.featureSetDefaults, options === null || options === void 0 ? void 0 : options.serializationOptions);
|
|
49
49
|
resolverByEdition.set(edition, resolveFeatures);
|
|
50
50
|
}
|
|
51
51
|
return newFile(proto, cart, resolveFeatures);
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// The messages in this file describe the definitions found in .proto files.
|
|
19
19
|
// A valid .proto file can be translated directly to a FileDescriptorProto
|
|
20
20
|
// without any other information (e.g. without reading its imports).
|
|
21
|
-
// @generated by protoc-gen-es v1.7.
|
|
21
|
+
// @generated by protoc-gen-es v1.7.1 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts"
|
|
22
22
|
// @generated from file google/protobuf/descriptor.proto (package google.protobuf, syntax proto2)
|
|
23
23
|
/* eslint-disable */
|
|
24
24
|
import { proto2 } from "../../proto2.js";
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
|
-
// @generated by protoc-gen-es v1.7.
|
|
14
|
+
// @generated by protoc-gen-es v1.7.1 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts"
|
|
15
15
|
// @generated from file google/protobuf/struct.proto (package google.protobuf, syntax proto3)
|
|
16
16
|
/* eslint-disable */
|
|
17
17
|
import { proto3 } from "../../proto3.js";
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
|
-
// @generated by protoc-gen-es v1.7.
|
|
14
|
+
// @generated by protoc-gen-es v1.7.1 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts"
|
|
15
15
|
// @generated from file google/protobuf/type.proto (package google.protobuf, syntax proto3)
|
|
16
16
|
/* eslint-disable */
|
|
17
17
|
import { proto3 } from "../../proto3.js";
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { Edition, FeatureSet, FeatureSetDefaults } from "../google/protobuf/descriptor_pb.js";
|
|
2
|
-
|
|
3
|
-
* Static edition feature defaults supported by @bufbuild/protobuf.
|
|
4
|
-
*/
|
|
5
|
-
export declare const featureSetDefaults: FeatureSetDefaults;
|
|
2
|
+
import type { BinaryReadOptions, BinaryWriteOptions } from "../binary-format.js";
|
|
6
3
|
/**
|
|
7
4
|
* A merged google.protobuf.FeaturesSet, with all fields guaranteed to be set.
|
|
8
5
|
*/
|
|
@@ -16,6 +13,7 @@ export type MergedFeatureSet = FeatureSet & Required<FeatureSet>;
|
|
|
16
13
|
*/
|
|
17
14
|
export type FeatureResolverFn = (a?: FeatureSet, b?: FeatureSet) => MergedFeatureSet;
|
|
18
15
|
/**
|
|
19
|
-
* Create an edition feature resolver with the given feature set defaults
|
|
16
|
+
* Create an edition feature resolver with the given feature set defaults, or
|
|
17
|
+
* the feature set defaults supported by @bufbuild/protobuf.
|
|
20
18
|
*/
|
|
21
|
-
export declare function createFeatureResolver(
|
|
19
|
+
export declare function createFeatureResolver(edition: Edition, compiledFeatureSetDefaults?: FeatureSetDefaults, serializationOptions?: Partial<BinaryReadOptions & BinaryWriteOptions>): FeatureResolverFn;
|
|
@@ -14,20 +14,24 @@
|
|
|
14
14
|
import { Edition, FeatureSet, FeatureSetDefaults, } from "../google/protobuf/descriptor_pb.js";
|
|
15
15
|
import { protoBase64 } from "../proto-base64.js";
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Return the edition feature defaults supported by @bufbuild/protobuf.
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
function getFeatureSetDefaults(options) {
|
|
20
|
+
return FeatureSetDefaults.fromBinary(protoBase64.dec(
|
|
21
|
+
/*upstream-inject-feature-defaults-start*/ "ChESDAgBEAIYAiABKAEwAhjmBwoREgwIAhABGAEgAigBMAEY5wcKERIMCAEQARgBIAIoATABGOgHIOYHKOgH" /*upstream-inject-feature-defaults-end*/), options);
|
|
22
|
+
}
|
|
21
23
|
/**
|
|
22
|
-
* Create an edition feature resolver with the given feature set defaults
|
|
24
|
+
* Create an edition feature resolver with the given feature set defaults, or
|
|
25
|
+
* the feature set defaults supported by @bufbuild/protobuf.
|
|
23
26
|
*/
|
|
24
|
-
export function createFeatureResolver(compiledFeatureSetDefaults,
|
|
27
|
+
export function createFeatureResolver(edition, compiledFeatureSetDefaults, serializationOptions) {
|
|
25
28
|
var _a, _b;
|
|
26
|
-
const
|
|
27
|
-
const
|
|
29
|
+
const fds = compiledFeatureSetDefaults !== null && compiledFeatureSetDefaults !== void 0 ? compiledFeatureSetDefaults : getFeatureSetDefaults(serializationOptions);
|
|
30
|
+
const min = fds.minimumEdition;
|
|
31
|
+
const max = fds.maximumEdition;
|
|
28
32
|
if (min === undefined ||
|
|
29
33
|
max === undefined ||
|
|
30
|
-
|
|
34
|
+
fds.defaults.some((d) => d.edition === undefined)) {
|
|
31
35
|
throw new Error("Invalid FeatureSetDefaults");
|
|
32
36
|
}
|
|
33
37
|
if (edition < min) {
|
|
@@ -37,7 +41,7 @@ export function createFeatureResolver(compiledFeatureSetDefaults, edition) {
|
|
|
37
41
|
throw new Error(`Edition ${Edition[edition]} is later than the maximum supported edition ${Edition[max]}`);
|
|
38
42
|
}
|
|
39
43
|
let highestMatch = undefined;
|
|
40
|
-
for (const c of
|
|
44
|
+
for (const c of fds.defaults) {
|
|
41
45
|
const e = (_a = c.edition) !== null && _a !== void 0 ? _a : 0;
|
|
42
46
|
if (e > edition) {
|
|
43
47
|
continue;
|
|
@@ -53,12 +57,12 @@ export function createFeatureResolver(compiledFeatureSetDefaults, edition) {
|
|
|
53
57
|
if (highestMatch === undefined) {
|
|
54
58
|
throw new Error(`No valid default found for edition ${Edition[edition]}`);
|
|
55
59
|
}
|
|
56
|
-
const
|
|
60
|
+
const featureSetBin = highestMatch.f.toBinary(serializationOptions);
|
|
57
61
|
return (...rest) => {
|
|
58
|
-
const f = FeatureSet.fromBinary(
|
|
62
|
+
const f = FeatureSet.fromBinary(featureSetBin, serializationOptions);
|
|
59
63
|
for (const c of rest) {
|
|
60
64
|
if (c !== undefined) {
|
|
61
|
-
f.fromBinary(c.toBinary());
|
|
65
|
+
f.fromBinary(c.toBinary(serializationOptions), serializationOptions);
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
if (!validateMergedFeatures(f)) {
|
|
@@ -3,7 +3,7 @@ import type { FieldInfo } from "../field.js";
|
|
|
3
3
|
import { ScalarType } from "../field.js";
|
|
4
4
|
import type { EnumType } from "../enum.js";
|
|
5
5
|
type JsonFormatWriteFieldFn = (field: FieldInfo, value: any, options: JsonWriteOptions) => JsonValue | undefined;
|
|
6
|
-
export declare function makeJsonFormatCommon(makeWriteField: (writeEnumFn: typeof writeEnum, writeScalarFn: typeof writeScalar) => JsonFormatWriteFieldFn): JsonFormat;
|
|
7
|
-
declare function writeEnum(type: EnumType, value: number | undefined,
|
|
8
|
-
declare function writeScalar(type: ScalarType, value: any,
|
|
6
|
+
export declare function makeJsonFormatCommon(nullAsZeroValue: boolean, makeWriteField: (writeEnumFn: typeof writeEnum, writeScalarFn: typeof writeScalar) => JsonFormatWriteFieldFn): JsonFormat;
|
|
7
|
+
declare function writeEnum(type: EnumType, value: number | undefined, emitZeroValue: boolean, enumAsInteger: boolean): JsonValue | undefined;
|
|
8
|
+
declare function writeScalar(type: ScalarType, value: any, emitZeroValue: boolean): JsonValue | undefined;
|
|
9
9
|
export {};
|
|
@@ -36,7 +36,7 @@ function makeReadOptions(options) {
|
|
|
36
36
|
function makeWriteOptions(options) {
|
|
37
37
|
return options ? Object.assign(Object.assign({}, jsonWriteDefaults), options) : jsonWriteDefaults;
|
|
38
38
|
}
|
|
39
|
-
export function makeJsonFormatCommon(makeWriteField) {
|
|
39
|
+
export function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
|
|
40
40
|
const writeField = makeWriteField(writeEnum, writeScalar);
|
|
41
41
|
return {
|
|
42
42
|
makeReadOptions,
|
|
@@ -62,7 +62,7 @@ export function makeJsonFormatCommon(makeWriteField) {
|
|
|
62
62
|
}
|
|
63
63
|
oneofSeen.set(field.oneof, jsonKey);
|
|
64
64
|
}
|
|
65
|
-
readField(message, jsonValue, field, options, type);
|
|
65
|
+
readField(message, jsonValue, field, options, type, nullAsZeroValue);
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
68
|
let found = false;
|
|
@@ -73,7 +73,7 @@ export function makeJsonFormatCommon(makeWriteField) {
|
|
|
73
73
|
if (ext && ext.extendee.typeName == type.typeName) {
|
|
74
74
|
found = true;
|
|
75
75
|
const [container, get] = createExtensionContainer(ext);
|
|
76
|
-
readField(container, jsonValue, ext.field, options, ext);
|
|
76
|
+
readField(container, jsonValue, ext.field, options, ext, true);
|
|
77
77
|
// We pass on the options as BinaryReadOptions/BinaryWriteOptions,
|
|
78
78
|
// so that users can bring their own binary reader and writer factories
|
|
79
79
|
// if necessary.
|
|
@@ -139,7 +139,7 @@ export function makeJsonFormatCommon(makeWriteField) {
|
|
|
139
139
|
}
|
|
140
140
|
return json;
|
|
141
141
|
},
|
|
142
|
-
readScalar,
|
|
142
|
+
readScalar: (type, json, longType) => readScalar(type, json, longType, nullAsZeroValue), // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
|
|
143
143
|
writeScalar,
|
|
144
144
|
debug: debugJsonValue,
|
|
145
145
|
};
|
|
@@ -159,8 +159,11 @@ function debugJsonValue(json) {
|
|
|
159
159
|
}
|
|
160
160
|
// Read a JSON value for a field.
|
|
161
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`.
|
|
162
165
|
function readField(target, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access
|
|
163
|
-
jsonValue, field, options, type) {
|
|
166
|
+
jsonValue, field, options, type, nullAsZeroValue) {
|
|
164
167
|
let localName = field.localName;
|
|
165
168
|
if (field.oneof) {
|
|
166
169
|
if (jsonValue === null && field.kind == "scalar") {
|
|
@@ -189,13 +192,13 @@ jsonValue, field, options, type) {
|
|
|
189
192
|
val = field.T.fromJson(jsonItem, options);
|
|
190
193
|
break;
|
|
191
194
|
case "enum":
|
|
192
|
-
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields);
|
|
195
|
+
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields, true);
|
|
193
196
|
if (val === undefined)
|
|
194
197
|
continue;
|
|
195
198
|
break;
|
|
196
199
|
case "scalar":
|
|
197
200
|
try {
|
|
198
|
-
val = readScalar(field.T, jsonItem, field.L);
|
|
201
|
+
val = readScalar(field.T, jsonItem, field.L, true);
|
|
199
202
|
}
|
|
200
203
|
catch (e) {
|
|
201
204
|
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`;
|
|
@@ -227,13 +230,13 @@ jsonValue, field, options, type) {
|
|
|
227
230
|
val = field.V.T.fromJson(jsonMapValue, options);
|
|
228
231
|
break;
|
|
229
232
|
case "enum":
|
|
230
|
-
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields);
|
|
233
|
+
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields, true);
|
|
231
234
|
if (val === undefined)
|
|
232
235
|
continue;
|
|
233
236
|
break;
|
|
234
237
|
case "scalar":
|
|
235
238
|
try {
|
|
236
|
-
val = readScalar(field.V.T, jsonMapValue, LongType.BIGINT);
|
|
239
|
+
val = readScalar(field.V.T, jsonMapValue, LongType.BIGINT, true);
|
|
237
240
|
}
|
|
238
241
|
catch (e) {
|
|
239
242
|
let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
@@ -251,7 +254,7 @@ jsonValue, field, options, type) {
|
|
|
251
254
|
: jsonMapKey == "false"
|
|
252
255
|
? false
|
|
253
256
|
: jsonMapKey
|
|
254
|
-
: jsonMapKey, LongType.BIGINT).toString()] = val;
|
|
257
|
+
: jsonMapKey, LongType.BIGINT, true).toString()] = val;
|
|
255
258
|
}
|
|
256
259
|
catch (e) {
|
|
257
260
|
let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
@@ -284,14 +287,14 @@ jsonValue, field, options, type) {
|
|
|
284
287
|
}
|
|
285
288
|
break;
|
|
286
289
|
case "enum":
|
|
287
|
-
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields);
|
|
290
|
+
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields, nullAsZeroValue);
|
|
288
291
|
if (enumValue !== undefined) {
|
|
289
292
|
target[localName] = enumValue;
|
|
290
293
|
}
|
|
291
294
|
break;
|
|
292
295
|
case "scalar":
|
|
293
296
|
try {
|
|
294
|
-
target[localName] = readScalar(field.T, jsonValue, field.L);
|
|
297
|
+
target[localName] = readScalar(field.T, jsonValue, field.L, nullAsZeroValue);
|
|
295
298
|
}
|
|
296
299
|
catch (e) {
|
|
297
300
|
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
|
|
@@ -306,7 +309,10 @@ jsonValue, field, options, type) {
|
|
|
306
309
|
}
|
|
307
310
|
// May throw an error. If the error message is non-blank, it should be shown.
|
|
308
311
|
// It is up to the caller to provide context.
|
|
309
|
-
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) {
|
|
310
316
|
// every valid case in the switch below returns, and every fall
|
|
311
317
|
// through is regarded as a failure.
|
|
312
318
|
switch (type) {
|
|
@@ -315,7 +321,7 @@ function readScalar(type, json, longType) {
|
|
|
315
321
|
case ScalarType.DOUBLE:
|
|
316
322
|
case ScalarType.FLOAT:
|
|
317
323
|
if (json === null)
|
|
318
|
-
return 0.0
|
|
324
|
+
return nullAsZeroValue ? 0.0 : undefined;
|
|
319
325
|
if (json === "NaN")
|
|
320
326
|
return Number.NaN;
|
|
321
327
|
if (json === "Infinity")
|
|
@@ -352,7 +358,7 @@ function readScalar(type, json, longType) {
|
|
|
352
358
|
case ScalarType.SINT32:
|
|
353
359
|
case ScalarType.UINT32:
|
|
354
360
|
if (json === null)
|
|
355
|
-
return
|
|
361
|
+
return nullAsZeroValue ? 0 : undefined;
|
|
356
362
|
let int32;
|
|
357
363
|
if (typeof json == "number")
|
|
358
364
|
int32 = json;
|
|
@@ -372,7 +378,7 @@ function readScalar(type, json, longType) {
|
|
|
372
378
|
case ScalarType.SFIXED64:
|
|
373
379
|
case ScalarType.SINT64:
|
|
374
380
|
if (json === null)
|
|
375
|
-
return protoInt64.zero
|
|
381
|
+
return nullAsZeroValue ? protoInt64.zero : undefined;
|
|
376
382
|
if (typeof json != "number" && typeof json != "string")
|
|
377
383
|
break;
|
|
378
384
|
const long = protoInt64.parse(json);
|
|
@@ -381,7 +387,7 @@ function readScalar(type, json, longType) {
|
|
|
381
387
|
case ScalarType.FIXED64:
|
|
382
388
|
case ScalarType.UINT64:
|
|
383
389
|
if (json === null)
|
|
384
|
-
return protoInt64.zero
|
|
390
|
+
return nullAsZeroValue ? protoInt64.zero : undefined;
|
|
385
391
|
if (typeof json != "number" && typeof json != "string")
|
|
386
392
|
break;
|
|
387
393
|
const uLong = protoInt64.uParse(json);
|
|
@@ -390,14 +396,14 @@ function readScalar(type, json, longType) {
|
|
|
390
396
|
// bool:
|
|
391
397
|
case ScalarType.BOOL:
|
|
392
398
|
if (json === null)
|
|
393
|
-
return
|
|
399
|
+
return nullAsZeroValue ? false : undefined;
|
|
394
400
|
if (typeof json !== "boolean")
|
|
395
401
|
break;
|
|
396
402
|
return json;
|
|
397
403
|
// string:
|
|
398
404
|
case ScalarType.STRING:
|
|
399
405
|
if (json === null)
|
|
400
|
-
return ""
|
|
406
|
+
return nullAsZeroValue ? "" : undefined;
|
|
401
407
|
if (typeof json !== "string") {
|
|
402
408
|
break;
|
|
403
409
|
}
|
|
@@ -413,19 +419,24 @@ function readScalar(type, json, longType) {
|
|
|
413
419
|
// bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
|
|
414
420
|
// Either standard or URL-safe base64 encoding with/without paddings are accepted.
|
|
415
421
|
case ScalarType.BYTES:
|
|
416
|
-
if (json === null
|
|
417
|
-
return new Uint8Array(0)
|
|
422
|
+
if (json === null)
|
|
423
|
+
return nullAsZeroValue ? new Uint8Array(0) : undefined;
|
|
424
|
+
if (json === "")
|
|
425
|
+
return new Uint8Array(0);
|
|
418
426
|
if (typeof json !== "string")
|
|
419
427
|
break;
|
|
420
428
|
return protoBase64.dec(json);
|
|
421
429
|
}
|
|
422
430
|
throw new Error();
|
|
423
431
|
}
|
|
424
|
-
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) {
|
|
425
436
|
if (json === null) {
|
|
426
|
-
// proto3 requires 0 to be default value for all enums
|
|
427
|
-
//
|
|
428
|
-
return 0;
|
|
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;
|
|
429
440
|
}
|
|
430
441
|
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
431
442
|
switch (typeof json) {
|
|
@@ -444,12 +455,12 @@ function readEnum(type, json, ignoreUnknownFields) {
|
|
|
444
455
|
}
|
|
445
456
|
throw new Error(`cannot decode enum ${type.typeName} from JSON: ${debugJsonValue(json)}`);
|
|
446
457
|
}
|
|
447
|
-
function writeEnum(type, value,
|
|
458
|
+
function writeEnum(type, value, emitZeroValue, enumAsInteger) {
|
|
448
459
|
var _a;
|
|
449
460
|
if (value === undefined) {
|
|
450
461
|
return value;
|
|
451
462
|
}
|
|
452
|
-
if (
|
|
463
|
+
if (!emitZeroValue && type.values[0].no === value) {
|
|
453
464
|
// proto3 requires 0 to be default value for all enums
|
|
454
465
|
return undefined;
|
|
455
466
|
}
|
|
@@ -462,7 +473,7 @@ function writeEnum(type, value, emitIntrinsicDefault, enumAsInteger) {
|
|
|
462
473
|
const val = type.findNumber(value);
|
|
463
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
|
|
464
475
|
}
|
|
465
|
-
function writeScalar(type, value,
|
|
476
|
+
function writeScalar(type, value, emitZeroValue) {
|
|
466
477
|
if (value === undefined) {
|
|
467
478
|
return undefined;
|
|
468
479
|
}
|
|
@@ -474,7 +485,7 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
474
485
|
case ScalarType.FIXED32:
|
|
475
486
|
case ScalarType.UINT32:
|
|
476
487
|
assert(typeof value == "number");
|
|
477
|
-
return value != 0 ||
|
|
488
|
+
return value != 0 || emitZeroValue ? value : undefined;
|
|
478
489
|
// float, double: JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity".
|
|
479
490
|
// Either numbers or strings are accepted. Exponent notation is also accepted.
|
|
480
491
|
case ScalarType.FLOAT:
|
|
@@ -487,15 +498,15 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
487
498
|
return "Infinity";
|
|
488
499
|
if (value === Number.NEGATIVE_INFINITY)
|
|
489
500
|
return "-Infinity";
|
|
490
|
-
return value !== 0 ||
|
|
501
|
+
return value !== 0 || emitZeroValue ? value : undefined;
|
|
491
502
|
// string:
|
|
492
503
|
case ScalarType.STRING:
|
|
493
504
|
assert(typeof value == "string");
|
|
494
|
-
return value.length > 0 ||
|
|
505
|
+
return value.length > 0 || emitZeroValue ? value : undefined;
|
|
495
506
|
// bool:
|
|
496
507
|
case ScalarType.BOOL:
|
|
497
508
|
assert(typeof value == "boolean");
|
|
498
|
-
return value ||
|
|
509
|
+
return value || emitZeroValue ? value : undefined;
|
|
499
510
|
// JSON value will be a decimal string. Either numbers or strings are accepted.
|
|
500
511
|
case ScalarType.UINT64:
|
|
501
512
|
case ScalarType.FIXED64:
|
|
@@ -508,14 +519,12 @@ function writeScalar(type, value, emitIntrinsicDefault) {
|
|
|
508
519
|
// We use implicit conversion with `value != 0` to catch both 0n and "0"
|
|
509
520
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
510
521
|
// @ts-ignore
|
|
511
|
-
return
|
|
512
|
-
? value.toString(10)
|
|
513
|
-
: undefined;
|
|
522
|
+
return emitZeroValue || value != 0 ? value.toString(10) : undefined;
|
|
514
523
|
// bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
|
|
515
524
|
// Either standard or URL-safe base64 encoding with/without paddings are accepted.
|
|
516
525
|
case ScalarType.BYTES:
|
|
517
526
|
assert(value instanceof Uint8Array);
|
|
518
|
-
return
|
|
527
|
+
return emitZeroValue || value.byteLength > 0
|
|
519
528
|
? protoBase64.enc(value)
|
|
520
529
|
: undefined;
|
|
521
530
|
}
|
|
@@ -16,8 +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
|
-
// TODO field presence: merge this function with
|
|
20
|
-
return makeJsonFormatCommon((writeEnum, writeScalar) => {
|
|
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) => {
|
|
21
21
|
return function writeField(field, value, options) {
|
|
22
22
|
if (field.kind == "map") {
|
|
23
23
|
const jsonObj = {};
|
|
@@ -16,8 +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
|
-
// TODO field presence: merge this function with proto2
|
|
20
|
-
return makeJsonFormatCommon((writeEnum, writeScalar) => {
|
|
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) => {
|
|
21
21
|
return function writeField(field, value, options) {
|
|
22
22
|
if (field.kind == "map") {
|
|
23
23
|
const jsonObj = {};
|
package/package.json
CHANGED