@bufbuild/protobuf
Advanced tools
Comparing version
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -322,4 +322,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
case WireType.StartGroup: | ||
// From descriptor.proto: Group type is deprecated, not supported in proto3. | ||
// But we must still be able to parse and treat as unknown. | ||
// TODO check for matching field numbers in StartGroup / EndGroup tags | ||
let t; | ||
@@ -326,0 +325,0 @@ while ((t = this.tag()[1]) !== WireType.EndGroup) { |
import type { Message } from "./message.js"; | ||
import type { IBinaryReader, IBinaryWriter, WireType } from "./binary-encoding.js"; | ||
import type { FieldInfo } from "./field.js"; | ||
/** | ||
@@ -31,2 +32,10 @@ * BinaryFormat is the contract for serializing messages to and from binary | ||
/** | ||
* Parse a field from binary data, and store it in the given target. | ||
* | ||
* The target must be an initialized message object, with oneof groups, | ||
* repeated fields and maps already present. | ||
*/ | ||
readField(target: Record<string, any>, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
reader: IBinaryReader, field: FieldInfo, wireType: WireType, options: BinaryReadOptions): void; | ||
/** | ||
* Serialize a message to binary data. | ||
@@ -36,2 +45,10 @@ */ | ||
/** | ||
* Serialize a field value to binary data. | ||
* | ||
* The value must be an array for repeated fields, a record object for map | ||
* fields. Only selected oneof fields should be passed to this method. | ||
*/ | ||
writeField(field: FieldInfo, value: any, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
writer: IBinaryWriter, options: BinaryWriteOptions): void; | ||
/** | ||
* Retrieve the unknown fields for the given message. | ||
@@ -38,0 +55,0 @@ * |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
import { reifyWkt } from "./private/reify-wkt.js"; | ||
import type { DescEnum, DescEnumValue, DescField, DescMessage, DescMethod, DescOneof, DescService } from "./descriptor-set"; | ||
import type { DescEnum, DescEnumValue, DescField, DescExtension, DescMessage, DescMethod, DescOneof, DescService } from "./descriptor-set"; | ||
import { LongType, ScalarType } from "./field.js"; | ||
@@ -9,5 +9,5 @@ interface CodegenInfo { | ||
readonly packageName: string; | ||
readonly localName: (desc: DescEnum | DescEnumValue | DescMessage | DescOneof | DescField | DescService | DescMethod) => string; | ||
readonly localName: (desc: DescEnum | DescEnumValue | DescMessage | DescExtension | DescOneof | DescField | DescService | DescMethod) => string; | ||
readonly symbols: Record<RuntimeSymbolName, RuntimeSymbolInfo>; | ||
readonly getUnwrappedFieldType: (field: DescField) => ScalarType | undefined; | ||
readonly getUnwrappedFieldType: (field: DescField | DescExtension) => ScalarType | undefined; | ||
readonly wktSourceFiles: readonly string[]; | ||
@@ -22,3 +22,3 @@ readonly scalarDefaultValue: (type: ScalarType, longType: LongType) => any; | ||
} | ||
type RuntimeSymbolName = "proto2" | "proto3" | "Message" | "PartialMessage" | "PlainMessage" | "FieldList" | "MessageType" | "BinaryReadOptions" | "BinaryWriteOptions" | "JsonReadOptions" | "JsonWriteOptions" | "JsonValue" | "JsonObject" | "protoDouble" | "protoInt64" | "ScalarType" | "LongType" | "MethodKind" | "MethodIdempotency" | "IMessageTypeRegistry"; | ||
type RuntimeSymbolName = "proto2" | "proto3" | "Message" | "PartialMessage" | "PlainMessage" | "FieldList" | "MessageType" | "Extension" | "BinaryReadOptions" | "BinaryWriteOptions" | "JsonReadOptions" | "JsonWriteOptions" | "JsonValue" | "JsonObject" | "protoDouble" | "protoInt64" | "ScalarType" | "LongType" | "MethodKind" | "MethodIdempotency" | "IMessageTypeRegistry"; | ||
type RuntimeSymbolInfo = { | ||
@@ -25,0 +25,0 @@ typeOnly: boolean; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -39,2 +39,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
MessageType: { typeOnly: true, privateImportPath: "./message-type.js", publicImportPath: packageName }, | ||
Extension: { typeOnly: true, privateImportPath: "./extension.js", publicImportPath: packageName }, | ||
BinaryReadOptions: { typeOnly: true, privateImportPath: "./binary-format.js", publicImportPath: packageName }, | ||
@@ -41,0 +42,0 @@ BinaryWriteOptions: { typeOnly: true, privateImportPath: "./binary-format.js", publicImportPath: packageName }, |
@@ -23,3 +23,3 @@ import { FeatureSetDefaults, FileDescriptorProto, FileDescriptorSet } from "./google/protobuf/descriptor_pb.js"; | ||
* you have to provide a google.protobuf.FeatureSetDefaults message in this | ||
* option. | ||
* option. It can also specify the minimum and maximum supported edition. | ||
* | ||
@@ -26,0 +26,0 @@ * The defaults can be generated with `protoc` - see the flag |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -33,3 +33,2 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
function createDescriptorSet(input, options) { | ||
var _a; | ||
const cart = { | ||
@@ -41,3 +40,2 @@ enums: new Map(), | ||
mapEntries: new Map(), | ||
resolveFeatures: (0, feature_set_js_1.createFeatureResolver)((_a = options === null || options === void 0 ? void 0 : options.featureSetDefaults) !== null && _a !== void 0 ? _a : feature_set_js_1.featureSetDefaults), | ||
}; | ||
@@ -49,3 +47,13 @@ const fileDescriptors = input instanceof descriptor_pb_js_1.FileDescriptorSet | ||
: input; | ||
const files = fileDescriptors.map((proto) => newFile(proto, cart)); | ||
const resolverByEdition = new Map(); | ||
const files = fileDescriptors.map((proto) => { | ||
var _a, _b; | ||
const edition = (_a = proto.edition) !== null && _a !== void 0 ? _a : parseFileSyntax(proto.syntax, proto.edition).edition; | ||
let resolveFeatures = resolverByEdition.get(edition); | ||
if (resolveFeatures === undefined) { | ||
resolveFeatures = (0, feature_set_js_1.createFeatureResolver)((_b = options === null || options === void 0 ? void 0 : options.featureSetDefaults) !== null && _b !== void 0 ? _b : feature_set_js_1.featureSetDefaults, edition); | ||
resolverByEdition.set(edition, resolveFeatures); | ||
} | ||
return newFile(proto, cart, resolveFeatures); | ||
}); | ||
return Object.assign({ files }, cart); | ||
@@ -57,3 +65,3 @@ } | ||
*/ | ||
function newFile(proto, cart) { | ||
function newFile(proto, cart, resolveFeatures) { | ||
var _a, _b; | ||
@@ -77,21 +85,21 @@ (0, assert_js_1.assert)(proto.name, `invalid FileDescriptorProto: missing name`); | ||
var _a; | ||
return cart.resolveFeatures(this.edition, (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures((_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
} }); | ||
cart.mapEntries.clear(); // map entries are local to the file, we can safely discard | ||
for (const enumProto of proto.enumType) { | ||
addEnum(enumProto, file, undefined, cart); | ||
addEnum(enumProto, file, undefined, cart, resolveFeatures); | ||
} | ||
for (const messageProto of proto.messageType) { | ||
addMessage(messageProto, file, undefined, cart); | ||
addMessage(messageProto, file, undefined, cart, resolveFeatures); | ||
} | ||
for (const serviceProto of proto.service) { | ||
addService(serviceProto, file, cart); | ||
addService(serviceProto, file, cart, resolveFeatures); | ||
} | ||
addExtensions(file, cart); | ||
addExtensions(file, cart, resolveFeatures); | ||
for (const mapEntry of cart.mapEntries.values()) { | ||
addFields(mapEntry, cart); | ||
addFields(mapEntry, cart, resolveFeatures); | ||
} | ||
for (const message of file.messages) { | ||
addFields(message, cart); | ||
addExtensions(message, cart); | ||
addFields(message, cart, resolveFeatures); | ||
addExtensions(message, cart, resolveFeatures); | ||
} | ||
@@ -106,7 +114,7 @@ cart.mapEntries.clear(); // map entries are local to the file, we can safely discard | ||
*/ | ||
function addExtensions(desc, cart) { | ||
function addExtensions(desc, cart, resolveFeatures) { | ||
switch (desc.kind) { | ||
case "file": | ||
for (const proto of desc.proto.extension) { | ||
const ext = newExtension(proto, desc, undefined, cart); | ||
const ext = newExtension(proto, desc, undefined, cart, resolveFeatures); | ||
desc.extensions.push(ext); | ||
@@ -118,3 +126,3 @@ cart.extensions.set(ext.typeName, ext); | ||
for (const proto of desc.proto.extension) { | ||
const ext = newExtension(proto, desc.file, desc, cart); | ||
const ext = newExtension(proto, desc.file, desc, cart, resolveFeatures); | ||
desc.nestedExtensions.push(ext); | ||
@@ -124,3 +132,3 @@ cart.extensions.set(ext.typeName, ext); | ||
for (const message of desc.nestedMessages) { | ||
addExtensions(message, cart); | ||
addExtensions(message, cart, resolveFeatures); | ||
} | ||
@@ -134,8 +142,8 @@ break; | ||
*/ | ||
function addFields(message, cart) { | ||
const allOneofs = message.proto.oneofDecl.map((proto) => newOneof(proto, message, cart)); | ||
function addFields(message, cart, resolveFeatures) { | ||
const allOneofs = message.proto.oneofDecl.map((proto) => newOneof(proto, message, resolveFeatures)); | ||
const oneofsSeen = new Set(); | ||
for (const proto of message.proto.field) { | ||
const oneof = findOneof(proto, allOneofs); | ||
const field = newField(proto, message.file, message, oneof, cart); | ||
const field = newField(proto, message.file, message, oneof, cart, resolveFeatures); | ||
message.fields.push(field); | ||
@@ -157,3 +165,3 @@ if (oneof === undefined) { | ||
for (const child of message.nestedMessages) { | ||
addFields(child, cart); | ||
addFields(child, cart, resolveFeatures); | ||
} | ||
@@ -165,3 +173,3 @@ } | ||
*/ | ||
function addEnum(proto, file, parent, cart) { | ||
function addEnum(proto, file, parent, cart, resolveFeatures) { | ||
var _a, _b, _c; | ||
@@ -196,5 +204,4 @@ (0, assert_js_1.assert)(proto.name, `invalid EnumDescriptorProto: missing name`); | ||
getFeatures() { | ||
var _a, _b, _c; | ||
const parentFeatures = (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.getFeatures()) !== null && _b !== void 0 ? _b : this.file.getFeatures(); | ||
return cart.resolveFeatures(this.file.edition, parentFeatures, (_c = this.proto.options) === null || _c === void 0 ? void 0 : _c.features); | ||
var _a, _b; | ||
return resolveFeatures((_a = parent === null || parent === void 0 ? void 0 : parent.getFeatures()) !== null && _a !== void 0 ? _a : file.getFeatures(), (_b = proto.options) === null || _b === void 0 ? void 0 : _b.features); | ||
}, | ||
@@ -235,3 +242,3 @@ }; | ||
var _a; | ||
return cart.resolveFeatures(this.parent.file.edition, this.parent.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(desc.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -246,3 +253,3 @@ }); | ||
*/ | ||
function addMessage(proto, file, parent, cart) { | ||
function addMessage(proto, file, parent, cart, resolveFeatures) { | ||
var _a, _b, _c, _d; | ||
@@ -281,5 +288,4 @@ (0, assert_js_1.assert)(proto.name, `invalid DescriptorProto: missing name`); | ||
getFeatures() { | ||
var _a, _b, _c; | ||
const parentFeatures = (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.getFeatures()) !== null && _b !== void 0 ? _b : this.file.getFeatures(); | ||
return cart.resolveFeatures(this.file.edition, parentFeatures, (_c = this.proto.options) === null || _c === void 0 ? void 0 : _c.features); | ||
var _a, _b; | ||
return resolveFeatures((_a = parent === null || parent === void 0 ? void 0 : parent.getFeatures()) !== null && _a !== void 0 ? _a : file.getFeatures(), (_b = proto.options) === null || _b === void 0 ? void 0 : _b.features); | ||
}, | ||
@@ -295,6 +301,6 @@ }; | ||
for (const enumProto of proto.enumType) { | ||
addEnum(enumProto, file, desc, cart); | ||
addEnum(enumProto, file, desc, cart, resolveFeatures); | ||
} | ||
for (const messageProto of proto.nestedType) { | ||
addMessage(messageProto, file, desc, cart); | ||
addMessage(messageProto, file, desc, cart, resolveFeatures); | ||
} | ||
@@ -306,3 +312,3 @@ } | ||
*/ | ||
function addService(proto, file, cart) { | ||
function addService(proto, file, cart, resolveFeatures) { | ||
var _a, _b; | ||
@@ -330,3 +336,3 @@ (0, assert_js_1.assert)(proto.name, `invalid ServiceDescriptorProto: missing name`); | ||
var _a; | ||
return cart.resolveFeatures(this.file.edition, this.file.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(file.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -337,3 +343,3 @@ }; | ||
for (const methodProto of proto.method) { | ||
desc.methods.push(newMethod(methodProto, desc, cart)); | ||
desc.methods.push(newMethod(methodProto, desc, cart, resolveFeatures)); | ||
} | ||
@@ -344,3 +350,3 @@ } | ||
*/ | ||
function newMethod(proto, parent, cart) { | ||
function newMethod(proto, parent, cart, resolveFeatures) { | ||
var _a, _b, _c; | ||
@@ -404,3 +410,3 @@ (0, assert_js_1.assert)(proto.name, `invalid MethodDescriptorProto: missing name`); | ||
var _a; | ||
return cart.resolveFeatures(this.parent.file.edition, this.parent.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(parent.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -412,3 +418,3 @@ }; | ||
*/ | ||
function newOneof(proto, parent, cart) { | ||
function newOneof(proto, parent, resolveFeatures) { | ||
(0, assert_js_1.assert)(proto.name, `invalid OneofDescriptorProto: missing name`); | ||
@@ -435,3 +441,3 @@ return { | ||
var _a; | ||
return cart.resolveFeatures(this.parent.file.edition, this.parent.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(parent.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -443,3 +449,3 @@ }; | ||
*/ | ||
function newField(proto, file, parent, oneof, cart) { | ||
function newField(proto, file, parent, oneof, cart, resolveFeatures) { | ||
var _a, _b, _c; | ||
@@ -457,4 +463,4 @@ (0, assert_js_1.assert)(proto.name, `invalid FieldDescriptorProto: missing name`); | ||
optional: isOptionalField(proto, file.syntax), | ||
packedByDefault: isPackedFieldByDefault(file, proto, cart.resolveFeatures), | ||
packed: isPackedField(file, parent, proto, cart.resolveFeatures), | ||
packedByDefault: isPackedFieldByDefault(proto, resolveFeatures), | ||
packed: isPackedField(file, parent, proto, resolveFeatures), | ||
jsonName: proto.jsonName === (0, names_js_1.fieldJsonName)(proto.name) ? undefined : proto.jsonName, | ||
@@ -482,3 +488,3 @@ scalar: undefined, | ||
var _a; | ||
return cart.resolveFeatures(file.edition, this.parent.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(parent.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -522,6 +528,6 @@ }; | ||
*/ | ||
function newExtension(proto, file, parent, cart) { | ||
function newExtension(proto, file, parent, cart, resolveFeatures) { | ||
(0, assert_js_1.assert)(proto.extendee, `invalid FieldDescriptorProto: missing extendee`); | ||
const field = newField(proto, file, null, // to safe us many lines of duplicated code, we trick the type system | ||
undefined, cart); | ||
undefined, cart, resolveFeatures); | ||
const extendee = cart.messages.get(trimLeadingDot(proto.extendee)); | ||
@@ -551,4 +557,4 @@ (0, assert_js_1.assert)(extendee, `invalid FieldDescriptorProto: extendee ${proto.extendee} not found`); | ||
getFeatures() { | ||
var _a, _b; | ||
return cart.resolveFeatures(this.file.edition, ((_a = this.parent) !== null && _a !== void 0 ? _a : this.file).getFeatures(), (_b = this.proto.options) === null || _b === void 0 ? void 0 : _b.features); | ||
var _a; | ||
return resolveFeatures((parent !== null && parent !== void 0 ? parent : file).getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
} }); | ||
@@ -709,4 +715,4 @@ } | ||
*/ | ||
function isPackedFieldByDefault(file, proto, resolveFeatures) { | ||
const { repeatedFieldEncoding } = resolveFeatures(file.edition); | ||
function isPackedFieldByDefault(proto, resolveFeatures) { | ||
const { repeatedFieldEncoding } = resolveFeatures(); | ||
if (repeatedFieldEncoding != descriptor_pb_js_1.FeatureSet_RepeatedFieldEncoding.PACKED) { | ||
@@ -752,3 +758,3 @@ return false; | ||
default: { | ||
const { repeatedFieldEncoding } = resolveFeatures(file.edition, (_e = parent === null || parent === void 0 ? void 0 : parent.getFeatures()) !== null && _e !== void 0 ? _e : file.getFeatures(), (_f = proto.options) === null || _f === void 0 ? void 0 : _f.features); | ||
const { repeatedFieldEncoding } = resolveFeatures((_e = parent === null || parent === void 0 ? void 0 : parent.getFeatures()) !== null && _e !== void 0 ? _e : file.getFeatures(), (_f = proto.options) === null || _f === void 0 ? void 0 : _f.features); | ||
return (repeatedFieldEncoding == descriptor_pb_js_1.FeatureSet_RepeatedFieldEncoding.PACKED); | ||
@@ -755,0 +761,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import type { IEnumTypeRegistry, IMessageTypeRegistry, IServiceTypeRegistry } from "./type-registry.js"; | ||
import type { IEnumTypeRegistry, IExtensionRegistry, IMessageTypeRegistry, IServiceTypeRegistry } from "./type-registry.js"; | ||
import { FileDescriptorSet } from "./google/protobuf/descriptor_pb.js"; | ||
@@ -15,2 +15,2 @@ import type { DescriptorSet } from "./descriptor-set.js"; | ||
*/ | ||
export declare function createRegistryFromDescriptors(input: DescriptorSet | FileDescriptorSet | Uint8Array, replaceWkt?: boolean): IMessageTypeRegistry & IEnumTypeRegistry & IServiceTypeRegistry; | ||
export declare function createRegistryFromDescriptors(input: DescriptorSet | FileDescriptorSet | Uint8Array, replaceWkt?: boolean): IMessageTypeRegistry & IEnumTypeRegistry & IExtensionRegistry & IServiceTypeRegistry; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -70,11 +70,13 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
: input; | ||
const enums = {}; | ||
const messages = {}; | ||
const enums = new Map(); | ||
const messages = new Map(); | ||
const extensions = new Map(); | ||
const extensionsByExtendee = new Map(); | ||
const services = {}; | ||
if (replaceWkt) { | ||
for (const mt of wkMessages) { | ||
messages[mt.typeName] = mt; | ||
messages.set(mt.typeName, mt); | ||
} | ||
for (const et of wkEnums) { | ||
enums[et.typeName] = et; | ||
enums.set(et.typeName, et); | ||
} | ||
@@ -87,3 +89,3 @@ } | ||
findEnum(typeName) { | ||
const existing = enums[typeName]; | ||
const existing = enums.get(typeName); | ||
if (existing) { | ||
@@ -102,3 +104,3 @@ return existing; | ||
})), {}); | ||
enums[typeName] = type; | ||
enums.set(typeName, type); | ||
return type; | ||
@@ -110,3 +112,3 @@ }, | ||
findMessage(typeName) { | ||
const existing = messages[typeName]; | ||
const existing = messages.get(typeName); | ||
if (existing) { | ||
@@ -124,3 +126,3 @@ return existing; | ||
}); | ||
messages[typeName] = type; | ||
messages.set(typeName, type); | ||
for (const field of desc.fields) { | ||
@@ -165,2 +167,43 @@ const fieldInfo = makeFieldInfo(field, this); | ||
}, | ||
/** | ||
* May raise an error on invalid descriptors. | ||
*/ | ||
findExtensionFor(typeName, no) { | ||
var _a; | ||
if (!set.messages.has(typeName)) { | ||
return undefined; | ||
} | ||
let extensionsByNo = extensionsByExtendee.get(typeName); | ||
if (!extensionsByNo) { | ||
// maintain a lookup for extension desc by number | ||
extensionsByNo = new Map(); | ||
extensionsByExtendee.set(typeName, extensionsByNo); | ||
for (const desc of set.extensions.values()) { | ||
if (desc.extendee.typeName == typeName) { | ||
extensionsByNo.set(desc.number, desc); | ||
} | ||
} | ||
} | ||
const desc = (_a = extensionsByExtendee.get(typeName)) === null || _a === void 0 ? void 0 : _a.get(no); | ||
return desc ? this.findExtension(desc.typeName) : undefined; | ||
}, | ||
/** | ||
* May raise an error on invalid descriptors. | ||
*/ | ||
findExtension(typeName) { | ||
const existing = extensions.get(typeName); | ||
if (existing) { | ||
return existing; | ||
} | ||
const desc = set.extensions.get(typeName); | ||
if (!desc) { | ||
return undefined; | ||
} | ||
const extendee = this.findMessage(desc.extendee.typeName); | ||
(0, assert_js_1.assert)(extendee, `message "${desc.extendee.typeName}" for ${desc.toString()} not found`); | ||
const runtime = desc.file.syntax == "proto3" ? proto3_js_1.proto3 : proto2_js_1.proto2; | ||
const ext = runtime.makeExtension(typeName, extendee, makeFieldInfo(desc, this)); | ||
extensions.set(typeName, ext); | ||
return ext; | ||
}, | ||
}; | ||
@@ -172,2 +215,3 @@ } | ||
case "map": | ||
(0, assert_js_1.assert)(desc.kind == "field"); // maps are not allowed for extensions | ||
return makeMapFieldInfo(desc, resolver); | ||
@@ -174,0 +218,0 @@ case "message": |
import type { MessageType } from "./message-type.js"; | ||
import type { EnumType } from "./enum.js"; | ||
import type { ServiceType } from "./service-type.js"; | ||
import type { IMessageTypeRegistry, IEnumTypeRegistry, IServiceTypeRegistry } from "./type-registry.js"; | ||
import type { IEnumTypeRegistry, IExtensionRegistry, IMessageTypeRegistry, IServiceTypeRegistry } from "./type-registry.js"; | ||
import type { Extension } from "./extension.js"; | ||
/** | ||
* Create a new registry from the given types. | ||
*/ | ||
export declare function createRegistry(...types: Array<MessageType | EnumType | ServiceType>): IMessageTypeRegistry & IEnumTypeRegistry & IServiceTypeRegistry; | ||
export declare function createRegistry(...types: Array<MessageType | EnumType | ServiceType | Extension>): IMessageTypeRegistry & IEnumTypeRegistry & IExtensionRegistry & IServiceTypeRegistry; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -24,38 +24,5 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
const services = {}; | ||
const extensionsByName = new Map(); | ||
const extensionsByExtendee = new Map(); | ||
const registry = { | ||
/** | ||
* Add a type to the registry. For messages, the types used in message | ||
* fields are added recursively. For services, the message types used | ||
* for requests and responses are added recursively. | ||
*/ | ||
add(type) { | ||
if ("fields" in type) { | ||
if (!this.findMessage(type.typeName)) { | ||
messages[type.typeName] = type; | ||
for (const field of type.fields.list()) { | ||
if (field.kind == "message") { | ||
this.add(field.T); | ||
} | ||
else if (field.kind == "map" && field.V.kind == "message") { | ||
this.add(field.V.T); | ||
} | ||
else if (field.kind == "enum") { | ||
this.add(field.T); | ||
} | ||
} | ||
} | ||
} | ||
else if ("methods" in type) { | ||
if (!this.findService(type.typeName)) { | ||
services[type.typeName] = type; | ||
for (const method of Object.values(type.methods)) { | ||
this.add(method.I); | ||
this.add(method.O); | ||
} | ||
} | ||
} | ||
else { | ||
enums[type.typeName] = type; | ||
} | ||
}, | ||
findMessage(typeName) { | ||
@@ -70,5 +37,57 @@ return messages[typeName]; | ||
}, | ||
findExtensionFor(typeName, no) { | ||
var _a, _b; | ||
return (_b = (_a = extensionsByExtendee.get(typeName)) === null || _a === void 0 ? void 0 : _a.get(no)) !== null && _b !== void 0 ? _b : undefined; | ||
}, | ||
findExtension(typeName) { | ||
var _a; | ||
return (_a = extensionsByName.get(typeName)) !== null && _a !== void 0 ? _a : undefined; | ||
}, | ||
}; | ||
function addType(type) { | ||
var _a; | ||
if ("fields" in type) { | ||
if (!registry.findMessage(type.typeName)) { | ||
messages[type.typeName] = type; | ||
type.fields.list().forEach(addField); | ||
} | ||
} | ||
else if ("methods" in type) { | ||
if (!registry.findService(type.typeName)) { | ||
services[type.typeName] = type; | ||
for (const method of Object.values(type.methods)) { | ||
addType(method.I); | ||
addType(method.O); | ||
} | ||
} | ||
} | ||
else if ("extendee" in type) { | ||
if (!extensionsByName.has(type.typeName)) { | ||
extensionsByName.set(type.typeName, type); | ||
const extendeeName = type.extendee.typeName; | ||
if (!extensionsByExtendee.has(extendeeName)) { | ||
extensionsByExtendee.set(extendeeName, new Map()); | ||
} | ||
(_a = extensionsByExtendee.get(extendeeName)) === null || _a === void 0 ? void 0 : _a.set(type.field.no, type); | ||
addType(type.extendee); | ||
addField(type.field); | ||
} | ||
} | ||
else { | ||
enums[type.typeName] = type; | ||
} | ||
} | ||
function addField(field) { | ||
if (field.kind == "message") { | ||
addType(field.T); | ||
} | ||
else if (field.kind == "map" && field.V.kind == "message") { | ||
addType(field.V.T); | ||
} | ||
else if (field.kind == "enum") { | ||
addType(field.T); | ||
} | ||
} | ||
for (const type of types) { | ||
registry.add(type); | ||
addType(type); | ||
} | ||
@@ -75,0 +94,0 @@ return registry; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -17,3 +17,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
exports.ListValue = exports.Value = exports.Struct = exports.NullValue = void 0; | ||
// @generated by protoc-gen-es v1.6.0 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts" | ||
// @generated by protoc-gen-es v1.7.0 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts" | ||
// @generated from file google/protobuf/struct.proto (package google.protobuf, syntax proto3) | ||
@@ -20,0 +20,0 @@ /* eslint-disable */ |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -17,3 +17,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
exports.Option = exports.EnumValue = exports.Enum = exports.Field_Cardinality = exports.Field_Kind = exports.Field = exports.Type = exports.Syntax = void 0; | ||
// @generated by protoc-gen-es v1.6.0 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts" | ||
// @generated by protoc-gen-es v1.7.0 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts" | ||
// @generated from file google/protobuf/type.proto (package google.protobuf, syntax proto3) | ||
@@ -20,0 +20,0 @@ /* eslint-disable */ |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -15,2 +15,4 @@ export { proto3 } from "./proto3.js"; | ||
export type { EnumType, EnumValueInfo } from "./enum.js"; | ||
export type { Extension } from "./extension.js"; | ||
export { getExtension, setExtension, hasExtension, clearExtension, } from "./extension-accessor.js"; | ||
export type { ServiceType, MethodInfo, MethodInfoUnary, MethodInfoServerStreaming, MethodInfoClientStreaming, MethodInfoBiDiStreaming, } from "./service-type.js"; | ||
@@ -24,3 +26,3 @@ export { MethodKind, MethodIdempotency } from "./service-type.js"; | ||
export { createDescriptorSet } from "./create-descriptor-set.js"; | ||
export type { IMessageTypeRegistry } from "./type-registry.js"; | ||
export type { IMessageTypeRegistry, IExtensionRegistry, } from "./type-registry.js"; | ||
export { createRegistry } from "./create-registry.js"; | ||
@@ -27,0 +29,0 @@ export { createRegistryFromDescriptors } from "./create-registry-from-desc.js"; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -30,3 +30,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.toPlainMessage = exports.createRegistryFromDescriptors = exports.createRegistry = exports.createDescriptorSet = exports.BinaryReader = exports.BinaryWriter = exports.WireType = exports.MethodIdempotency = exports.MethodKind = exports.LongType = exports.ScalarType = exports.Message = exports.codegenInfo = exports.protoDelimited = exports.protoBase64 = exports.protoInt64 = exports.protoDouble = exports.proto2 = exports.proto3 = void 0; | ||
exports.toPlainMessage = exports.createRegistryFromDescriptors = exports.createRegistry = exports.createDescriptorSet = exports.BinaryReader = exports.BinaryWriter = exports.WireType = exports.MethodIdempotency = exports.MethodKind = exports.clearExtension = exports.hasExtension = exports.setExtension = exports.getExtension = exports.LongType = exports.ScalarType = exports.Message = exports.codegenInfo = exports.protoDelimited = exports.protoBase64 = exports.protoInt64 = exports.protoDouble = exports.proto2 = exports.proto3 = void 0; | ||
var proto3_js_1 = require("./proto3.js"); | ||
@@ -51,2 +51,7 @@ Object.defineProperty(exports, "proto3", { enumerable: true, get: function () { return proto3_js_1.proto3; } }); | ||
Object.defineProperty(exports, "LongType", { enumerable: true, get: function () { return field_js_1.LongType; } }); | ||
var extension_accessor_js_1 = require("./extension-accessor.js"); | ||
Object.defineProperty(exports, "getExtension", { enumerable: true, get: function () { return extension_accessor_js_1.getExtension; } }); | ||
Object.defineProperty(exports, "setExtension", { enumerable: true, get: function () { return extension_accessor_js_1.setExtension; } }); | ||
Object.defineProperty(exports, "hasExtension", { enumerable: true, get: function () { return extension_accessor_js_1.hasExtension; } }); | ||
Object.defineProperty(exports, "clearExtension", { enumerable: true, get: function () { return extension_accessor_js_1.clearExtension; } }); | ||
var service_type_js_1 = require("./service-type.js"); | ||
@@ -53,0 +58,0 @@ Object.defineProperty(exports, "MethodKind", { enumerable: true, get: function () { return service_type_js_1.MethodKind; } }); |
@@ -5,3 +5,3 @@ import type { Message } from "./message.js"; | ||
import { LongType } from "./field.js"; | ||
import type { IMessageTypeRegistry } from "./type-registry.js"; | ||
import type { IExtensionRegistry, IMessageTypeRegistry } from "./type-registry.js"; | ||
/** | ||
@@ -56,6 +56,6 @@ * JsonFormat is the contract for serializing messages to and from JSON. | ||
/** | ||
* This option is required to read `google.protobuf.Any` | ||
* This option is required to read `google.protobuf.Any` and extensions | ||
* from JSON format. | ||
*/ | ||
typeRegistry?: IMessageTypeRegistry; | ||
typeRegistry?: IMessageTypeRegistry & Partial<IExtensionRegistry>; | ||
} | ||
@@ -88,6 +88,6 @@ /** | ||
/** | ||
* This option is required to write `google.protobuf.Any` | ||
* This option is required to write `google.protobuf.Any` and extensions | ||
* to JSON format. | ||
*/ | ||
typeRegistry?: IMessageTypeRegistry; | ||
typeRegistry?: IMessageTypeRegistry & Partial<IExtensionRegistry>; | ||
} | ||
@@ -94,0 +94,0 @@ /** |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,7 +0,6 @@ | ||
import type { IBinaryReader, IBinaryWriter } from "../binary-encoding.js"; | ||
import type { IBinaryWriter } from "../binary-encoding.js"; | ||
import type { BinaryFormat, BinaryWriteOptions } from "../binary-format.js"; | ||
import type { FieldInfo } from "../field.js"; | ||
import { ScalarType } from "../field.js"; | ||
export declare function makeBinaryFormatCommon(): Omit<BinaryFormat, "writeMessage">; | ||
export declare function readScalarLTString(reader: IBinaryReader, type: ScalarType): any; | ||
export declare function makeBinaryFormatCommon(): Omit<BinaryFormat, "writeMessage" | "writeField">; | ||
export declare function writeMapEntry(writer: IBinaryWriter, options: BinaryWriteOptions, field: FieldInfo & { | ||
@@ -8,0 +7,0 @@ kind: "map"; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -16,3 +16,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.writePacked = exports.writeScalar = exports.writeMessageField = exports.writeMapEntry = exports.readScalarLTString = exports.makeBinaryFormatCommon = void 0; | ||
exports.writePacked = exports.writeScalar = exports.writeMessageField = exports.writeMapEntry = exports.makeBinaryFormatCommon = void 0; | ||
const binary_encoding_js_1 = require("../binary-encoding.js"); | ||
@@ -89,64 +89,3 @@ const message_js_1 = require("../message.js"); | ||
} | ||
let target = message, repeated = field.repeated, localName = field.localName; | ||
if (field.oneof) { | ||
target = target[field.oneof.localName]; | ||
if (target.case != localName) { | ||
delete target.value; | ||
} | ||
target.case = localName; | ||
localName = "value"; | ||
} | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
const scalarType = field.kind == "enum" ? field_js_1.ScalarType.INT32 : field.T; | ||
let read = readScalar; | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison -- acceptable since it's covered by tests | ||
if (field.kind == "scalar" && field.L > 0) { | ||
read = readScalarLTString; | ||
} | ||
if (repeated) { | ||
let arr = target[localName]; // safe to assume presence of array, oneof cannot contain repeated values | ||
if (wireType == binary_encoding_js_1.WireType.LengthDelimited && | ||
scalarType != field_js_1.ScalarType.STRING && | ||
scalarType != field_js_1.ScalarType.BYTES) { | ||
let e = reader.uint32() + reader.pos; | ||
while (reader.pos < e) { | ||
arr.push(read(reader, scalarType)); | ||
} | ||
} | ||
else { | ||
arr.push(read(reader, scalarType)); | ||
} | ||
} | ||
else { | ||
target[localName] = read(reader, scalarType); | ||
} | ||
break; | ||
case "message": | ||
const messageType = field.T; | ||
if (repeated) { | ||
// safe to assume presence of array, oneof cannot contain repeated values | ||
target[localName].push(readMessageField(reader, new messageType(), options, field)); | ||
} | ||
else { | ||
if (target[localName] instanceof message_js_1.Message) { | ||
readMessageField(reader, target[localName], options, field); | ||
} | ||
else { | ||
target[localName] = readMessageField(reader, new messageType(), options, field); | ||
if (messageType.fieldWrapper && | ||
!field.oneof && | ||
!field.repeated) { | ||
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]); | ||
} | ||
} | ||
} | ||
break; | ||
case "map": | ||
let [mapKey, mapVal] = readMapEntry(field, reader, options); | ||
// safe to assume presence of map object, oneof cannot contain repeated values | ||
target[localName][mapKey] = mapVal; | ||
break; | ||
} | ||
readField(message, reader, field, wireType, options); | ||
} | ||
@@ -158,5 +97,70 @@ if (delimitedMessageEncoding && // eslint-disable-line @typescript-eslint/strict-boolean-expressions | ||
}, | ||
readField, | ||
}; | ||
} | ||
exports.makeBinaryFormatCommon = makeBinaryFormatCommon; | ||
function readField(target, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
reader, field, wireType, options) { | ||
let { repeated, localName } = field; | ||
if (field.oneof) { | ||
target = target[field.oneof.localName]; | ||
if (target.case != localName) { | ||
delete target.value; | ||
} | ||
target.case = localName; | ||
localName = "value"; | ||
} | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
const scalarType = field.kind == "enum" ? field_js_1.ScalarType.INT32 : field.T; | ||
let read = readScalar; | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison -- acceptable since it's covered by tests | ||
if (field.kind == "scalar" && field.L > 0) { | ||
read = readScalarLTString; | ||
} | ||
if (repeated) { | ||
let arr = target[localName]; // safe to assume presence of array, oneof cannot contain repeated values | ||
const isPacked = wireType == binary_encoding_js_1.WireType.LengthDelimited && | ||
scalarType != field_js_1.ScalarType.STRING && | ||
scalarType != field_js_1.ScalarType.BYTES; | ||
if (isPacked) { | ||
let e = reader.uint32() + reader.pos; | ||
while (reader.pos < e) { | ||
arr.push(read(reader, scalarType)); | ||
} | ||
} | ||
else { | ||
arr.push(read(reader, scalarType)); | ||
} | ||
} | ||
else { | ||
target[localName] = read(reader, scalarType); | ||
} | ||
break; | ||
case "message": | ||
const messageType = field.T; | ||
if (repeated) { | ||
// safe to assume presence of array, oneof cannot contain repeated values | ||
target[localName].push(readMessageField(reader, new messageType(), options, field)); | ||
} | ||
else { | ||
if (target[localName] instanceof message_js_1.Message) { | ||
readMessageField(reader, target[localName], options, field); | ||
} | ||
else { | ||
target[localName] = readMessageField(reader, new messageType(), options, field); | ||
if (messageType.fieldWrapper && !field.oneof && !field.repeated) { | ||
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]); | ||
} | ||
} | ||
} | ||
break; | ||
case "map": | ||
let [mapKey, mapVal] = readMapEntry(field, reader, options); | ||
// safe to assume presence of map object, oneof cannot contain repeated values | ||
target[localName][mapKey] = mapVal; | ||
break; | ||
} | ||
} | ||
// Read a message, avoiding MessageType.fromBinary() to re-use the | ||
@@ -227,3 +231,2 @@ // BinaryReadOptions and the IBinaryReader. | ||
} | ||
exports.readScalarLTString = readScalarLTString; | ||
// Does not use scalarTypeInfo() for better performance. | ||
@@ -301,16 +304,15 @@ function readScalar(reader, type) { | ||
exports.writeMapEntry = writeMapEntry; | ||
// Value must not be undefined | ||
function writeMessageField(writer, options, field, value) { | ||
if (value !== undefined) { | ||
const message = (0, field_wrapper_js_1.wrapField)(field.T, value); | ||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions | ||
if (field === null || field === void 0 ? void 0 : field.delimited) | ||
writer | ||
.tag(field.no, binary_encoding_js_1.WireType.StartGroup) | ||
.raw(message.toBinary(options)) | ||
.tag(field.no, binary_encoding_js_1.WireType.EndGroup); | ||
else | ||
writer | ||
.tag(field.no, binary_encoding_js_1.WireType.LengthDelimited) | ||
.bytes(message.toBinary(options)); | ||
} | ||
const message = (0, field_wrapper_js_1.wrapField)(field.T, value); | ||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions | ||
if (field === null || field === void 0 ? void 0 : field.delimited) | ||
writer | ||
.tag(field.no, binary_encoding_js_1.WireType.StartGroup) | ||
.raw(message.toBinary(options)) | ||
.tag(field.no, binary_encoding_js_1.WireType.EndGroup); | ||
else | ||
writer | ||
.tag(field.no, binary_encoding_js_1.WireType.LengthDelimited) | ||
.bytes(message.toBinary(options)); | ||
} | ||
@@ -317,0 +319,0 @@ exports.writeMessageField = writeMessageField; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -21,71 +21,25 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
function makeBinaryFormatProto2() { | ||
return Object.assign(Object.assign({}, (0, binary_format_common_js_1.makeBinaryFormatCommon)()), { writeMessage(message, writer, options) { | ||
return Object.assign(Object.assign({}, (0, binary_format_common_js_1.makeBinaryFormatCommon)()), { writeField, | ||
writeMessage(message, writer, options) { | ||
const type = message.getType(); | ||
let field; | ||
try { | ||
for (field of type.fields.byNumber()) { | ||
let value, // this will be our field value, whether it is member of a oneof or not | ||
repeated = field.repeated, localName = field.localName; | ||
if (field.oneof) { | ||
const oneof = message[field.oneof.localName]; | ||
if (oneof.case !== localName) { | ||
continue; // field is not selected, skip | ||
} | ||
value = oneof.value; | ||
for (field of type.fields.byNumber()) { | ||
let value, localName = field.localName; | ||
if (field.oneof) { | ||
const oneof = message[field.oneof.localName]; | ||
if (oneof.case !== localName) { | ||
continue; // field is not selected, skip | ||
} | ||
else { | ||
value = message[localName]; | ||
// In contrast to proto3, we raise an error if a non-optional (proto2 required) | ||
// field is missing a value. | ||
if (value === undefined && !field.oneof && !field.opt) { | ||
throw new Error(`cannot encode field ${type.typeName}.${field.name} to binary: required field not set`); | ||
} | ||
value = oneof.value; | ||
} | ||
else { | ||
value = message[localName]; | ||
// In contrast to proto3, we raise an error if a non-optional (proto2 required) | ||
// field is missing a value. | ||
if (value === undefined && !field.oneof && !field.opt) { | ||
throw new Error(`cannot encode field ${type.typeName}.${field === null || field === void 0 ? void 0 : field.name} to binary: required field not set`); | ||
} | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
let scalarType = field.kind == "enum" ? field_js_1.ScalarType.INT32 : field.T; | ||
if (repeated) { | ||
if (field.packed) { | ||
(0, binary_format_common_js_1.writePacked)(writer, scalarType, field.no, value); | ||
} | ||
else { | ||
for (const item of value) { | ||
(0, binary_format_common_js_1.writeScalar)(writer, scalarType, field.no, item, true); | ||
} | ||
} | ||
} | ||
else { | ||
if (value !== undefined) { | ||
// In contrast to proto3, we do not skip intrinsic default values. | ||
// Explicit default values are not special cased either. | ||
(0, binary_format_common_js_1.writeScalar)(writer, scalarType, field.no, value, true); | ||
} | ||
} | ||
break; | ||
case "message": | ||
if (repeated) { | ||
for (const item of value) { | ||
(0, binary_format_common_js_1.writeMessageField)(writer, options, field, item); | ||
} | ||
} | ||
else { | ||
(0, binary_format_common_js_1.writeMessageField)(writer, options, field, value); | ||
} | ||
break; | ||
case "map": | ||
for (const [key, val] of Object.entries(value)) { | ||
(0, binary_format_common_js_1.writeMapEntry)(writer, options, field, key, val); | ||
} | ||
break; | ||
} | ||
} | ||
writeField(field, value, writer, options); | ||
} | ||
catch (e) { | ||
let m = field | ||
? `cannot encode field ${type.typeName}.${field === null || field === void 0 ? void 0 : field.name} to binary` | ||
: `cannot encode message ${type.typeName} to binary`; | ||
let r = e instanceof Error ? e.message : String(e); | ||
throw new Error(m + (r.length > 0 ? `: ${r}` : "")); | ||
} | ||
if (options.writeUnknownFields) { | ||
@@ -98,1 +52,42 @@ this.writeUnknownFields(message, writer); | ||
exports.makeBinaryFormatProto2 = makeBinaryFormatProto2; | ||
// TODO field presence: merge this function with proto3 | ||
function writeField(field, value, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
writer, options) { | ||
const repeated = field.repeated; | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
let scalarType = field.kind == "enum" ? field_js_1.ScalarType.INT32 : field.T; | ||
if (repeated) { | ||
if (field.packed) { | ||
(0, binary_format_common_js_1.writePacked)(writer, scalarType, field.no, value); | ||
} | ||
else { | ||
for (const item of value) { | ||
(0, binary_format_common_js_1.writeScalar)(writer, scalarType, field.no, item, true); | ||
} | ||
} | ||
} | ||
else if (value !== undefined) { | ||
// In contrast to proto3, we do not skip intrinsic default values. | ||
// Explicit default values are not special cased either. | ||
(0, binary_format_common_js_1.writeScalar)(writer, scalarType, field.no, value, true); | ||
} | ||
break; | ||
case "message": | ||
if (repeated) { | ||
for (const item of value) { | ||
(0, binary_format_common_js_1.writeMessageField)(writer, options, field, item); | ||
} | ||
} | ||
else if (value !== undefined) { | ||
(0, binary_format_common_js_1.writeMessageField)(writer, options, field, value); | ||
} | ||
break; | ||
case "map": | ||
for (const [key, val] of Object.entries(value)) { | ||
(0, binary_format_common_js_1.writeMapEntry)(writer, options, field, key, val); | ||
} | ||
break; | ||
} | ||
} |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -21,7 +21,7 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
function makeBinaryFormatProto3() { | ||
return Object.assign(Object.assign({}, (0, binary_format_common_js_1.makeBinaryFormatCommon)()), { writeMessage(message, writer, options) { | ||
return Object.assign(Object.assign({}, (0, binary_format_common_js_1.makeBinaryFormatCommon)()), { writeField, | ||
writeMessage(message, writer, options) { | ||
const type = message.getType(); | ||
for (const field of type.fields.byNumber()) { | ||
let value, // this will be our field value, whether it is member of a oneof or regular field | ||
repeated = field.repeated, localName = field.localName; | ||
let value, localName = field.localName; | ||
if (field.oneof) { | ||
@@ -37,38 +37,3 @@ const oneof = message[field.oneof.localName]; | ||
} | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
let scalarType = field.kind == "enum" ? field_js_1.ScalarType.INT32 : field.T; | ||
if (repeated) { | ||
if (field.packed) { | ||
(0, binary_format_common_js_1.writePacked)(writer, scalarType, field.no, value); | ||
} | ||
else { | ||
for (const item of value) { | ||
(0, binary_format_common_js_1.writeScalar)(writer, scalarType, field.no, item, true); | ||
} | ||
} | ||
} | ||
else { | ||
if (value !== undefined) { | ||
(0, binary_format_common_js_1.writeScalar)(writer, scalarType, field.no, value, !!field.oneof || field.opt); | ||
} | ||
} | ||
break; | ||
case "message": | ||
if (repeated) { | ||
for (const item of value) { | ||
(0, binary_format_common_js_1.writeMessageField)(writer, options, field, item); | ||
} | ||
} | ||
else { | ||
(0, binary_format_common_js_1.writeMessageField)(writer, options, field, value); | ||
} | ||
break; | ||
case "map": | ||
for (const [key, val] of Object.entries(value)) { | ||
(0, binary_format_common_js_1.writeMapEntry)(writer, options, field, key, val); | ||
} | ||
break; | ||
} | ||
writeField(field, value, writer, options); | ||
} | ||
@@ -82,1 +47,40 @@ if (options.writeUnknownFields) { | ||
exports.makeBinaryFormatProto3 = makeBinaryFormatProto3; | ||
// TODO field presence: merge this function with proto2 | ||
function writeField(field, value, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
writer, options) { | ||
const repeated = field.repeated; | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
let scalarType = field.kind == "enum" ? field_js_1.ScalarType.INT32 : field.T; | ||
if (repeated) { | ||
if (field.packed) { | ||
(0, binary_format_common_js_1.writePacked)(writer, scalarType, field.no, value); | ||
} | ||
else { | ||
for (const item of value) { | ||
(0, binary_format_common_js_1.writeScalar)(writer, scalarType, field.no, item, true); | ||
} | ||
} | ||
} | ||
else if (value !== undefined) { | ||
(0, binary_format_common_js_1.writeScalar)(writer, scalarType, field.no, value, !!field.oneof || field.opt); | ||
} | ||
break; | ||
case "message": | ||
if (repeated) { | ||
for (const item of value) { | ||
(0, binary_format_common_js_1.writeMessageField)(writer, options, field, item); | ||
} | ||
} | ||
else if (value !== undefined) { | ||
(0, binary_format_common_js_1.writeMessageField)(writer, options, field, value); | ||
} | ||
break; | ||
case "map": | ||
for (const [key, val] of Object.entries(value)) { | ||
(0, binary_format_common_js_1.writeMapEntry)(writer, options, field, key, val); | ||
} | ||
break; | ||
} | ||
} |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -11,3 +11,3 @@ import { Edition, FeatureSet, FeatureSetDefaults } from "../google/protobuf/descriptor_pb.js"; | ||
/** | ||
* A function that resolves features for the given edition. | ||
* A function that resolves features. | ||
* | ||
@@ -18,6 +18,6 @@ * If no feature set is provided, the default feature set for the edition is | ||
*/ | ||
export type FeatureResolverFn = (edition: Edition, a?: FeatureSet, b?: FeatureSet) => MergedFeatureSet; | ||
export type FeatureResolverFn = (a?: FeatureSet, b?: FeatureSet) => MergedFeatureSet; | ||
/** | ||
* Create an edition feature resolver with the given feature set defaults. | ||
*/ | ||
export declare function createFeatureResolver(compiledFeatureSetDefaults: FeatureSetDefaults): FeatureResolverFn; | ||
export declare function createFeatureResolver(compiledFeatureSetDefaults: FeatureSetDefaults, edition: Edition): FeatureResolverFn; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -27,3 +27,4 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
*/ | ||
function createFeatureResolver(compiledFeatureSetDefaults) { | ||
function createFeatureResolver(compiledFeatureSetDefaults, edition) { | ||
var _a, _b; | ||
const min = compiledFeatureSetDefaults.minimumEdition; | ||
@@ -36,33 +37,27 @@ const max = compiledFeatureSetDefaults.maximumEdition; | ||
} | ||
const defaultsBinByEdition = new Map(); | ||
return (edition, ...rest) => { | ||
var _a, _b; | ||
let defaultsBin = defaultsBinByEdition.get(edition); | ||
if (defaultsBin === undefined) { | ||
if (edition < min) { | ||
throw new Error(`Edition ${descriptor_pb_js_1.Edition[edition]} is earlier than the minimum supported edition ${descriptor_pb_js_1.Edition[min]}`); | ||
} | ||
if (max < edition) { | ||
throw new Error(`Edition ${descriptor_pb_js_1.Edition[edition]} is later than the maximum supported edition ${descriptor_pb_js_1.Edition[max]}`); | ||
} | ||
let highestMatch = undefined; | ||
for (const c of compiledFeatureSetDefaults.defaults) { | ||
const e = (_a = c.edition) !== null && _a !== void 0 ? _a : 0; | ||
if (e > edition) { | ||
continue; | ||
} | ||
if (highestMatch !== undefined && highestMatch.e > e) { | ||
continue; | ||
} | ||
highestMatch = { | ||
e, | ||
f: (_b = c.features) !== null && _b !== void 0 ? _b : new descriptor_pb_js_1.FeatureSet(), | ||
}; | ||
} | ||
if (highestMatch === undefined) { | ||
throw new Error(`No valid default found for edition ${descriptor_pb_js_1.Edition[edition]}`); | ||
} | ||
defaultsBin = highestMatch.f.toBinary(); | ||
defaultsBinByEdition.set(edition, defaultsBin); | ||
if (edition < min) { | ||
throw new Error(`Edition ${descriptor_pb_js_1.Edition[edition]} is earlier than the minimum supported edition ${descriptor_pb_js_1.Edition[min]}`); | ||
} | ||
if (max < edition) { | ||
throw new Error(`Edition ${descriptor_pb_js_1.Edition[edition]} is later than the maximum supported edition ${descriptor_pb_js_1.Edition[max]}`); | ||
} | ||
let highestMatch = undefined; | ||
for (const c of compiledFeatureSetDefaults.defaults) { | ||
const e = (_a = c.edition) !== null && _a !== void 0 ? _a : 0; | ||
if (e > edition) { | ||
continue; | ||
} | ||
if (highestMatch !== undefined && highestMatch.e > e) { | ||
continue; | ||
} | ||
highestMatch = { | ||
e, | ||
f: (_b = c.features) !== null && _b !== void 0 ? _b : new descriptor_pb_js_1.FeatureSet(), | ||
}; | ||
} | ||
if (highestMatch === undefined) { | ||
throw new Error(`No valid default found for edition ${descriptor_pb_js_1.Edition[edition]}`); | ||
} | ||
const defaultsBin = highestMatch.f.toBinary(); | ||
return (...rest) => { | ||
const f = descriptor_pb_js_1.FeatureSet.fromBinary(defaultsBin); | ||
@@ -69,0 +64,0 @@ for (const c of rest) { |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
import { Message } from "../message.js"; | ||
import type { MessageType } from "../message-type.js"; | ||
import type { DescField } from "../descriptor-set.js"; | ||
import type { DescExtension, DescField } from "../descriptor-set.js"; | ||
import { ScalarType } from "../field.js"; | ||
@@ -25,2 +25,2 @@ /** | ||
*/ | ||
export declare function getUnwrappedFieldType(field: DescField): ScalarType | undefined; | ||
export declare function getUnwrappedFieldType(field: DescField | DescExtension): ScalarType | undefined; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -22,2 +22,4 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
const proto_base64_js_1 = require("../proto-base64.js"); | ||
const extensions_js_1 = require("./extensions.js"); | ||
const extension_accessor_js_1 = require("../extension-accessor.js"); | ||
/* 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 */ | ||
@@ -48,160 +50,41 @@ // Default options for parsing JSON. | ||
if (json == null || Array.isArray(json) || typeof json != "object") { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: ${this.debug(json)}`); | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: ${debugJsonValue(json)}`); | ||
} | ||
message = message !== null && message !== void 0 ? message : new type(); | ||
const oneofSeen = {}; | ||
const oneofSeen = new Map(); | ||
const registry = options.typeRegistry; | ||
for (const [jsonKey, jsonValue] of Object.entries(json)) { | ||
const field = type.fields.findJsonName(jsonKey); | ||
if (!field) { | ||
if (!options.ignoreUnknownFields) { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: key "${jsonKey}" is unknown`); | ||
} | ||
continue; | ||
} | ||
let localName = field.localName; | ||
let target = message; | ||
if (field.oneof) { | ||
if (jsonValue === null && field.kind == "scalar") { | ||
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second} | ||
continue; | ||
} | ||
const seen = oneofSeen[field.oneof.localName]; | ||
if (seen) { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: multiple keys for oneof "${field.oneof.name}" present: "${seen}", "${jsonKey}"`); | ||
} | ||
oneofSeen[field.oneof.localName] = jsonKey; | ||
target = target[field.oneof.localName] = { case: localName }; | ||
localName = "value"; | ||
} | ||
if (field.repeated) { | ||
if (jsonValue === null) { | ||
continue; | ||
} | ||
if (!Array.isArray(jsonValue)) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`); | ||
} | ||
const targetArray = target[localName]; | ||
for (const jsonItem of jsonValue) { | ||
if (jsonItem === null) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonItem)}`); | ||
if (field) { | ||
if (field.oneof) { | ||
if (jsonValue === null && field.kind == "scalar") { | ||
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second} | ||
continue; | ||
} | ||
let val; | ||
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "map" is invalid for repeated fields | ||
switch (field.kind) { | ||
case "message": | ||
val = field.T.fromJson(jsonItem, options); | ||
break; | ||
case "enum": | ||
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields); | ||
if (val === undefined) | ||
continue; | ||
break; | ||
case "scalar": | ||
try { | ||
val = readScalar(field.T, jsonItem, field.L); | ||
} | ||
catch (e) { | ||
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonItem)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
const seen = oneofSeen.get(field.oneof); | ||
if (seen !== undefined) { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: multiple keys for oneof "${field.oneof.name}" present: "${seen}", "${jsonKey}"`); | ||
} | ||
targetArray.push(val); | ||
oneofSeen.set(field.oneof, jsonKey); | ||
} | ||
readField(message, jsonValue, field, options, type); | ||
} | ||
else if (field.kind == "map") { | ||
if (jsonValue === null) { | ||
continue; | ||
} | ||
if (Array.isArray(jsonValue) || typeof jsonValue != "object") { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`); | ||
} | ||
const targetMap = target[localName]; | ||
for (const [jsonMapKey, jsonMapValue] of Object.entries(jsonValue)) { | ||
if (jsonMapValue === null) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: map value null`); | ||
else { | ||
let found = false; | ||
if ((registry === null || registry === void 0 ? void 0 : registry.findExtension) && | ||
jsonKey.startsWith("[") && | ||
jsonKey.endsWith("]")) { | ||
const ext = registry.findExtension(jsonKey.substring(1, jsonKey.length - 1)); | ||
if (ext && ext.extendee.typeName == type.typeName) { | ||
found = true; | ||
const [container, get] = (0, extensions_js_1.createExtensionContainer)(ext); | ||
readField(container, jsonValue, ext.field, options, ext); | ||
// We pass on the options as BinaryReadOptions/BinaryWriteOptions, | ||
// so that users can bring their own binary reader and writer factories | ||
// if necessary. | ||
(0, extension_accessor_js_1.setExtension)(message, ext, get(), options); | ||
} | ||
let val; | ||
switch (field.V.kind) { | ||
case "message": | ||
val = field.V.T.fromJson(jsonMapValue, options); | ||
break; | ||
case "enum": | ||
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields); | ||
if (val === undefined) | ||
continue; | ||
break; | ||
case "scalar": | ||
try { | ||
val = readScalar(field.V.T, jsonMapValue, field_js_1.LongType.BIGINT); | ||
} | ||
catch (e) { | ||
let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
} | ||
try { | ||
targetMap[readScalar(field.K, field.K == field_js_1.ScalarType.BOOL | ||
? jsonMapKey == "true" | ||
? true | ||
: jsonMapKey == "false" | ||
? false | ||
: jsonMapKey | ||
: jsonMapKey, field_js_1.LongType.BIGINT).toString()] = val; | ||
} | ||
catch (e) { | ||
let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
} | ||
} | ||
else { | ||
switch (field.kind) { | ||
case "message": | ||
const messageType = field.T; | ||
if (jsonValue === null && | ||
messageType.typeName != "google.protobuf.Value") { | ||
if (field.oneof) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: null is invalid for oneof field "${jsonKey}"`); | ||
} | ||
continue; | ||
} | ||
if (target[localName] instanceof message_js_1.Message) { | ||
target[localName].fromJson(jsonValue, options); | ||
} | ||
else { | ||
target[localName] = messageType.fromJson(jsonValue, options); | ||
if (messageType.fieldWrapper && !field.oneof) { | ||
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]); | ||
} | ||
} | ||
break; | ||
case "enum": | ||
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields); | ||
if (enumValue !== undefined) { | ||
target[localName] = enumValue; | ||
} | ||
break; | ||
case "scalar": | ||
try { | ||
target[localName] = readScalar(field.T, jsonValue, field.L); | ||
} | ||
catch (e) { | ||
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
if (!found && !options.ignoreUnknownFields) { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: key "${jsonKey}" is unknown`); | ||
} | ||
@@ -239,2 +122,17 @@ } | ||
} | ||
const registry = options.typeRegistry; | ||
if (registry === null || registry === void 0 ? void 0 : registry.findExtensionFor) { | ||
for (const uf of type.runtime.bin.listUnknownFields(message)) { | ||
const ext = registry.findExtensionFor(type.typeName, uf.no); | ||
if (ext && (0, extension_accessor_js_1.hasExtension)(message, ext)) { | ||
// We pass on the options as BinaryReadOptions, so that users can bring their own | ||
// binary reader factory if necessary. | ||
const value = (0, extension_accessor_js_1.getExtension)(message, ext, options); | ||
const jsonValue = writeField(ext.field, value, options); | ||
if (jsonValue !== undefined) { | ||
json[ext.field.jsonName] = jsonValue; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
@@ -269,2 +167,149 @@ catch (e) { | ||
} | ||
// Read a JSON value for a field. | ||
// The "type" argument is only used to provide context in errors. | ||
function readField(target, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
jsonValue, field, options, type) { | ||
let localName = field.localName; | ||
if (field.oneof) { | ||
if (jsonValue === null && field.kind == "scalar") { | ||
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second} | ||
return; | ||
} | ||
target = target[field.oneof.localName] = { case: localName }; | ||
localName = "value"; | ||
} | ||
if (field.repeated) { | ||
if (jsonValue === null) { | ||
return; | ||
} | ||
if (!Array.isArray(jsonValue)) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`); | ||
} | ||
const targetArray = target[localName]; | ||
for (const jsonItem of jsonValue) { | ||
if (jsonItem === null) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`); | ||
} | ||
let val; | ||
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "map" is invalid for repeated fields | ||
switch (field.kind) { | ||
case "message": | ||
val = field.T.fromJson(jsonItem, options); | ||
break; | ||
case "enum": | ||
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields); | ||
if (val === undefined) | ||
continue; | ||
break; | ||
case "scalar": | ||
try { | ||
val = readScalar(field.T, jsonItem, field.L); | ||
} | ||
catch (e) { | ||
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
} | ||
targetArray.push(val); | ||
} | ||
} | ||
else if (field.kind == "map") { | ||
if (jsonValue === null) { | ||
return; | ||
} | ||
if (typeof jsonValue != "object" || Array.isArray(jsonValue)) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`); | ||
} | ||
const targetMap = target[localName]; | ||
for (const [jsonMapKey, jsonMapValue] of Object.entries(jsonValue)) { | ||
if (jsonMapValue === null) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: map value null`); | ||
} | ||
let val; | ||
switch (field.V.kind) { | ||
case "message": | ||
val = field.V.T.fromJson(jsonMapValue, options); | ||
break; | ||
case "enum": | ||
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields); | ||
if (val === undefined) | ||
continue; | ||
break; | ||
case "scalar": | ||
try { | ||
val = readScalar(field.V.T, jsonMapValue, field_js_1.LongType.BIGINT); | ||
} | ||
catch (e) { | ||
let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
} | ||
try { | ||
targetMap[readScalar(field.K, field.K == field_js_1.ScalarType.BOOL | ||
? jsonMapKey == "true" | ||
? true | ||
: jsonMapKey == "false" | ||
? false | ||
: jsonMapKey | ||
: jsonMapKey, field_js_1.LongType.BIGINT).toString()] = val; | ||
} | ||
catch (e) { | ||
let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
} | ||
} | ||
else { | ||
switch (field.kind) { | ||
case "message": | ||
const messageType = field.T; | ||
if (jsonValue === null && | ||
messageType.typeName != "google.protobuf.Value") { | ||
if (field.oneof) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: null is invalid for oneof field`); | ||
} | ||
return; | ||
} | ||
if (target[localName] instanceof message_js_1.Message) { | ||
target[localName].fromJson(jsonValue, options); | ||
} | ||
else { | ||
target[localName] = messageType.fromJson(jsonValue, options); | ||
if (messageType.fieldWrapper && !field.oneof) { | ||
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]); | ||
} | ||
} | ||
break; | ||
case "enum": | ||
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields); | ||
if (enumValue !== undefined) { | ||
target[localName] = enumValue; | ||
} | ||
break; | ||
case "scalar": | ||
try { | ||
target[localName] = readScalar(field.T, jsonValue, field.L); | ||
} | ||
catch (e) { | ||
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
// May throw an error. If the error message is non-blank, it should be shown. | ||
@@ -281,3 +326,3 @@ // It is up to the caller to provide context. | ||
if (json === null) | ||
return 0.0; | ||
return 0.0; // TODO field presence: this should reset the field with explicit presence | ||
if (json === "NaN") | ||
@@ -319,3 +364,3 @@ return Number.NaN; | ||
if (json === null) | ||
return 0; | ||
return 0; // TODO field presence: this should reset the field with explicit presence | ||
let int32; | ||
@@ -340,3 +385,3 @@ if (typeof json == "number") | ||
if (json === null) | ||
return proto_int64_js_1.protoInt64.zero; | ||
return proto_int64_js_1.protoInt64.zero; // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json != "number" && typeof json != "string") | ||
@@ -350,3 +395,3 @@ break; | ||
if (json === null) | ||
return proto_int64_js_1.protoInt64.zero; | ||
return proto_int64_js_1.protoInt64.zero; // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json != "number" && typeof json != "string") | ||
@@ -360,3 +405,3 @@ break; | ||
if (json === null) | ||
return false; | ||
return false; // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json !== "boolean") | ||
@@ -368,3 +413,3 @@ break; | ||
if (json === null) | ||
return ""; | ||
return ""; // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json !== "string") { | ||
@@ -386,3 +431,3 @@ break; | ||
if (json === null || json === "") | ||
return new Uint8Array(0); | ||
return new Uint8Array(0); // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json !== "string") | ||
@@ -397,2 +442,3 @@ break; | ||
// proto3 requires 0 to be default value for all enums | ||
// TODO field presence: this should reset the field with explicit presence | ||
return 0; | ||
@@ -399,0 +445,0 @@ } |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -22,2 +22,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
function makeJsonFormatProto2() { | ||
// TODO field presence: merge this function with proto2 | ||
return (0, json_format_common_js_1.makeJsonFormatCommon)((writeEnum, writeScalar) => { | ||
@@ -24,0 +25,0 @@ return function writeField(field, value, options) { |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -22,2 +22,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
function makeJsonFormatProto3() { | ||
// TODO field presence: merge this function with proto2 | ||
return (0, json_format_common_js_1.makeJsonFormatCommon)((writeEnum, writeScalar) => { | ||
@@ -70,3 +71,3 @@ return function writeField(field, value, options) { | ||
for (let i = 0; i < value.length; i++) { | ||
jsonArr.push((0, field_wrapper_js_1.wrapField)(field.T, value[i]).toJson(options)); | ||
jsonArr.push(value[i].toJson(options)); | ||
} | ||
@@ -80,2 +81,5 @@ break; | ||
else { | ||
if (value === undefined) { | ||
return undefined; | ||
} | ||
switch (field.kind) { | ||
@@ -87,5 +91,3 @@ case "scalar": | ||
case "message": | ||
return value !== undefined | ||
? (0, field_wrapper_js_1.wrapField)(field.T, value).toJson(options) | ||
: undefined; | ||
return (0, field_wrapper_js_1.wrapField)(field.T, value).toJson(options); | ||
} | ||
@@ -92,0 +94,0 @@ } |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
import type { DescEnum, DescEnumValue, DescField, DescMessage, DescService } from "../descriptor-set.js"; | ||
import type { DescEnum, DescEnumValue, DescExtension, DescField, DescMessage, DescService } from "../descriptor-set.js"; | ||
import type { DescMethod, DescOneof } from "../descriptor-set.js"; | ||
@@ -11,3 +11,3 @@ /** | ||
*/ | ||
export declare function localName(desc: DescEnum | DescEnumValue | DescMessage | DescOneof | DescField | DescService | DescMethod): string; | ||
export declare function localName(desc: DescEnum | DescEnumValue | DescMessage | DescExtension | DescOneof | DescField | DescService | DescMethod): string; | ||
/** | ||
@@ -14,0 +14,0 @@ * Returns the name of a field in generated code. |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -33,3 +33,4 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
case "message": | ||
case "service": { | ||
case "service": | ||
case "extension": { | ||
const pkg = desc.file.proto.package; | ||
@@ -36,0 +37,0 @@ const offset = pkg === undefined ? 0 : pkg.length + 1; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -10,2 +10,4 @@ import type { JsonFormat } from "../json-format.js"; | ||
import type { Util } from "./util.js"; | ||
import type { Extension } from "../extension.js"; | ||
import type { ExtensionFieldSource } from "./extensions.js"; | ||
/** | ||
@@ -47,3 +49,7 @@ * A facade that provides serialization and other internal functionality. | ||
getEnumType(enumObject: EnumObject): EnumType; | ||
/** | ||
* Create an extension at runtime, without generating code. | ||
*/ | ||
makeExtension<E extends Message<E> = AnyMessage, V = unknown>(typeName: string, extendee: MessageType<E>, field: ExtensionFieldSource): Extension<E, V>; | ||
} | ||
export declare function makeProtoRuntime(syntax: string, json: JsonFormat, bin: BinaryFormat, util: Util): ProtoRuntime; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -19,2 +19,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
const message_type_js_1 = require("./message-type.js"); | ||
const extensions_js_1 = require("./extensions.js"); | ||
function makeProtoRuntime(syntax, json, bin, util) { | ||
@@ -32,4 +33,7 @@ return { | ||
getEnumType: enum_js_1.getEnumType, | ||
makeExtension(typeName, extendee, field) { | ||
return (0, extensions_js_1.makeExtension)(this, typeName, extendee, field); | ||
}, | ||
}; | ||
} | ||
exports.makeProtoRuntime = makeProtoRuntime; |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
import type { MessageType } from "./message-type.js"; | ||
import type { EnumType } from "./enum.js"; | ||
import type { ServiceType } from "./service-type.js"; | ||
import type { Extension } from "./extension.js"; | ||
/** | ||
@@ -44,1 +45,14 @@ * IMessageTypeRegistry provides look-up for message types. | ||
} | ||
/** | ||
* IExtensionRegistry provides look-up for extensions. | ||
*/ | ||
export interface IExtensionRegistry { | ||
/** | ||
* Find an extension by the extendee type name and the extension number. | ||
*/ | ||
findExtensionFor(extendee: string, no: number): Extension | undefined; | ||
/** | ||
* Find an extension type by its protobuf type name. | ||
*/ | ||
findExtension(typeName: string): Extension | undefined; | ||
} |
"use strict"; | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -4,0 +4,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -318,4 +318,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
case WireType.StartGroup: | ||
// From descriptor.proto: Group type is deprecated, not supported in proto3. | ||
// But we must still be able to parse and treat as unknown. | ||
// TODO check for matching field numbers in StartGroup / EndGroup tags | ||
let t; | ||
@@ -322,0 +321,0 @@ while ((t = this.tag()[1]) !== WireType.EndGroup) { |
import type { Message } from "./message.js"; | ||
import type { IBinaryReader, IBinaryWriter, WireType } from "./binary-encoding.js"; | ||
import type { FieldInfo } from "./field.js"; | ||
/** | ||
@@ -31,2 +32,10 @@ * BinaryFormat is the contract for serializing messages to and from binary | ||
/** | ||
* Parse a field from binary data, and store it in the given target. | ||
* | ||
* The target must be an initialized message object, with oneof groups, | ||
* repeated fields and maps already present. | ||
*/ | ||
readField(target: Record<string, any>, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
reader: IBinaryReader, field: FieldInfo, wireType: WireType, options: BinaryReadOptions): void; | ||
/** | ||
* Serialize a message to binary data. | ||
@@ -36,2 +45,10 @@ */ | ||
/** | ||
* Serialize a field value to binary data. | ||
* | ||
* The value must be an array for repeated fields, a record object for map | ||
* fields. Only selected oneof fields should be passed to this method. | ||
*/ | ||
writeField(field: FieldInfo, value: any, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
writer: IBinaryWriter, options: BinaryWriteOptions): void; | ||
/** | ||
* Retrieve the unknown fields for the given message. | ||
@@ -38,0 +55,0 @@ * |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
import { reifyWkt } from "./private/reify-wkt.js"; | ||
import type { DescEnum, DescEnumValue, DescField, DescMessage, DescMethod, DescOneof, DescService } from "./descriptor-set"; | ||
import type { DescEnum, DescEnumValue, DescField, DescExtension, DescMessage, DescMethod, DescOneof, DescService } from "./descriptor-set"; | ||
import { LongType, ScalarType } from "./field.js"; | ||
@@ -9,5 +9,5 @@ interface CodegenInfo { | ||
readonly packageName: string; | ||
readonly localName: (desc: DescEnum | DescEnumValue | DescMessage | DescOneof | DescField | DescService | DescMethod) => string; | ||
readonly localName: (desc: DescEnum | DescEnumValue | DescMessage | DescExtension | DescOneof | DescField | DescService | DescMethod) => string; | ||
readonly symbols: Record<RuntimeSymbolName, RuntimeSymbolInfo>; | ||
readonly getUnwrappedFieldType: (field: DescField) => ScalarType | undefined; | ||
readonly getUnwrappedFieldType: (field: DescField | DescExtension) => ScalarType | undefined; | ||
readonly wktSourceFiles: readonly string[]; | ||
@@ -22,3 +22,3 @@ readonly scalarDefaultValue: (type: ScalarType, longType: LongType) => any; | ||
} | ||
type RuntimeSymbolName = "proto2" | "proto3" | "Message" | "PartialMessage" | "PlainMessage" | "FieldList" | "MessageType" | "BinaryReadOptions" | "BinaryWriteOptions" | "JsonReadOptions" | "JsonWriteOptions" | "JsonValue" | "JsonObject" | "protoDouble" | "protoInt64" | "ScalarType" | "LongType" | "MethodKind" | "MethodIdempotency" | "IMessageTypeRegistry"; | ||
type RuntimeSymbolName = "proto2" | "proto3" | "Message" | "PartialMessage" | "PlainMessage" | "FieldList" | "MessageType" | "Extension" | "BinaryReadOptions" | "BinaryWriteOptions" | "JsonReadOptions" | "JsonWriteOptions" | "JsonValue" | "JsonObject" | "protoDouble" | "protoInt64" | "ScalarType" | "LongType" | "MethodKind" | "MethodIdempotency" | "IMessageTypeRegistry"; | ||
type RuntimeSymbolInfo = { | ||
@@ -25,0 +25,0 @@ typeOnly: boolean; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -37,2 +37,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
MessageType: { typeOnly: true, privateImportPath: "./message-type.js", publicImportPath: packageName }, | ||
Extension: { typeOnly: true, privateImportPath: "./extension.js", publicImportPath: packageName }, | ||
BinaryReadOptions: { typeOnly: true, privateImportPath: "./binary-format.js", publicImportPath: packageName }, | ||
@@ -39,0 +40,0 @@ BinaryWriteOptions: { typeOnly: true, privateImportPath: "./binary-format.js", publicImportPath: packageName }, |
@@ -23,3 +23,3 @@ import { FeatureSetDefaults, FileDescriptorProto, FileDescriptorSet } from "./google/protobuf/descriptor_pb.js"; | ||
* you have to provide a google.protobuf.FeatureSetDefaults message in this | ||
* option. | ||
* option. It can also specify the minimum and maximum supported edition. | ||
* | ||
@@ -26,0 +26,0 @@ * The defaults can be generated with `protoc` - see the flag |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -30,3 +30,2 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
export function createDescriptorSet(input, options) { | ||
var _a; | ||
const cart = { | ||
@@ -38,3 +37,2 @@ enums: new Map(), | ||
mapEntries: new Map(), | ||
resolveFeatures: createFeatureResolver((_a = options === null || options === void 0 ? void 0 : options.featureSetDefaults) !== null && _a !== void 0 ? _a : featureSetDefaults), | ||
}; | ||
@@ -46,3 +44,13 @@ const fileDescriptors = input instanceof FileDescriptorSet | ||
: input; | ||
const files = fileDescriptors.map((proto) => newFile(proto, cart)); | ||
const resolverByEdition = new Map(); | ||
const files = fileDescriptors.map((proto) => { | ||
var _a, _b; | ||
const edition = (_a = proto.edition) !== null && _a !== void 0 ? _a : parseFileSyntax(proto.syntax, proto.edition).edition; | ||
let resolveFeatures = resolverByEdition.get(edition); | ||
if (resolveFeatures === undefined) { | ||
resolveFeatures = createFeatureResolver((_b = options === null || options === void 0 ? void 0 : options.featureSetDefaults) !== null && _b !== void 0 ? _b : featureSetDefaults, edition); | ||
resolverByEdition.set(edition, resolveFeatures); | ||
} | ||
return newFile(proto, cart, resolveFeatures); | ||
}); | ||
return Object.assign({ files }, cart); | ||
@@ -53,3 +61,3 @@ } | ||
*/ | ||
function newFile(proto, cart) { | ||
function newFile(proto, cart, resolveFeatures) { | ||
var _a, _b; | ||
@@ -73,21 +81,21 @@ assert(proto.name, `invalid FileDescriptorProto: missing name`); | ||
var _a; | ||
return cart.resolveFeatures(this.edition, (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures((_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
} }); | ||
cart.mapEntries.clear(); // map entries are local to the file, we can safely discard | ||
for (const enumProto of proto.enumType) { | ||
addEnum(enumProto, file, undefined, cart); | ||
addEnum(enumProto, file, undefined, cart, resolveFeatures); | ||
} | ||
for (const messageProto of proto.messageType) { | ||
addMessage(messageProto, file, undefined, cart); | ||
addMessage(messageProto, file, undefined, cart, resolveFeatures); | ||
} | ||
for (const serviceProto of proto.service) { | ||
addService(serviceProto, file, cart); | ||
addService(serviceProto, file, cart, resolveFeatures); | ||
} | ||
addExtensions(file, cart); | ||
addExtensions(file, cart, resolveFeatures); | ||
for (const mapEntry of cart.mapEntries.values()) { | ||
addFields(mapEntry, cart); | ||
addFields(mapEntry, cart, resolveFeatures); | ||
} | ||
for (const message of file.messages) { | ||
addFields(message, cart); | ||
addExtensions(message, cart); | ||
addFields(message, cart, resolveFeatures); | ||
addExtensions(message, cart, resolveFeatures); | ||
} | ||
@@ -102,7 +110,7 @@ cart.mapEntries.clear(); // map entries are local to the file, we can safely discard | ||
*/ | ||
function addExtensions(desc, cart) { | ||
function addExtensions(desc, cart, resolveFeatures) { | ||
switch (desc.kind) { | ||
case "file": | ||
for (const proto of desc.proto.extension) { | ||
const ext = newExtension(proto, desc, undefined, cart); | ||
const ext = newExtension(proto, desc, undefined, cart, resolveFeatures); | ||
desc.extensions.push(ext); | ||
@@ -114,3 +122,3 @@ cart.extensions.set(ext.typeName, ext); | ||
for (const proto of desc.proto.extension) { | ||
const ext = newExtension(proto, desc.file, desc, cart); | ||
const ext = newExtension(proto, desc.file, desc, cart, resolveFeatures); | ||
desc.nestedExtensions.push(ext); | ||
@@ -120,3 +128,3 @@ cart.extensions.set(ext.typeName, ext); | ||
for (const message of desc.nestedMessages) { | ||
addExtensions(message, cart); | ||
addExtensions(message, cart, resolveFeatures); | ||
} | ||
@@ -130,8 +138,8 @@ break; | ||
*/ | ||
function addFields(message, cart) { | ||
const allOneofs = message.proto.oneofDecl.map((proto) => newOneof(proto, message, cart)); | ||
function addFields(message, cart, resolveFeatures) { | ||
const allOneofs = message.proto.oneofDecl.map((proto) => newOneof(proto, message, resolveFeatures)); | ||
const oneofsSeen = new Set(); | ||
for (const proto of message.proto.field) { | ||
const oneof = findOneof(proto, allOneofs); | ||
const field = newField(proto, message.file, message, oneof, cart); | ||
const field = newField(proto, message.file, message, oneof, cart, resolveFeatures); | ||
message.fields.push(field); | ||
@@ -153,3 +161,3 @@ if (oneof === undefined) { | ||
for (const child of message.nestedMessages) { | ||
addFields(child, cart); | ||
addFields(child, cart, resolveFeatures); | ||
} | ||
@@ -161,3 +169,3 @@ } | ||
*/ | ||
function addEnum(proto, file, parent, cart) { | ||
function addEnum(proto, file, parent, cart, resolveFeatures) { | ||
var _a, _b, _c; | ||
@@ -192,5 +200,4 @@ assert(proto.name, `invalid EnumDescriptorProto: missing name`); | ||
getFeatures() { | ||
var _a, _b, _c; | ||
const parentFeatures = (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.getFeatures()) !== null && _b !== void 0 ? _b : this.file.getFeatures(); | ||
return cart.resolveFeatures(this.file.edition, parentFeatures, (_c = this.proto.options) === null || _c === void 0 ? void 0 : _c.features); | ||
var _a, _b; | ||
return resolveFeatures((_a = parent === null || parent === void 0 ? void 0 : parent.getFeatures()) !== null && _a !== void 0 ? _a : file.getFeatures(), (_b = proto.options) === null || _b === void 0 ? void 0 : _b.features); | ||
}, | ||
@@ -231,3 +238,3 @@ }; | ||
var _a; | ||
return cart.resolveFeatures(this.parent.file.edition, this.parent.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(desc.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -242,3 +249,3 @@ }); | ||
*/ | ||
function addMessage(proto, file, parent, cart) { | ||
function addMessage(proto, file, parent, cart, resolveFeatures) { | ||
var _a, _b, _c, _d; | ||
@@ -277,5 +284,4 @@ assert(proto.name, `invalid DescriptorProto: missing name`); | ||
getFeatures() { | ||
var _a, _b, _c; | ||
const parentFeatures = (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.getFeatures()) !== null && _b !== void 0 ? _b : this.file.getFeatures(); | ||
return cart.resolveFeatures(this.file.edition, parentFeatures, (_c = this.proto.options) === null || _c === void 0 ? void 0 : _c.features); | ||
var _a, _b; | ||
return resolveFeatures((_a = parent === null || parent === void 0 ? void 0 : parent.getFeatures()) !== null && _a !== void 0 ? _a : file.getFeatures(), (_b = proto.options) === null || _b === void 0 ? void 0 : _b.features); | ||
}, | ||
@@ -291,6 +297,6 @@ }; | ||
for (const enumProto of proto.enumType) { | ||
addEnum(enumProto, file, desc, cart); | ||
addEnum(enumProto, file, desc, cart, resolveFeatures); | ||
} | ||
for (const messageProto of proto.nestedType) { | ||
addMessage(messageProto, file, desc, cart); | ||
addMessage(messageProto, file, desc, cart, resolveFeatures); | ||
} | ||
@@ -302,3 +308,3 @@ } | ||
*/ | ||
function addService(proto, file, cart) { | ||
function addService(proto, file, cart, resolveFeatures) { | ||
var _a, _b; | ||
@@ -326,3 +332,3 @@ assert(proto.name, `invalid ServiceDescriptorProto: missing name`); | ||
var _a; | ||
return cart.resolveFeatures(this.file.edition, this.file.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(file.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -333,3 +339,3 @@ }; | ||
for (const methodProto of proto.method) { | ||
desc.methods.push(newMethod(methodProto, desc, cart)); | ||
desc.methods.push(newMethod(methodProto, desc, cart, resolveFeatures)); | ||
} | ||
@@ -340,3 +346,3 @@ } | ||
*/ | ||
function newMethod(proto, parent, cart) { | ||
function newMethod(proto, parent, cart, resolveFeatures) { | ||
var _a, _b, _c; | ||
@@ -400,3 +406,3 @@ assert(proto.name, `invalid MethodDescriptorProto: missing name`); | ||
var _a; | ||
return cart.resolveFeatures(this.parent.file.edition, this.parent.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(parent.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -408,3 +414,3 @@ }; | ||
*/ | ||
function newOneof(proto, parent, cart) { | ||
function newOneof(proto, parent, resolveFeatures) { | ||
assert(proto.name, `invalid OneofDescriptorProto: missing name`); | ||
@@ -431,3 +437,3 @@ return { | ||
var _a; | ||
return cart.resolveFeatures(this.parent.file.edition, this.parent.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(parent.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -439,3 +445,3 @@ }; | ||
*/ | ||
function newField(proto, file, parent, oneof, cart) { | ||
function newField(proto, file, parent, oneof, cart, resolveFeatures) { | ||
var _a, _b, _c; | ||
@@ -453,4 +459,4 @@ assert(proto.name, `invalid FieldDescriptorProto: missing name`); | ||
optional: isOptionalField(proto, file.syntax), | ||
packedByDefault: isPackedFieldByDefault(file, proto, cart.resolveFeatures), | ||
packed: isPackedField(file, parent, proto, cart.resolveFeatures), | ||
packedByDefault: isPackedFieldByDefault(proto, resolveFeatures), | ||
packed: isPackedField(file, parent, proto, resolveFeatures), | ||
jsonName: proto.jsonName === fieldJsonName(proto.name) ? undefined : proto.jsonName, | ||
@@ -478,3 +484,3 @@ scalar: undefined, | ||
var _a; | ||
return cart.resolveFeatures(file.edition, this.parent.getFeatures(), (_a = this.proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
return resolveFeatures(parent.getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
}, | ||
@@ -518,6 +524,6 @@ }; | ||
*/ | ||
function newExtension(proto, file, parent, cart) { | ||
function newExtension(proto, file, parent, cart, resolveFeatures) { | ||
assert(proto.extendee, `invalid FieldDescriptorProto: missing extendee`); | ||
const field = newField(proto, file, null, // to safe us many lines of duplicated code, we trick the type system | ||
undefined, cart); | ||
undefined, cart, resolveFeatures); | ||
const extendee = cart.messages.get(trimLeadingDot(proto.extendee)); | ||
@@ -547,4 +553,4 @@ assert(extendee, `invalid FieldDescriptorProto: extendee ${proto.extendee} not found`); | ||
getFeatures() { | ||
var _a, _b; | ||
return cart.resolveFeatures(this.file.edition, ((_a = this.parent) !== null && _a !== void 0 ? _a : this.file).getFeatures(), (_b = this.proto.options) === null || _b === void 0 ? void 0 : _b.features); | ||
var _a; | ||
return resolveFeatures((parent !== null && parent !== void 0 ? parent : file).getFeatures(), (_a = proto.options) === null || _a === void 0 ? void 0 : _a.features); | ||
} }); | ||
@@ -705,4 +711,4 @@ } | ||
*/ | ||
function isPackedFieldByDefault(file, proto, resolveFeatures) { | ||
const { repeatedFieldEncoding } = resolveFeatures(file.edition); | ||
function isPackedFieldByDefault(proto, resolveFeatures) { | ||
const { repeatedFieldEncoding } = resolveFeatures(); | ||
if (repeatedFieldEncoding != FeatureSet_RepeatedFieldEncoding.PACKED) { | ||
@@ -748,3 +754,3 @@ return false; | ||
default: { | ||
const { repeatedFieldEncoding } = resolveFeatures(file.edition, (_e = parent === null || parent === void 0 ? void 0 : parent.getFeatures()) !== null && _e !== void 0 ? _e : file.getFeatures(), (_f = proto.options) === null || _f === void 0 ? void 0 : _f.features); | ||
const { repeatedFieldEncoding } = resolveFeatures((_e = parent === null || parent === void 0 ? void 0 : parent.getFeatures()) !== null && _e !== void 0 ? _e : file.getFeatures(), (_f = proto.options) === null || _f === void 0 ? void 0 : _f.features); | ||
return (repeatedFieldEncoding == FeatureSet_RepeatedFieldEncoding.PACKED); | ||
@@ -751,0 +757,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import type { IEnumTypeRegistry, IMessageTypeRegistry, IServiceTypeRegistry } from "./type-registry.js"; | ||
import type { IEnumTypeRegistry, IExtensionRegistry, IMessageTypeRegistry, IServiceTypeRegistry } from "./type-registry.js"; | ||
import { FileDescriptorSet } from "./google/protobuf/descriptor_pb.js"; | ||
@@ -15,2 +15,2 @@ import type { DescriptorSet } from "./descriptor-set.js"; | ||
*/ | ||
export declare function createRegistryFromDescriptors(input: DescriptorSet | FileDescriptorSet | Uint8Array, replaceWkt?: boolean): IMessageTypeRegistry & IEnumTypeRegistry & IServiceTypeRegistry; | ||
export declare function createRegistryFromDescriptors(input: DescriptorSet | FileDescriptorSet | Uint8Array, replaceWkt?: boolean): IMessageTypeRegistry & IEnumTypeRegistry & IExtensionRegistry & IServiceTypeRegistry; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -67,11 +67,13 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
: input; | ||
const enums = {}; | ||
const messages = {}; | ||
const enums = new Map(); | ||
const messages = new Map(); | ||
const extensions = new Map(); | ||
const extensionsByExtendee = new Map(); | ||
const services = {}; | ||
if (replaceWkt) { | ||
for (const mt of wkMessages) { | ||
messages[mt.typeName] = mt; | ||
messages.set(mt.typeName, mt); | ||
} | ||
for (const et of wkEnums) { | ||
enums[et.typeName] = et; | ||
enums.set(et.typeName, et); | ||
} | ||
@@ -84,3 +86,3 @@ } | ||
findEnum(typeName) { | ||
const existing = enums[typeName]; | ||
const existing = enums.get(typeName); | ||
if (existing) { | ||
@@ -99,3 +101,3 @@ return existing; | ||
})), {}); | ||
enums[typeName] = type; | ||
enums.set(typeName, type); | ||
return type; | ||
@@ -107,3 +109,3 @@ }, | ||
findMessage(typeName) { | ||
const existing = messages[typeName]; | ||
const existing = messages.get(typeName); | ||
if (existing) { | ||
@@ -121,3 +123,3 @@ return existing; | ||
}); | ||
messages[typeName] = type; | ||
messages.set(typeName, type); | ||
for (const field of desc.fields) { | ||
@@ -162,2 +164,43 @@ const fieldInfo = makeFieldInfo(field, this); | ||
}, | ||
/** | ||
* May raise an error on invalid descriptors. | ||
*/ | ||
findExtensionFor(typeName, no) { | ||
var _a; | ||
if (!set.messages.has(typeName)) { | ||
return undefined; | ||
} | ||
let extensionsByNo = extensionsByExtendee.get(typeName); | ||
if (!extensionsByNo) { | ||
// maintain a lookup for extension desc by number | ||
extensionsByNo = new Map(); | ||
extensionsByExtendee.set(typeName, extensionsByNo); | ||
for (const desc of set.extensions.values()) { | ||
if (desc.extendee.typeName == typeName) { | ||
extensionsByNo.set(desc.number, desc); | ||
} | ||
} | ||
} | ||
const desc = (_a = extensionsByExtendee.get(typeName)) === null || _a === void 0 ? void 0 : _a.get(no); | ||
return desc ? this.findExtension(desc.typeName) : undefined; | ||
}, | ||
/** | ||
* May raise an error on invalid descriptors. | ||
*/ | ||
findExtension(typeName) { | ||
const existing = extensions.get(typeName); | ||
if (existing) { | ||
return existing; | ||
} | ||
const desc = set.extensions.get(typeName); | ||
if (!desc) { | ||
return undefined; | ||
} | ||
const extendee = this.findMessage(desc.extendee.typeName); | ||
assert(extendee, `message "${desc.extendee.typeName}" for ${desc.toString()} not found`); | ||
const runtime = desc.file.syntax == "proto3" ? proto3 : proto2; | ||
const ext = runtime.makeExtension(typeName, extendee, makeFieldInfo(desc, this)); | ||
extensions.set(typeName, ext); | ||
return ext; | ||
}, | ||
}; | ||
@@ -168,2 +211,3 @@ } | ||
case "map": | ||
assert(desc.kind == "field"); // maps are not allowed for extensions | ||
return makeMapFieldInfo(desc, resolver); | ||
@@ -170,0 +214,0 @@ case "message": |
import type { MessageType } from "./message-type.js"; | ||
import type { EnumType } from "./enum.js"; | ||
import type { ServiceType } from "./service-type.js"; | ||
import type { IMessageTypeRegistry, IEnumTypeRegistry, IServiceTypeRegistry } from "./type-registry.js"; | ||
import type { IEnumTypeRegistry, IExtensionRegistry, IMessageTypeRegistry, IServiceTypeRegistry } from "./type-registry.js"; | ||
import type { Extension } from "./extension.js"; | ||
/** | ||
* Create a new registry from the given types. | ||
*/ | ||
export declare function createRegistry(...types: Array<MessageType | EnumType | ServiceType>): IMessageTypeRegistry & IEnumTypeRegistry & IServiceTypeRegistry; | ||
export declare function createRegistry(...types: Array<MessageType | EnumType | ServiceType | Extension>): IMessageTypeRegistry & IEnumTypeRegistry & IExtensionRegistry & IServiceTypeRegistry; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -21,38 +21,5 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
const services = {}; | ||
const extensionsByName = new Map(); | ||
const extensionsByExtendee = new Map(); | ||
const registry = { | ||
/** | ||
* Add a type to the registry. For messages, the types used in message | ||
* fields are added recursively. For services, the message types used | ||
* for requests and responses are added recursively. | ||
*/ | ||
add(type) { | ||
if ("fields" in type) { | ||
if (!this.findMessage(type.typeName)) { | ||
messages[type.typeName] = type; | ||
for (const field of type.fields.list()) { | ||
if (field.kind == "message") { | ||
this.add(field.T); | ||
} | ||
else if (field.kind == "map" && field.V.kind == "message") { | ||
this.add(field.V.T); | ||
} | ||
else if (field.kind == "enum") { | ||
this.add(field.T); | ||
} | ||
} | ||
} | ||
} | ||
else if ("methods" in type) { | ||
if (!this.findService(type.typeName)) { | ||
services[type.typeName] = type; | ||
for (const method of Object.values(type.methods)) { | ||
this.add(method.I); | ||
this.add(method.O); | ||
} | ||
} | ||
} | ||
else { | ||
enums[type.typeName] = type; | ||
} | ||
}, | ||
findMessage(typeName) { | ||
@@ -67,7 +34,59 @@ return messages[typeName]; | ||
}, | ||
findExtensionFor(typeName, no) { | ||
var _a, _b; | ||
return (_b = (_a = extensionsByExtendee.get(typeName)) === null || _a === void 0 ? void 0 : _a.get(no)) !== null && _b !== void 0 ? _b : undefined; | ||
}, | ||
findExtension(typeName) { | ||
var _a; | ||
return (_a = extensionsByName.get(typeName)) !== null && _a !== void 0 ? _a : undefined; | ||
}, | ||
}; | ||
function addType(type) { | ||
var _a; | ||
if ("fields" in type) { | ||
if (!registry.findMessage(type.typeName)) { | ||
messages[type.typeName] = type; | ||
type.fields.list().forEach(addField); | ||
} | ||
} | ||
else if ("methods" in type) { | ||
if (!registry.findService(type.typeName)) { | ||
services[type.typeName] = type; | ||
for (const method of Object.values(type.methods)) { | ||
addType(method.I); | ||
addType(method.O); | ||
} | ||
} | ||
} | ||
else if ("extendee" in type) { | ||
if (!extensionsByName.has(type.typeName)) { | ||
extensionsByName.set(type.typeName, type); | ||
const extendeeName = type.extendee.typeName; | ||
if (!extensionsByExtendee.has(extendeeName)) { | ||
extensionsByExtendee.set(extendeeName, new Map()); | ||
} | ||
(_a = extensionsByExtendee.get(extendeeName)) === null || _a === void 0 ? void 0 : _a.set(type.field.no, type); | ||
addType(type.extendee); | ||
addField(type.field); | ||
} | ||
} | ||
else { | ||
enums[type.typeName] = type; | ||
} | ||
} | ||
function addField(field) { | ||
if (field.kind == "message") { | ||
addType(field.T); | ||
} | ||
else if (field.kind == "map" && field.V.kind == "message") { | ||
addType(field.V.T); | ||
} | ||
else if (field.kind == "enum") { | ||
addType(field.T); | ||
} | ||
} | ||
for (const type of types) { | ||
registry.add(type); | ||
addType(type); | ||
} | ||
return registry; | ||
} |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -14,3 +14,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
// limitations under the License. | ||
// @generated by protoc-gen-es v1.6.0 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts" | ||
// @generated by protoc-gen-es v1.7.0 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts" | ||
// @generated from file google/protobuf/struct.proto (package google.protobuf, syntax proto3) | ||
@@ -17,0 +17,0 @@ /* eslint-disable */ |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -14,3 +14,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
// limitations under the License. | ||
// @generated by protoc-gen-es v1.6.0 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts" | ||
// @generated by protoc-gen-es v1.7.0 with parameter "bootstrap_wkt=true,ts_nocheck=false,target=ts" | ||
// @generated from file google/protobuf/type.proto (package google.protobuf, syntax proto3) | ||
@@ -17,0 +17,0 @@ /* eslint-disable */ |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -15,2 +15,4 @@ export { proto3 } from "./proto3.js"; | ||
export type { EnumType, EnumValueInfo } from "./enum.js"; | ||
export type { Extension } from "./extension.js"; | ||
export { getExtension, setExtension, hasExtension, clearExtension, } from "./extension-accessor.js"; | ||
export type { ServiceType, MethodInfo, MethodInfoUnary, MethodInfoServerStreaming, MethodInfoClientStreaming, MethodInfoBiDiStreaming, } from "./service-type.js"; | ||
@@ -24,3 +26,3 @@ export { MethodKind, MethodIdempotency } from "./service-type.js"; | ||
export { createDescriptorSet } from "./create-descriptor-set.js"; | ||
export type { IMessageTypeRegistry } from "./type-registry.js"; | ||
export type { IMessageTypeRegistry, IExtensionRegistry, } from "./type-registry.js"; | ||
export { createRegistry } from "./create-registry.js"; | ||
@@ -27,0 +29,0 @@ export { createRegistryFromDescriptors } from "./create-registry-from-desc.js"; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -23,2 +23,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
export { ScalarType, LongType } from "./field.js"; | ||
export { getExtension, setExtension, hasExtension, clearExtension, } from "./extension-accessor.js"; | ||
export { MethodKind, MethodIdempotency } from "./service-type.js"; | ||
@@ -25,0 +26,0 @@ export { WireType, BinaryWriter, BinaryReader } from "./binary-encoding.js"; |
@@ -5,3 +5,3 @@ import type { Message } from "./message.js"; | ||
import { LongType } from "./field.js"; | ||
import type { IMessageTypeRegistry } from "./type-registry.js"; | ||
import type { IExtensionRegistry, IMessageTypeRegistry } from "./type-registry.js"; | ||
/** | ||
@@ -56,6 +56,6 @@ * JsonFormat is the contract for serializing messages to and from JSON. | ||
/** | ||
* This option is required to read `google.protobuf.Any` | ||
* This option is required to read `google.protobuf.Any` and extensions | ||
* from JSON format. | ||
*/ | ||
typeRegistry?: IMessageTypeRegistry; | ||
typeRegistry?: IMessageTypeRegistry & Partial<IExtensionRegistry>; | ||
} | ||
@@ -88,6 +88,6 @@ /** | ||
/** | ||
* This option is required to write `google.protobuf.Any` | ||
* This option is required to write `google.protobuf.Any` and extensions | ||
* to JSON format. | ||
*/ | ||
typeRegistry?: IMessageTypeRegistry; | ||
typeRegistry?: IMessageTypeRegistry & Partial<IExtensionRegistry>; | ||
} | ||
@@ -94,0 +94,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,7 +0,6 @@ | ||
import type { IBinaryReader, IBinaryWriter } from "../binary-encoding.js"; | ||
import type { IBinaryWriter } from "../binary-encoding.js"; | ||
import type { BinaryFormat, BinaryWriteOptions } from "../binary-format.js"; | ||
import type { FieldInfo } from "../field.js"; | ||
import { ScalarType } from "../field.js"; | ||
export declare function makeBinaryFormatCommon(): Omit<BinaryFormat, "writeMessage">; | ||
export declare function readScalarLTString(reader: IBinaryReader, type: ScalarType): any; | ||
export declare function makeBinaryFormatCommon(): Omit<BinaryFormat, "writeMessage" | "writeField">; | ||
export declare function writeMapEntry(writer: IBinaryWriter, options: BinaryWriteOptions, field: FieldInfo & { | ||
@@ -8,0 +7,0 @@ kind: "map"; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -85,64 +85,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
} | ||
let target = message, repeated = field.repeated, localName = field.localName; | ||
if (field.oneof) { | ||
target = target[field.oneof.localName]; | ||
if (target.case != localName) { | ||
delete target.value; | ||
} | ||
target.case = localName; | ||
localName = "value"; | ||
} | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
const scalarType = field.kind == "enum" ? ScalarType.INT32 : field.T; | ||
let read = readScalar; | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison -- acceptable since it's covered by tests | ||
if (field.kind == "scalar" && field.L > 0) { | ||
read = readScalarLTString; | ||
} | ||
if (repeated) { | ||
let arr = target[localName]; // safe to assume presence of array, oneof cannot contain repeated values | ||
if (wireType == WireType.LengthDelimited && | ||
scalarType != ScalarType.STRING && | ||
scalarType != ScalarType.BYTES) { | ||
let e = reader.uint32() + reader.pos; | ||
while (reader.pos < e) { | ||
arr.push(read(reader, scalarType)); | ||
} | ||
} | ||
else { | ||
arr.push(read(reader, scalarType)); | ||
} | ||
} | ||
else { | ||
target[localName] = read(reader, scalarType); | ||
} | ||
break; | ||
case "message": | ||
const messageType = field.T; | ||
if (repeated) { | ||
// safe to assume presence of array, oneof cannot contain repeated values | ||
target[localName].push(readMessageField(reader, new messageType(), options, field)); | ||
} | ||
else { | ||
if (target[localName] instanceof Message) { | ||
readMessageField(reader, target[localName], options, field); | ||
} | ||
else { | ||
target[localName] = readMessageField(reader, new messageType(), options, field); | ||
if (messageType.fieldWrapper && | ||
!field.oneof && | ||
!field.repeated) { | ||
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]); | ||
} | ||
} | ||
} | ||
break; | ||
case "map": | ||
let [mapKey, mapVal] = readMapEntry(field, reader, options); | ||
// safe to assume presence of map object, oneof cannot contain repeated values | ||
target[localName][mapKey] = mapVal; | ||
break; | ||
} | ||
readField(message, reader, field, wireType, options); | ||
} | ||
@@ -154,4 +93,69 @@ if (delimitedMessageEncoding && // eslint-disable-line @typescript-eslint/strict-boolean-expressions | ||
}, | ||
readField, | ||
}; | ||
} | ||
function readField(target, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
reader, field, wireType, options) { | ||
let { repeated, localName } = field; | ||
if (field.oneof) { | ||
target = target[field.oneof.localName]; | ||
if (target.case != localName) { | ||
delete target.value; | ||
} | ||
target.case = localName; | ||
localName = "value"; | ||
} | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
const scalarType = field.kind == "enum" ? ScalarType.INT32 : field.T; | ||
let read = readScalar; | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison -- acceptable since it's covered by tests | ||
if (field.kind == "scalar" && field.L > 0) { | ||
read = readScalarLTString; | ||
} | ||
if (repeated) { | ||
let arr = target[localName]; // safe to assume presence of array, oneof cannot contain repeated values | ||
const isPacked = wireType == WireType.LengthDelimited && | ||
scalarType != ScalarType.STRING && | ||
scalarType != ScalarType.BYTES; | ||
if (isPacked) { | ||
let e = reader.uint32() + reader.pos; | ||
while (reader.pos < e) { | ||
arr.push(read(reader, scalarType)); | ||
} | ||
} | ||
else { | ||
arr.push(read(reader, scalarType)); | ||
} | ||
} | ||
else { | ||
target[localName] = read(reader, scalarType); | ||
} | ||
break; | ||
case "message": | ||
const messageType = field.T; | ||
if (repeated) { | ||
// safe to assume presence of array, oneof cannot contain repeated values | ||
target[localName].push(readMessageField(reader, new messageType(), options, field)); | ||
} | ||
else { | ||
if (target[localName] instanceof Message) { | ||
readMessageField(reader, target[localName], options, field); | ||
} | ||
else { | ||
target[localName] = readMessageField(reader, new messageType(), options, field); | ||
if (messageType.fieldWrapper && !field.oneof && !field.repeated) { | ||
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]); | ||
} | ||
} | ||
} | ||
break; | ||
case "map": | ||
let [mapKey, mapVal] = readMapEntry(field, reader, options); | ||
// safe to assume presence of map object, oneof cannot contain repeated values | ||
target[localName][mapKey] = mapVal; | ||
break; | ||
} | ||
} | ||
// Read a message, avoiding MessageType.fromBinary() to re-use the | ||
@@ -218,3 +222,3 @@ // BinaryReadOptions and the IBinaryReader. | ||
// sint64, fixed64, sfixed64) as string instead of bigint. | ||
export function readScalarLTString(reader, type) { | ||
function readScalarLTString(reader, type) { | ||
const v = readScalar(reader, type); | ||
@@ -294,16 +298,15 @@ return typeof v == "bigint" ? v.toString() : v; | ||
} | ||
// Value must not be undefined | ||
export function writeMessageField(writer, options, field, value) { | ||
if (value !== undefined) { | ||
const message = wrapField(field.T, value); | ||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions | ||
if (field === null || field === void 0 ? void 0 : field.delimited) | ||
writer | ||
.tag(field.no, WireType.StartGroup) | ||
.raw(message.toBinary(options)) | ||
.tag(field.no, WireType.EndGroup); | ||
else | ||
writer | ||
.tag(field.no, WireType.LengthDelimited) | ||
.bytes(message.toBinary(options)); | ||
} | ||
const message = wrapField(field.T, value); | ||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions | ||
if (field === null || field === void 0 ? void 0 : field.delimited) | ||
writer | ||
.tag(field.no, WireType.StartGroup) | ||
.raw(message.toBinary(options)) | ||
.tag(field.no, WireType.EndGroup); | ||
else | ||
writer | ||
.tag(field.no, WireType.LengthDelimited) | ||
.bytes(message.toBinary(options)); | ||
} | ||
@@ -310,0 +313,0 @@ export function writeScalar(writer, type, fieldNo, value, emitIntrinsicDefault) { |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -18,71 +18,25 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
export function makeBinaryFormatProto2() { | ||
return Object.assign(Object.assign({}, makeBinaryFormatCommon()), { writeMessage(message, writer, options) { | ||
return Object.assign(Object.assign({}, makeBinaryFormatCommon()), { writeField, | ||
writeMessage(message, writer, options) { | ||
const type = message.getType(); | ||
let field; | ||
try { | ||
for (field of type.fields.byNumber()) { | ||
let value, // this will be our field value, whether it is member of a oneof or not | ||
repeated = field.repeated, localName = field.localName; | ||
if (field.oneof) { | ||
const oneof = message[field.oneof.localName]; | ||
if (oneof.case !== localName) { | ||
continue; // field is not selected, skip | ||
} | ||
value = oneof.value; | ||
for (field of type.fields.byNumber()) { | ||
let value, localName = field.localName; | ||
if (field.oneof) { | ||
const oneof = message[field.oneof.localName]; | ||
if (oneof.case !== localName) { | ||
continue; // field is not selected, skip | ||
} | ||
else { | ||
value = message[localName]; | ||
// In contrast to proto3, we raise an error if a non-optional (proto2 required) | ||
// field is missing a value. | ||
if (value === undefined && !field.oneof && !field.opt) { | ||
throw new Error(`cannot encode field ${type.typeName}.${field.name} to binary: required field not set`); | ||
} | ||
value = oneof.value; | ||
} | ||
else { | ||
value = message[localName]; | ||
// In contrast to proto3, we raise an error if a non-optional (proto2 required) | ||
// field is missing a value. | ||
if (value === undefined && !field.oneof && !field.opt) { | ||
throw new Error(`cannot encode field ${type.typeName}.${field === null || field === void 0 ? void 0 : field.name} to binary: required field not set`); | ||
} | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
let scalarType = field.kind == "enum" ? ScalarType.INT32 : field.T; | ||
if (repeated) { | ||
if (field.packed) { | ||
writePacked(writer, scalarType, field.no, value); | ||
} | ||
else { | ||
for (const item of value) { | ||
writeScalar(writer, scalarType, field.no, item, true); | ||
} | ||
} | ||
} | ||
else { | ||
if (value !== undefined) { | ||
// In contrast to proto3, we do not skip intrinsic default values. | ||
// Explicit default values are not special cased either. | ||
writeScalar(writer, scalarType, field.no, value, true); | ||
} | ||
} | ||
break; | ||
case "message": | ||
if (repeated) { | ||
for (const item of value) { | ||
writeMessageField(writer, options, field, item); | ||
} | ||
} | ||
else { | ||
writeMessageField(writer, options, field, value); | ||
} | ||
break; | ||
case "map": | ||
for (const [key, val] of Object.entries(value)) { | ||
writeMapEntry(writer, options, field, key, val); | ||
} | ||
break; | ||
} | ||
} | ||
writeField(field, value, writer, options); | ||
} | ||
catch (e) { | ||
let m = field | ||
? `cannot encode field ${type.typeName}.${field === null || field === void 0 ? void 0 : field.name} to binary` | ||
: `cannot encode message ${type.typeName} to binary`; | ||
let r = e instanceof Error ? e.message : String(e); | ||
throw new Error(m + (r.length > 0 ? `: ${r}` : "")); | ||
} | ||
if (options.writeUnknownFields) { | ||
@@ -94,1 +48,42 @@ this.writeUnknownFields(message, writer); | ||
} | ||
// TODO field presence: merge this function with proto3 | ||
function writeField(field, value, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
writer, options) { | ||
const repeated = field.repeated; | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
let scalarType = field.kind == "enum" ? ScalarType.INT32 : field.T; | ||
if (repeated) { | ||
if (field.packed) { | ||
writePacked(writer, scalarType, field.no, value); | ||
} | ||
else { | ||
for (const item of value) { | ||
writeScalar(writer, scalarType, field.no, item, true); | ||
} | ||
} | ||
} | ||
else if (value !== undefined) { | ||
// In contrast to proto3, we do not skip intrinsic default values. | ||
// Explicit default values are not special cased either. | ||
writeScalar(writer, scalarType, field.no, value, true); | ||
} | ||
break; | ||
case "message": | ||
if (repeated) { | ||
for (const item of value) { | ||
writeMessageField(writer, options, field, item); | ||
} | ||
} | ||
else if (value !== undefined) { | ||
writeMessageField(writer, options, field, value); | ||
} | ||
break; | ||
case "map": | ||
for (const [key, val] of Object.entries(value)) { | ||
writeMapEntry(writer, options, field, key, val); | ||
} | ||
break; | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -18,7 +18,7 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
export function makeBinaryFormatProto3() { | ||
return Object.assign(Object.assign({}, makeBinaryFormatCommon()), { writeMessage(message, writer, options) { | ||
return Object.assign(Object.assign({}, makeBinaryFormatCommon()), { writeField, | ||
writeMessage(message, writer, options) { | ||
const type = message.getType(); | ||
for (const field of type.fields.byNumber()) { | ||
let value, // this will be our field value, whether it is member of a oneof or regular field | ||
repeated = field.repeated, localName = field.localName; | ||
let value, localName = field.localName; | ||
if (field.oneof) { | ||
@@ -34,38 +34,3 @@ const oneof = message[field.oneof.localName]; | ||
} | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
let scalarType = field.kind == "enum" ? ScalarType.INT32 : field.T; | ||
if (repeated) { | ||
if (field.packed) { | ||
writePacked(writer, scalarType, field.no, value); | ||
} | ||
else { | ||
for (const item of value) { | ||
writeScalar(writer, scalarType, field.no, item, true); | ||
} | ||
} | ||
} | ||
else { | ||
if (value !== undefined) { | ||
writeScalar(writer, scalarType, field.no, value, !!field.oneof || field.opt); | ||
} | ||
} | ||
break; | ||
case "message": | ||
if (repeated) { | ||
for (const item of value) { | ||
writeMessageField(writer, options, field, item); | ||
} | ||
} | ||
else { | ||
writeMessageField(writer, options, field, value); | ||
} | ||
break; | ||
case "map": | ||
for (const [key, val] of Object.entries(value)) { | ||
writeMapEntry(writer, options, field, key, val); | ||
} | ||
break; | ||
} | ||
writeField(field, value, writer, options); | ||
} | ||
@@ -78,1 +43,40 @@ if (options.writeUnknownFields) { | ||
} | ||
// TODO field presence: merge this function with proto2 | ||
function writeField(field, value, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
writer, options) { | ||
const repeated = field.repeated; | ||
switch (field.kind) { | ||
case "scalar": | ||
case "enum": | ||
let scalarType = field.kind == "enum" ? ScalarType.INT32 : field.T; | ||
if (repeated) { | ||
if (field.packed) { | ||
writePacked(writer, scalarType, field.no, value); | ||
} | ||
else { | ||
for (const item of value) { | ||
writeScalar(writer, scalarType, field.no, item, true); | ||
} | ||
} | ||
} | ||
else if (value !== undefined) { | ||
writeScalar(writer, scalarType, field.no, value, !!field.oneof || field.opt); | ||
} | ||
break; | ||
case "message": | ||
if (repeated) { | ||
for (const item of value) { | ||
writeMessageField(writer, options, field, item); | ||
} | ||
} | ||
else if (value !== undefined) { | ||
writeMessageField(writer, options, field, value); | ||
} | ||
break; | ||
case "map": | ||
for (const [key, val] of Object.entries(value)) { | ||
writeMapEntry(writer, options, field, key, val); | ||
} | ||
break; | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -11,3 +11,3 @@ import { Edition, FeatureSet, FeatureSetDefaults } from "../google/protobuf/descriptor_pb.js"; | ||
/** | ||
* A function that resolves features for the given edition. | ||
* A function that resolves features. | ||
* | ||
@@ -18,6 +18,6 @@ * If no feature set is provided, the default feature set for the edition is | ||
*/ | ||
export type FeatureResolverFn = (edition: Edition, a?: FeatureSet, b?: FeatureSet) => MergedFeatureSet; | ||
export type FeatureResolverFn = (a?: FeatureSet, b?: FeatureSet) => MergedFeatureSet; | ||
/** | ||
* Create an edition feature resolver with the given feature set defaults. | ||
*/ | ||
export declare function createFeatureResolver(compiledFeatureSetDefaults: FeatureSetDefaults): FeatureResolverFn; | ||
export declare function createFeatureResolver(compiledFeatureSetDefaults: FeatureSetDefaults, edition: Edition): FeatureResolverFn; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -24,3 +24,4 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
*/ | ||
export function createFeatureResolver(compiledFeatureSetDefaults) { | ||
export function createFeatureResolver(compiledFeatureSetDefaults, edition) { | ||
var _a, _b; | ||
const min = compiledFeatureSetDefaults.minimumEdition; | ||
@@ -33,33 +34,27 @@ const max = compiledFeatureSetDefaults.maximumEdition; | ||
} | ||
const defaultsBinByEdition = new Map(); | ||
return (edition, ...rest) => { | ||
var _a, _b; | ||
let defaultsBin = defaultsBinByEdition.get(edition); | ||
if (defaultsBin === undefined) { | ||
if (edition < min) { | ||
throw new Error(`Edition ${Edition[edition]} is earlier than the minimum supported edition ${Edition[min]}`); | ||
} | ||
if (max < edition) { | ||
throw new Error(`Edition ${Edition[edition]} is later than the maximum supported edition ${Edition[max]}`); | ||
} | ||
let highestMatch = undefined; | ||
for (const c of compiledFeatureSetDefaults.defaults) { | ||
const e = (_a = c.edition) !== null && _a !== void 0 ? _a : 0; | ||
if (e > edition) { | ||
continue; | ||
} | ||
if (highestMatch !== undefined && highestMatch.e > e) { | ||
continue; | ||
} | ||
highestMatch = { | ||
e, | ||
f: (_b = c.features) !== null && _b !== void 0 ? _b : new FeatureSet(), | ||
}; | ||
} | ||
if (highestMatch === undefined) { | ||
throw new Error(`No valid default found for edition ${Edition[edition]}`); | ||
} | ||
defaultsBin = highestMatch.f.toBinary(); | ||
defaultsBinByEdition.set(edition, defaultsBin); | ||
if (edition < min) { | ||
throw new Error(`Edition ${Edition[edition]} is earlier than the minimum supported edition ${Edition[min]}`); | ||
} | ||
if (max < edition) { | ||
throw new Error(`Edition ${Edition[edition]} is later than the maximum supported edition ${Edition[max]}`); | ||
} | ||
let highestMatch = undefined; | ||
for (const c of compiledFeatureSetDefaults.defaults) { | ||
const e = (_a = c.edition) !== null && _a !== void 0 ? _a : 0; | ||
if (e > edition) { | ||
continue; | ||
} | ||
if (highestMatch !== undefined && highestMatch.e > e) { | ||
continue; | ||
} | ||
highestMatch = { | ||
e, | ||
f: (_b = c.features) !== null && _b !== void 0 ? _b : new FeatureSet(), | ||
}; | ||
} | ||
if (highestMatch === undefined) { | ||
throw new Error(`No valid default found for edition ${Edition[edition]}`); | ||
} | ||
const defaultsBin = highestMatch.f.toBinary(); | ||
return (...rest) => { | ||
const f = FeatureSet.fromBinary(defaultsBin); | ||
@@ -66,0 +61,0 @@ for (const c of rest) { |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
import { Message } from "../message.js"; | ||
import type { MessageType } from "../message-type.js"; | ||
import type { DescField } from "../descriptor-set.js"; | ||
import type { DescExtension, DescField } from "../descriptor-set.js"; | ||
import { ScalarType } from "../field.js"; | ||
@@ -25,2 +25,2 @@ /** | ||
*/ | ||
export declare function getUnwrappedFieldType(field: DescField): ScalarType | undefined; | ||
export declare function getUnwrappedFieldType(field: DescField | DescExtension): ScalarType | undefined; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -19,2 +19,4 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
import { protoBase64 } from "../proto-base64.js"; | ||
import { createExtensionContainer } from "./extensions.js"; | ||
import { getExtension, hasExtension, setExtension, } from "../extension-accessor.js"; | ||
/* 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 */ | ||
@@ -45,160 +47,41 @@ // Default options for parsing JSON. | ||
if (json == null || Array.isArray(json) || typeof json != "object") { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: ${this.debug(json)}`); | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: ${debugJsonValue(json)}`); | ||
} | ||
message = message !== null && message !== void 0 ? message : new type(); | ||
const oneofSeen = {}; | ||
const oneofSeen = new Map(); | ||
const registry = options.typeRegistry; | ||
for (const [jsonKey, jsonValue] of Object.entries(json)) { | ||
const field = type.fields.findJsonName(jsonKey); | ||
if (!field) { | ||
if (!options.ignoreUnknownFields) { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: key "${jsonKey}" is unknown`); | ||
} | ||
continue; | ||
} | ||
let localName = field.localName; | ||
let target = message; | ||
if (field.oneof) { | ||
if (jsonValue === null && field.kind == "scalar") { | ||
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second} | ||
continue; | ||
} | ||
const seen = oneofSeen[field.oneof.localName]; | ||
if (seen) { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: multiple keys for oneof "${field.oneof.name}" present: "${seen}", "${jsonKey}"`); | ||
} | ||
oneofSeen[field.oneof.localName] = jsonKey; | ||
target = target[field.oneof.localName] = { case: localName }; | ||
localName = "value"; | ||
} | ||
if (field.repeated) { | ||
if (jsonValue === null) { | ||
continue; | ||
} | ||
if (!Array.isArray(jsonValue)) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`); | ||
} | ||
const targetArray = target[localName]; | ||
for (const jsonItem of jsonValue) { | ||
if (jsonItem === null) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonItem)}`); | ||
if (field) { | ||
if (field.oneof) { | ||
if (jsonValue === null && field.kind == "scalar") { | ||
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second} | ||
continue; | ||
} | ||
let val; | ||
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "map" is invalid for repeated fields | ||
switch (field.kind) { | ||
case "message": | ||
val = field.T.fromJson(jsonItem, options); | ||
break; | ||
case "enum": | ||
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields); | ||
if (val === undefined) | ||
continue; | ||
break; | ||
case "scalar": | ||
try { | ||
val = readScalar(field.T, jsonItem, field.L); | ||
} | ||
catch (e) { | ||
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonItem)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
const seen = oneofSeen.get(field.oneof); | ||
if (seen !== undefined) { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: multiple keys for oneof "${field.oneof.name}" present: "${seen}", "${jsonKey}"`); | ||
} | ||
targetArray.push(val); | ||
oneofSeen.set(field.oneof, jsonKey); | ||
} | ||
readField(message, jsonValue, field, options, type); | ||
} | ||
else if (field.kind == "map") { | ||
if (jsonValue === null) { | ||
continue; | ||
} | ||
if (Array.isArray(jsonValue) || typeof jsonValue != "object") { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`); | ||
} | ||
const targetMap = target[localName]; | ||
for (const [jsonMapKey, jsonMapValue] of Object.entries(jsonValue)) { | ||
if (jsonMapValue === null) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: map value null`); | ||
else { | ||
let found = false; | ||
if ((registry === null || registry === void 0 ? void 0 : registry.findExtension) && | ||
jsonKey.startsWith("[") && | ||
jsonKey.endsWith("]")) { | ||
const ext = registry.findExtension(jsonKey.substring(1, jsonKey.length - 1)); | ||
if (ext && ext.extendee.typeName == type.typeName) { | ||
found = true; | ||
const [container, get] = createExtensionContainer(ext); | ||
readField(container, jsonValue, ext.field, options, ext); | ||
// We pass on the options as BinaryReadOptions/BinaryWriteOptions, | ||
// so that users can bring their own binary reader and writer factories | ||
// if necessary. | ||
setExtension(message, ext, get(), options); | ||
} | ||
let val; | ||
switch (field.V.kind) { | ||
case "message": | ||
val = field.V.T.fromJson(jsonMapValue, options); | ||
break; | ||
case "enum": | ||
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields); | ||
if (val === undefined) | ||
continue; | ||
break; | ||
case "scalar": | ||
try { | ||
val = readScalar(field.V.T, jsonMapValue, LongType.BIGINT); | ||
} | ||
catch (e) { | ||
let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
} | ||
try { | ||
targetMap[readScalar(field.K, field.K == ScalarType.BOOL | ||
? jsonMapKey == "true" | ||
? true | ||
: jsonMapKey == "false" | ||
? false | ||
: jsonMapKey | ||
: jsonMapKey, LongType.BIGINT).toString()] = val; | ||
} | ||
catch (e) { | ||
let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
} | ||
} | ||
else { | ||
switch (field.kind) { | ||
case "message": | ||
const messageType = field.T; | ||
if (jsonValue === null && | ||
messageType.typeName != "google.protobuf.Value") { | ||
if (field.oneof) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: null is invalid for oneof field "${jsonKey}"`); | ||
} | ||
continue; | ||
} | ||
if (target[localName] instanceof Message) { | ||
target[localName].fromJson(jsonValue, options); | ||
} | ||
else { | ||
target[localName] = messageType.fromJson(jsonValue, options); | ||
if (messageType.fieldWrapper && !field.oneof) { | ||
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]); | ||
} | ||
} | ||
break; | ||
case "enum": | ||
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields); | ||
if (enumValue !== undefined) { | ||
target[localName] = enumValue; | ||
} | ||
break; | ||
case "scalar": | ||
try { | ||
target[localName] = readScalar(field.T, jsonValue, field.L); | ||
} | ||
catch (e) { | ||
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
if (!found && !options.ignoreUnknownFields) { | ||
throw new Error(`cannot decode message ${type.typeName} from JSON: key "${jsonKey}" is unknown`); | ||
} | ||
@@ -236,2 +119,17 @@ } | ||
} | ||
const registry = options.typeRegistry; | ||
if (registry === null || registry === void 0 ? void 0 : registry.findExtensionFor) { | ||
for (const uf of type.runtime.bin.listUnknownFields(message)) { | ||
const ext = registry.findExtensionFor(type.typeName, uf.no); | ||
if (ext && hasExtension(message, ext)) { | ||
// We pass on the options as BinaryReadOptions, so that users can bring their own | ||
// binary reader factory if necessary. | ||
const value = getExtension(message, ext, options); | ||
const jsonValue = writeField(ext.field, value, options); | ||
if (jsonValue !== undefined) { | ||
json[ext.field.jsonName] = jsonValue; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
@@ -265,2 +163,149 @@ catch (e) { | ||
} | ||
// Read a JSON value for a field. | ||
// The "type" argument is only used to provide context in errors. | ||
function readField(target, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access | ||
jsonValue, field, options, type) { | ||
let localName = field.localName; | ||
if (field.oneof) { | ||
if (jsonValue === null && field.kind == "scalar") { | ||
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second} | ||
return; | ||
} | ||
target = target[field.oneof.localName] = { case: localName }; | ||
localName = "value"; | ||
} | ||
if (field.repeated) { | ||
if (jsonValue === null) { | ||
return; | ||
} | ||
if (!Array.isArray(jsonValue)) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`); | ||
} | ||
const targetArray = target[localName]; | ||
for (const jsonItem of jsonValue) { | ||
if (jsonItem === null) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`); | ||
} | ||
let val; | ||
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "map" is invalid for repeated fields | ||
switch (field.kind) { | ||
case "message": | ||
val = field.T.fromJson(jsonItem, options); | ||
break; | ||
case "enum": | ||
val = readEnum(field.T, jsonItem, options.ignoreUnknownFields); | ||
if (val === undefined) | ||
continue; | ||
break; | ||
case "scalar": | ||
try { | ||
val = readScalar(field.T, jsonItem, field.L); | ||
} | ||
catch (e) { | ||
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
} | ||
targetArray.push(val); | ||
} | ||
} | ||
else if (field.kind == "map") { | ||
if (jsonValue === null) { | ||
return; | ||
} | ||
if (typeof jsonValue != "object" || Array.isArray(jsonValue)) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`); | ||
} | ||
const targetMap = target[localName]; | ||
for (const [jsonMapKey, jsonMapValue] of Object.entries(jsonValue)) { | ||
if (jsonMapValue === null) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: map value null`); | ||
} | ||
let val; | ||
switch (field.V.kind) { | ||
case "message": | ||
val = field.V.T.fromJson(jsonMapValue, options); | ||
break; | ||
case "enum": | ||
val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields); | ||
if (val === undefined) | ||
continue; | ||
break; | ||
case "scalar": | ||
try { | ||
val = readScalar(field.V.T, jsonMapValue, LongType.BIGINT); | ||
} | ||
catch (e) { | ||
let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
} | ||
try { | ||
targetMap[readScalar(field.K, field.K == ScalarType.BOOL | ||
? jsonMapKey == "true" | ||
? true | ||
: jsonMapKey == "false" | ||
? false | ||
: jsonMapKey | ||
: jsonMapKey, LongType.BIGINT).toString()] = val; | ||
} | ||
catch (e) { | ||
let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
} | ||
} | ||
else { | ||
switch (field.kind) { | ||
case "message": | ||
const messageType = field.T; | ||
if (jsonValue === null && | ||
messageType.typeName != "google.protobuf.Value") { | ||
if (field.oneof) { | ||
throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: null is invalid for oneof field`); | ||
} | ||
return; | ||
} | ||
if (target[localName] instanceof Message) { | ||
target[localName].fromJson(jsonValue, options); | ||
} | ||
else { | ||
target[localName] = messageType.fromJson(jsonValue, options); | ||
if (messageType.fieldWrapper && !field.oneof) { | ||
target[localName] = messageType.fieldWrapper.unwrapField(target[localName]); | ||
} | ||
} | ||
break; | ||
case "enum": | ||
const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields); | ||
if (enumValue !== undefined) { | ||
target[localName] = enumValue; | ||
} | ||
break; | ||
case "scalar": | ||
try { | ||
target[localName] = readScalar(field.T, jsonValue, field.L); | ||
} | ||
catch (e) { | ||
let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`; | ||
if (e instanceof Error && e.message.length > 0) { | ||
m += `: ${e.message}`; | ||
} | ||
throw new Error(m); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
// May throw an error. If the error message is non-blank, it should be shown. | ||
@@ -277,3 +322,3 @@ // It is up to the caller to provide context. | ||
if (json === null) | ||
return 0.0; | ||
return 0.0; // TODO field presence: this should reset the field with explicit presence | ||
if (json === "NaN") | ||
@@ -315,3 +360,3 @@ return Number.NaN; | ||
if (json === null) | ||
return 0; | ||
return 0; // TODO field presence: this should reset the field with explicit presence | ||
let int32; | ||
@@ -336,3 +381,3 @@ if (typeof json == "number") | ||
if (json === null) | ||
return protoInt64.zero; | ||
return protoInt64.zero; // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json != "number" && typeof json != "string") | ||
@@ -346,3 +391,3 @@ break; | ||
if (json === null) | ||
return protoInt64.zero; | ||
return protoInt64.zero; // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json != "number" && typeof json != "string") | ||
@@ -356,3 +401,3 @@ break; | ||
if (json === null) | ||
return false; | ||
return false; // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json !== "boolean") | ||
@@ -364,3 +409,3 @@ break; | ||
if (json === null) | ||
return ""; | ||
return ""; // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json !== "string") { | ||
@@ -382,3 +427,3 @@ break; | ||
if (json === null || json === "") | ||
return new Uint8Array(0); | ||
return new Uint8Array(0); // TODO field presence: this should reset the field with explicit presence | ||
if (typeof json !== "string") | ||
@@ -393,2 +438,3 @@ break; | ||
// proto3 requires 0 to be default value for all enums | ||
// TODO field presence: this should reset the field with explicit presence | ||
return 0; | ||
@@ -395,0 +441,0 @@ } |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -19,2 +19,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
export function makeJsonFormatProto2() { | ||
// TODO field presence: merge this function with proto2 | ||
return makeJsonFormatCommon((writeEnum, writeScalar) => { | ||
@@ -21,0 +22,0 @@ return function writeField(field, value, options) { |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -19,2 +19,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
export function makeJsonFormatProto3() { | ||
// TODO field presence: merge this function with proto2 | ||
return makeJsonFormatCommon((writeEnum, writeScalar) => { | ||
@@ -67,3 +68,3 @@ return function writeField(field, value, options) { | ||
for (let i = 0; i < value.length; i++) { | ||
jsonArr.push(wrapField(field.T, value[i]).toJson(options)); | ||
jsonArr.push(value[i].toJson(options)); | ||
} | ||
@@ -77,2 +78,5 @@ break; | ||
else { | ||
if (value === undefined) { | ||
return undefined; | ||
} | ||
switch (field.kind) { | ||
@@ -84,5 +88,3 @@ case "scalar": | ||
case "message": | ||
return value !== undefined | ||
? wrapField(field.T, value).toJson(options) | ||
: undefined; | ||
return wrapField(field.T, value).toJson(options); | ||
} | ||
@@ -89,0 +91,0 @@ } |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
import type { DescEnum, DescEnumValue, DescField, DescMessage, DescService } from "../descriptor-set.js"; | ||
import type { DescEnum, DescEnumValue, DescExtension, DescField, DescMessage, DescService } from "../descriptor-set.js"; | ||
import type { DescMethod, DescOneof } from "../descriptor-set.js"; | ||
@@ -11,3 +11,3 @@ /** | ||
*/ | ||
export declare function localName(desc: DescEnum | DescEnumValue | DescMessage | DescOneof | DescField | DescService | DescMethod): string; | ||
export declare function localName(desc: DescEnum | DescEnumValue | DescMessage | DescExtension | DescOneof | DescField | DescService | DescMethod): string; | ||
/** | ||
@@ -14,0 +14,0 @@ * Returns the name of a field in generated code. |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -30,3 +30,4 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
case "message": | ||
case "service": { | ||
case "service": | ||
case "extension": { | ||
const pkg = desc.file.proto.package; | ||
@@ -33,0 +34,0 @@ const offset = pkg === undefined ? 0 : pkg.length + 1; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -10,2 +10,4 @@ import type { JsonFormat } from "../json-format.js"; | ||
import type { Util } from "./util.js"; | ||
import type { Extension } from "../extension.js"; | ||
import type { ExtensionFieldSource } from "./extensions.js"; | ||
/** | ||
@@ -47,3 +49,7 @@ * A facade that provides serialization and other internal functionality. | ||
getEnumType(enumObject: EnumObject): EnumType; | ||
/** | ||
* Create an extension at runtime, without generating code. | ||
*/ | ||
makeExtension<E extends Message<E> = AnyMessage, V = unknown>(typeName: string, extendee: MessageType<E>, field: ExtensionFieldSource): Extension<E, V>; | ||
} | ||
export declare function makeProtoRuntime(syntax: string, json: JsonFormat, bin: BinaryFormat, util: Util): ProtoRuntime; |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -16,2 +16,3 @@ // Licensed under the Apache License, Version 2.0 (the "License"); | ||
import { makeMessageType } from "./message-type.js"; | ||
import { makeExtension } from "./extensions.js"; | ||
export function makeProtoRuntime(syntax, json, bin, util) { | ||
@@ -29,3 +30,6 @@ return { | ||
getEnumType, | ||
makeExtension(typeName, extendee, field) { | ||
return makeExtension(this, typeName, extendee, field); | ||
}, | ||
}; | ||
} |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
import type { MessageType } from "./message-type.js"; | ||
import type { EnumType } from "./enum.js"; | ||
import type { ServiceType } from "./service-type.js"; | ||
import type { Extension } from "./extension.js"; | ||
/** | ||
@@ -44,1 +45,14 @@ * IMessageTypeRegistry provides look-up for message types. | ||
} | ||
/** | ||
* IExtensionRegistry provides look-up for extensions. | ||
*/ | ||
export interface IExtensionRegistry { | ||
/** | ||
* Find an extension by the extendee type name and the extension number. | ||
*/ | ||
findExtensionFor(extendee: string, no: number): Extension | undefined; | ||
/** | ||
* Find an extension type by its protobuf type name. | ||
*/ | ||
findExtension(typeName: string): Extension | undefined; | ||
} |
@@ -1,2 +0,2 @@ | ||
// Copyright 2021-2023 Buf Technologies, Inc. | ||
// Copyright 2021-2024 Buf Technologies, Inc. | ||
// | ||
@@ -3,0 +3,0 @@ // Licensed under the Apache License, Version 2.0 (the "License"); |
{ | ||
"name": "@bufbuild/protobuf", | ||
"version": "1.6.0", | ||
"version": "1.7.0", | ||
"license": "(Apache-2.0 AND BSD-3-Clause)", | ||
@@ -5,0 +5,0 @@ "description": "A complete implementation of Protocol Buffers in TypeScript, suitable for web browsers and Node.js.", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
1448265
2.56%245
5.15%36723
2.55%