Add existing to tracked

This commit is contained in:
Jay
2026-08-11 09:53:42 -04:00
parent afe07f3055
commit ffd6e3d73c
8531 changed files with 4396230 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
This license applies to all parts of protobuf.js except those files
either explicitly including or referencing a different license or
located in a directory containing a different LICENSE file.
---
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
Code generated by the command line utilities is owned by the owner
of the input file used when generating it. This code is not
standalone and requires a support library to be linked with it. This
support library is itself covered by the above license.
+440
View File
@@ -0,0 +1,440 @@
<h1><p align="center"><img alt="protobuf.js" src="https://github.com/protobufjs/protobuf.js/raw/master/pbjs.svg" height="100" /><br/>protobuf.js</p></h1>
<p align="center">
<a href="https://github.com/protobufjs/protobuf.js/actions/workflows/test.yml"><img src="https://img.shields.io/github/actions/workflow/status/protobufjs/protobuf.js/test.yml?branch=master&label=build&logo=github" alt=""></a>
<a href="https://github.com/protobufjs/protobuf.js/actions/workflows/release.yaml"><img src="https://img.shields.io/github/actions/workflow/status/protobufjs/protobuf.js/release.yaml?branch=master&label=release&logo=github" alt=""></a>
<a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/v/protobufjs.svg?logo=npm" alt=""></a>
<a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/dm/protobufjs.svg?label=downloads&logo=npm" alt=""></a>
<a href="https://www.jsdelivr.com/package/npm/protobufjs"><img src="https://img.shields.io/jsdelivr/npm/hm/protobufjs?label=requests&logo=jsdelivr" alt=""></a>
</p>
**Protocol Buffers** are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more, originally designed at Google ([see](https://protobuf.dev/)).
**protobuf.js** is a very fast, conformant, and unusually versatile JavaScript implementation of Protocol Buffers for Node.js and browsers. It works with `.proto` files out of the box, does not require protoc, and supports runtime reflection as well as specialized code generation with strong TypeScript declarations.
If protobuf.js is important to your project or organization, or if you depend on it commercially, [consider supporting](https://github.com/sponsors/dcodeIO) its ongoing maintenance. Sponsorship helps make bug fixes, releases, LTS/security handling, and user support more sustainable.
## Getting started
Getting up and running is simple: Install the package, load a `.proto` file, and you are all set to encode and decode Protobuf messages. From there, protobuf.js grows with your requirements: Add any combination of capabilities, such as [code generation](#code-generation), [TypeScript declarations](#typescript-integration), [transport-agnostic services](#services), [programmatic schemas](#programmatic-schemas), [optional extensions](#extensions), and more as needed. All in one flexible toolkit.
### Install
```sh
npm install protobufjs
```
The [command line utility](./cli/#readme) for generating reflection bundles, static code and TypeScript declarations is published as an add-on package:
```sh
npm install --save-dev protobufjs-cli
```
The CLI is a JS-native protobuf.js toolchain that does not require setting up `protoc`. If you prefer a `protoc`-based workflow, it provides `protoc-gen-pbjs` as an option.
#### Browser builds
Canonical browser builds for each runtime variant are [provided via the jsDelivr CDN](https://cdn.jsdelivr.net/npm/protobufjs@8.X.X/dist/), supporting CommonJS, AMD and global `window.protobuf`. Make sure to pin an exact version in production.
## Usage
The examples below use this schema:
```proto
syntax = "proto3";
package awesomepackage;
message AwesomeMessage {
string awesome_field = 1;
}
```
protobuf.js converts `.proto` field names to camelCase by default, so `awesome_field` is used as `awesomeField` in JavaScript. Use the `keepCase` option when loading or parsing `.proto` files to preserve field names as written.
### Load a schema
```ts
const protobuf = require("protobufjs");
const root = await protobuf.load("awesome.proto");
const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");
```
Optionally use `load()` with a callback, or `loadSync()` for synchronous loading on Node.js. Imports resolve relative to the importing file by default. To resolve imports against a specific base directory, create a `Root` and override `root.resolvePath` before calling `root.load()`.
### Encode and decode
```ts
const payload = { awesomeField: "hello" };
// Optionally create a message instance from already valid data
const message = AwesomeMessage.create(payload);
const encoded = AwesomeMessage.encode(message).finish();
const decoded = AwesomeMessage.decode(encoded);
```
`encode` expects a message instance or equivalent plain object and does not verify input implicitly. Use `create` to create a message instance from already valid data when useful, `verify` for plain objects whose shape is not guaranteed, and `fromObject` when conversion from broader JavaScript objects is needed.
Plain objects can be encoded directly when they already use protobuf.js runtime types: numbers for 32-bit numeric fields, booleans for `bool`, strings for `string`, `Uint8Array` or `Buffer` for `bytes`, arrays for repeated fields, and plain objects for maps. Map keys are the string representation of the respective value or an 8-character hash string for 64-bit keys.
Unknown fields present on the wire are discarded by default. To preserve and forward unknown fields, set `reader.discardUnknown = false` before decoding with that reader, or make this the default for subsequently created readers with `Reader.discardUnknown = false`. Preserved unknown field data can be dropped from a decoded message with `delete message.$unknowns`.
### Convert plain objects
Conversion is an explicit interoperability boundary. `fromObject` accepts common JavaScript inputs such as enum values by name, base64 bytes, decimal 64-bit strings, `Long`, and `BigInt`; `toObject` lets callers choose the output expected by their application or transport.
```ts
const message = AwesomeMessage.fromObject({ awesomeField: 42 });
const object = AwesomeMessage.toObject(message, {
longs: String,
enums: String,
bytes: String
});
```
Common `ConversionOptions` are:
| Option | Effect |
|--------|--------|
| `longs: BigInt` | Converts 64-bit values to bigint values |
| `longs: String` | Converts 64-bit values to decimal strings |
| `longs: Number` | Converts 64-bit values to JS numbers (may lose precision) |
| `enums: String` | Converts enum values to names |
| `bytes: String` | Converts bytes to base64 strings |
| `defaults: true` | Includes default values for unset fields |
| `arrays: true` | Includes empty arrays for repeated fields |
| `objects: true` | Includes empty objects for map fields |
| `oneofs: true` | Includes virtual oneof discriminator properties |
## Message API
Message types expose focused methods for validation, conversion, and binary I/O.
* **encode**(message: `Message | object`, writer?: `Writer`): `Writer`
Encodes a message or equivalent plain object. Call `.finish()` on the returned writer to obtain a buffer.
* **encodeDelimited**(message: `Message | object`, writer?: `Writer`): `Writer`
Encodes a length-delimited message.
* **decode**(reader: `Reader | Uint8Array`): `Message`
Decodes a message from protobuf binary data.
* **decodeDelimited**(reader: `Reader | Uint8Array`): `Message`
Decodes a length-delimited message.
* **create**(properties?: `object`): `Message`
Creates a message instance from already valid data.
* **verify**(object: `object`): `null | string`
Checks whether a plain object can be encoded as-is. Returns `null` if valid, otherwise an error message.
* **fromObject**(object: `object`): `Message`
Converts broader JavaScript input into a message instance.
* **toObject**(message: `Message`, options?: `ConversionOptions`): `object`
Converts a message instance to a configurable plain JavaScript object.
* **message.toJSON**(): `object`
Converts a message instance to JSON-compatible output using default conversion options.
Message instances provide runtime identity, so they can be tested with `instanceof`. Their `toJSON` method integrates them with `JSON.stringify`.
Length-delimited methods read and write a varint byte length before the message, which is useful for streams and framed protocols.
If required fields are missing while decoding proto2 data, `decode` throws `protobuf.util.ProtocolError` with the partially decoded message available as `err.instance`.
## Runtimes
protobuf.js provides three runtime entry points, keeping parser and reflection support optional: Runtime `.proto` loading needs the parser, JSON/reflection bundles need reflection support, and generated static modules only need the minimal runtime.
| Import | Includes | Use when
| ----------------------- | ------------------ | --------
| `protobufjs` | Reflection, Parser | You load `.proto` files at runtime
| `protobufjs/light.js` | Reflection | You load JSON bundles or build schemas programmatically
| `protobufjs/minimal.js` | Static runtime | You use generated static code
The full build includes the light build, and the light build includes the minimal runtime.
## Code generation
Use [`protobufjs-cli`](./cli/#readme) to generate reflection bundles, static JavaScript code, and matching TypeScript declarations, either directly with `pbjs` or through the optional `protoc-gen-pbjs` plugin for `protoc`.
Reflection keeps schemas as JSON metadata and generates optimized functions at runtime. Static code emits schema-specific, reflection-free functions ahead of time. The main tradeoffs are how schemas are loaded, how bundle size scales with schema size, and whether reflection metadata should remain available at runtime.
| Target | Output | Minimum Runtime |
|--------|--------|-----------------|
| `json` | JSON bundle | `protobufjs/light.js` |
| `json-module` | JSON bundle module | `protobufjs/light.js` |
| `static-module` | Static code module | `protobufjs/minimal.js` |
Module targets support `--wrap default` for CommonJS and AMD, plus `esm`, `commonjs`, `amd`, and `closure`; `--wrap` can also load a custom wrapper module.
### Static modules
Static modules emit dedicated JavaScript for your schema, so they only need `protobufjs/minimal.js` at runtime.
```sh
npx pbjs -t static-module -w esm -o awesome.js --dts awesome.proto
```
```ts
import { awesomepackage } from "./awesome.js";
const message = awesomepackage.AwesomeMessage.create({ awesomeField: "hello" });
```
While static code is verbose by design, its repeated patterns compress well with Brotli or gzip, and it works in [CSP](https://w3c.github.io/webappsec-csp/)-restricted environments that disallow unsafe-eval without sacrificing performance.
### Reflection bundles
Reflection bundles store schemas as compact JSON metadata, avoiding `.proto` parsing at runtime and letting browsers load schema metadata in one request. While they require at least `protobufjs/light.js`, large schemas can produce smaller combined bundles than equivalent static modules because common code is shared through reflection.
```sh
npx pbjs -t json -o awesome.json awesome1.proto awesome2.proto ...
```
```ts
const bundle = require("./awesome.json");
const root = protobuf.Root.fromJSON(bundle);
const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");
```
```sh
npx pbjs -t json-module -w esm -o awesome.js --dts awesome.proto
```
```ts
import { awesomepackage } from "./awesome.js";
const AwesomeMessage = awesomepackage.AwesomeMessage;
```
JSON modules export the reflection root and, with `-w esm`, also provide top-level named exports that align with static modules. Their declarations mirror `static-module` typings, but because JSON modules are backed by reflection objects, message instances should be created with `MyMessage.create(...)` instead of constructors. Code using `create(...)` works with static modules as well.
### TypeScript integration
protobuf.js works with TypeScript out of the box: the runtime API is typed, and generated JavaScript can be paired with strong TypeScript declarations in the same CLI invocation. Generated output is directly usable from JavaScript without a transpile step, and strongly typed in TypeScript projects, with type-checked oneofs and JavaScript-friendly plain-object input.
For example, given the oneof:
```proto
message Profile {
oneof contact {
string email = 1;
string phone = 2;
}
}
```
Generated declarations narrow both the `contact` oneof and the concrete values:
```ts
const profile = Profile.create({
contact: "email",
email: "hello@example.com"
});
if (profile.contact === "email") {
profile.email; // string
}
const decoded = Profile.decode(bytes);
if (decoded.contact === "phone") {
decoded.phone; // string
}
```
Plain objects can use the same narrowed shape through a collision-free scoped type:
```ts
const object: Profile.$Shape = {
contact: "email",
email: "hello@example.com"
};
```
## Advanced usage
### Programmatic schemas
The full and light builds can construct schemas directly through reflection:
```ts
const AwesomeMessage = new protobuf.Type("AwesomeMessage")
.add(new protobuf.Field("awesomeField", 1, "string"));
const root = new protobuf.Root()
.define("awesomepackage")
.add(AwesomeMessage);
```
### Custom message classes
A reflected type can use a custom class as its runtime constructor:
```ts
class AwesomeMessage extends protobuf.Message<AwesomeMessage> {
awesomeField = "";
constructor(properties?: protobuf.Properties<AwesomeMessage>) {
super(properties);
// ...
}
customInstanceMethod() {
return this.awesomeField.toLowerCase();
}
}
root.lookupType("awesomepackage.AwesomeMessage").ctor = AwesomeMessage;
const decoded = AwesomeMessage.decode(bytes);
decoded.customInstanceMethod(); // string
```
protobuf.js will populate the constructor with the usual static runtime methods and use it for decoded messages. When assigning constructors manually, add the type to its parent namespace/root first if fields reference other reflected types. In TypeScript, custom members are visible when using the custom class type in consuming code.
### Services
protobuf.js supports service clients built from service definitions. The service API is transport-agnostic: provide an `rpcImpl` function to connect it to HTTP, WebSocket, gRPC, or another transport.
```js
function myRpcImpl(method, requestData, callback) {
// method.name
// method.path
// method.requestStream?
// method.responseStream?
performRequest(requestData, function(err, responseData) {
callback(err, responseData);
});
}
const myService = MyService.create(myRpcImpl/*, requestDelimited?, responseDelimited? */);
```
See [examples/streaming-rpc.js](./examples/streaming-rpc.js) for a streaming example.
Integration example with [@grpc/grpc-js](https://www.npmjs.com/package/@grpc/grpc-js):
```js
const grpc = require('@grpc/grpc-js');
const Client = grpc.makeGenericClientConstructor({});
const client = new Client(serverAddress, grpc.credentials.createInsecure());
const rpcImpl = (method, requestData, callback) =>
client.makeUnaryRequest(method.path, (data) => data, (data) => data, requestData, callback);
const greeter = root.lookupService("example.Greeter").create(rpcImpl);
const reply = await greeter.sayHello({ name: "world" });
```
See [examples/grpc-service.js](./examples/grpc-service.js) for a complete example.
### Extensions
The following extensions provide descriptor conversion and text-based protobuf formats when reflection metadata is available. Most applications only need the binary APIs above.
#### Descriptors
protobuf.js uses a compact JSON-based reflection representation internally that is easy to embed and fast to parse, so schemas can be loaded directly without first decoding binary descriptor blobs or postprocessing their full JSON representation. See [ext/descriptor](./ext/README.md#descriptor) for use cases that need conversion between reflected roots and `protoc` descriptor messages.
#### ProtoJSON
Protocol Buffers support a special [ProtoJSON format](https://protobuf.dev/programming-guides/json/) to share data with systems that do not support the binary wire format, for example when implementing gateways. Spec-compliant ProtoJSON is supported via [ext/protojson](./ext/README.md#protojson).
#### Text Format
Protocol Buffers [Text Format](https://protobuf.dev/reference/protobuf/textformat-spec/) is a special syntax for representing protobuf data in text form, which can be useful for configurations or tests. Spec-compliant Text Format is supported via [ext/textformat](./ext/README.md#textformat).
## Conformance
protobuf.js is validated against the official Protocol Buffers conformance suite, achieving complete binary wire-format conformance for **Proto2**, **Proto3** and **Editions**, plus complete **ProtoJSON** and **Text Format** conformance in its default configuration with reflection metadata present.
<!-- BEGIN CONFORMANCE DATA -->
| Category | Total | Required | Recommended |
| ---------- | ------------------: | ------------------: | ------------------: |
| Binary | 100.00% (2835/2835) | 100.00% (1958/1958) | 100.00% (877/877) |
| ↳ Proto2 | 100.00% (707/707) | 100.00% (489/489) | 100.00% (218/218) |
| ↳ Proto3 | 100.00% (707/707) | 100.00% (486/486) | 100.00% (221/221) |
| ↳ Editions | 100.00% (1421/1421) | 100.00% (983/983) | 100.00% (438/438) |
| ProtoJSON | 100.00% (2796/2796) | 100.00% (2362/2362) | 100.00% (434/434) |
| TextFormat | 100.00% (909/909) | 100.00% (845/845) | 100.00% (64/64) |
| Overall | 100.00% (6540/6540) | 100.00% (5165/5165) | 100.00% (1375/1375) |
<!-- END CONFORMANCE DATA -->
[Structured results](https://github.com/protobufjs/protobuf.js/actions/workflows/test.yml?query=branch%3Amaster+event%3Apush) are available as CI artifacts. In case of contradicting claims by your favorite LLM, [see](https://dev.to/dcode/when-the-model-is-the-marketing-device-a-protobuf-short-story-2p7p).
## Performance
In both reflection and reflection-free modes, protobuf.js builds specialized encoders and decoders on top of hand-tuned reader and writer primitives, making it a strong fit from battery-powered devices to high-traffic servers, or generally for projects and their downstream users adopting protobuf as a faster, smaller alternative to JSON.
The repository includes a [small benchmark](./bench) over a common message shape, plus Mapbox's vector tile fixture and Buf's perf payload, both unmodified. For each case, it compares protobuf.js encode and decode throughput against JSON encode/decode, Google's protoc-gen-js, and Buf's protoc-gen-es. Results show that protobuf.js is consistently faster than the other Protobuf implementations, up to an order of magnitude on real-world data, and among the libraries tested, it is the only one that is an upgrade over using JSON.
<!-- BEGIN BENCHMARK DATA -->
![Encode benchmark](./bench/results/encode.svg)
| Case | protobuf.js static | protobuf.js reflect | JSON | protoc-gen-js | protoc-gen-es |
| --- | ---: | ---: | ---: | ---: | ---: |
| Common | 3.18M ops/s | 3.25M ops/s | 2.07M ops/s | 1.01M ops/s | 395K ops/s |
| Vector tile | 2.82K ops/s | 2.76K ops/s | 859 ops/s | 680 ops/s | 231 ops/s |
| Buf perf | 41.4K ops/s | 39.9K ops/s | 6.59K ops/s | 13.5K ops/s | 8.00K ops/s |
![Decode benchmark](./bench/results/decode.svg)
| Case | protobuf.js static | protobuf.js reflect | JSON | protoc-gen-js | protoc-gen-es |
| --- | ---: | ---: | ---: | ---: | ---: |
| Common | 6.11M ops/s | 6.09M ops/s | 1.31M ops/s | 790K ops/s | 710K ops/s |
| Vector tile | 2.45K ops/s | 2.78K ops/s | 1.04K ops/s | 858 ops/s | 392 ops/s |
| Buf perf | 72.5K ops/s | 66.4K ops/s | 19.0K ops/s | 21.1K ops/s | 14.2K ops/s |
<!-- END BENCHMARK DATA -->
[Structured results](./bench/results/latest.json) of this run are available as committed artifacts.
To run the benchmark yourself on your own hardware:
```sh
npm --prefix bench install
npm run bench
```
## Compatibility
Supported runtimes are browsers, Node.js v12+, Deno and Bun. When using the CLI with Bun, Node.js must also be installed.
## Security
Security-impacting reports are handled through coordinated GitHub Security Advisories where appropriate. See [SECURITY.md](./SECURITY.md) for supported release lines and reporting instructions.
## Development
```sh
git clone https://github.com/protobufjs/protobuf.js
cd protobuf.js
npm install
npm --prefix cli install
```
Running the tests:
```sh
npm test
```
Building the development and production versions with their respective source maps to `dist/`:
```sh
npm run build
```
## Additional documentation
* [API Documentation](https://protobufjs.github.io/protobuf.js)
* [Changelog](./CHANGELOG.md)
* [Protocol Buffers Documentation](https://protobuf.dev/)
+9276
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3556
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+11233
View File
File diff suppressed because it is too large Load Diff
+1
View File
File diff suppressed because one or more lines are too long
+8
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+70
View File
@@ -0,0 +1,70 @@
# protobuf.js Extensions
## descriptor
Optional `descriptor.proto` support for converting reflected protobuf.js roots and objects to and from descriptor messages.
```js
import protobuf from "protobufjs";
import descriptor from "protobufjs/ext/descriptor.js";
// Convert an existing root to a FileDescriptorSet message.
const root = ...;
const set = root.toDescriptor("proto2");
// Encode descriptor buffers.
const buffer = descriptor.FileDescriptorSet.encode(set).finish();
// Convert a FileDescriptorSet message or buffer back to a root.
const decodedRoot = protobuf.Root.fromDescriptor(buffer);
```
The extension requires reflection metadata and also works with `protobufjs/light.js` when schemas are loaded from JSON or otherwise provided as reflection objects.
Importing the extension adds `.fromDescriptor(descriptor[, editionOrContext])` and `#toDescriptor([syntaxOrEdition])` methods to reflection objects and exports the bundled descriptor types from `google.protobuf`. Descriptor inputs can be decoded messages, readers, or buffers of the corresponding descriptor messages. Direct object descriptor imports accept either an edition string or a descriptor context with `edition`, `features` and `keepCase`.
The conversion covers descriptor messages that correspond to protobuf.js reflection objects: files and file sets, messages, fields and map fields, oneofs, enums, services and methods. Descriptor-only metadata such as source locations, generated-code annotations and uninterpreted options remains available through the exported descriptor message types, but is not mapped onto reflection objects. File names are inferred when generating descriptors because roots do not retain exact file/package boundaries.
## protojson
Optional ProtoJSON support for reflected message types.
> [!NOTE]
> Specialized code generation for the `pbjs` static-module target is a potential future extension. If you need this for high-throughput JSON transcoding or REST fallbacks in production, consider getting in touch and supporting the codegen and conformance work.
```js
import protobuf from "protobufjs";
import protojson from "protobufjs/ext/protojson.js";
const root = ...;
const MyType = root.lookupType("MyType");
const message = protojson.fromJson(MyType, { value: 1 });
const json = protojson.toJson(MyType, message);
```
```js
const messageFromString = protojson.fromJsonString(MyType, '{"value":1}');
const jsonString = protojson.toJsonString(MyType, messageFromString);
```
Importing the extension has no prototype side effects. Calling `protojson.install()` installs `fromJson`, `fromJsonString`, `toJson` and `toJsonString` convenience methods on `protobuf.Type.prototype`. It works with `protobufjs/light.js` when schemas are loaded from JSON or otherwise provided as reflection objects.
Unknown fields can be ignored while parsing by passing `{ ignoreUnknownFields: true }` to `fromJson` or `fromJsonString`.
## textformat
Optional Text Format support for reflected message types.
```js
import protobuf from "protobufjs";
import textformat from "protobufjs/ext/textformat.js";
const root = ...;
const MyType = root.lookupType("MyType");
const message = textformat.fromText(MyType, "value: 1");
const text = textformat.toText(MyType, message);
```
Importing the extension has no prototype side effects. Calling `textformat.install()` installs `fromText` and `toText` convenience methods on `protobuf.Type.prototype`. It works with `protobufjs/light.js` when schemas are loaded from JSON or otherwise provided as reflection objects.
Unknown fields can be printed with numeric field names by passing `{ unknowns: true }` to `toText`.
+4
View File
@@ -0,0 +1,4 @@
protobufjs/ext/debug
=========================
Experimental debugging extension.
+71
View File
@@ -0,0 +1,71 @@
"use strict";
var protobuf = require("../..");
/**
* Debugging utility functions. Only present in debug builds.
* @namespace
*/
var debug = protobuf.debug = module.exports = {};
var codegen = protobuf.util.codegen;
var debugFnRe = /function ([^(]+)\(([^)]*)\) {/g;
// Counts number of calls to any generated function
function codegen_debug() {
codegen_debug.supported = codegen.supported;
codegen_debug.verbose = codegen.verbose;
var gen = codegen.apply(null, Array.prototype.slice.call(arguments));
gen.str = (function(str) { return function str_debug() {
return str.apply(null, Array.prototype.slice.call(arguments)).replace(debugFnRe, "function $1($2) {\n\t$1.calls=($1.calls|0)+1");
};})(gen.str);
return gen;
}
/**
* Returns a list of unused types within the specified root.
* @param {NamespaceBase} ns Namespace to search
* @returns {Type[]} Unused types
*/
debug.unusedTypes = function unusedTypes(ns) {
/* istanbul ignore if */
if (!(ns instanceof protobuf.Namespace))
throw TypeError("ns must be a Namespace");
/* istanbul ignore if */
if (!ns.nested)
return [];
var unused = [];
for (var names = Object.keys(ns.nested), i = 0; i < names.length; ++i) {
var nested = ns.nested[names[i]];
if (nested instanceof protobuf.Type) {
var calls = (nested.encode.calls|0)
+ (nested.decode.calls|0)
+ (nested.verify.calls|0)
+ (nested.toObject.calls|0)
+ (nested.fromObject.calls|0);
if (!calls)
unused.push(nested);
} else if (nested instanceof protobuf.Namespace)
Array.prototype.push.apply(unused, unusedTypes(nested));
}
return unused;
};
/**
* Enables debugging extensions.
* @returns {undefined}
*/
debug.enable = function enable() {
protobuf.util.codegen = codegen_debug;
};
/**
* Disables debugging extensions.
* @returns {undefined}
*/
debug.disable = function disable() {
protobuf.util.codegen = codegen;
};
+87
View File
@@ -0,0 +1,87 @@
import * as $protobuf from "..";
import {
IDescriptorProto,
IDescriptorContext,
IEnumDescriptorProto,
IFieldDescriptorProto,
IFileDescriptorSet,
IMethodDescriptorProto,
IOneofDescriptorProto,
IServiceDescriptorProto
} from "./descriptor.generated";
export * from "./descriptor.generated";
type DescriptorInput<T> = T | $protobuf.Reader | Uint8Array;
declare module ".." {
namespace Root {
/** Creates a root from a descriptor set. */
function fromDescriptor(descriptor: DescriptorInput<IFileDescriptorSet>, options?: { keepCase?: boolean }): $protobuf.Root;
}
interface Root {
/** Converts this root to a descriptor set. */
toDescriptor(edition?: string): $protobuf.Message<IFileDescriptorSet> & IFileDescriptorSet;
}
namespace Type {
/** Creates a type from a descriptor. */
function fromDescriptor(descriptor: DescriptorInput<IDescriptorProto>, editionOrContext?: string | IDescriptorContext): $protobuf.Type;
}
interface Type {
/** Converts this type to a descriptor. */
toDescriptor(edition?: string): $protobuf.Message<IDescriptorProto> & IDescriptorProto;
}
namespace Field {
/** Creates a field from a descriptor. */
function fromDescriptor(descriptor: DescriptorInput<IFieldDescriptorProto>, editionOrContext?: string | IDescriptorContext): $protobuf.Field;
}
interface Field {
/** Converts this field to a descriptor. */
toDescriptor(edition?: string): $protobuf.Message<IFieldDescriptorProto> & IFieldDescriptorProto;
}
namespace Enum {
/** Creates an enum from a descriptor. */
function fromDescriptor(descriptor: DescriptorInput<IEnumDescriptorProto>, editionOrContext?: string | IDescriptorContext): $protobuf.Enum;
}
interface Enum {
/** Converts this enum to a descriptor. */
toDescriptor(): $protobuf.Message<IEnumDescriptorProto> & IEnumDescriptorProto;
}
namespace OneOf {
/** Creates a oneof from a descriptor. */
function fromDescriptor(descriptor: DescriptorInput<IOneofDescriptorProto>, editionOrContext?: string | IDescriptorContext): $protobuf.OneOf;
}
interface OneOf {
/** Converts this oneof to a descriptor. */
toDescriptor(): $protobuf.Message<IOneofDescriptorProto> & IOneofDescriptorProto;
}
namespace Service {
/** Creates a service from a descriptor. */
function fromDescriptor(descriptor: DescriptorInput<IServiceDescriptorProto>, editionOrContext?: string | IDescriptorContext): $protobuf.Service;
}
interface Service {
/** Converts this service to a descriptor. */
toDescriptor(): $protobuf.Message<IServiceDescriptorProto> & IServiceDescriptorProto;
}
namespace Method {
/** Creates a method from a descriptor. */
function fromDescriptor(descriptor: DescriptorInput<IMethodDescriptorProto>, editionOrContext?: string | IDescriptorContext): $protobuf.Method;
}
interface Method {
/** Converts this method to a descriptor. */
toDescriptor(): $protobuf.Message<IMethodDescriptorProto> & IMethodDescriptorProto;
}
}
+417
View File
@@ -0,0 +1,417 @@
// DO NOT EDIT! This is a generated file. Edit the source file instead and regenerate.
import * as $protobuf from "..";
/** Reflected file descriptor set. */
export const FileDescriptorSet: $protobuf.Type;
/** Reflected file descriptor proto. */
export const FileDescriptorProto: $protobuf.Type;
/** Reflected descriptor proto. */
export const DescriptorProto: $protobuf.Type & {
ExtensionRange: $protobuf.Type,
ReservedRange: $protobuf.Type
};
/** Reflected field descriptor proto. */
export const FieldDescriptorProto: $protobuf.Type & {
Label: $protobuf.Enum,
Type: $protobuf.Enum
};
/** Reflected oneof descriptor proto. */
export const OneofDescriptorProto: $protobuf.Type;
/** Reflected enum descriptor proto. */
export const EnumDescriptorProto: $protobuf.Type;
/** Reflected service descriptor proto. */
export const ServiceDescriptorProto: $protobuf.Type;
/** Reflected enum value descriptor proto. */
export const EnumValueDescriptorProto: $protobuf.Type;
/** Reflected method descriptor proto. */
export const MethodDescriptorProto: $protobuf.Type;
/** Reflected file options. */
export const FileOptions: $protobuf.Type & {
OptimizeMode: $protobuf.Enum
};
/** Reflected message options. */
export const MessageOptions: $protobuf.Type;
/** Reflected field options. */
export const FieldOptions: $protobuf.Type & {
CType: $protobuf.Enum,
JSType: $protobuf.Enum
};
/** Reflected oneof options. */
export const OneofOptions: $protobuf.Type;
/** Reflected enum options. */
export const EnumOptions: $protobuf.Type;
/** Reflected enum value options. */
export const EnumValueOptions: $protobuf.Type;
/** Reflected service options. */
export const ServiceOptions: $protobuf.Type;
/** Reflected method options. */
export const MethodOptions: $protobuf.Type;
/** Reflected feature set. */
export const FeatureSet: $protobuf.Type & {
FieldPresence: $protobuf.Enum,
EnumType: $protobuf.Enum,
RepeatedFieldEncoding: $protobuf.Enum,
Utf8Validation: $protobuf.Enum,
MessageEncoding: $protobuf.Enum,
JsonFormat: $protobuf.Enum,
EnforceNamingStyle: $protobuf.Enum,
VisibilityFeature: $protobuf.Type
};
/** Reflected feature set defaults. */
export const FeatureSetDefaults: $protobuf.Type & {
FeatureSetEditionDefault: $protobuf.Type
};
/** Reflected uninterpretet option. */
export const UninterpretedOption: $protobuf.Type & {
NamePart: $protobuf.Type
};
/** Reflected source code info. */
export const SourceCodeInfo: $protobuf.Type & {
Location: $protobuf.Type
};
/** Reflected generated code info. */
export const GeneratedCodeInfo: $protobuf.Type & {
Annotation: $protobuf.Type
};
/** Properties of a FileDescriptorSet message. */
export interface IFileDescriptorSet {
/** Files */
file: IFileDescriptorProto[];
}
/** Properties of a FileDescriptorProto message. */
export interface IFileDescriptorProto {
/** File name */
name?: string;
/** Package */
package?: string;
/** Not supported */
dependency?: any;
/** Not supported */
publicDependency?: any;
/** Not supported */
weakDependency?: any;
/** Nested message types */
messageType?: IDescriptorProto[];
/** Nested enums */
enumType?: IEnumDescriptorProto[];
/** Nested services */
service?: IServiceDescriptorProto[];
/** Nested extension fields */
extension?: IFieldDescriptorProto[];
/** Options */
options?: IFileOptions;
/** Not supported */
sourceCodeInfo?: any;
/** Syntax */
syntax?: string;
/** Edition */
edition?: IEdition;
}
/** Values of the Edition enum. */
export type IEdition = number;
/** Properties of a FileOptions message. */
export interface IFileOptions {
javaPackage?: string;
javaOuterClassname?: string;
javaMultipleFiles?: boolean;
javaGenerateEqualsAndHash?: boolean;
javaStringCheckUtf8?: boolean;
optimizeFor?: IFileOptionsOptimizeMode;
goPackage?: string;
ccGenericServices?: boolean;
javaGenericServices?: boolean;
pyGenericServices?: boolean;
deprecated?: boolean;
ccEnableArenas?: boolean;
objcClassPrefix?: string;
csharpNamespace?: string;
}
/** Values of he FileOptions.OptimizeMode enum. */
export type IFileOptionsOptimizeMode = number;
/** Descriptor context. */
export interface IDescriptorContext {
/** Syntax or edition to use for direct object descriptor imports */
edition?: string;
/** File-level features to apply for direct object descriptor imports */
features?: IFeatureSet;
/** Uses proto field names as reflected field names */
keepCase?: boolean;
}
/** Properties of a DescriptorProto message. */
export interface IDescriptorProto {
/** Message type name */
name?: string;
/** Fields */
field?: IFieldDescriptorProto[];
/** Extension fields */
extension?: IFieldDescriptorProto[];
/** Nested message types */
nestedType?: IDescriptorProto[];
/** Nested enums */
enumType?: IEnumDescriptorProto[];
/** Extension ranges */
extensionRange?: IDescriptorProtoExtensionRange[];
/** Oneofs */
oneofDecl?: IOneofDescriptorProto[];
/** Not supported */
options?: IMessageOptions;
/** Reserved ranges */
reservedRange?: IDescriptorProtoReservedRange[];
/** Reserved names */
reservedName?: string[];
}
/** Properties of a MessageOptions message. */
export interface IMessageOptions {
/** Whether this message is a map entry */
mapEntry?: boolean;
}
/** Properties of an ExtensionRange message. */
export interface IDescriptorProtoExtensionRange {
/** Start field id */
start?: number;
/** End field id */
end?: number;
}
/** Properties of a ReservedRange message. */
export interface IDescriptorProtoReservedRange {
/** Start field id */
start?: number;
/** End field id */
end?: number;
}
/** Properties of a FieldDescriptorProto message. */
export interface IFieldDescriptorProto {
/** Field name */
name?: string;
/** Field id */
number?: number;
/** Field rule */
label?: IFieldDescriptorProtoLabel;
/** Field basic type */
type?: IFieldDescriptorProtoType;
/** Field type name */
typeName?: string;
/** Extended type name */
extendee?: string;
/** Literal default value */
defaultValue?: string;
/** Oneof index if part of a oneof */
oneofIndex?: number;
/** JSON name (lowerCamelCase) */
jsonName?: string;
/** Field options */
options?: IFieldOptions;
/** Whether this is a proto3 optional field */
proto3Optional?: boolean;
}
/** Values of the FieldDescriptorProto.Label enum. */
export type IFieldDescriptorProtoLabel = number;
/** Values of the FieldDescriptorProto.Type enum. */
export type IFieldDescriptorProtoType = number;
/** Properties of a FieldOptions message. */
export interface IFieldOptions {
/** Whether packed or not (defaults to `false` for proto2 and `true` for proto3) */
packed?: boolean;
/** JavaScript value type (not used by protobuf.js) */
jstype?: IFieldOptionsJSType;
}
/** Values of the FieldOptions.JSType enum. */
export type IFieldOptionsJSType = number;
/** Properties of an EnumDescriptorProto message. */
export interface IEnumDescriptorProto {
/** Enum name */
name?: string;
/** Enum values */
value?: IEnumValueDescriptorProto[];
/** Enum options */
options?: IEnumOptions;
}
/** Properties of an EnumValueDescriptorProto message. */
export interface IEnumValueDescriptorProto {
/** Name */
name?: string;
/** Value */
number?: number;
/** Enum value options */
options?: IEnumValueOptions;
}
/** Properties of an EnumValueOptions message. */
export interface IEnumValueOptions {
deprecated?: boolean;
features?: IFeatureSet;
debugRedact?: boolean;
featureSupport?: any;
uninterpretedOption?: any[];
}
/** Properties of an EnumOptions message. */
export interface IEnumOptions {
/** Whether aliases are allowed */
allowAlias?: boolean;
deprecated?: boolean;
}
/** Properties of a FeatureSet message. */
export interface IFeatureSet {
fieldPresence?: number;
enumType?: number;
repeatedFieldEncoding?: number;
utf8Validation?: number;
messageEncoding?: number;
jsonFormat?: number;
enforceNamingStyle?: number;
defaultSymbolVisibility?: number;
}
/** Properties of a OneofDescriptorProto message. */
export interface IOneofDescriptorProto {
/** Oneof name */
name?: string;
/** Oneof options */
options?: IOneofOptions;
}
/** Properties of a OneofOptions message. */
export interface IOneofOptions {
features?: IFeatureSet;
uninterpretedOption?: any[];
}
/** Properties of a ServiceDescriptorProto message. */
export interface IServiceDescriptorProto {
/** Service name */
name?: string;
/** Methods */
method?: IMethodDescriptorProto[];
/** Options */
options?: IServiceOptions;
}
/** Properties of a ServiceOptions message. */
export interface IServiceOptions {
deprecated?: boolean;
}
/** Properties of a MethodDescriptorProto message. */
export interface IMethodDescriptorProto {
/** Method name */
name?: string;
/** Request type name */
inputType?: string;
/** Response type name */
outputType?: string;
/** Not supported */
options?: IMethodOptions;
/** Whether requests are streamed */
clientStreaming?: boolean;
/** Whether responses are streamed */
serverStreaming?: boolean;
}
/** Properties of a MethodOptions message. */
export interface IMethodOptions {
deprecated?: boolean;
}
+1356
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -0,0 +1,5 @@
# protobufjs/ext/descriptor
This directory is kept as a backwards-compatible shim for `protobufjs/ext/descriptor` and may be removed in a future major release.
The descriptor extension documentation now lives in [../README.md](../README.md#descriptor).
+2
View File
@@ -0,0 +1,2 @@
import * as $protobuf from "../..";
import Long = require("long");
+2
View File
@@ -0,0 +1,2 @@
"use strict";
module.exports = require("../descriptor");
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+20
View File
@@ -0,0 +1,20 @@
import * as $protobuf from "..";
import { IProtoJsonOptions } from "./protojson.generated";
export * from "./protojson.generated";
declare module ".." {
interface Type {
/** Installed by `protojson.install()`. Parses an already-parsed ProtoJSON value. */
fromJson(json: any, options?: IProtoJsonOptions): $protobuf.Message<{}>;
/** Installed by `protojson.install()`. Parses ProtoJSON text. */
fromJsonString(json: string, options?: IProtoJsonOptions): $protobuf.Message<{}>;
/** Installed by `protojson.install()`. Formats a message as ProtoJSON. */
toJson(message: ($protobuf.Message<{}>|{ [k: string]: any }), options?: IProtoJsonOptions): any;
/** Installed by `protojson.install()`. Formats a message as ProtoJSON text. */
toJsonString(message: ($protobuf.Message<{}>|{ [k: string]: any }), options?: IProtoJsonOptions): string;
}
}
+49
View File
@@ -0,0 +1,49 @@
// DO NOT EDIT! This is a generated file. Edit the source file instead and regenerate.
import * as $protobuf from "..";
/** ProtoJSON conversion options. */
export interface IProtoJsonOptions {
/** Ignores unknown object members and unrecognized enum names while parsing. */
ignoreUnknownFields?: boolean;
}
/**
* Parses a message from an already-parsed ProtoJSON value using the specified reflected type.
* @param type Reflected message type
* @param json Already-parsed ProtoJSON value
* @param [options] Conversion options
* @returns Message instance
*/
export function fromJson(type: $protobuf.Type, json: any, options?: IProtoJsonOptions): $protobuf.Message<{}>;
/**
* Parses a message from ProtoJSON text using the specified reflected type.
* @param type Reflected message type
* @param json ProtoJSON text
* @param [options] Conversion options
* @returns Message instance
*/
export function fromJsonString(type: $protobuf.Type, json: string, options?: IProtoJsonOptions): $protobuf.Message<{}>;
/**
* Formats a message as ProtoJSON using the specified reflected type.
* @param type Reflected message type
* @param message Message instance or plain object
* @param [options] Conversion options
* @returns ProtoJSON value (object, array, string, number, boolean or null)
*/
export function toJson(type: $protobuf.Type, message: ($protobuf.Message<{}>|{ [k: string]: any }), options?: IProtoJsonOptions): any;
/**
* Formats a message as ProtoJSON text using the specified reflected type.
* @param type Reflected message type
* @param message Message instance or plain object
* @param [options] Conversion options
* @returns ProtoJSON text
*/
export function toJsonString(type: $protobuf.Type, message: ($protobuf.Message<{}>|{ [k: string]: any }), options?: IProtoJsonOptions): string;
/** Installs reflected {@link Type} convenience methods. */
export function install(): void;
+951
View File
@@ -0,0 +1,951 @@
// Copyright 2021 Google LLC
// Copyright 2026 The protobuf.js Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Derived from proto3-json-serializer v3.0.4 and modified by The protobuf.js Authors.
"use strict";
var protobuf = require("../light");
/* global BigInt */
var Type = protobuf.Type,
Enum = protobuf.Enum,
util = protobuf.util;
var protojson = protobuf.protojson = module.exports = {};
function isExtension(field) {
return Boolean(field.declaringField) || field.name.charAt(0) === ".";
}
function extensionName(field) {
var df = field.declaringField || field,
full = df.fullName.charAt(0) === "." ? df.fullName.slice(1) : df.fullName;
return "[" + (df.protoName ? full.replace(/[^.]+$/, df.protoName) : full) + "]";
}
function indexField(index, key, field, type) {
var existing = index[key];
if (existing !== undefined && existing !== field)
throw Error(type.fullName + ": duplicate ProtoJSON field name " + JSON.stringify(key));
index[key] = field;
}
function fieldsByJsonName(type) {
if (type._fieldsByJsonName)
return type._fieldsByJsonName;
var index = Object.create(null),
fields = type.fieldsArray,
i = 0;
for (; i < fields.length; ++i) {
var field = fields[i].resolve();
if (isExtension(field))
indexField(index, extensionName(field), field, type);
else {
indexField(index, field.name, field, type);
indexField(index, field.jsonName, field, type);
indexField(index, field.protoName, field, type);
}
}
type._fieldsByJsonName = index;
return index;
}
// --- reading scalars ---
var INT_RANGE = {
int32: ["-2147483648", "2147483647"],
sint32: ["-2147483648", "2147483647"],
sfixed32: ["-2147483648", "2147483647"],
uint32: ["0", "4294967295"],
fixed32: ["0", "4294967295"],
int64: ["-9223372036854775808", "9223372036854775807"],
sint64: ["-9223372036854775808", "9223372036854775807"],
sfixed64: ["-9223372036854775808", "9223372036854775807"],
uint64: ["0", "18446744073709551615"],
fixed64: ["0", "18446744073709551615"]
};
var LONG_TYPE = { int64: 1, uint64: 1, sint64: 1, fixed64: 1, sfixed64: 1 };
var MAX_FLOAT = 3.4028234663852886e38;
var hasBigInt = typeof BigInt !== "undefined";
var NUMERIC_RE = /^[+-]?(?:[0-9]*\.[0-9]+|[0-9]+\.?)(?:[eE][+-]?[0-9]+)?$/;
var SKIP = {};
function invalid(name, value, what) {
return Error(name + ": " + what + ": " + JSON.stringify(value));
}
function parseIntegerString(value, type, name) {
var str;
if (typeof value === "number") {
if (!isFinite(value) || Math.floor(value) !== value)
throw invalid(name, value, "not an integer");
str = numberToIntString(value);
} else if (typeof value === "string") {
if (value.length === 0 || /^\s|\s$/.test(value))
throw invalid(name, value, "invalid integer");
if (/^[+-]?[0-9]+$/.test(value))
str = value;
else if (NUMERIC_RE.test(value)) {
var num = Number(value);
if (!isFinite(num) || Math.floor(num) !== num)
throw invalid(name, value, "not an integer");
str = numberToIntString(num);
} else
throw invalid(name, value, "invalid integer");
} else
throw invalid(name, value, "expected integer (number or string)");
var range = INT_RANGE[type];
if (LONG_TYPE[type]) {
if (hasBigInt) {
var big = BigInt(str);
if (big < BigInt(range[0]) || big > BigInt(range[1]))
throw invalid(name, value, "out of range for " + type);
}
} else if (Number(str) < Number(range[0]) || Number(str) > Number(range[1]))
throw invalid(name, value, "out of range for " + type);
return str;
}
function parseMapIntegerKey(key, type, name) {
var unsigned = type === "uint32" || type === "fixed32" || type === "uint64" || type === "fixed64";
if (!(unsigned ? /^[0-9]+$/ : /^-?[0-9]+$/).test(key))
throw invalid(name, key, "invalid " + type + " map key");
if (hasBigInt) {
var big = BigInt(key),
range = INT_RANGE[type];
if (big < BigInt(range[0]) || big > BigInt(range[1]))
throw invalid(name, key, "out of range for " + type + " map key");
return big.toString();
}
parseIntegerString(key, type, name);
if (LONG_TYPE[type]) {
var normalized = key.replace(/^-?0+(?=\d)/, key.charAt(0) === "-" ? "-" : "");
return normalized === "-0" ? "0" : normalized;
}
return String(Number(key));
}
function numberToIntString(num) {
if (num >= -9007199254740991 && num <= 9007199254740991)
return String(num);
return num.toFixed(0);
}
function parseFloat32Or64(value, isFloat, name) {
var num;
if (typeof value === "number") {
if (!isFinite(value))
throw invalid(name, value, "number out of range");
num = value;
} else if (value === "NaN")
return NaN;
else if (value === "Infinity")
return Infinity;
else if (value === "-Infinity")
return -Infinity;
else if (typeof value === "string") {
if (value.length === 0 || /^\s|\s$/.test(value) || !NUMERIC_RE.test(value))
throw invalid(name, value, "invalid number");
num = Number(value);
if (!isFinite(num))
throw invalid(name, value, "invalid number");
} else
throw invalid(name, value, "expected number");
if (isFloat && Math.abs(num) > MAX_FLOAT)
throw invalid(name, value, "out of range for float");
return num;
}
function validateUtf16(value, name) {
for (var i = 0; i < value.length; ++i) {
var c = value.charCodeAt(i);
if (c >= 0xD800 && c <= 0xDBFF) {
var next = value.charCodeAt(i + 1);
if (!(next >= 0xDC00 && next <= 0xDFFF))
throw invalid(name, value, "unpaired high surrogate");
++i;
} else if (c >= 0xDC00 && c <= 0xDFFF)
throw invalid(name, value, "unpaired low surrogate");
}
}
function parseBytes(value, name) {
if (typeof value !== "string")
throw invalid(name, value, "expected base64 string");
var s = value.replace(/-/g, "+").replace(/_/g, "/");
while (s.length % 4)
s += "=";
var buffer = util.newBuffer(util.base64.length(s));
util.base64.decode(s, buffer, 0);
return buffer;
}
function longFromString(str, unsigned) {
return util.Long ? util.Long.fromString(str, unsigned) : parseInt(str, 10);
}
function readScalar(type, value, name) {
switch (type) {
case "int32": case "sint32": case "sfixed32":
case "uint32": case "fixed32":
return Number(parseIntegerString(value, type, name));
case "int64": case "sint64": case "sfixed64":
return longFromString(parseIntegerString(value, type, name), false);
case "uint64": case "fixed64":
return longFromString(parseIntegerString(value, type, name), true);
case "float":
return parseFloat32Or64(value, true, name);
case "double":
return parseFloat32Or64(value, false, name);
case "bool":
if (typeof value !== "boolean")
throw invalid(name, value, "expected boolean");
return value;
case "string":
if (typeof value !== "string")
throw invalid(name, value, "expected string");
validateUtf16(value, name);
return value;
case "bytes":
return parseBytes(value, name);
default:
throw Error(name + ": unsupported scalar type " + type);
}
}
function readEnum(enm, value, name, options) {
if (typeof value === "string") {
var num = enm.values[value];
if (num !== undefined)
return num;
if (options.ignoreUnknownFields)
return SKIP;
throw invalid(name, value, "unknown enum value");
}
if (typeof value === "number") {
if ((value | 0) !== value)
throw invalid(name, value, "invalid enum number");
if (enm._features.enum_type === "CLOSED" && enm.valuesById[value] === undefined)
throw invalid(name, value, "unknown enum value");
return value;
}
if (value === null && enm.fullName === ".google.protobuf.NullValue")
return 0;
throw invalid(name, value, "expected enum string or number");
}
function readMapKey(field, key) {
switch (field.keyType) {
case "bool":
if (key !== "true" && key !== "false")
throw invalid(field.fullName, key, "invalid bool map key");
return key;
case "string":
validateUtf16(key, field.fullName);
return key;
case "int32": case "sint32": case "sfixed32":
case "uint32": case "fixed32":
case "int64": case "sint64": case "sfixed64":
case "uint64": case "fixed64":
return parseMapIntegerKey(key, field.keyType, field.fullName);
default:
throw Error(field.fullName + ": unsupported map key type " + field.keyType);
}
}
// --- reading messages ---
function readField(field, value, options, depth) {
if (field.map) {
if (value === null || typeof value !== "object" || Array.isArray(value))
throw invalid(field.fullName, value, "expected object for map");
var map = Object.create(null), k;
for (k in value)
if (hasOwn(value, k)) {
var mk = readMapKey(field, k),
mv = readSingular(field, value[k], options, depth);
if (mv !== SKIP) {
if (hasOwn(map, mk))
throw invalid(field.fullName, k, "duplicate map key");
map[mk] = mv;
}
}
return map;
}
if (field.repeated) {
if (!Array.isArray(value))
throw invalid(field.fullName, value, "expected array");
var arr = [], i = 0;
for (; i < value.length; ++i) {
if (value[i] === null && !isValueType(field.resolvedType) && !isNullValueType(field.resolvedType))
throw invalid(field.fullName, null, "null element");
var el = readSingular(field, value[i], options, depth);
if (el !== SKIP)
arr.push(el);
}
return arr;
}
return readSingular(field, value, options, depth);
}
function readSingular(field, value, options, depth) {
if (field.resolvedType instanceof Type)
return readMessage(field.resolvedType, value, options, depth + 1);
if (field.resolvedType instanceof Enum)
return readEnum(field.resolvedType, value, field.fullName, options);
return readScalar(field.type, value, field.fullName);
}
function isValueType(type) {
return type instanceof Type && type.fullName === ".google.protobuf.Value";
}
function isNullValueType(type) {
return type instanceof Enum && type.fullName === ".google.protobuf.NullValue";
}
function isImplicitDefault(field, value) {
if (field.hasPresence || field.repeated || field.map || field.resolvedType instanceof Type)
return false;
if (field.resolvedType instanceof Enum)
return value === 0;
switch (field.type) {
case "bool": return value === false;
case "string": return value === "";
case "bytes": return value == null || value.length === 0;
default: return longToNumber(value) === 0;
}
}
function readMessage(type, value, options, depth) {
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
var wkt = WKT_FROM[type.fullName];
if (wkt)
return wkt(type, value, options, depth);
if (value === null || typeof value !== "object" || Array.isArray(value))
throw invalid(type.fullName, value, "expected object");
var index = fieldsByJsonName(type),
out = {},
seenFields = Object.create(null),
seenOneofs = Object.create(null),
key;
for (key in value) {
if (!hasOwn(value, key))
continue;
var field = index[key];
if (field === undefined) {
if (options.ignoreUnknownFields)
continue;
throw invalid(type.fullName, key, "unknown field");
}
if (seenFields[field.name])
throw invalid(type.fullName, key, "duplicate field");
seenFields[field.name] = true;
var fv = value[key], fieldValue;
if (fv === null) {
if (isValueType(field.resolvedType))
fieldValue = { nullValue: 0 };
else if (field.resolvedType instanceof Enum && field.resolvedType.fullName === ".google.protobuf.NullValue")
fieldValue = 0;
else
continue;
} else
fieldValue = readField(field, fv, options, depth);
if (fieldValue === SKIP)
continue;
if (field.partOf) {
if (seenOneofs[field.partOf.name])
throw Error(type.fullName + ": multiple values for oneof " + field.partOf.name);
seenOneofs[field.partOf.name] = true;
}
if (!isImplicitDefault(field, fieldValue))
out[field.name] = fieldValue;
}
return out;
}
// --- writing messages ---
function hasOwn(o, k) {
return o != null && Object.prototype.hasOwnProperty.call(o, k);
}
function setOwn(o, k, v) {
if (k === "__proto__")
util.makeProp(o, k);
o[k] = v;
}
function wktFieldName(type, name) {
var field = fieldsByJsonName(type)[name];
return field ? field.name : name;
}
function wktFieldValue(type, message, name) {
var field = fieldsByJsonName(type)[name];
if (!field)
return message && message[name];
if (hasOwn(message, field.name))
return message[field.name];
if (hasOwn(message, field.protoName))
return message[field.protoName];
if (hasOwn(message, field.jsonName))
return message[field.jsonName];
return undefined;
}
function writeScalar(type, value) {
switch (type) {
case "int64": case "sint64": case "sfixed64":
case "uint64": case "fixed64":
return value == null ? "0" : String(value);
case "float": case "double":
return typeof value === "number" && !isFinite(value) ? String(value) : value;
case "bytes":
return value == null ? "" : util.base64.encode(value, 0, value.length);
default:
return value;
}
}
function writeSingular(field, value, options, depth) {
if (field.resolvedType instanceof Type)
return toJsonValue(field.resolvedType, value, options, depth + 1);
if (field.resolvedType instanceof Enum) {
if (field.resolvedType.fullName === ".google.protobuf.NullValue")
return null;
var name = field.resolvedType.valuesById[value];
return name === undefined ? value : name;
}
return writeScalar(field.type, value);
}
function toJsonValue(type, message, options, depth) {
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
var wkt = WKT_TO[type.fullName];
if (wkt)
return wkt(type, message, options, depth);
var out = {},
fields = type.fieldsArray,
i = 0;
for (; i < fields.length; ++i) {
var field = fields[i].resolve(),
value = message[field.name];
if (value == null)
continue;
var key = isExtension(field) ? extensionName(field) : field.jsonName;
if (field.map) {
var mk = Object.keys(value);
if (!mk.length)
continue;
var longKey = LONG_TYPE[field.keyType],
unsignedKey = field.keyType === "uint64" || field.keyType === "fixed64",
mo = {}, ki = 0;
for (; ki < mk.length; ++ki) {
var outKey = longKey ? util.longFromKey(mk[ki], unsignedKey).toString() : mk[ki];
setOwn(mo, outKey, writeSingular(field, value[mk[ki]], options, depth));
}
setOwn(out, key, mo);
} else if (field.repeated) {
if (!value.length)
continue;
var arr = new Array(value.length), j = 0;
for (; j < value.length; ++j)
arr[j] = writeSingular(field, value[j], options, depth);
setOwn(out, key, arr);
} else {
if (!hasOwn(message, field.name) || isImplicitDefault(field, value))
continue;
setOwn(out, key, writeSingular(field, value, options, depth));
}
}
return out;
}
// --- well-known types ---
function longToNumber(value) {
if (value == null) return 0;
if (typeof value === "number") return value;
if (typeof value.toNumber === "function") return value.toNumber();
return Number(value) || 0;
}
function nanosToString(nanos) {
var str = String(nanos < 0 ? -nanos : nanos);
while (str.length < 9) str = "0" + str;
while (str.length > 3 && str.slice(str.length - 3) === "000") str = str.slice(0, str.length - 3);
return str;
}
function fracToNanos(frac) {
while (frac.length < 9) frac += "0";
return parseInt(frac.slice(0, 9), 10);
}
function daysInMonth(year, month) {
switch (month) {
case 2:
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28;
case 4:
case 6:
case 9:
case 11:
return 30;
default:
return 31;
}
}
function camelToSnake(path) {
return path.replace(/[A-Z]/g, function ($0) { return "_" + $0.toLowerCase(); });
}
var WKT_FROM = {};
var WKT_TO = {};
WKT_FROM[".google.protobuf.Duration"] = function (type, value) {
if (typeof value !== "string")
throw invalid(type.fullName, value, "expected duration string");
var match = /^(-)?([0-9]+)(?:\.([0-9]{1,9}))?s$/.exec(value);
if (!match)
throw invalid(type.fullName, value, "invalid duration");
var sign = match[1] ? -1 : 1,
seconds = parseInt(match[2], 10) * sign || 0,
nanos = match[3] ? fracToNanos(match[3]) * sign || 0 : 0;
if (seconds > 315576000000 || seconds < -315576000000)
throw invalid(type.fullName, value, "duration out of range");
var message = {};
if (seconds !== 0)
message.seconds = seconds;
if (nanos !== 0)
message.nanos = nanos;
return message;
};
WKT_TO[".google.protobuf.Duration"] = function (type, message) {
var seconds = longToNumber(message.seconds),
nanos = message.nanos || 0;
if (seconds > 315576000000 || seconds < -315576000000)
throw Error("google.protobuf.Duration out of range");
if (nanos > 999999999 || nanos < -999999999 || seconds && nanos && seconds < 0 !== nanos < 0)
throw Error("google.protobuf.Duration nanos invalid");
var result = (seconds < 0 || nanos < 0 ? "-" : "") + Math.abs(seconds);
if (nanos)
result += "." + nanosToString(nanos);
return result + "s";
};
WKT_FROM[".google.protobuf.Timestamp"] = function (type, value) {
if (typeof value !== "string")
throw invalid(type.fullName, value, "expected timestamp string");
var match = /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(?:\.(\d{1,9}))?(Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.exec(value);
if (!match)
throw invalid(type.fullName, value, "invalid timestamp");
var year = parseInt(match[1], 10),
month = parseInt(match[2], 10),
day = parseInt(match[3], 10);
if (day > daysInMonth(year, month))
throw invalid(type.fullName, value, "invalid timestamp date");
var millis = new Date(value).getTime();
if (isNaN(millis))
throw invalid(type.fullName, value, "invalid timestamp");
var seconds = Math.floor(millis / 1000),
nanos = match[7] ? fracToNanos(match[7]) : 0;
if (seconds < -62135596800 || seconds > 253402300799)
throw invalid(type.fullName, value, "timestamp out of range");
var message = {};
if (seconds !== 0)
message.seconds = seconds;
if (nanos !== 0)
message.nanos = nanos;
return message;
};
WKT_TO[".google.protobuf.Timestamp"] = function (type, message) {
var seconds = longToNumber(message.seconds),
nanos = message.nanos || 0;
if (seconds < -62135596800 || seconds > 253402300799)
throw Error("google.protobuf.Timestamp out of range");
if (nanos < 0 || nanos > 999999999)
throw Error("google.protobuf.Timestamp nanos out of range");
var iso = new Date(seconds * 1000).toISOString();
return nanos
? iso.replace(/\.\d+Z$/, "." + nanosToString(nanos) + "Z")
: iso.replace(/\.\d+Z$/, "Z");
};
WKT_FROM[".google.protobuf.FieldMask"] = function (type, value) {
if (typeof value !== "string")
throw invalid(type.fullName, value, "expected field mask string");
if (value.indexOf("_") !== -1)
throw invalid(type.fullName, value, "field mask path must be lowerCamelCase");
var paths = value.length ? value.split(",") : [],
i = 0;
for (; i < paths.length; ++i)
paths[i] = camelToSnake(paths[i]);
return { paths: paths };
};
WKT_TO[".google.protobuf.FieldMask"] = function (type, message) {
var paths = message.paths || [],
out = [],
i = 0;
for (; i < paths.length; ++i) {
var camel = util.jsonName(paths[i]);
if (camelToSnake(camel) !== paths[i])
throw Error("google.protobuf.FieldMask path does not round-trip: " + paths[i]);
out.push(camel);
}
return out.join(",");
};
["DoubleValue", "FloatValue", "Int64Value", "UInt64Value", "Int32Value",
"UInt32Value", "BoolValue", "StringValue", "BytesValue"].forEach(function (name) {
var fullName = ".google.protobuf." + name;
WKT_FROM[fullName] = function (type, value, options, depth) {
var field = type.fields.value.resolve(),
fieldValue = readSingular(field, value, options, depth),
message = {};
if (!isImplicitDefault(field, fieldValue))
message.value = fieldValue;
return message;
};
WKT_TO[fullName] = function (type, message, options, depth) {
var field = type.fields.value.resolve(),
value = wktFieldValue(type, message, "value");
return writeSingular(field, value === undefined ? field.defaultValue : value, options, depth);
};
});
function valueFromJson(json, depth) {
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
if (json === null)
return { nullValue: 0 };
switch (typeof json) {
case "number":
if (!isFinite(json))
throw Error("google.protobuf.Value cannot hold a non-finite number");
return { numberValue: json };
case "string":
validateUtf16(json, "google.protobuf.Value.string_value");
return { stringValue: json };
case "boolean":
return { boolValue: json };
}
if (Array.isArray(json)) {
var values = new Array(json.length), i = 0;
for (; i < json.length; ++i)
values[i] = valueFromJson(json[i], depth + 1);
return { listValue: { values: values } };
}
return { structValue: { fields: structFieldsFromJson(json, depth + 1) } };
}
function structFieldsFromJson(json, depth) {
var fields = Object.create(null), k;
for (k in json)
if (hasOwn(json, k)) {
validateUtf16(k, "google.protobuf.Struct.fields");
fields[k] = valueFromJson(json[k], depth);
}
return fields;
}
WKT_FROM[".google.protobuf.Value"] = function (type, value, options, depth) {
return valueFromJson(value, depth);
};
WKT_FROM[".google.protobuf.Struct"] = function (type, value, options, depth) {
if (value === null || typeof value !== "object" || Array.isArray(value))
throw invalid(type.fullName, value, "google.protobuf.Struct must be an object");
return { fields: structFieldsFromJson(value, depth + 1) };
};
WKT_FROM[".google.protobuf.ListValue"] = function (type, value, options, depth) {
if (!Array.isArray(value))
throw invalid(type.fullName, value, "google.protobuf.ListValue must be an array");
var values = new Array(value.length), i = 0;
for (; i < value.length; ++i)
values[i] = valueFromJson(value[i], depth + 1);
return { values: values };
};
function valueToJson(message, options, depth) {
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
if (message == null || hasOwn(message, "nullValue"))
return null;
if (hasOwn(message, "numberValue")) {
if (typeof message.numberValue === "number" && !isFinite(message.numberValue))
throw Error("google.protobuf.Value cannot hold a non-finite number");
return message.numberValue;
}
if (hasOwn(message, "stringValue")) return message.stringValue;
if (hasOwn(message, "boolValue")) return message.boolValue;
if (hasOwn(message, "structValue")) return structToJson(message.structValue, options, depth + 1);
if (hasOwn(message, "listValue")) return listToJson(message.listValue, options, depth + 1);
return null;
}
function structToJson(message, options, depth) {
var out = {}, fields = message && message.fields, k;
if (fields)
for (k in fields)
if (hasOwn(fields, k))
setOwn(out, k, valueToJson(fields[k], options, depth));
return out;
}
function listToJson(message, options, depth) {
var values = message && message.values;
if (!values) return [];
var arr = new Array(values.length), i = 0;
for (; i < values.length; ++i)
arr[i] = valueToJson(values[i], options, depth);
return arr;
}
WKT_TO[".google.protobuf.Value"] = function (type, message, options, depth) {
return valueToJson(message, options, depth);
};
WKT_TO[".google.protobuf.Struct"] = function (type, message, options, depth) {
return structToJson(message, options, depth);
};
WKT_TO[".google.protobuf.ListValue"] = function (type, message, options, depth) {
return listToJson(message, options, depth);
};
WKT_FROM[".google.protobuf.Any"] = function (type, value, options, depth) {
if (value === null || typeof value !== "object" || Array.isArray(value))
throw invalid(type.fullName, value, "google.protobuf.Any must be an object");
var typeUrl = value["@type"];
if (typeUrl === undefined)
return {};
if (typeof typeUrl !== "string")
throw Error("google.protobuf.Any @type must be a string");
var name = typeUrl.substring(typeUrl.lastIndexOf("/") + 1),
msgType = type.root.lookupType(name),
custom = WKT_FROM[msgType.fullName] !== undefined,
body;
if (custom)
body = value.value;
else {
body = {};
for (var k in value)
if (hasOwn(value, k) && k !== "@type")
setOwn(body, k, value[k]);
}
var inner = readMessage(msgType, body, options, depth + 1);
var url = typeUrl.charAt(0) === "." ? typeUrl.slice(1) : typeUrl,
out = {};
if (url.indexOf("/") === -1)
url = "/" + url;
out[wktFieldName(type, "type_url")] = url;
var bytes = msgType.encode(inner).finish();
if (bytes.length)
out[wktFieldName(type, "value")] = bytes;
return out;
};
WKT_TO[".google.protobuf.Any"] = function (type, message, options, depth) {
var typeUrl = wktFieldValue(type, message, "type_url");
if (!typeUrl)
return {};
var name = typeUrl.substring(typeUrl.lastIndexOf("/") + 1),
msgType = type.root.lookupType(name),
value = wktFieldValue(type, message, "value"),
decoded = msgType.decode(value || util.emptyArray),
body = toJsonValue(msgType, decoded, options, depth + 1),
result;
if (WKT_TO[msgType.fullName])
result = { "@type": typeUrl, "value": body };
else {
result = { "@type": typeUrl };
for (var k in body)
if (hasOwn(body, k))
setOwn(result, k, body[k]);
}
return result;
};
// --- duplicate keys ---
// JSON.parse keeps the last duplicate key, but ProtoJSON rejects duplicates.
function checkDuplicateKeys(str) {
var stack = [],
expectKey = false,
i = 0,
n = str.length;
while (i < n) {
var c = str.charAt(i);
if (c === "{") {
stack.push(Object.create(null));
expectKey = true;
++i;
} else if (c === "[") {
stack.push(null);
expectKey = false;
++i;
} else if (c === "}" || c === "]") {
stack.pop();
expectKey = false;
++i;
} else if (c === ":") {
expectKey = false;
++i;
} else if (c === ",") {
expectKey = stack.length > 0 && stack[stack.length - 1] !== null;
++i;
} else if (c === "\"") {
var start = i++;
while (i < n) {
var ch = str.charAt(i++);
if (ch === "\\") ++i;
else if (ch === "\"") break;
}
if (expectKey) {
var seen = stack[stack.length - 1],
name = JSON.parse(str.slice(start, i));
if (seen[name])
throw Error("duplicate key in JSON object: " + JSON.stringify(name));
seen[name] = true;
expectKey = false;
}
} else
++i;
}
}
// --- public API ---
/**
* ProtoJSON conversion options.
* @interface IProtoJsonOptions
* @property {boolean} [ignoreUnknownFields=false] Ignores unknown object members and unrecognized enum names while parsing.
*/
/**
* Parses a message from an already-parsed ProtoJSON value using the specified reflected type.
* @function fromJson
* @name fromJson
* @param {$protobuf.Type} type Reflected message type
* @param {*} json Already-parsed ProtoJSON value
* @param {IProtoJsonOptions} [options] Conversion options
* @returns {$protobuf.Message<{}>} Message instance
*/
protojson.fromJson = function fromJson(type, json, options) {
if (!(type instanceof Type))
throw TypeError("type must be a Type");
type.root.resolveAll();
return type.create(readMessage(type, json, options || {}, 0));
};
/**
* Parses a message from ProtoJSON text using the specified reflected type.
* @function fromJsonString
* @name fromJsonString
* @param {$protobuf.Type} type Reflected message type
* @param {string} json ProtoJSON text
* @param {IProtoJsonOptions} [options] Conversion options
* @returns {$protobuf.Message<{}>} Message instance
*/
protojson.fromJsonString = function fromJsonString(type, json, options) {
if (typeof json !== "string")
throw TypeError("json must be a string");
checkDuplicateKeys(json);
return protojson.fromJson(type, JSON.parse(json), options);
};
/**
* Formats a message as ProtoJSON using the specified reflected type.
* @function toJson
* @name toJson
* @param {$protobuf.Type} type Reflected message type
* @param {$protobuf.Message<{}>|Object.<string,*>} message Message instance or plain object
* @param {IProtoJsonOptions} [options] Conversion options
* @returns {*} ProtoJSON value (object, array, string, number, boolean or null)
*/
protojson.toJson = function toJson(type, message, options) {
if (!(type instanceof Type))
throw TypeError("type must be a Type");
type.root.resolveAll();
return toJsonValue(type, message, options || {}, 0);
};
/**
* Formats a message as ProtoJSON text using the specified reflected type.
* @function toJsonString
* @name toJsonString
* @param {$protobuf.Type} type Reflected message type
* @param {$protobuf.Message<{}>|Object.<string,*>} message Message instance or plain object
* @param {IProtoJsonOptions} [options] Conversion options
* @returns {string} ProtoJSON text
*/
protojson.toJsonString = function toJsonString(type, message, options) {
return JSON.stringify(protojson.toJson(type, message, options));
};
/**
* Installs reflected {@link Type} convenience methods.
* @function install
* @name install
* @returns {undefined}
*/
protojson.install = function install() {
/**
* Parses a message of this type from an already-parsed ProtoJSON value. Convenience for {@link protojson.fromJson}.
* @param {*} json Already-parsed ProtoJSON value
* @param {IProtoJsonOptions} [options] Conversion options
* @returns {Message<{}>} Message instance
*/
Type.prototype.fromJson = function fromJson(json, options) {
return protojson.fromJson(this, json, options);
};
/**
* Parses a message of this type from ProtoJSON text. Convenience for {@link protojson.fromJsonString}.
* @param {string} json ProtoJSON text
* @param {IProtoJsonOptions} [options] Conversion options
* @returns {Message<{}>} Message instance
*/
Type.prototype.fromJsonString = function fromJsonString(json, options) {
return protojson.fromJsonString(this, json, options);
};
/**
* Formats a message of this type as ProtoJSON. Convenience for {@link protojson.toJson}.
* @param {Message<{}>|Object.<string,*>} message Message instance or plain object
* @param {IProtoJsonOptions} [options] Conversion options
* @returns {*} ProtoJSON value
*/
Type.prototype.toJson = function toJson(message, options) {
return protojson.toJson(this, message, options);
};
/**
* Formats a message of this type as ProtoJSON text. Convenience for {@link protojson.toJsonString}.
* @param {Message<{}>|Object.<string,*>} message Message instance or plain object
* @param {IProtoJsonOptions} [options] Conversion options
* @returns {string} ProtoJSON text
*/
Type.prototype.toJsonString = function toJsonString(message, options) {
return protojson.toJsonString(this, message, options);
};
};
+19
View File
@@ -0,0 +1,19 @@
import * as $protobuf from "..";
import { ITextFormatOptions } from "./textformat.generated";
export * from "./textformat.generated";
declare module ".." {
namespace textformat {
/** Maximum recursion depth for formatting length-delimited unknown fields. */
let unknownRecursionLimit: number;
}
interface Type {
/** Installed by `textformat.install()`. Parses this type from protobuf text format. */
fromText(text: string): $protobuf.Message<{}>;
/** Installed by `textformat.install()`. Formats a message of this type as protobuf text format. */
toText(message: ($protobuf.Message<{}>|{ [k: string]: any }), options?: ITextFormatOptions): string;
}
}
+33
View File
@@ -0,0 +1,33 @@
// DO NOT EDIT! This is a generated file. Edit the source file instead and regenerate.
import * as $protobuf from "..";
/** Maximum recursion depth for formatting length-delimited unknown fields. */
export let unknownRecursionLimit: number;
/** Text format options. */
export interface ITextFormatOptions {
/** Also includes and formats unknown fields. */
unknowns?: boolean;
}
/**
* Parses a message from protobuf text format using the specified reflected type.
* @param type Reflected message type
* @param text Text format input
* @returns Message instance
*/
export function fromText(type: $protobuf.Type, text: string): $protobuf.Message<{}>;
/**
* Formats a message as protobuf text format using the specified reflected type.
* @param type Reflected message type
* @param message Message instance or plain object
* @param [options] Text format options
* @returns Text format output
*/
export function toText(type: $protobuf.Type, message: ($protobuf.Message<{}>|{ [k: string]: any }), options?: ITextFormatOptions): string;
/** Installs reflected {@link Type} convenience methods. */
export function install(): void;
+1276
View File
File diff suppressed because it is too large Load Diff
+27
View File
@@ -0,0 +1,27 @@
Copyright 2014, Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+1
View File
@@ -0,0 +1 @@
This folder contains stripped and pre-parsed definitions of common Google types. These files are not used by protobuf.js directly but are here so you can use or include them where required.
+85
View File
@@ -0,0 +1,85 @@
{
"nested": {
"google": {
"nested": {
"api": {
"nested": {
"http": {
"type": "HttpRule",
"id": 72295728,
"extend": "google.protobuf.MethodOptions"
},
"HttpRule": {
"oneofs": {
"pattern": {
"oneof": [
"get",
"put",
"post",
"delete",
"patch",
"custom"
]
}
},
"fields": {
"get": {
"type": "string",
"id": 2
},
"put": {
"type": "string",
"id": 3
},
"post": {
"type": "string",
"id": 4
},
"delete": {
"type": "string",
"id": 5
},
"patch": {
"type": "string",
"id": 6
},
"custom": {
"type": "CustomHttpPattern",
"id": 8
},
"selector": {
"type": "string",
"id": 1
},
"body": {
"type": "string",
"id": 7
},
"additionalBindings": {
"rule": "repeated",
"type": "HttpRule",
"id": 11,
"protoName": "additional_bindings"
}
}
}
}
},
"protobuf": {
"nested": {
"MethodOptions": {
"edition": "proto2",
"fields": {},
"extensions": [
[
1000,
536870911
]
]
}
}
}
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
syntax = "proto3";
package google.api;
import "google/api/http.proto";
import "google/protobuf/descriptor.proto";
extend google.protobuf.MethodOptions {
HttpRule http = 72295728;
}
+87
View File
@@ -0,0 +1,87 @@
{
"nested": {
"google": {
"nested": {
"api": {
"nested": {
"Http": {
"fields": {
"rules": {
"rule": "repeated",
"type": "HttpRule",
"id": 1
}
}
},
"HttpRule": {
"oneofs": {
"pattern": {
"oneof": [
"get",
"put",
"post",
"delete",
"patch",
"custom"
]
}
},
"fields": {
"get": {
"type": "string",
"id": 2
},
"put": {
"type": "string",
"id": 3
},
"post": {
"type": "string",
"id": 4
},
"delete": {
"type": "string",
"id": 5
},
"patch": {
"type": "string",
"id": 6
},
"custom": {
"type": "CustomHttpPattern",
"id": 8
},
"selector": {
"type": "string",
"id": 1
},
"body": {
"type": "string",
"id": 7
},
"additionalBindings": {
"rule": "repeated",
"type": "HttpRule",
"id": 11,
"protoName": "additional_bindings"
}
}
},
"CustomHttpPattern": {
"fields": {
"kind": {
"type": "string",
"id": 1
},
"path": {
"type": "string",
"id": 2
}
}
}
}
}
}
}
}
}
+31
View File
@@ -0,0 +1,31 @@
syntax = "proto3";
package google.api;
message Http {
repeated HttpRule rules = 1;
}
message HttpRule {
oneof pattern {
string get = 2;
string put = 3;
string post = 4;
string delete = 5;
string patch = 6;
CustomHttpPattern custom = 8;
}
string selector = 1;
string body = 7;
repeated HttpRule additional_bindings = 11;
}
message CustomHttpPattern {
string kind = 1;
string path = 2;
}
+124
View File
@@ -0,0 +1,124 @@
{
"nested": {
"google": {
"nested": {
"protobuf": {
"nested": {
"Api": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"methods": {
"rule": "repeated",
"type": "Method",
"id": 2
},
"options": {
"rule": "repeated",
"type": "Option",
"id": 3
},
"version": {
"type": "string",
"id": 4
},
"sourceContext": {
"type": "SourceContext",
"id": 5,
"protoName": "source_context"
},
"mixins": {
"rule": "repeated",
"type": "Mixin",
"id": 6
},
"syntax": {
"type": "Syntax",
"id": 7
}
}
},
"Method": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"requestTypeUrl": {
"type": "string",
"id": 2,
"protoName": "request_type_url"
},
"requestStreaming": {
"type": "bool",
"id": 3,
"protoName": "request_streaming"
},
"responseTypeUrl": {
"type": "string",
"id": 4,
"protoName": "response_type_url"
},
"responseStreaming": {
"type": "bool",
"id": 5,
"protoName": "response_streaming"
},
"options": {
"rule": "repeated",
"type": "Option",
"id": 6
},
"syntax": {
"type": "Syntax",
"id": 7
}
}
},
"Mixin": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"root": {
"type": "string",
"id": 2
}
}
},
"SourceContext": {
"fields": {
"fileName": {
"type": "string",
"id": 1,
"protoName": "file_name"
}
}
},
"Option": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"value": {
"type": "Any",
"id": 2
}
}
},
"Syntax": {
"values": {
"SYNTAX_PROTO2": 0,
"SYNTAX_PROTO3": 1
}
}
}
}
}
}
}
}
+34
View File
@@ -0,0 +1,34 @@
syntax = "proto3";
package google.protobuf;
import "google/protobuf/source_context.proto";
import "google/protobuf/type.proto";
message Api {
string name = 1;
repeated Method methods = 2;
repeated Option options = 3;
string version = 4;
SourceContext source_context = 5;
repeated Mixin mixins = 6;
Syntax syntax = 7;
}
message Method {
string name = 1;
string request_type_url = 2;
bool request_streaming = 3;
string response_type_url = 4;
bool response_streaming = 5;
repeated Option options = 6;
Syntax syntax = 7;
}
message Mixin {
string name = 1;
string root = 2;
}
+126
View File
@@ -0,0 +1,126 @@
{
"nested": {
"google": {
"nested": {
"protobuf": {
"nested": {
"compiler": {
"options": {
"java_package": "com.google.protobuf.compiler",
"java_outer_classname": "PluginProtos",
"csharp_namespace": "Google.Protobuf.Compiler",
"go_package": "google.golang.org/protobuf/types/pluginpb"
},
"nested": {
"Version": {
"edition": "proto2",
"fields": {
"major": {
"type": "int32",
"id": 1
},
"minor": {
"type": "int32",
"id": 2
},
"patch": {
"type": "int32",
"id": 3
},
"suffix": {
"type": "string",
"id": 4
}
}
},
"CodeGeneratorRequest": {
"edition": "proto2",
"fields": {
"fileToGenerate": {
"rule": "repeated",
"type": "string",
"id": 1
},
"parameter": {
"type": "string",
"id": 2
},
"protoFile": {
"rule": "repeated",
"type": "FileDescriptorProto",
"id": 15
},
"sourceFileDescriptors": {
"rule": "repeated",
"type": "FileDescriptorProto",
"id": 17
},
"compilerVersion": {
"type": "Version",
"id": 3
}
}
},
"CodeGeneratorResponse": {
"edition": "proto2",
"fields": {
"error": {
"type": "string",
"id": 1
},
"supportedFeatures": {
"type": "uint64",
"id": 2
},
"minimumEdition": {
"type": "int32",
"id": 3
},
"maximumEdition": {
"type": "int32",
"id": 4
},
"file": {
"rule": "repeated",
"type": "File",
"id": 15
}
},
"nested": {
"Feature": {
"values": {
"FEATURE_NONE": 0,
"FEATURE_PROTO3_OPTIONAL": 1,
"FEATURE_SUPPORTS_EDITIONS": 2
}
},
"File": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"insertionPoint": {
"type": "string",
"id": 2
},
"content": {
"type": "string",
"id": 15
},
"generatedCodeInfo": {
"type": "GeneratedCodeInfo",
"id": 16
}
}
}
}
}
}
}
}
}
}
}
}
}
+47
View File
@@ -0,0 +1,47 @@
syntax = "proto2";
package google.protobuf.compiler;
option java_package = "com.google.protobuf.compiler";
option java_outer_classname = "PluginProtos";
import "google/protobuf/descriptor.proto";
option csharp_namespace = "Google.Protobuf.Compiler";
option go_package = "google.golang.org/protobuf/types/pluginpb";
message Version {
optional int32 major = 1;
optional int32 minor = 2;
optional int32 patch = 3;
optional string suffix = 4;
}
message CodeGeneratorRequest {
repeated string file_to_generate = 1;
optional string parameter = 2;
repeated FileDescriptorProto proto_file = 15;
repeated FileDescriptorProto source_file_descriptors = 17;
optional Version compiler_version = 3;
}
message CodeGeneratorResponse {
optional string error = 1;
optional uint64 supported_features = 2;
enum Feature {
FEATURE_NONE = 0;
FEATURE_PROTO3_OPTIONAL = 1;
FEATURE_SUPPORTS_EDITIONS = 2;
}
optional int32 minimum_edition = 3;
optional int32 maximum_edition = 4;
message File {
optional string name = 1;
optional string insertion_point = 2;
optional string content = 15;
optional GeneratedCodeInfo generated_code_info = 16;
}
repeated File file = 15;
}
File diff suppressed because it is too large Load Diff
+527
View File
@@ -0,0 +1,527 @@
syntax = "proto2";
package google.protobuf;
message FileDescriptorSet {
repeated FileDescriptorProto file = 1;
extensions 536000000;
}
enum Edition {
EDITION_UNKNOWN = 0;
EDITION_LEGACY = 900;
EDITION_PROTO2 = 998;
EDITION_PROTO3 = 999;
EDITION_2023 = 1000;
EDITION_2024 = 1001;
EDITION_1_TEST_ONLY = 1;
EDITION_2_TEST_ONLY = 2;
EDITION_99997_TEST_ONLY = 99997;
EDITION_99998_TEST_ONLY = 99998;
EDITION_99999_TEST_ONLY = 99999;
EDITION_MAX = 2147483647;
}
message FileDescriptorProto {
optional string name = 1;
optional string package = 2;
repeated string dependency = 3;
repeated int32 public_dependency = 10;
repeated int32 weak_dependency = 11;
repeated string option_dependency = 15;
repeated DescriptorProto message_type = 4;
repeated EnumDescriptorProto enum_type = 5;
repeated ServiceDescriptorProto service = 6;
repeated FieldDescriptorProto extension = 7;
optional FileOptions options = 8;
optional SourceCodeInfo source_code_info = 9;
optional string syntax = 12;
optional Edition edition = 14;
}
message DescriptorProto {
optional string name = 1;
repeated FieldDescriptorProto field = 2;
repeated FieldDescriptorProto extension = 6;
repeated DescriptorProto nested_type = 3;
repeated EnumDescriptorProto enum_type = 4;
repeated ExtensionRange extension_range = 5;
repeated OneofDescriptorProto oneof_decl = 8;
optional MessageOptions options = 7;
repeated ReservedRange reserved_range = 9;
repeated string reserved_name = 10;
optional SymbolVisibility visibility = 11;
message ExtensionRange {
optional int32 start = 1;
optional int32 end = 2;
optional ExtensionRangeOptions options = 3;
}
message ReservedRange {
optional int32 start = 1;
optional int32 end = 2;
}
}
message ExtensionRangeOptions {
repeated UninterpretedOption uninterpreted_option = 999;
repeated Declaration declaration = 2 [retention="RETENTION_SOURCE"];
optional FeatureSet features = 50;
optional VerificationState verification = 3 [default=UNVERIFIED, retention="RETENTION_SOURCE"];
message Declaration {
optional int32 number = 1;
optional string full_name = 2;
optional string type = 3;
optional bool reserved = 5;
optional bool repeated = 6;
reserved 4;
}
enum VerificationState {
DECLARATION = 0;
UNVERIFIED = 1;
}
extensions 1000 to max;
}
message FieldDescriptorProto {
optional string name = 1;
optional int32 number = 3;
optional Label label = 4;
optional Type type = 5;
optional string type_name = 6;
optional string extendee = 2;
optional string default_value = 7;
optional int32 oneof_index = 9;
optional string json_name = 10;
optional FieldOptions options = 8;
optional bool proto3_optional = 17;
enum Type {
TYPE_DOUBLE = 1;
TYPE_FLOAT = 2;
TYPE_INT64 = 3;
TYPE_UINT64 = 4;
TYPE_INT32 = 5;
TYPE_FIXED64 = 6;
TYPE_FIXED32 = 7;
TYPE_BOOL = 8;
TYPE_STRING = 9;
TYPE_GROUP = 10;
TYPE_MESSAGE = 11;
TYPE_BYTES = 12;
TYPE_UINT32 = 13;
TYPE_ENUM = 14;
TYPE_SFIXED32 = 15;
TYPE_SFIXED64 = 16;
TYPE_SINT32 = 17;
TYPE_SINT64 = 18;
}
enum Label {
LABEL_OPTIONAL = 1;
LABEL_REPEATED = 3;
LABEL_REQUIRED = 2;
}
}
message OneofDescriptorProto {
optional string name = 1;
optional OneofOptions options = 2;
}
message EnumDescriptorProto {
optional string name = 1;
repeated EnumValueDescriptorProto value = 2;
optional EnumOptions options = 3;
repeated EnumReservedRange reserved_range = 4;
repeated string reserved_name = 5;
optional SymbolVisibility visibility = 6;
message EnumReservedRange {
optional int32 start = 1;
optional int32 end = 2;
}
}
message EnumValueDescriptorProto {
optional string name = 1;
optional int32 number = 2;
optional EnumValueOptions options = 3;
}
message ServiceDescriptorProto {
optional string name = 1;
repeated MethodDescriptorProto method = 2;
optional ServiceOptions options = 3;
}
message MethodDescriptorProto {
optional string name = 1;
optional string input_type = 2;
optional string output_type = 3;
optional MethodOptions options = 4;
optional bool client_streaming = 5;
optional bool server_streaming = 6;
}
message FileOptions {
optional string java_package = 1;
optional string java_outer_classname = 8;
optional bool java_multiple_files = 10;
optional bool java_generate_equals_and_hash = 20 [deprecated=true];
optional bool java_string_check_utf8 = 27;
optional OptimizeMode optimize_for = 9 [default=SPEED];
optional string go_package = 11;
optional bool cc_generic_services = 16;
optional bool java_generic_services = 17;
optional bool py_generic_services = 18;
optional bool deprecated = 23;
optional bool cc_enable_arenas = 31 [default=true];
optional string objc_class_prefix = 36;
optional string csharp_namespace = 37;
optional string swift_prefix = 39;
optional string php_class_prefix = 40;
optional string php_namespace = 41;
optional string php_metadata_namespace = 44;
optional string ruby_package = 45;
optional FeatureSet features = 50;
repeated UninterpretedOption uninterpreted_option = 999;
enum OptimizeMode {
SPEED = 1;
CODE_SIZE = 2;
LITE_RUNTIME = 3;
}
extensions 1000 to max;
reserved 42, 38;
reserved "php_generic_services";
}
message MessageOptions {
optional bool message_set_wire_format = 1;
optional bool no_standard_descriptor_accessor = 2;
optional bool deprecated = 3;
optional bool map_entry = 7;
optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated=true];
optional FeatureSet features = 12;
repeated UninterpretedOption uninterpreted_option = 999;
extensions 1000 to max;
reserved 4, 5, 6, 8, 9;
}
message FieldOptions {
optional CType ctype = 1 [default=STRING];
optional bool packed = 2;
optional JSType jstype = 6 [default=JS_NORMAL];
optional bool lazy = 5;
optional bool unverified_lazy = 15;
optional bool deprecated = 3;
optional bool weak = 10 [deprecated=true];
optional bool debug_redact = 16;
optional OptionRetention retention = 17;
repeated OptionTargetType targets = 19;
repeated EditionDefault edition_defaults = 20;
optional FeatureSet features = 21;
optional FeatureSupport feature_support = 22;
repeated UninterpretedOption uninterpreted_option = 999;
enum CType {
STRING = 0;
CORD = 1;
STRING_PIECE = 2;
}
enum JSType {
JS_NORMAL = 0;
JS_STRING = 1;
JS_NUMBER = 2;
}
enum OptionRetention {
RETENTION_UNKNOWN = 0;
RETENTION_RUNTIME = 1;
RETENTION_SOURCE = 2;
}
enum OptionTargetType {
TARGET_TYPE_UNKNOWN = 0;
TARGET_TYPE_FILE = 1;
TARGET_TYPE_EXTENSION_RANGE = 2;
TARGET_TYPE_MESSAGE = 3;
TARGET_TYPE_FIELD = 4;
TARGET_TYPE_ONEOF = 5;
TARGET_TYPE_ENUM = 6;
TARGET_TYPE_ENUM_ENTRY = 7;
TARGET_TYPE_SERVICE = 8;
TARGET_TYPE_METHOD = 9;
}
message EditionDefault {
optional Edition edition = 3;
optional string value = 2;
}
message FeatureSupport {
optional Edition edition_introduced = 1;
optional Edition edition_deprecated = 2;
optional string deprecation_warning = 3;
optional Edition edition_removed = 4;
}
extensions 1000 to max;
reserved 4, 18;
}
message OneofOptions {
optional FeatureSet features = 1;
repeated UninterpretedOption uninterpreted_option = 999;
extensions 1000 to max;
}
message EnumOptions {
optional bool allow_alias = 2;
optional bool deprecated = 3;
optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated=true];
optional FeatureSet features = 7;
repeated UninterpretedOption uninterpreted_option = 999;
extensions 1000 to max;
reserved 5;
}
message EnumValueOptions {
optional bool deprecated = 1;
optional FeatureSet features = 2;
optional bool debug_redact = 3;
optional FieldOptions.FeatureSupport feature_support = 4;
repeated UninterpretedOption uninterpreted_option = 999;
extensions 1000 to max;
}
message ServiceOptions {
optional FeatureSet features = 34;
optional bool deprecated = 33;
repeated UninterpretedOption uninterpreted_option = 999;
extensions 1000 to max;
}
message MethodOptions {
optional bool deprecated = 33;
optional IdempotencyLevel idempotency_level = 34 [default=IDEMPOTENCY_UNKNOWN];
optional FeatureSet features = 35;
repeated UninterpretedOption uninterpreted_option = 999;
enum IdempotencyLevel {
IDEMPOTENCY_UNKNOWN = 0;
NO_SIDE_EFFECTS = 1;
IDEMPOTENT = 2;
}
extensions 1000 to max;
}
message UninterpretedOption {
repeated NamePart name = 2;
optional string identifier_value = 3;
optional uint64 positive_int_value = 4;
optional int64 negative_int_value = 5;
optional double double_value = 6;
optional bytes string_value = 7;
optional string aggregate_value = 8;
message NamePart {
required string name_part = 1;
required bool is_extension = 2;
}
}
message FeatureSet {
optional FieldPresence field_presence = 1 [retention="RETENTION_RUNTIME", targets="TARGET_TYPE_FILE", feature_support.edition_introduced="EDITION_2023", edition_defaults.edition="EDITION_2023", edition_defaults.value="EXPLICIT"];
optional EnumType enum_type = 2 [retention="RETENTION_RUNTIME", targets="TARGET_TYPE_FILE", feature_support.edition_introduced="EDITION_2023", edition_defaults.edition="EDITION_PROTO3", edition_defaults.value="OPEN"];
optional RepeatedFieldEncoding repeated_field_encoding = 3 [retention="RETENTION_RUNTIME", targets="TARGET_TYPE_FILE", feature_support.edition_introduced="EDITION_2023", edition_defaults.edition="EDITION_PROTO3", edition_defaults.value="PACKED"];
optional Utf8Validation utf8_validation = 4 [retention="RETENTION_RUNTIME", targets="TARGET_TYPE_FILE", feature_support.edition_introduced="EDITION_2023", edition_defaults.edition="EDITION_PROTO3", edition_defaults.value="VERIFY"];
optional MessageEncoding message_encoding = 5 [retention="RETENTION_RUNTIME", targets="TARGET_TYPE_FILE", feature_support.edition_introduced="EDITION_2023", edition_defaults.edition="EDITION_LEGACY", edition_defaults.value="LENGTH_PREFIXED"];
optional JsonFormat json_format = 6 [retention="RETENTION_RUNTIME", targets="TARGET_TYPE_FILE", feature_support.edition_introduced="EDITION_2023", edition_defaults.edition="EDITION_PROTO3", edition_defaults.value="ALLOW"];
optional EnforceNamingStyle enforce_naming_style = 7 [retention="RETENTION_SOURCE", targets="TARGET_TYPE_METHOD", feature_support.edition_introduced="EDITION_2024", edition_defaults.edition="EDITION_2024", edition_defaults.value="STYLE2024"];
optional VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = 8 [retention="RETENTION_SOURCE", targets="TARGET_TYPE_FILE", feature_support.edition_introduced="EDITION_2024", edition_defaults.edition="EDITION_2024", edition_defaults.value="EXPORT_TOP_LEVEL"];
enum FieldPresence {
FIELD_PRESENCE_UNKNOWN = 0;
EXPLICIT = 1;
IMPLICIT = 2;
LEGACY_REQUIRED = 3;
}
enum EnumType {
ENUM_TYPE_UNKNOWN = 0;
OPEN = 1;
CLOSED = 2;
}
enum RepeatedFieldEncoding {
REPEATED_FIELD_ENCODING_UNKNOWN = 0;
PACKED = 1;
EXPANDED = 2;
}
enum Utf8Validation {
UTF8_VALIDATION_UNKNOWN = 0;
VERIFY = 2;
NONE = 3;
}
enum MessageEncoding {
MESSAGE_ENCODING_UNKNOWN = 0;
LENGTH_PREFIXED = 1;
DELIMITED = 2;
}
enum JsonFormat {
JSON_FORMAT_UNKNOWN = 0;
ALLOW = 1;
LEGACY_BEST_EFFORT = 2;
}
enum EnforceNamingStyle {
ENFORCE_NAMING_STYLE_UNKNOWN = 0;
STYLE2024 = 1;
STYLE_LEGACY = 2;
}
message VisibilityFeature {
enum DefaultSymbolVisibility {
DEFAULT_SYMBOL_VISIBILITY_UNKNOWN = 0;
EXPORT_ALL = 1;
EXPORT_TOP_LEVEL = 2;
LOCAL_ALL = 3;
STRICT = 4;
}
reserved 1 to max;
}
extensions 1000 to 9994, 9995 to 9999, 10000;
reserved 999;
}
message FeatureSetDefaults {
repeated FeatureSetEditionDefault defaults = 1;
optional Edition minimum_edition = 4;
optional Edition maximum_edition = 5;
message FeatureSetEditionDefault {
optional Edition edition = 3;
optional FeatureSet overridable_features = 4;
optional FeatureSet fixed_features = 5;
reserved 1, 2, "features";
}
}
message SourceCodeInfo {
repeated Location location = 1;
message Location {
repeated int32 path = 1 [packed=true];
repeated int32 span = 2 [packed=true];
optional string leading_comments = 3;
optional string trailing_comments = 4;
repeated string leading_detached_comments = 6;
}
extensions 536000000;
}
message GeneratedCodeInfo {
repeated Annotation annotation = 1;
message Annotation {
repeated int32 path = 1 [packed=true];
optional string source_file = 2;
optional int32 begin = 3;
optional int32 end = 4;
optional Semantic semantic = 5;
enum Semantic {
NONE = 0;
SET = 1;
ALIAS = 2;
}
}
}
enum SymbolVisibility {
VISIBILITY_UNSET = 0;
VISIBILITY_LOCAL = 1;
VISIBILITY_EXPORT = 2;
}
+21
View File
@@ -0,0 +1,21 @@
{
"nested": {
"google": {
"nested": {
"protobuf": {
"nested": {
"SourceContext": {
"fields": {
"fileName": {
"type": "string",
"id": 1,
"protoName": "file_name"
}
}
}
}
}
}
}
}
}
+7
View File
@@ -0,0 +1,7 @@
syntax = "proto3";
package google.protobuf;
message SourceContext {
string file_name = 1;
}
+209
View File
@@ -0,0 +1,209 @@
{
"nested": {
"google": {
"nested": {
"protobuf": {
"nested": {
"Type": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"fields": {
"rule": "repeated",
"type": "Field",
"id": 2
},
"oneofs": {
"rule": "repeated",
"type": "string",
"id": 3
},
"options": {
"rule": "repeated",
"type": "Option",
"id": 4
},
"sourceContext": {
"type": "SourceContext",
"id": 5,
"protoName": "source_context"
},
"syntax": {
"type": "Syntax",
"id": 6
}
}
},
"Field": {
"fields": {
"kind": {
"type": "Kind",
"id": 1
},
"cardinality": {
"type": "Cardinality",
"id": 2
},
"number": {
"type": "int32",
"id": 3
},
"name": {
"type": "string",
"id": 4
},
"typeUrl": {
"type": "string",
"id": 6,
"protoName": "type_url"
},
"oneofIndex": {
"type": "int32",
"id": 7,
"protoName": "oneof_index"
},
"packed": {
"type": "bool",
"id": 8
},
"options": {
"rule": "repeated",
"type": "Option",
"id": 9
},
"jsonName": {
"type": "string",
"id": 10,
"protoName": "json_name"
},
"defaultValue": {
"type": "string",
"id": 11,
"protoName": "default_value"
}
},
"nested": {
"Kind": {
"values": {
"TYPE_UNKNOWN": 0,
"TYPE_DOUBLE": 1,
"TYPE_FLOAT": 2,
"TYPE_INT64": 3,
"TYPE_UINT64": 4,
"TYPE_INT32": 5,
"TYPE_FIXED64": 6,
"TYPE_FIXED32": 7,
"TYPE_BOOL": 8,
"TYPE_STRING": 9,
"TYPE_GROUP": 10,
"TYPE_MESSAGE": 11,
"TYPE_BYTES": 12,
"TYPE_UINT32": 13,
"TYPE_ENUM": 14,
"TYPE_SFIXED32": 15,
"TYPE_SFIXED64": 16,
"TYPE_SINT32": 17,
"TYPE_SINT64": 18
}
},
"Cardinality": {
"values": {
"CARDINALITY_UNKNOWN": 0,
"CARDINALITY_OPTIONAL": 1,
"CARDINALITY_REQUIRED": 2,
"CARDINALITY_REPEATED": 3
}
}
}
},
"Enum": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"enumvalue": {
"rule": "repeated",
"type": "EnumValue",
"id": 2
},
"options": {
"rule": "repeated",
"type": "Option",
"id": 3
},
"sourceContext": {
"type": "SourceContext",
"id": 4,
"protoName": "source_context"
},
"syntax": {
"type": "Syntax",
"id": 5
}
}
},
"EnumValue": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"number": {
"type": "int32",
"id": 2
},
"options": {
"rule": "repeated",
"type": "Option",
"id": 3
}
}
},
"Option": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"value": {
"type": "Any",
"id": 2
}
}
},
"Syntax": {
"values": {
"SYNTAX_PROTO2": 0,
"SYNTAX_PROTO3": 1
}
},
"Any": {
"fields": {
"type_url": {
"type": "string",
"id": 1
},
"value": {
"type": "bytes",
"id": 2
}
}
},
"SourceContext": {
"fields": {
"fileName": {
"type": "string",
"id": 1,
"protoName": "file_name"
}
}
}
}
}
}
}
}
}
+89
View File
@@ -0,0 +1,89 @@
syntax = "proto3";
package google.protobuf;
import "google/protobuf/any.proto";
import "google/protobuf/source_context.proto";
message Type {
string name = 1;
repeated Field fields = 2;
repeated string oneofs = 3;
repeated Option options = 4;
SourceContext source_context = 5;
Syntax syntax = 6;
}
message Field {
Kind kind = 1;
Cardinality cardinality = 2;
int32 number = 3;
string name = 4;
string type_url = 6;
int32 oneof_index = 7;
bool packed = 8;
repeated Option options = 9;
string json_name = 10;
string default_value = 11;
enum Kind {
TYPE_UNKNOWN = 0;
TYPE_DOUBLE = 1;
TYPE_FLOAT = 2;
TYPE_INT64 = 3;
TYPE_UINT64 = 4;
TYPE_INT32 = 5;
TYPE_FIXED64 = 6;
TYPE_FIXED32 = 7;
TYPE_BOOL = 8;
TYPE_STRING = 9;
TYPE_GROUP = 10;
TYPE_MESSAGE = 11;
TYPE_BYTES = 12;
TYPE_UINT32 = 13;
TYPE_ENUM = 14;
TYPE_SFIXED32 = 15;
TYPE_SFIXED64 = 16;
TYPE_SINT32 = 17;
TYPE_SINT64 = 18;
}
enum Cardinality {
CARDINALITY_UNKNOWN = 0;
CARDINALITY_OPTIONAL = 1;
CARDINALITY_REQUIRED = 2;
CARDINALITY_REPEATED = 3;
}
}
message Enum {
string name = 1;
repeated EnumValue enumvalue = 2;
repeated Option options = 3;
SourceContext source_context = 4;
Syntax syntax = 5;
}
message EnumValue {
string name = 1;
int32 number = 2;
repeated Option options = 3;
}
message Option {
string name = 1;
Any value = 2;
}
enum Syntax {
SYNTAX_PROTO2 = 0;
SYNTAX_PROTO3 = 1;
}
+3203
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
// full library entry point.
"use strict";
module.exports = require("./src/index");
+2
View File
@@ -0,0 +1,2 @@
export as namespace protobuf;
export * from "./index";
+4
View File
@@ -0,0 +1,4 @@
// light library entry point.
"use strict";
module.exports = require("./src/index-light");
+2
View File
@@ -0,0 +1,2 @@
export as namespace protobuf;
export * from "./index";
+4
View File
@@ -0,0 +1,4 @@
// minimal library entry point.
"use strict";
module.exports = require("./src/index-minimal");
+93
View File
@@ -0,0 +1,93 @@
{
"name": "protobufjs",
"version": "8.7.1",
"description": "Protocol Buffers for JavaScript & TypeScript.",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"license": "BSD-3-Clause",
"repository": "protobufjs/protobuf.js",
"bugs": "https://github.com/protobufjs/protobuf.js/issues",
"engines": {
"node": ">=12.0.0"
},
"keywords": [
"protobuf",
"protocol-buffers",
"serialization",
"typescript"
],
"main": "index.js",
"type": "commonjs",
"types": "index.d.ts",
"browser": {
"fs": false
},
"scripts": {
"bench": "npm --prefix bench run bench",
"build": "npm run build:bundle && npm run build:types",
"build:bundle": "gulp --gulpfile scripts/gulpfile.js",
"build:tests": "node ./scripts/gentests.js",
"build:types": "node cli/bin/pbts --main --global protobuf --out index.d.ts src/ && node cli/bin/pbts --main --import \"\\$protobuf=..\" --out ext/descriptor.generated.d.ts ext/descriptor.js && node cli/bin/pbts --main --import \"\\$protobuf=..\" --out ext/textformat.generated.d.ts ext/textformat.js && node cli/bin/pbts --main --import \"\\$protobuf=..\" --out ext/protojson.generated.d.ts ext/protojson.js",
"coverage": "npm run coverage:test && npm run coverage:report",
"coverage:test": "nyc --silent tape -r ./lib/tape-adapter tests/*.js tests/node/*.js",
"coverage:report": "nyc report --reporter=lcov --reporter=text",
"docs": "npm run docs:build",
"docs:build": "jsdoc -c config/jsdoc.json -R README.md --verbose --pedantic",
"docs:publish": "npm run docs:build && node scripts/pages",
"lint": "npm run lint:sources && npm run lint:types",
"lint:sources": "eslint \"**/*.js\"",
"lint:types": "tslint \"**/*.d.ts\" -e \"**/node_modules/**\" -t stylish -c config/tslint.json",
"prepublish": "cd cli && npm install && cd .. && npm run build",
"prepublishOnly": "cd cli && npm install && cd .. && npm run build",
"prof": "node bench/prof",
"test": "npm run test:sources && npm run test:types",
"test:sources": "tape -r ./lib/tape-adapter tests/*.js tests/node/*.js",
"test:types": "tsc tests/comp_typescript.ts --target es2019 --module commonjs --types node --lib es2019 --esModuleInterop --strictNullChecks --experimentalDecorators --emitDecoratorMetadata && tsc -p tsconfig.test-types.json",
"make": "npm run lint:sources && npm run build && npm run lint:types && npm run build:tests && npm test"
},
"dependencies": {
"long": "^5.3.2"
},
"devDependencies": {
"@eslint/js": "^10.0.0",
"@types/node": "^18.19.130",
"browserify": "^17.0.0",
"browserify-wrap": "^1.0.2",
"bundle-collapser": "^1.3.0",
"escodegen": "^2.0.0",
"eslint": "^10.0.0",
"eslint-plugin-jsdoc": "^63.0.0",
"espree": "^9.0.0",
"estraverse": "^5.1.0",
"gh-pages": "^6.0.0",
"globals": "^17.0.0",
"gulp": "^5.0.0",
"gulp-header": "^2.0.9",
"gulp-if": "^3.0.0",
"gulp-sourcemaps": "^3.0.0",
"gulp-uglify": "^3.0.2",
"jsdoc": "^4.0.0",
"minimist": "^1.2.8",
"nyc": "^18.0.0",
"reflect-metadata": "^0.2.0",
"tape": "^5.0.0",
"tslint": "^6.0.0",
"typescript": "^4.9.5",
"vinyl-buffer": "^1.0.1",
"vinyl-fs": "^4.0.0",
"vinyl-source-stream": "^2.0.0"
},
"files": [
"index.js",
"index.d.ts",
"light.d.ts",
"light.js",
"minimal.d.ts",
"minimal.js",
"package-lock.json",
"tsconfig.json",
"dist/**",
"ext/**",
"google/**",
"src/**"
]
}
+405
View File
@@ -0,0 +1,405 @@
"use strict";
module.exports = common;
var commonRe = /\/|\./;
/**
* Provides common type definitions.
* Can also be used to provide additional google types or your own custom types.
* @param {string} name Short name as in `google/protobuf/[name].proto` or full file name
* @param {Object.<string,*>} json JSON definition within `google.protobuf` if a short name, otherwise the file's root definition
* @returns {undefined}
* @property {INamespace} google/protobuf/any.proto Any
* @property {INamespace} google/protobuf/duration.proto Duration
* @property {INamespace} google/protobuf/empty.proto Empty
* @property {INamespace} google/protobuf/field_mask.proto FieldMask
* @property {INamespace} google/protobuf/struct.proto Struct, Value, NullValue and ListValue
* @property {INamespace} google/protobuf/timestamp.proto Timestamp
* @property {INamespace} google/protobuf/wrappers.proto Wrappers
* @example
* // manually provides descriptor.proto (assumes google/protobuf/ namespace and .proto extension)
* protobuf.common("descriptor", descriptorJson);
*
* // manually provides a custom definition (uses my.foo namespace)
* protobuf.common("my/foo/bar.proto", myFooBarJson);
*/
function common(name, json) {
if (!commonRe.test(name)) {
name = "google/protobuf/" + name + ".proto";
json = { nested: { google: { nested: { protobuf: { nested: json } } } } };
}
common[name] = json;
}
// Not provided because of limited use (feel free to discuss or to provide yourself):
//
// google/protobuf/descriptor.proto
// google/protobuf/source_context.proto
// google/protobuf/type.proto
//
// Stripped and pre-parsed versions of these non-bundled files are instead available as part of
// the repository or package within the google/protobuf directory.
common("any", {
/**
* Properties of a google.protobuf.Any message.
* @interface IAny
* @type {Object}
* @property {string} [typeUrl]
* @property {Uint8Array} [bytes]
* @memberof common
*/
Any: {
fields: {
type_url: {
type: "string",
id: 1
},
value: {
type: "bytes",
id: 2
}
}
}
});
var timeType;
common("duration", {
/**
* Properties of a google.protobuf.Duration message.
* @interface IDuration
* @type {Object}
* @property {number|Long} [seconds]
* @property {number} [nanos]
* @memberof common
*/
Duration: timeType = {
fields: {
seconds: {
type: "int64",
id: 1
},
nanos: {
type: "int32",
id: 2
}
}
}
});
common("timestamp", {
/**
* Properties of a google.protobuf.Timestamp message.
* @interface ITimestamp
* @type {Object}
* @property {number|Long} [seconds]
* @property {number} [nanos]
* @memberof common
*/
Timestamp: timeType
});
common("empty", {
/**
* Properties of a google.protobuf.Empty message.
* @interface IEmpty
* @memberof common
*/
Empty: {
fields: {}
}
});
common("struct", {
/**
* Properties of a google.protobuf.Struct message.
* @interface IStruct
* @type {Object}
* @property {Object.<string,IValue>} [fields]
* @memberof common
*/
Struct: {
fields: {
fields: {
keyType: "string",
type: "Value",
id: 1
}
}
},
/**
* Properties of a google.protobuf.Value message.
* @interface IValue
* @type {Object}
* @property {string} [kind]
* @property {0} [nullValue]
* @property {number} [numberValue]
* @property {string} [stringValue]
* @property {boolean} [boolValue]
* @property {IStruct} [structValue]
* @property {IListValue} [listValue]
* @memberof common
*/
Value: {
oneofs: {
kind: {
oneof: [
"nullValue",
"numberValue",
"stringValue",
"boolValue",
"structValue",
"listValue"
]
}
},
fields: {
nullValue: {
type: "NullValue",
id: 1,
protoName: "null_value"
},
numberValue: {
type: "double",
id: 2,
protoName: "number_value"
},
stringValue: {
type: "string",
id: 3,
protoName: "string_value"
},
boolValue: {
type: "bool",
id: 4,
protoName: "bool_value"
},
structValue: {
type: "Struct",
id: 5,
protoName: "struct_value"
},
listValue: {
type: "ListValue",
id: 6,
protoName: "list_value"
}
}
},
NullValue: {
values: {
NULL_VALUE: 0
}
},
/**
* Properties of a google.protobuf.ListValue message.
* @interface IListValue
* @type {Object}
* @property {Array.<IValue>} [values]
* @memberof common
*/
ListValue: {
fields: {
values: {
rule: "repeated",
type: "Value",
id: 1
}
}
}
});
common("wrappers", {
/**
* Properties of a google.protobuf.DoubleValue message.
* @interface IDoubleValue
* @type {Object}
* @property {number} [value]
* @memberof common
*/
DoubleValue: {
fields: {
value: {
type: "double",
id: 1
}
}
},
/**
* Properties of a google.protobuf.FloatValue message.
* @interface IFloatValue
* @type {Object}
* @property {number} [value]
* @memberof common
*/
FloatValue: {
fields: {
value: {
type: "float",
id: 1
}
}
},
/**
* Properties of a google.protobuf.Int64Value message.
* @interface IInt64Value
* @type {Object}
* @property {number|Long} [value]
* @memberof common
*/
Int64Value: {
fields: {
value: {
type: "int64",
id: 1
}
}
},
/**
* Properties of a google.protobuf.UInt64Value message.
* @interface IUInt64Value
* @type {Object}
* @property {number|Long} [value]
* @memberof common
*/
UInt64Value: {
fields: {
value: {
type: "uint64",
id: 1
}
}
},
/**
* Properties of a google.protobuf.Int32Value message.
* @interface IInt32Value
* @type {Object}
* @property {number} [value]
* @memberof common
*/
Int32Value: {
fields: {
value: {
type: "int32",
id: 1
}
}
},
/**
* Properties of a google.protobuf.UInt32Value message.
* @interface IUInt32Value
* @type {Object}
* @property {number} [value]
* @memberof common
*/
UInt32Value: {
fields: {
value: {
type: "uint32",
id: 1
}
}
},
/**
* Properties of a google.protobuf.BoolValue message.
* @interface IBoolValue
* @type {Object}
* @property {boolean} [value]
* @memberof common
*/
BoolValue: {
fields: {
value: {
type: "bool",
id: 1
}
}
},
/**
* Properties of a google.protobuf.StringValue message.
* @interface IStringValue
* @type {Object}
* @property {string} [value]
* @memberof common
*/
StringValue: {
fields: {
value: {
type: "string",
id: 1
}
}
},
/**
* Properties of a google.protobuf.BytesValue message.
* @interface IBytesValue
* @type {Object}
* @property {Uint8Array} [value]
* @memberof common
*/
BytesValue: {
fields: {
value: {
type: "bytes",
id: 1
}
}
}
});
common("field_mask", {
/**
* Properties of a google.protobuf.FieldMask message.
* @interface IFieldMask
* @type {Object}
* @property {string[]} [paths]
* @memberof common
*/
FieldMask: {
fields: {
paths: {
rule: "repeated",
type: "string",
id: 1
}
}
}
});
/**
* Gets the root definition of the specified common proto file.
*
* Bundled definitions are:
* - google/protobuf/any.proto
* - google/protobuf/duration.proto
* - google/protobuf/empty.proto
* - google/protobuf/field_mask.proto
* - google/protobuf/struct.proto
* - google/protobuf/timestamp.proto
* - google/protobuf/wrappers.proto
*
* @param {string} file Proto file name
* @returns {INamespace|null} Root definition or `null` if not defined
*/
common.get = function get(file) {
return common[file] || null;
};
+352
View File
@@ -0,0 +1,352 @@
"use strict";
/**
* Runtime message from/to plain object converters.
* @namespace
*/
var converter = exports;
var Enum = require("./enum"),
types = require("./types"),
util = require("./util");
/**
* Generates a partial value fromObject conveter.
* @param {Codegen} gen Codegen instance
* @param {Field} field Reflected field
* @param {number} fieldIndex Field index
* @param {string} prop Property reference
* @param {string} [dstProp] Repeated destination property reference
* @returns {Codegen} Codegen instance
* @ignore
*/
function genValuePartial_fromObject(gen, field, fieldIndex, prop, dstProp) {
/* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */
if (field.resolvedType) {
if (field.resolvedType instanceof Enum) {
var dst = dstProp
? "m" + dstProp + "[m" + dstProp + ".length]"
: "m" + prop;
gen
("switch(d%s){", prop);
for (var values = field.resolvedType.values, keys = Object.keys(values), i = 0; i < keys.length; ++i) { gen
("case%j:", keys[i])
("case %i:", values[keys[i]])
("%s=%j", dst, values[keys[i]])
("break");
}
gen
("default:");
if (field.resolvedType._features.enum_type !== "CLOSED") {
gen
("if(typeof d%s===\"number\"&&(d%s|0)===d%s)", prop, prop, prop)
("%s=d%s", dst, prop);
}
gen
("}");
} else gen
("if(!util.isObject(d%s))", prop)
("throw TypeError(%j)", field.fullName + ": object expected")
("m%s=types[%i].fromObject(d%s,q+1)", prop, fieldIndex, prop);
} else {
var isUnsigned = false;
switch (field.type) {
case "double":
case "float": gen
("m%s=Number(d%s)", prop, prop); // also catches "NaN", "Infinity"
break;
case "uint32":
case "fixed32": gen
("m%s=d%s>>>0", prop, prop);
break;
case "int32":
case "sint32":
case "sfixed32": gen
("m%s=d%s|0", prop, prop);
break;
case "uint64":
case "fixed64":
isUnsigned = true;
// eslint-disable-next-line no-fallthrough
case "int64":
case "sint64":
case "sfixed64": gen
("if(util.Long)")
("m%s=util.Long.fromValue(d%s,%j)", prop, prop, isUnsigned)
("else if(typeof d%s===\"string\")", prop)
("m%s=parseInt(d%s,10)", prop, prop)
("else if(typeof d%s===\"number\")", prop)
("m%s=d%s", prop, prop)
("else if(typeof d%s===\"object\")", prop)
("m%s=new util.LongBits(d%s.low>>>0,d%s.high>>>0).toNumber(%s)", prop, prop, prop, isUnsigned ? "true" : "");
break;
case "bytes": gen
("if(typeof d%s===\"string\")", prop)
("util.base64.decode(d%s,m%s=util.newBuffer(util.base64.length(d%s)),0)", prop, prop, prop)
("else if(d%s.length>=0)", prop)
("m%s=d%s", prop, prop);
break;
case "string": gen
("m%s=String(d%s)", prop, prop);
break;
case "bool": gen
("m%s=Boolean(d%s)", prop, prop);
break;
/* default: gen
("m%s=d%s", prop, prop);
break; */
}
}
return gen;
/* eslint-enable no-unexpected-multiline, block-scoped-var, no-redeclare */
}
/**
* Generates a plain object to runtime message converter specific to the specified message type.
* @param {Type} mtype Message type
* @returns {Codegen} Codegen instance
*/
converter.fromObject = function fromObject(mtype) {
/* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */
var fields = mtype.fieldsArray;
var gen = util.codegen(["d", "q"])
("if(d instanceof C)")
("return d")
("if(!util.isObject(d))")
("throw TypeError(%j)", mtype.fullName + ": object expected")
("if(q===undefined)q=0")
("if(q>util.recursionLimit)")
("throw Error(\"max depth exceeded\")");
if (!fields.length) return gen
("return new C");
gen
("var m=new C");
for (var i = 0; i < fields.length; ++i) {
var field = fields[i].resolve(),
prop = util.safeProp(field.name),
implicitPresence = !field.hasPresence && !field.repeated && !field.map
&& (field.resolvedType instanceof Enum || types.basic[field.type] !== undefined);
// Map fields
if (field.map) { gen
("if(d%s){", prop)
("if(!util.isObject(d%s))", prop)
("throw TypeError(%j)", field.fullName + ": object expected")
("m%s={}", prop)
("for(var ks=Object.keys(d%s),i=0;i<ks.length;++i){", prop);
gen
("if(ks[i]===\"__proto__\")")
("util.makeProp(m%s,ks[i])", prop);
genValuePartial_fromObject(gen, field, /* not sorted */ i, prop + "[ks[i]]")
("}")
("}");
// Repeated fields
} else if (field.repeated) { gen
("if(d%s){", prop)
("if(!Array.isArray(d%s))", prop)
("throw TypeError(%j)", field.fullName + ": array expected");
if (field.resolvedType instanceof Enum) gen
("m%s=[]", prop);
else gen
("m%s=Array(d%s.length)", prop, prop);
gen
("for(var i=0;i<d%s.length;++i){", prop);
genValuePartial_fromObject(gen, field, /* not sorted */ i, prop + "[i]", field.resolvedType instanceof Enum ? prop : undefined)
("}")
("}");
// Non-repeated fields
} else {
if (!(field.resolvedType instanceof Enum)) gen // no need to test for null/undefined if an enum (uses switch)
("if(d%s!=null){", prop); // !== undefined && !== null
if (implicitPresence) {
if (field.resolvedType instanceof Enum) gen
("if(d%s!==%j&&(typeof d%s!==\"string\"||types[%i].values[d%s]!==%j)){", prop, field.typeDefault, prop, i, prop, field.typeDefault);
else if (field.type === "string") gen
("if(typeof d%s!==\"string\"||d%s.length){", prop, prop);
else if (field.type === "bytes") gen
("if(d%s.length){", prop);
else if (field.type === "bool") gen
("if(d%s){", prop);
else if (field.type === "double" || field.type === "float") gen
("if(!Object.is(Number(d%s),0)){", prop);
else if (types.long[field.type] !== undefined) gen
("if(typeof d%s===\"object\"?d%s.low||d%s.high:Number(d%s)!==0){", prop, prop, prop, prop);
else gen
("if(Number(d%s)!==0){", prop);
}
genValuePartial_fromObject(gen, field, /* not sorted */ i, prop);
if (implicitPresence) gen
("}");
if (!(field.resolvedType instanceof Enum)) gen
("}");
}
} return gen
("return m");
/* eslint-enable no-unexpected-multiline, block-scoped-var, no-redeclare */
};
/**
* Generates a partial value toObject converter.
* @param {Codegen} gen Codegen instance
* @param {Field} field Reflected field
* @param {number} fieldIndex Field index
* @param {string} dstProp Destination property reference
* @param {string} [srcProp] Source property reference
* @returns {Codegen} Codegen instance
* @ignore
*/
function genValuePartial_toObject(gen, field, fieldIndex, dstProp, srcProp) {
/* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */
if (!srcProp)
srcProp = dstProp;
if (field.resolvedType) {
if (field.resolvedType instanceof Enum) gen
("d%s=o.enums===String?(types[%i].values[m%s]===undefined?m%s:types[%i].values[m%s]):m%s", dstProp, fieldIndex, srcProp, srcProp, fieldIndex, srcProp, srcProp);
else gen
("d%s=types[%i].toObject(m%s,o,q+1)", dstProp, fieldIndex, srcProp);
} else {
var isUnsigned = false;
switch (field.type) {
case "double":
case "float": gen
("d%s=o.json&&!isFinite(m%s)?String(m%s):m%s", dstProp, srcProp, srcProp, srcProp);
break;
case "uint64":
case "fixed64":
isUnsigned = true;
// eslint-disable-next-line no-fallthrough
case "int64":
case "sint64":
case "sfixed64": gen
("if(typeof BigInt!==\"undefined\"&&o.longs===BigInt)")
("d%s=typeof m%s===\"number\"?BigInt(m%s):util.Long.fromBits(m%s.low>>>0,m%s.high>>>0,%j).toBigInt()", dstProp, srcProp, srcProp, srcProp, srcProp, isUnsigned)
("else if(typeof m%s===\"number\")", srcProp)
("d%s=o.longs===String?String(m%s):m%s", dstProp, srcProp, srcProp)
("else") // Long-like
("d%s=o.longs===String?util.Long.prototype.toString.call(m%s):o.longs===Number?new util.LongBits(m%s.low>>>0,m%s.high>>>0).toNumber(%s):m%s", dstProp, srcProp, srcProp, srcProp, isUnsigned ? "true": "", srcProp);
break;
case "bytes": gen
("d%s=o.bytes===String?util.base64.encode(m%s,0,m%s.length):o.bytes===Array?Array.prototype.slice.call(m%s):m%s", dstProp, srcProp, srcProp, srcProp, srcProp);
break;
default: gen
("d%s=m%s", dstProp, srcProp);
break;
}
}
return gen;
/* eslint-enable no-unexpected-multiline, block-scoped-var, no-redeclare */
}
/**
* Generates a runtime message to plain object converter specific to the specified message type.
* @param {Type} mtype Message type
* @returns {Codegen} Codegen instance
*/
converter.toObject = function toObject(mtype) {
/* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */
var fields = mtype.fieldsArray.slice().sort(util.compareFieldsById);
if (!fields.length)
return util.codegen()("return {}");
var gen = util.codegen(["m", "o", "q"])
("if(!o)")
("o={}")
("if(q===undefined)q=0")
("if(q>util.recursionLimit)")
("throw Error(\"max depth exceeded\")")
("var d={}");
var repeatedFields = [],
mapFields = [],
normalFields = [],
i = 0;
for (; i < fields.length; ++i)
if (!fields[i].partOf)
( fields[i].resolve().repeated ? repeatedFields
: fields[i].map ? mapFields
: normalFields).push(fields[i]);
if (repeatedFields.length) { gen
("if(o.arrays||o.defaults){");
for (i = 0; i < repeatedFields.length; ++i) gen
("d%s=[]", util.safeProp(repeatedFields[i].name));
gen
("}");
}
if (mapFields.length) { gen
("if(o.objects||o.defaults){");
for (i = 0; i < mapFields.length; ++i) gen
("d%s={}", util.safeProp(mapFields[i].name));
gen
("}");
}
if (normalFields.length) { gen
("if(o.defaults){");
for (i = 0; i < normalFields.length; ++i) {
var field = normalFields[i],
prop = util.safeProp(field.name);
if (field.resolvedType instanceof Enum) gen
("d%s=o.enums===String?%j:%j", prop, field.resolvedType.valuesById[field.typeDefault], field.typeDefault);
else if (field.long) gen
("if(util.Long){")
("var n=new util.Long(%i,%i,%j)", field.typeDefault.low, field.typeDefault.high, field.typeDefault.unsigned)
("d%s=o.longs===String?n.toString():o.longs===Number?n.toNumber():typeof BigInt!==\"undefined\"&&o.longs===BigInt?n.toBigInt():n", prop)
("}else")
("d%s=o.longs===String?%j:typeof BigInt!==\"undefined\"&&o.longs===BigInt?BigInt(%j):%i", prop, field.typeDefault.toString(), field.typeDefault.toString(), field.typeDefault.toNumber());
else if (field.bytes) {
var arrayDefault = Array.prototype.slice.call(field.typeDefault);
gen
("if(o.bytes===String)d%s=%j", prop, util.base64.encode(field.typeDefault, 0, field.typeDefault.length))
("else{")
("d%s=%j", prop, arrayDefault)
("if(o.bytes!==Array)d%s=util.newBuffer(d%s)", prop, prop)
("}");
} else gen
("d%s=%j", prop, field.typeDefault); // also messages (=null)
} gen
("}");
}
var hasKs2 = false;
for (i = 0; i < fields.length; ++i) {
var field = fields[i],
index = mtype._fieldsArray.indexOf(field),
prop = util.safeProp(field.name);
if (field.map) {
if (!hasKs2) { hasKs2 = true; gen
("var ks2");
} gen
("if(m%s&&(ks2=Object.keys(m%s)).length){", prop, prop)
("d%s={}", prop);
var longKey = types.long[field.keyType] !== undefined,
srcProp = prop + "[ks2[j]]";
gen
("for(var j=0;j<ks2.length;++j){");
if (longKey) gen
("var k2=util.longFromKey(ks2[j],%j).toString()", field.keyType === "uint64" || field.keyType === "fixed64");
gen
("if(ks2[j]===\"__proto__\")")
("util.makeProp(d%s,ks2[j])", prop);
genValuePartial_toObject(gen, field, /* sorted */ index, longKey ? prop + "[k2]" : srcProp, srcProp)
("}");
} else if (field.repeated) { gen
("if(m%s&&m%s.length){", prop, prop)
("d%s=Array(m%s.length)", prop, prop)
("for(var j=0;j<m%s.length;++j){", prop);
genValuePartial_toObject(gen, field, /* sorted */ index, prop + "[j]")
("}");
} else { gen
("if(m%s!=null&&Object.hasOwnProperty.call(m,%j)){", prop, field.name); // !== undefined && !== null
genValuePartial_toObject(gen, field, /* sorted */ index, prop);
if (field.partOf && !field.partOf.isProto3Optional) gen
("if(o.oneofs)")
("d%s=%j", util.safeProp(field.partOf.name), field.name);
}
gen
("}");
}
return gen
("return d");
/* eslint-enable no-unexpected-multiline, block-scoped-var, no-redeclare */
};
+279
View File
@@ -0,0 +1,279 @@
"use strict";
module.exports = decoder;
var Enum = require("./enum"),
types = require("./types"),
util = require("./util");
function missing(field) {
return "missing required '" + field.name + "'";
}
function stringMethod(field) {
return field._features.utf8_validation === "VERIFY" ? "stringVerify" : "string";
}
function genPreserveUnknown(gen, ref) {
/* eslint-disable no-unexpected-multiline */
return gen
("if(!r.discardUnknown){")
("util.makeProp(m,\"$unknowns\",false);")
("(m.$unknowns||(m.$unknowns=[])).push(%s)", ref)
("}");
/* eslint-enable no-unexpected-multiline */
}
/**
* Generates a decoder specific to the specified message type.
* @param {Type} mtype Message type
* @returns {Codegen} Codegen instance
*/
function decoder(mtype) {
/* eslint-disable no-unexpected-multiline */
var hasMapField = false,
needsValueVar = false,
i = 0;
for (; i < mtype.fieldsArray.length; ++i) {
var pfield = mtype._fieldsArray[i];
if (pfield.map)
hasMapField = true;
if (pfield.resolvedType instanceof Enum || !pfield.repeated && !pfield.map && !pfield.hasPresence)
needsValueVar = true;
}
var gen = util.codegen(["r", "l", "z", "q", "g"])
("if(!(r instanceof Reader))")
("r=Reader.create(r)")
("if(q===undefined)q=0")
("if(q>Reader.recursionLimit)")
("throw Error(\"max depth exceeded\")")
("var c=l===undefined?r.len:r.pos+l,m=g||new C" + (hasMapField ? ",k,v" : needsValueVar ? ",v" : ""))
("while(r.pos<c){")
("var s=r.pos")
("var t=r.tag()")
("if(t===z){")
("z=undefined")
("break")
("}");
if (mtype.fieldsArray.length) gen
("var u=t&7")
("switch(t>>>=3){");
for (i = 0; i < /* initializes */ mtype.fieldsArray.length; ++i) {
var field = mtype._fieldsArray[i].resolve(),
type = field.resolvedType instanceof Enum ? "int32" : field.type,
ref = "m" + util.safeProp(field.name),
closed = field.resolvedType instanceof Enum && field.resolvedType._features.enum_type === "CLOSED";
// Map fields
if (field.map) {
gen
("case %i:{", field.id)
("if(u!==2)")
("break");
if (!closed) gen
("if(%s===util.emptyObject)", ref)
("%s={}", ref);
gen
("var c2=r.uint32()+r.pos");
if (types.defaults[field.keyType] !== undefined) gen
("k=%j", types.defaults[field.keyType]);
else gen
("k=null");
if (types.long[type] !== undefined) gen
("v=util.Long?util.Long.fromNumber(0,%j):0", type === "uint64" || type === "fixed64");
else if (types.defaults[type] !== undefined) gen
("v=%j", types.defaults[type]);
else gen
("v=null");
gen
("while(r.pos<c2){")
("var t2=r.tag()")
("u=t2&7")
("switch(t2>>>=3){")
("case 1:")
("if(u!==%i)", types.mapKey[field.keyType])
("break")
("k=r.%s()", field.keyType === "string" ? stringMethod(field) : field.keyType)
("continue")
("case 2:")
("if(u!==%i)", types.basic[type] === undefined ? 2 : types.basic[type])
("break");
if (types.basic[type] === undefined) gen
("v=types[%i].decode(r,r.uint32(),undefined,q+1,v)", i); // can't be groups
else gen
("v=r.%s()", type === "string" ? stringMethod(field) : type);
gen
("continue")
("}")
("r.skipType(u,q,t2)")
("}");
if (closed) { gen
("if(types[%i].valuesById[v]===undefined){", i);
genPreserveUnknown(gen, "r.raw(s,r.pos)")
("continue")
("}")
("if(%s===util.emptyObject)", ref)
("%s={}", ref);
}
var val = types.basic[type] === undefined ? "v||new types[" + i + "].ctor" : "v";
if (types.long[field.keyType] !== undefined) gen
("%s[typeof k===\"object\"?util.longToHash(k):k]=%s", ref, val);
else {
if (field.keyType === "string") gen
("if(k===\"__proto__\")")
("util.makeProp(%s,k)", ref);
gen
("%s[k]=%s", ref, val);
}
// Repeated fields
} else if (field.repeated) { gen
("case %i:", field.id)
("{");
// Packable (always check for forward and backward compatiblity)
if (types.packed[type] !== undefined) {
gen
("if(u===2){");
if (closed) {
gen
("var c2=r.uint32()+r.pos")
("while(r.pos<c2){")
("s=r.pos")
("v=r.%s()", type)
("if(types[%i].valuesById[v]!==undefined){", i)
("if(!(%s&&%s.length))", ref, ref)
("%s=[]", ref)
("%s.push(v)", ref)
("}else");
genPreserveUnknown(gen, "util.rawField(" + field.id + ",0,r.raw(s,r.pos))")
("}");
} else gen
("if(!(%s&&%s.length))", ref, ref)
("%s=[]", ref)
("r.%ss(%s)", type, ref);
gen
("continue")
("}");
}
// Non-packed
gen
("if(u!==%i)", types.basic[type] === undefined ? field.delimited ? 3 : 2 : types.basic[type])
("break");
if (!closed) gen
("if(!(%s&&%s.length))", ref, ref)
("%s=[]", ref);
if (types.basic[type] === undefined) {
if (field.delimited) gen
("%s.push(types[%i].decode(r,undefined,%i,q+1))", ref, i, field.id * 8 + 4);
else gen
("%s.push(types[%i].decode(r,r.uint32(),undefined,q+1))", ref, i);
} else if (closed) { gen
("v=r.%s()", type)
("if(types[%i].valuesById[v]!==undefined){", i)
("if(!(%s&&%s.length))", ref, ref)
("%s=[]", ref)
("%s.push(v)", ref)
("}else");
genPreserveUnknown(gen, "r.raw(s,r.pos)");
} else gen
("%s.push(r.%s())", ref, type === "string" ? stringMethod(field) : type);
// Non-repeated
} else if (types.basic[type] === undefined) {
gen
("case %i:{", field.id)
("if(u!==%i)", field.delimited ? 3 : 2)
("break");
if (field.delimited) gen
("%s=types[%i].decode(r,undefined,%i,q+1,%s)", ref, i, field.id * 8 + 4, ref);
else gen
("%s=types[%i].decode(r,r.uint32(),undefined,q+1,%s)", ref, i, ref);
}
else if (field.hasPresence) {
gen
("case %i:{", field.id)
("if(u!==%i)", types.basic[type])
("break");
if (closed) { gen
("v=r.%s()", type)
("if(types[%i].valuesById[v]!==undefined){", i)
("%s=v", ref);
if (field.partOf) gen
("m%s=%j", util.safeProp(field.partOf.name), field.name);
gen
("}else");
genPreserveUnknown(gen, "r.raw(s,r.pos)");
} else gen
("%s=r.%s()", ref, type === "string" ? stringMethod(field) : type);
} else {
gen
("case %i:{", field.id)
("if(u!==%i)", types.basic[type])
("break");
if (closed) { gen
("v=r.%s()", type)
("if(types[%i].valuesById[v]!==undefined){", i)
("if(v!==%j)", field.typeDefault)
("%s=v", ref)
("else")
("delete %s", ref)
("}else{");
genPreserveUnknown(gen, "r.raw(s,r.pos)")
("}");
} else {
if (field.resolvedType instanceof Enum && field.typeDefault !== 0) gen
// TODO: Protoc rejects open enums whose first value is not zero.
// We should do the same, but for v8 this would be a regression.
("if((v=r.%s())!==%j)", type, field.typeDefault);
else if (type === "string") gen
("if((v=r.%s()).length)", stringMethod(field));
else if (type === "bytes") gen
("if((v=r.%s()).length)", type);
else if (types.long[type] !== undefined) gen
("if(typeof(v=r.%s())===\"object\"?v.low||v.high:v!==0)", type);
else if (type === "double" || type === "float") gen
("if(!Object.is(v=r.%s(),0))", type);
else gen
("if(v=r.%s())", type);
gen
("%s=v", ref)
("else")
("delete %s", ref); // rare/odd case: later default clears earlier non-default
}
}
if (field.partOf && !closed) gen
("m%s=%j", util.safeProp(field.partOf.name), field.name);
gen
("continue")
("}");
}
if (i) gen
("}");
// Unknown fields
gen
("r.skipType(%s,q,t)", i ? "u" : "t&7");
genPreserveUnknown(gen, "r.raw(s,r.pos)")
("}")
("if(z!==undefined)")
("throw Error(\"missing end group\")");
// Field presence
for (i = 0; i < mtype._fieldsArray.length; ++i) {
var rfield = mtype._fieldsArray[i];
if (rfield.required) gen
("if(!Object.hasOwnProperty.call(m,%j))", rfield.name)
("throw util.ProtocolError(%j,{instance:m})", missing(rfield));
}
return gen
("return m");
/* eslint-enable no-unexpected-multiline */
}
+123
View File
@@ -0,0 +1,123 @@
"use strict";
module.exports = encoder;
var Enum = require("./enum"),
types = require("./types"),
util = require("./util");
/**
* Generates a partial message type encoder.
* @param {Codegen} gen Codegen instance
* @param {Field} field Reflected field
* @param {number} fieldIndex Field index
* @param {string} ref Variable reference
* @returns {Codegen} Codegen instance
* @ignore
*/
function genTypePartial(gen, field, fieldIndex, ref) {
return field.delimited
? gen("types[%i].encode(%s,w.uint32(%i),q+1).uint32(%i)", fieldIndex, ref, (field.id << 3 | 3) >>> 0, (field.id << 3 | 4) >>> 0)
: gen("types[%i].encode(%s,w.uint32(%i).fork(),q+1).ldelim()", fieldIndex, ref, (field.id << 3 | 2) >>> 0);
}
/**
* Generates an encoder specific to the specified message type.
* @param {Type} mtype Message type
* @returns {Codegen} Codegen instance
*/
function encoder(mtype) {
/* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */
var gen = util.codegen(["m", "w", "q"])
("if(!w)")
("w=Writer.create()")
("if(q===undefined)q=0")
("if(q>util.recursionLimit)")
("throw Error(\"max depth exceeded\")");
var i, ref;
// "when a message is serialized its known fields should be written sequentially by field number"
var fields = /* initializes */ mtype.fieldsArray.slice().sort(util.compareFieldsById);
for (var i = 0; i < fields.length; ++i) {
var field = fields[i].resolve(),
index = mtype._fieldsArray.indexOf(field),
type = field.resolvedType instanceof Enum ? "int32" : field.type,
wireType = types.basic[type];
ref = "m" + util.safeProp(field.name);
// Map fields
if (field.map) {
gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)){", ref, field.name) // !== undefined && !== null
("for(var ks=Object.keys(%s),i=0;i<ks.length;++i){", ref);
if (field.keyType === "bool") gen
("w.uint32(%i).fork().uint32(%i).bool(util.boolFromKey(ks[i]))", (field.id << 3 | 2) >>> 0, 8 | types.mapKey[field.keyType]);
else if (types.long[field.keyType] !== undefined) gen
("w.uint32(%i).fork().uint32(%i).%s(util.longFromKey(ks[i],%j))", (field.id << 3 | 2) >>> 0, 8 | types.mapKey[field.keyType], field.keyType, field.keyType === "uint64" || field.keyType === "fixed64");
else gen
("w.uint32(%i).fork().uint32(%i).%s(ks[i])", (field.id << 3 | 2) >>> 0, 8 | types.mapKey[field.keyType], field.keyType);
if (wireType === undefined) gen
("types[%i].encode(%s[ks[i]],w.uint32(18).fork(),q+1).ldelim().ldelim()", index, ref); // can't be groups
else gen
(".uint32(%i).%s(%s[ks[i]]).ldelim()", 16 | wireType, type, ref);
gen
("}")
("}");
// Repeated fields
} else if (field.repeated) { gen
("if(%s!=null&&%s.length){", ref, ref); // !== undefined && !== null
// Packed repeated
if (field.packed && types.packed[type] !== undefined) { gen
("w.uint32(%i).%ss(%s)", (field.id << 3 | 2) >>> 0, type, ref);
// Non-packed
} else { gen
("for(var i=0;i<%s.length;++i)", ref);
if (wireType === undefined)
genTypePartial(gen, field, index, ref + "[i]");
else gen
("w.uint32(%i).%s(%s[i])", (field.id << 3 | wireType) >>> 0, type, ref);
} gen
("}");
// Non-repeated
} else {
if (!field.required)
if (field.hasPresence || !(field.resolvedType instanceof Enum || types.basic[type] !== undefined)) gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j))", ref, field.name); // !== undefined && !== null
else if (field.resolvedType instanceof Enum) gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)&&%s!==%j)", ref, field.name, ref, field.typeDefault);
else if (type === "bool") gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)&&%s!==false)", ref, field.name, ref);
else if (type === "string") gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)&&%s!==\"\")", ref, field.name, ref);
else if (type === "bytes") gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)&&%s.length)", ref, field.name, ref);
else if (type === "double" || type === "float") gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)&&!Object.is(%s,0))", ref, field.name, ref);
else if (types.long[type] !== undefined) gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)&&(typeof %s===\"object\"?%s.low||%s.high:%s!==0))", ref, field.name, ref, ref, ref, ref);
else gen
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)&&%s!==0)", ref, field.name, ref);
if (wireType === undefined)
genTypePartial(gen, field, index, ref);
else gen
("w.uint32(%i).%s(%s)", (field.id << 3 | wireType) >>> 0, type, ref);
}
}
return gen
("if(m.$unknowns!=null&&Object.hasOwnProperty.call(m,\"$unknowns\"))")
("for(var i=0;i<m.$unknowns.length;++i)")
("w.raw(m.$unknowns[i])")
("return w");
/* eslint-enable no-unexpected-multiline, block-scoped-var, no-redeclare */
}
+239
View File
@@ -0,0 +1,239 @@
"use strict";
module.exports = Enum;
// extends ReflectionObject
var ReflectionObject = require("./object");
Enum.prototype = Object.create(ReflectionObject.prototype, {
constructor: {
value: Enum,
writable: true,
enumerable: false,
configurable: true
}
});
Enum.className = "Enum";
var Namespace = require("./namespace"),
util = require("./util");
/**
* Constructs a new enum instance.
* @classdesc Reflected enum.
* @extends ReflectionObject
* @constructor
* @param {string} name Unique name within its namespace
* @param {Object.<string,number>} [values] Enum values as an object, by name
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] The comment for this enum
* @param {Object.<string,string|null>} [comments] The value comments for this enum
* @param {Object.<string,Object<string,*>>|undefined} [valuesOptions] The value options for this enum
*/
function Enum(name, values, options, comment, comments, valuesOptions) {
ReflectionObject.call(this, name, options);
if (values && typeof values !== "object")
throw TypeError("values must be an object");
/**
* Enum values by id.
* @type {Object.<number,string>}
*/
this.valuesById = Object.create(null);
/**
* Enum values by name.
* @type {Object.<string,number>}
*/
this.values = Object.create(this.valuesById); // toJSON, marker
/**
* Enum comment text.
* @type {string|null}
*/
this.comment = comment;
/**
* Value comment texts, if any.
* @type {Object.<string,string|null>}
*/
this.comments = comments || {};
/**
* Values options, if any
* @type {Object<string, Object<string, *>>|undefined}
*/
this.valuesOptions = valuesOptions;
/**
* Resolved values features, if any
* @type {Object<string, Object<string, *>>|undefined}
*/
this._valuesFeatures = {};
/**
* Reserved ranges, if any.
* @type {Array.<number[]|string>}
*/
this.reserved = undefined; // toJSON
// Note that values inherit valuesById on their prototype which makes them a TypeScript-
// compatible enum. This is used by pbts to write actual enum definitions that work for
// static and reflection code alike instead of emitting generic object definitions.
if (values)
for (var keys = Object.keys(values), i = 0; i < keys.length; ++i)
if (keys[i] !== "__proto__" && typeof values[keys[i]] === "number") // use forward entries only
this.valuesById[ this.values[keys[i]] = values[keys[i]] ] = keys[i];
}
/**
* @override
*/
Enum.prototype._resolveFeatures = function _resolveFeatures(edition) {
edition = this._edition || edition;
ReflectionObject.prototype._resolveFeatures.call(this, edition);
Object.keys(this.values).forEach(key => {
var parentFeaturesCopy = util.merge({}, this._features);
this._valuesFeatures[key] = util.merge(parentFeaturesCopy, this.valuesOptions && this.valuesOptions[key] && this.valuesOptions[key].features || {});
});
return this;
};
/**
* Enum descriptor.
* @interface IEnum
* @property {string} [edition] Edition
* @property {Object.<string,number>} values Enum values
* @property {Object.<string,*>} [options] Enum options
* @property {Object.<string,Object.<string,*>>} [valuesOptions] Enum value options
* @property {Array.<number[]|string>} [reserved] Reserved ranges
* @property {string|null} [comment] Enum comment
* @property {Object.<string,string|null>} [comments] Value comments
*/
/**
* Constructs an enum from an enum descriptor.
* @param {string} name Enum name
* @param {IEnum} json Enum descriptor
* @returns {Enum} Created enum
* @throws {TypeError} If arguments are invalid
*/
Enum.fromJSON = function fromJSON(name, json) {
var enm = new Enum(name, json.values, json.options, json.comment, json.comments, json.valuesOptions);
enm.reserved = json.reserved;
if (json.edition)
enm._edition = json.edition;
enm._defaultEdition = "proto3"; // For backwards-compatibility.
return enm;
};
/**
* Converts this enum to an enum descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IEnum} Enum descriptor
*/
Enum.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"edition" , this._editionToJSON(),
"options" , this.options,
"valuesOptions" , this.valuesOptions,
"values" , this.values,
"reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
"comment" , keepComments ? this.comment : undefined,
"comments" , keepComments ? this.comments : undefined
]);
};
/**
* Adds a value to this enum.
* @param {string} name Value name
* @param {number} id Value id
* @param {string} [comment] Comment, if any
* @param {Object.<string, *>|undefined} [options] Options, if any
* @returns {Enum} `this`
* @throws {TypeError} If arguments are invalid
* @throws {Error} If there is already a value with this name or id
*/
Enum.prototype.add = function add(name, id, comment, options) {
// utilized by the parser but not by .fromJSON
if (!util.isString(name))
throw TypeError("name must be a string");
if (!util.isInteger(id))
throw TypeError("id must be an integer");
if (name === "__proto__")
return this;
if (this.values[name] !== undefined)
throw Error("duplicate name '" + name + "' in " + this);
if (this.isReservedId(id))
throw Error("id " + id + " is reserved in " + this);
if (this.isReservedName(name))
throw Error("name '" + name + "' is reserved in " + this);
if (this.valuesById[id] !== undefined) {
if (!(this.options && this.options.allow_alias))
throw Error("duplicate id " + id + " in " + this);
this.values[name] = id;
} else
this.valuesById[this.values[name] = id] = name;
if (options) {
if (this.valuesOptions === undefined)
this.valuesOptions = {};
this.valuesOptions[name] = options || null;
}
this.comments[name] = comment || null;
return this;
};
/**
* Removes a value from this enum
* @param {string} name Value name
* @returns {Enum} `this`
* @throws {TypeError} If arguments are invalid
* @throws {Error} If `name` is not a name of this enum
*/
Enum.prototype.remove = function remove(name) {
if (!util.isString(name))
throw TypeError("name must be a string");
var val = this.values[name];
if (val == null)
throw Error("name '" + name + "' does not exist in " + this);
delete this.valuesById[val];
delete this.values[name];
delete this.comments[name];
if (this.valuesOptions)
delete this.valuesOptions[name];
return this;
};
/**
* Tests if the specified id is reserved.
* @param {number} id Id to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
Enum.prototype.isReservedId = function isReservedId(id) {
return Namespace.isReservedId(this.reserved, id);
};
/**
* Tests if the specified name is reserved.
* @param {string} name Name to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
Enum.prototype.isReservedName = function isReservedName(name) {
return Namespace.isReservedName(this.reserved, name);
};
+505
View File
@@ -0,0 +1,505 @@
"use strict";
module.exports = Field;
// extends ReflectionObject
var ReflectionObject = require("./object");
Field.prototype = Object.create(ReflectionObject.prototype, {
constructor: {
value: Field,
writable: true,
enumerable: false,
configurable: true
}
});
Field.className = "Field";
var Enum = require("./enum"),
types = require("./types"),
util = require("./util");
var Type; // cyclic
var ruleRe = /^(?:required|optional|repeated)$/;
/**
* Constructs a new message field instance. Note that {@link MapField|map fields} have their own class.
* @name Field
* @classdesc Reflected message field.
* @extends FieldBase
* @constructor
* @param {string} name Unique name within its namespace
* @param {number} id Unique id within its namespace
* @param {string} type Value type
* @param {string|Object.<string,*>} [rule="optional"] Field rule
* @param {string|Object.<string,*>} [extend] Extended type if different from parent
* @param {Object.<string,*>} [options] Declared options
*/
/**
* Constructs a field from a field descriptor.
* @param {string} name Field name
* @param {IField} json Field descriptor
* @returns {Field} Created field
* @throws {TypeError} If arguments are invalid
*/
Field.fromJSON = function fromJSON(name, json) {
var field = new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
if (json.edition)
field._edition = json.edition;
if (json.protoName)
field.protoName = json.protoName;
if (json.jsonName !== undefined)
field.jsonName = json.jsonName;
else if (json.options && json.options.json_name !== undefined)
field.jsonName = json.options.json_name;
field._defaultEdition = "proto3"; // For backwards-compatibility.
return field;
};
/**
* Not an actual constructor. Use {@link Field} instead.
* @classdesc Base class of all reflected message fields. This is not an actual class but here for the sake of having consistent type definitions.
* @exports FieldBase
* @extends ReflectionObject
* @constructor
* @param {string} name Unique name within its namespace
* @param {number} id Unique id within its namespace
* @param {string} type Value type
* @param {string|Object.<string,*>} [rule="optional"] Field rule
* @param {string|Object.<string,*>} [extend] Extended type if different from parent
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] Comment associated with this field
*/
function Field(name, id, type, rule, extend, options, comment) {
if (util.isObject(rule)) {
comment = extend;
options = rule;
rule = extend = undefined;
} else if (util.isObject(extend)) {
comment = options;
options = extend;
extend = undefined;
}
ReflectionObject.call(this, name, options);
if (!util.isInteger(id) || id < 0)
throw TypeError("id must be a non-negative integer");
if (!util.isString(type))
throw TypeError("type must be a string");
if (rule !== undefined && !ruleRe.test(rule = rule.toString().toLowerCase()))
throw TypeError("rule must be a string rule");
if (extend !== undefined && !util.isString(extend))
throw TypeError("extend must be a string");
/**
* Field rule, if any.
* @type {string|undefined}
*/
this.rule = rule && rule !== "optional" ? rule : undefined; // toJSON
/**
* Field type.
* @type {string}
*/
this.type = type; // toJSON
/**
* Unique field id.
* @type {number}
*/
this.id = id; // toJSON, marker
/**
* Extended type if different from parent.
* @type {string|undefined}
*/
this.extend = extend || undefined; // toJSON
/**
* Whether this field is repeated.
* @type {boolean}
*/
this.repeated = rule === "repeated";
/**
* Whether this field is a map or not.
* @type {boolean}
*/
this.map = false;
/**
* Message this field belongs to.
* @type {Type|null}
*/
this.message = null;
/**
* OneOf this field belongs to, if any,
* @type {OneOf|null}
*/
this.partOf = null;
/**
* The field type's default value.
* @type {*}
*/
this.typeDefault = null;
/**
* The field's default value on prototypes.
* @type {*}
*/
this.defaultValue = null;
/**
* Whether this field's value should be treated as a long.
* @type {boolean}
*/
this.long = util.Long ? types.long[type] !== undefined : /* istanbul ignore next */ false;
/**
* Whether this field's value is a buffer.
* @type {boolean}
*/
this.bytes = type === "bytes";
/**
* Resolved type if not a basic type.
* @type {Type|Enum|null}
*/
this.resolvedType = null;
/**
* Sister-field within the extended type if a declaring extension field.
* @type {Field|null}
*/
this.extensionField = null;
/**
* Sister-field within the declaring namespace if an extended field.
* @type {Field|null}
*/
this.declaringField = null;
/**
* Comment for this field.
* @type {string|null}
*/
this.comment = comment;
/**
* Field name as declared in the .proto source, if different from `name`.
* @type {string|undefined}
*/
this.protoName = undefined;
/**
* JSON name, if different from the derived default.
* @type {string|undefined}
*/
this.jsonName = undefined;
}
/**
* Determines whether this field is required.
* @name Field#required
* @type {boolean}
* @readonly
*/
Object.defineProperty(Field.prototype, "required", {
get: function() {
return this._features.field_presence === "LEGACY_REQUIRED";
}
});
/**
* Determines whether this field is not required.
* @name Field#optional
* @type {boolean}
* @readonly
*/
Object.defineProperty(Field.prototype, "optional", {
get: function() {
return !this.required;
}
});
/**
* Determines whether this field uses tag-delimited encoding. In proto2 this
* corresponded to group syntax.
* @name Field#delimited
* @type {boolean}
* @readonly
*/
Object.defineProperty(Field.prototype, "delimited", {
get: function() {
return this.resolvedType instanceof Type &&
this._features.message_encoding === "DELIMITED";
}
});
/**
* Determines whether this field is packed. Only relevant when repeated.
* @name Field#packed
* @type {boolean}
* @readonly
*/
Object.defineProperty(Field.prototype, "packed", {
get: function() {
return this._features.repeated_field_encoding === "PACKED";
}
});
/**
* Determines whether this field tracks presence.
* @name Field#hasPresence
* @type {boolean}
* @readonly
*/
Object.defineProperty(Field.prototype, "hasPresence", {
get: function() {
if (this.repeated || this.map) {
return false;
}
return this.partOf || // oneofs
this.declaringField || this.extensionField || // extensions
this._features.field_presence !== "IMPLICIT";
}
});
/**
* The field name as declared in the .proto source (snake_case). Populated on resolve,
* falling back to `name`. Mirrors `FieldDescriptorProto.name`.
* @name Field#protoName
* @type {string}
* @readonly
*/
/**
* The JSON name of this field (lowerCamelCase per protoc's `ToJsonName`, or an
* explicit `[json_name]`). Populated on resolve. This is the key used on ProtoJSON output.
* @name Field#jsonName
* @type {string}
* @readonly
*/
/**
* @override
*/
Field.prototype.setOption = function setOption(name, value, ifNotSet) {
return ReflectionObject.prototype.setOption.call(this, name, value, ifNotSet);
};
/**
* Field descriptor.
* @interface IField
* @property {string} [edition] Edition
* @property {string} [rule="optional"] Field rule
* @property {string} type Field type
* @property {number} id Field id
* @property {Object.<string,*>} [options] Field options
* @property {string|null} [comment] Field comment
*/
/**
* Extension field descriptor.
* @interface IExtensionField
* @extends IField
* @property {string} extend Extended type
*/
/**
* Converts this field to a field descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IField} Field descriptor
*/
Field.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"edition" , this._editionToJSON(),
"rule" , this.rule !== "optional" && this.rule || undefined,
"type" , this.type,
"id" , this.id,
"extend" , this.extend,
"protoName" , this.protoName !== this.name ? this.protoName : undefined,
"jsonName" , this.jsonName !== util.jsonName(this.protoName || this.name) ? this.jsonName : undefined,
"options" , this.options,
"comment" , keepComments ? this.comment : undefined
]);
};
/**
* Resolves this field's type references.
* @returns {Field} `this`
* @throws {Error} If any reference cannot be resolved
*/
Field.prototype.resolve = function resolve() {
if (this.resolved)
return this;
if ((this.typeDefault = types.defaults[this.type]) === undefined) { // if not a basic type, resolve it
this.resolvedType = (this.declaringField ? this.declaringField.parent : this.parent).lookupTypeOrEnum(this.type);
if (this.resolvedType instanceof Type)
this.typeDefault = null;
else // instanceof Enum
this.typeDefault = this.resolvedType.values[Object.keys(this.resolvedType.values)[0]]; // first defined
} else if (this.options && this.options.proto3_optional) {
// proto3 scalar value marked optional; should default to null
this.typeDefault = null;
}
// use explicitly set default value if present
if (this.options && this.options["default"] != null) {
this.typeDefault = this.options["default"];
if (this.resolvedType instanceof Enum && typeof this.typeDefault === "string")
this.typeDefault = this.resolvedType.values[this.typeDefault];
}
// remove unnecessary options
if (this.options) {
if (this.options.packed !== undefined && this.resolvedType && !(this.resolvedType instanceof Enum))
delete this.options.packed;
if (!Object.keys(this.options).length)
this.options = undefined;
}
// convert to internal data type if necesssary
if (this.long) {
this.typeDefault = util.Long.fromNumber(this.typeDefault, this.type === "uint64" || this.type === "fixed64");
/* istanbul ignore else */
if (Object.freeze)
Object.freeze(this.typeDefault); // long instances are meant to be immutable anyway (i.e. use small int cache that even requires it)
} else if (this.bytes && typeof this.typeDefault === "string") {
var buf;
if (util.base64.test(this.typeDefault))
util.base64.decode(this.typeDefault, buf = util.newBuffer(util.base64.length(this.typeDefault)), 0);
else
util.utf8.write(this.typeDefault, buf = util.newBuffer(util.utf8.length(this.typeDefault)), 0);
this.typeDefault = buf;
}
// take special care of maps and repeated fields
if (this.map)
this.defaultValue = util.emptyObject;
else if (this.repeated)
this.defaultValue = util.emptyArray;
else
this.defaultValue = this.typeDefault;
// ensure proper value on prototype
if (this.parent instanceof Type && this.parent._ctor)
this.parent._ctor.prototype[this.name] = this.defaultValue;
// derive the proto/JSON names
if (this.protoName === undefined)
this.protoName = this.name;
if (this.jsonName === undefined)
this.jsonName = util.jsonName(this.protoName);
return ReflectionObject.prototype.resolve.call(this);
};
/**
* Infers field features from legacy syntax that may have been specified differently.
* in older editions.
* @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
* @returns {object} The feature values to override
*/
Field.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(edition) {
if (edition !== "proto2" && edition !== "proto3") {
return {};
}
var features = {};
if (this.rule === "required") {
features.field_presence = "LEGACY_REQUIRED";
}
if (this.parent && types.defaults[this.type] === undefined) {
// We can't use resolvedType because types may not have been resolved yet. However,
// legacy groups are always in the same scope as the field so we don't have to do a
// full scan of the tree.
var type = this.parent.get(this.type.split(".").pop());
if (type && type instanceof Type && type.group) {
features.message_encoding = "DELIMITED";
}
}
if (this.getOption("packed") === true) {
features.repeated_field_encoding = "PACKED";
} else if (this.getOption("packed") === false) {
features.repeated_field_encoding = "EXPANDED";
}
return features;
};
/**
* @override
*/
Field.prototype._resolveFeatures = function _resolveFeatures(edition) {
return ReflectionObject.prototype._resolveFeatures.call(this, this._edition || edition);
};
/**
* Decorator function as returned by {@link Field.d} and {@link MapField.d} (TypeScript).
* @typedef FieldDecorator
* @type {function}
* @param {Object} prototype Target prototype
* @param {string} fieldName Field name
* @returns {undefined}
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
/**
* Field decorator (TypeScript).
* @name Field.d
* @function
* @param {number} fieldId Field id
* @param {"double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"string"|"bool"|"bytes"|Object} fieldType Field type
* @param {"optional"|"required"|"repeated"} [fieldRule="optional"] Field rule
* @param {T} [defaultValue] Default value
* @returns {FieldDecorator} Decorator function
* @template T extends number | number[] | Long | Long[] | string | string[] | boolean | boolean[] | Uint8Array | Uint8Array[] | Buffer | Buffer[]
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
Field.d = function decorateField(fieldId, fieldType, fieldRule, defaultValue) {
// submessage: decorate the submessage and use its name as the type
if (typeof fieldType === "function")
fieldType = util.decorateType(fieldType).name;
// enum reference: create a reflected copy of the enum and keep reuseing it
else if (fieldType && typeof fieldType === "object")
fieldType = util.decorateEnum(fieldType).name;
return function fieldDecorator(prototype, fieldName) {
util.decorateType(prototype.constructor)
.add(new Field(fieldName, fieldId, fieldType, fieldRule, { "default": defaultValue }));
};
};
// Sets up cyclic dependencies (called in index-light)
Field._configure = function configure(Type_) {
Type = Type_;
};
/**
* Field decorator (TypeScript).
* @name Field.d
* @function
* @param {number} fieldId Field id
* @param {Constructor<T>|string} fieldType Field type
* @param {"optional"|"required"|"repeated"} [fieldRule="optional"] Field rule
* @returns {FieldDecorator} Decorator function
* @template T extends Message<T>
* @variation 2
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
// like Field.d but without a default value
+104
View File
@@ -0,0 +1,104 @@
"use strict";
exports = module.exports = require("./index-minimal");
exports.build = "light";
/**
* A node-style callback as used by {@link load} and {@link Root#load}.
* @typedef LoadCallback
* @type {function}
* @param {Error|null} error Error, if any, otherwise `null`
* @param {Root} [root] Root, if there hasn't been an error
* @returns {undefined}
*/
/**
* Loads one or multiple .proto or preprocessed .json files into a common root namespace and calls the callback.
* @param {string|string[]} filename One or multiple files to load
* @param {Root} root Root namespace, defaults to create a new one if omitted.
* @param {LoadCallback} callback Callback function
* @returns {undefined}
* @see {@link Root#load}
*/
function load(filename, root, callback) {
if (typeof root === "function") {
callback = root;
root = new exports.Root();
} else if (!root)
root = new exports.Root();
return root.load(filename, callback);
}
/**
* Loads one or multiple .proto or preprocessed .json files into a common root namespace and calls the callback.
* @name load
* @function
* @param {string|string[]} filename One or multiple files to load
* @param {LoadCallback} callback Callback function
* @returns {undefined}
* @see {@link Root#load}
* @variation 2
*/
// function load(filename:string, callback:LoadCallback):undefined
/**
* Loads one or multiple .proto or preprocessed .json files into a common root namespace and returns a promise.
* @name load
* @function
* @param {string|string[]} filename One or multiple files to load
* @param {Root} [root] Root namespace, defaults to create a new one if omitted.
* @returns {Promise<Root>} Promise
* @see {@link Root#load}
* @variation 3
*/
// function load(filename:string, [root:Root]):Promise<Root>
exports.load = load;
/**
* Synchronously loads one or multiple .proto or preprocessed .json files into a common root namespace (node only).
* @param {string|string[]} filename One or multiple files to load
* @param {Root} [root] Root namespace, defaults to create a new one if omitted.
* @returns {Root} Root namespace
* @throws {Error} If synchronous fetching is not supported (i.e. in browsers) or if a file's syntax is invalid
* @see {@link Root#loadSync}
*/
function loadSync(filename, root) {
if (!root)
root = new exports.Root();
return root.loadSync(filename);
}
exports.loadSync = loadSync;
// Serialization
exports.encoder = require("./encoder");
exports.decoder = require("./decoder");
exports.verifier = require("./verifier");
exports.converter = require("./converter");
// Reflection
exports.ReflectionObject = require("./object");
exports.Namespace = require("./namespace");
exports.Root = require("./root");
exports.Enum = require("./enum");
exports.Type = require("./type");
exports.Field = require("./field");
exports.OneOf = require("./oneof");
exports.MapField = require("./mapfield");
exports.Service = require("./service");
exports.Method = require("./method");
// Runtime
exports.Message = require("./message");
exports.wrappers = require("./wrappers");
// Utility
exports.types = require("./types");
exports.util = require("./util");
// Set up possibly cyclic reflection dependencies
exports.ReflectionObject._configure(exports.Root);
exports.Namespace._configure(exports.Type, exports.Service, exports.Enum);
exports.Root._configure(exports.Type, undefined, {});
exports.Field._configure(exports.Type);
+35
View File
@@ -0,0 +1,35 @@
"use strict";
/**
* Build type, one of `"full"`, `"light"` or `"minimal"`.
* @name build
* @type {string}
* @const
*/
exports.build = "minimal";
// Serialization
exports.Writer = require("./writer");
exports.BufferWriter = require("./writer_buffer");
exports.Reader = require("./reader");
exports.BufferReader = require("./reader_buffer");
// Utility
exports.util = require("./util/minimal");
exports.rpc = require("./rpc");
exports.roots = require("./roots");
exports.configure = configure;
/* istanbul ignore next */
/**
* Reconfigures the library according to the environment.
* @returns {undefined}
*/
function configure() {
exports.util.LongBits._configure(exports.util.Long);
exports.Writer._configure(exports.BufferWriter);
exports.Reader._configure(exports.BufferReader);
}
// Set up buffer utility according to the environment
configure();
+12
View File
@@ -0,0 +1,12 @@
"use strict";
exports = module.exports = require("./index-light");
exports.build = "full";
// Parser
exports.tokenize = require("./tokenize");
exports.parse = require("./parse");
exports.common = require("./common");
// Configure parser
exports.Root._configure(exports.Type, exports.parse, exports.common);
+144
View File
@@ -0,0 +1,144 @@
"use strict";
module.exports = MapField;
// extends Field
var Field = require("./field");
MapField.prototype = Object.create(Field.prototype, {
constructor: {
value: MapField,
writable: true,
enumerable: false,
configurable: true
}
});
MapField.className = "MapField";
var types = require("./types"),
util = require("./util");
/**
* Constructs a new map field instance.
* @classdesc Reflected map field.
* @extends FieldBase
* @constructor
* @param {string} name Unique name within its namespace
* @param {number} id Unique id within its namespace
* @param {string} keyType Key type
* @param {string} type Value type
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] Comment associated with this field
*/
function MapField(name, id, keyType, type, options, comment) {
Field.call(this, name, id, type, undefined, undefined, options, comment);
/* istanbul ignore if */
if (!util.isString(keyType))
throw TypeError("keyType must be a string");
/**
* Key type.
* @type {string}
*/
this.keyType = keyType; // toJSON, marker
/**
* Resolved key type if not a basic type.
* @type {ReflectionObject|null}
*/
this.resolvedKeyType = null;
// Overrides Field#map
this.map = true;
}
/**
* Map field descriptor.
* @interface IMapField
* @extends {IField}
* @property {string} keyType Key type
*/
/**
* Extension map field descriptor.
* @interface IExtensionMapField
* @extends IMapField
* @property {string} extend Extended type
*/
/**
* Constructs a map field from a map field descriptor.
* @param {string} name Field name
* @param {IMapField} json Map field descriptor
* @returns {MapField} Created map field
* @throws {TypeError} If arguments are invalid
*/
MapField.fromJSON = function fromJSON(name, json) {
var field = new MapField(name, json.id, json.keyType, json.type, json.options, json.comment);
if (json.protoName)
field.protoName = json.protoName;
if (json.jsonName !== undefined)
field.jsonName = json.jsonName;
else if (json.options && json.options.json_name !== undefined)
field.jsonName = json.options.json_name;
return field;
};
/**
* Converts this map field to a map field descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IMapField} Map field descriptor
*/
MapField.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"keyType" , this.keyType,
"type" , this.type,
"id" , this.id,
"extend" , this.extend,
"protoName" , this.protoName !== this.name ? this.protoName : undefined,
"jsonName" , this.jsonName !== util.jsonName(this.protoName || this.name) ? this.jsonName : undefined,
"options" , this.options,
"comment" , keepComments ? this.comment : undefined
]);
};
/**
* @override
*/
MapField.prototype.resolve = function resolve() {
if (this.resolved)
return this;
// Besides a value type, map fields have a key type that may be "any scalar type except for floating point types and bytes"
if (types.mapKey[this.keyType] === undefined)
throw Error("invalid key type: " + this.keyType);
return Field.prototype.resolve.call(this);
};
/**
* Map field decorator (TypeScript).
* @name MapField.d
* @function
* @param {number} fieldId Field id
* @param {"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"} fieldKeyType Field key type
* @param {"double"|"float"|"int32"|"uint32"|"sint32"|"fixed32"|"sfixed32"|"int64"|"uint64"|"sint64"|"fixed64"|"sfixed64"|"bool"|"string"|"bytes"|Object|Constructor<{}>} fieldValueType Field value type
* @returns {FieldDecorator} Decorator function
* @template T extends { [key: string]: number | Long | string | boolean | Uint8Array | Buffer | number[] | Message<{}> }
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
MapField.d = function decorateMapField(fieldId, fieldKeyType, fieldValueType) {
// submessage value: decorate the submessage and use its name as the type
if (typeof fieldValueType === "function")
fieldValueType = util.decorateType(fieldValueType).name;
// enum reference value: create a reflected copy of the enum and keep reuseing it
else if (fieldValueType && typeof fieldValueType === "object")
fieldValueType = util.decorateEnum(fieldValueType).name;
return function mapFieldDecorator(prototype, fieldName) {
util.decorateType(prototype.constructor)
.add(new MapField(fieldName, fieldId, fieldKeyType, fieldValueType));
};
};
+137
View File
@@ -0,0 +1,137 @@
"use strict";
module.exports = Message;
var util = require("./util/minimal");
/**
* Constructs a new message instance.
* @classdesc Abstract runtime message.
* @constructor
* @param {Properties<T>} [properties] Properties to set
* @property {Array.<Uint8Array>} [$unknowns] Unknown fields preserved while decoding when enabled
* @template T extends object = object
*/
function Message(properties) {
// not used internally
if (properties)
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
if (properties[keys[i]] != null && keys[i] !== "__proto__")
this[keys[i]] = properties[keys[i]];
}
/**
* Reference to the reflected type.
* @name Message.$type
* @type {Type}
* @readonly
*/
/**
* Reference to the reflected type.
* @name Message#$type
* @type {Type}
* @readonly
*/
/**
* Creates a new message of this type using the specified properties.
* @param {Object.<string,*>} [properties] Properties to set
* @returns {T} Message instance
* @template T extends Message<T>
* @this Constructor<T>
*/
Message.create = function create(properties) {
return this.$type.create(properties);
};
/**
* Encodes a message of this type.
* @param {T|Object.<string,*>} message Message to encode
* @param {Writer} [writer] Writer to use
* @returns {Writer} Writer
* @template T extends Message<T>
* @this Constructor<T>
*/
Message.encode = function encode(message, writer) {
return this.$type.encode(message, writer);
};
/**
* Encodes a message of this type preceeded by its length as a varint.
* @param {T|Object.<string,*>} message Message to encode
* @param {Writer} [writer] Writer to use
* @returns {Writer} Writer
* @template T extends Message<T>
* @this Constructor<T>
*/
Message.encodeDelimited = function encodeDelimited(message, writer) {
return this.$type.encodeDelimited(message, writer);
};
/**
* Decodes a message of this type.
* @name Message.decode
* @function
* @param {Reader|Uint8Array} reader Reader or buffer to decode
* @returns {T} Decoded message
* @template T extends Message<T>
* @this Constructor<T>
*/
Message.decode = function decode(reader) {
return this.$type.decode(reader);
};
/**
* Decodes a message of this type preceeded by its length as a varint.
* @name Message.decodeDelimited
* @function
* @param {Reader|Uint8Array} reader Reader or buffer to decode
* @returns {T} Decoded message
* @template T extends Message<T>
* @this Constructor<T>
*/
Message.decodeDelimited = function decodeDelimited(reader) {
return this.$type.decodeDelimited(reader);
};
/**
* Verifies a message of this type.
* @name Message.verify
* @function
* @param {Object.<string,*>} message Plain object to verify
* @returns {string|null} `null` if valid, otherwise the reason why it is not
*/
Message.verify = function verify(message) {
return this.$type.verify(message);
};
/**
* Creates a new message of this type from a plain object. Also converts values to their respective internal types.
* @param {Object.<string,*>} object Plain object
* @returns {T} Message instance
* @template T extends Message<T>
* @this Constructor<T>
*/
Message.fromObject = function fromObject(object) {
return this.$type.fromObject(object);
};
/**
* Creates a plain object from a message of this type. Also converts values to other types if specified.
* @param {T} message Message instance
* @param {IConversionOptions} [options] Conversion options
* @returns {Object.<string,*>} Plain object
* @template T extends Message<T>
* @this Constructor<T>
*/
Message.toObject = function toObject(message, options) {
return this.$type.toObject(message, options);
};
/**
* Converts this message to JSON.
* @returns {Object.<string,*>} JSON object
*/
Message.prototype.toJSON = function toJSON() {
return this.$type.toObject(this, util.toJSONOptions);
};
+183
View File
@@ -0,0 +1,183 @@
"use strict";
module.exports = Method;
// extends ReflectionObject
var ReflectionObject = require("./object");
Method.prototype = Object.create(ReflectionObject.prototype, {
constructor: {
value: Method,
writable: true,
enumerable: false,
configurable: true
}
});
Method.className = "Method";
var util = require("./util");
/**
* Constructs a new service method instance.
* @classdesc Reflected service method.
* @extends ReflectionObject
* @constructor
* @param {string} name Method name
* @param {string|undefined} type Method type, usually `"rpc"`
* @param {string} requestType Request message type
* @param {string} responseType Response message type
* @param {boolean|Object.<string,*>} [requestStream] Whether the request is streamed
* @param {boolean|Object.<string,*>} [responseStream] Whether the response is streamed
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] The comment for this method
* @param {Array.<Object.<string,*>>} [parsedOptions] Declared options, properly parsed into objects
*/
function Method(name, type, requestType, responseType, requestStream, responseStream, options, comment, parsedOptions) {
/* istanbul ignore next */
if (util.isObject(requestStream)) {
options = requestStream;
requestStream = responseStream = undefined;
} else if (util.isObject(responseStream)) {
options = responseStream;
responseStream = undefined;
}
/* istanbul ignore if */
if (!(type === undefined || util.isString(type)))
throw TypeError("type must be a string");
/* istanbul ignore if */
if (!util.isString(requestType))
throw TypeError("requestType must be a string");
/* istanbul ignore if */
if (!util.isString(responseType))
throw TypeError("responseType must be a string");
ReflectionObject.call(this, name, options);
/**
* Method type.
* @type {string}
*/
this.type = type || "rpc"; // toJSON
/**
* Request type.
* @type {string}
*/
this.requestType = requestType; // toJSON, marker
/**
* Whether requests are streamed or not.
* @type {true|undefined}
*/
this.requestStream = requestStream ? true : undefined; // toJSON
/**
* Response type.
* @type {string}
*/
this.responseType = responseType; // toJSON
/**
* Whether responses are streamed or not.
* @type {true|undefined}
*/
this.responseStream = responseStream ? true : undefined; // toJSON
/**
* gRPC-style method path.
* @type {string}
*/
this.path = "/" + this.name;
/**
* Resolved request type.
* @type {Type|null}
*/
this.resolvedRequestType = null;
/**
* Resolved response type.
* @type {Type|null}
*/
this.resolvedResponseType = null;
/**
* Comment for this method
* @type {string|null}
*/
this.comment = comment;
/**
* Options properly parsed into objects
* @type {Array.<Object.<string,*>>|undefined}
*/
this.parsedOptions = parsedOptions;
}
/**
* Method descriptor.
* @interface IMethod
* @property {string} [type="rpc"] Method type
* @property {string} requestType Request type
* @property {string} responseType Response type
* @property {boolean} [requestStream=false] Whether requests are streamed
* @property {boolean} [responseStream=false] Whether responses are streamed
* @property {Object.<string,*>} [options] Method options
* @property {string|null} [comment] Method comment
* @property {Array.<Object.<string,*>>} [parsedOptions] Method options properly parsed into objects
*/
/**
* Constructs a method from a method descriptor.
* @param {string} name Method name
* @param {IMethod} json Method descriptor
* @returns {Method} Created method
* @throws {TypeError} If arguments are invalid
*/
Method.fromJSON = function fromJSON(name, json) {
return new Method(name, json.type, json.requestType, json.responseType, json.requestStream, json.responseStream, json.options, json.comment, json.parsedOptions);
};
/**
* Converts this method to a method descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IMethod} Method descriptor
*/
Method.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"type" , this.type !== "rpc" && /* istanbul ignore next */ this.type || undefined,
"requestType" , this.requestType,
"requestStream" , this.requestStream,
"responseType" , this.responseType,
"responseStream" , this.responseStream,
"options" , this.options,
"comment" , keepComments ? this.comment : undefined,
"parsedOptions" , this.parsedOptions,
]);
};
/**
* @override
*/
Method.prototype.resolve = function resolve() {
/* istanbul ignore if */
if (this.resolved)
return this;
if (this.parent) {
var serviceName = this.parent.fullName;
if (serviceName.charAt(0) === ".")
serviceName = serviceName.substring(1);
this.path = "/" + serviceName + "/" + this.name;
} else
this.path = "/" + this.name;
this.resolvedRequestType = this.parent.lookupType(this.requestType);
this.resolvedResponseType = this.parent.lookupType(this.responseType);
return ReflectionObject.prototype.resolve.call(this);
};
+574
View File
@@ -0,0 +1,574 @@
"use strict";
module.exports = Namespace;
// extends ReflectionObject
var ReflectionObject = require("./object");
Namespace.prototype = Object.create(ReflectionObject.prototype, {
constructor: {
value: Namespace,
writable: true,
enumerable: false,
configurable: true
}
});
Namespace.className = "Namespace";
var Field = require("./field"),
util = require("./util"),
OneOf = require("./oneof");
var Type, // cyclic
Service,
Enum;
/**
* Constructs a new namespace instance.
* @name Namespace
* @classdesc Reflected namespace.
* @extends NamespaceBase
* @constructor
* @param {string} name Namespace name
* @param {Object.<string,*>} [options] Declared options
*/
/**
* Constructs a namespace from JSON.
* @memberof Namespace
* @function
* @param {string} name Namespace name
* @param {Object.<string,*>} json JSON object
* @param {number} [depth] Current nesting depth, defaults to `0`
* @returns {Namespace} Created namespace
* @throws {TypeError} If arguments are invalid
*/
Namespace.fromJSON = function fromJSON(name, json, depth) {
if (depth === undefined)
depth = 0;
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
return new Namespace(name, json.options).addJSON(json.nested, depth);
};
/**
* Converts an array of reflection objects to JSON.
* @memberof Namespace
* @param {ReflectionObject[]} array Object array
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {Object.<string,*>|undefined} JSON object or `undefined` when array is empty
*/
function arrayToJSON(array, toJSONOptions) {
if (!(array && array.length))
return undefined;
var obj = {};
for (var i = 0; i < array.length; ++i)
obj[array[i].name] = array[i].toJSON(toJSONOptions);
return obj;
}
Namespace.arrayToJSON = arrayToJSON;
/**
* Tests if the specified id is reserved.
* @param {Array.<number[]|string>|undefined} reserved Array of reserved ranges and names
* @param {number} id Id to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
Namespace.isReservedId = function isReservedId(reserved, id) {
if (reserved)
for (var i = 0; i < reserved.length; ++i)
if (typeof reserved[i] !== "string" && reserved[i][0] <= id && reserved[i][1] >= id)
return true;
return false;
};
/**
* Tests if the specified name is reserved.
* @param {Array.<number[]|string>|undefined} reserved Array of reserved ranges and names
* @param {string} name Name to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
Namespace.isReservedName = function isReservedName(reserved, name) {
if (reserved)
for (var i = 0; i < reserved.length; ++i)
if (reserved[i] === name)
return true;
return false;
};
/**
* Not an actual constructor. Use {@link Namespace} instead.
* @classdesc Base class of all reflection objects containing nested objects. This is not an actual class but here for the sake of having consistent type definitions.
* @exports NamespaceBase
* @extends ReflectionObject
* @abstract
* @constructor
* @param {string} name Namespace name
* @param {Object.<string,*>} [options] Declared options
* @see {@link Namespace}
*/
function Namespace(name, options) {
ReflectionObject.call(this, name, options);
/**
* Nested objects by name.
* @type {Object.<string,ReflectionObject>|undefined}
*/
this.nested = undefined; // toJSON
/**
* Cached nested objects as an array.
* @type {ReflectionObject[]|null}
* @private
*/
this._nestedArray = null;
/**
* Cache lookup calls for any objects contains anywhere under this namespace.
* This drastically speeds up resolve for large cross-linked protos where the same
* types are looked up repeatedly.
* @type {Object.<string,ReflectionObject|null>}
* @private
*/
this._lookupCache = Object.create(null);
/**
* Whether or not objects contained in this namespace need feature resolution.
* @type {boolean}
* @protected
*/
this._needsRecursiveFeatureResolution = true;
/**
* Whether or not objects contained in this namespace need a resolve.
* @type {boolean}
* @protected
*/
this._needsRecursiveResolve = true;
}
function clearCache(namespace) {
namespace._nestedArray = null;
namespace._lookupCache = Object.create(null);
// Also clear parent caches, since they include nested lookups.
var parent = namespace;
while(parent = parent.parent) {
parent._lookupCache = Object.create(null);
}
return namespace;
}
/**
* Nested objects of this namespace as an array for iteration.
* @name NamespaceBase#nestedArray
* @type {ReflectionObject[]}
* @readonly
*/
Object.defineProperty(Namespace.prototype, "nestedArray", {
get: function() {
return this._nestedArray || (this._nestedArray = util.toArray(this.nested));
}
});
/**
* Namespace descriptor.
* @interface INamespace
* @property {Object.<string,*>} [options] Namespace options
* @property {Object.<string,AnyNestedObject>} [nested] Nested object descriptors
*/
/**
* Any extension field descriptor.
* @typedef AnyExtensionField
* @type {IExtensionField|IExtensionMapField}
*/
/**
* Any nested object descriptor.
* @typedef AnyNestedObject
* @type {IEnum|IType|IService|AnyExtensionField|INamespace|IOneOf}
*/
/**
* Converts this namespace to a namespace descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {INamespace} Namespace descriptor
*/
Namespace.prototype.toJSON = function toJSON(toJSONOptions) {
return util.toObject([
"options" , this.options,
"nested" , arrayToJSON(this.nestedArray, toJSONOptions)
]);
};
/**
* Adds nested objects to this namespace from nested object descriptors.
* @param {Object.<string,AnyNestedObject>} nestedJson Any nested object descriptors
* @param {number} [depth] Current nesting depth, defaults to `0`
* @returns {Namespace} `this`
*/
Namespace.prototype.addJSON = function addJSON(nestedJson, depth) {
if (depth === undefined)
depth = 0;
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
var ns = this;
/* istanbul ignore else */
if (nestedJson) {
for (var names = Object.keys(nestedJson), i = 0, nested; i < names.length; ++i) {
nested = nestedJson[names[i]];
ns.add( // most to least likely
( nested.fields !== undefined
? Type.fromJSON
: nested.values !== undefined
? Enum.fromJSON
: nested.methods !== undefined
? Service.fromJSON
: nested.id !== undefined
? Field.fromJSON
: Namespace.fromJSON )(names[i], nested, depth + 1)
);
}
}
return this;
};
/**
* Gets the nested object of the specified name.
* @param {string} name Nested object name
* @returns {ReflectionObject|null} The reflection object or `null` if it doesn't exist
*/
Namespace.prototype.get = function get(name) {
return this.nested && Object.prototype.hasOwnProperty.call(this.nested, name)
? this.nested[name]
: null;
};
/**
* Gets the values of the nested {@link Enum|enum} of the specified name.
* This methods differs from {@link Namespace#get|get} in that it returns an enum's values directly and throws instead of returning `null`.
* @param {string} name Nested enum name
* @returns {Object.<string,number>} Enum values
* @throws {Error} If there is no such enum
*/
Namespace.prototype.getEnum = function getEnum(name) {
if (this.nested && Object.prototype.hasOwnProperty.call(this.nested, name) && this.nested[name] instanceof Enum)
return this.nested[name].values;
throw Error("no such enum: " + name);
};
/**
* Adds a nested object to this namespace.
* @param {ReflectionObject} object Nested object to add
* @returns {Namespace} `this`
* @throws {TypeError} If arguments are invalid
* @throws {Error} If there is already a nested object with this name
*/
Namespace.prototype.add = function add(object) {
if (!(object instanceof Field && object.extend !== undefined || object instanceof Type || object instanceof OneOf || object instanceof Enum || object instanceof Service || object instanceof Namespace))
throw TypeError("object must be a valid nested object");
if (object.name === "__proto__")
return this;
if (!this.nested)
this.nested = {};
else {
var prev = this.get(object.name);
if (prev) {
if (prev instanceof Namespace && object instanceof Namespace && !(prev instanceof Type || prev instanceof Service)) {
// replace plain namespace but keep existing nested elements and options
var nested = prev.nestedArray;
for (var i = 0; i < nested.length; ++i)
object.add(nested[i]);
this.remove(prev);
if (!this.nested)
this.nested = {};
object.setOptions(prev.options, true);
} else
throw Error("duplicate name '" + object.name + "' in " + this);
}
}
this.nested[object.name] = object;
if (!(this instanceof Type || this instanceof Service || this instanceof Enum || this instanceof Field)) {
// This is a package or a root namespace.
if (!object._edition) {
// Make sure that some edition is set if it hasn't already been specified.
object._edition = object._defaultEdition;
}
}
this._needsRecursiveFeatureResolution = true;
this._needsRecursiveResolve = true;
// Also clear parent caches, since they need to recurse down.
var parent = this;
while(parent = parent.parent) {
parent._needsRecursiveFeatureResolution = true;
parent._needsRecursiveResolve = true;
}
object.onAdd(this);
return clearCache(this);
};
/**
* Removes a nested object from this namespace.
* @param {ReflectionObject} object Nested object to remove
* @returns {Namespace} `this`
* @throws {TypeError} If arguments are invalid
* @throws {Error} If `object` is not a member of this namespace
*/
Namespace.prototype.remove = function remove(object) {
if (!(object instanceof ReflectionObject))
throw TypeError("object must be a ReflectionObject");
if (object.parent !== this)
throw Error(object + " is not a member of " + this);
if (!util.remove(this.nested, object, object.name))
throw Error(object + " is not a member of " + this);
if (!Object.keys(this.nested).length)
this.nested = undefined;
object.onRemove(this);
return clearCache(this);
};
/**
* Defines additial namespaces within this one if not yet existing.
* @param {string|string[]} path Path to create
* @param {*} [json] Nested types to create from JSON
* @returns {Namespace} Pointer to the last namespace created or `this` if path is empty
*/
Namespace.prototype.define = function define(path, json) {
if (util.isString(path))
path = path.split(".");
else if (!Array.isArray(path))
throw TypeError("illegal path");
if (path && path.length && path[0] === "")
throw Error("path must be relative");
if (path.length > util.recursionLimit)
throw Error("max depth exceeded");
var ptr = this;
while (path.length > 0) {
var part = path.shift();
if (ptr.nested && ptr.nested[part]) {
ptr = ptr.nested[part];
if (!(ptr instanceof Namespace))
throw Error("path conflicts with non-namespace objects");
} else
ptr.add(ptr = new Namespace(part));
}
if (json)
ptr.addJSON(json);
return ptr;
};
/**
* Resolves this namespace's and all its nested objects' type references. Useful to validate a reflection tree, but comes at a cost.
* @returns {Namespace} `this`
*/
Namespace.prototype.resolveAll = function resolveAll() {
if (!this._needsRecursiveResolve) return this;
if (this._needsRecursiveFeatureResolution)
this._resolveFeaturesRecursive(this._edition);
var nested = this.nestedArray, i = 0;
this.resolve();
while (i < nested.length)
if (nested[i] instanceof Namespace)
nested[i++].resolveAll();
else
nested[i++].resolve();
this._needsRecursiveResolve = false;
return this;
};
/**
* @override
*/
Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
if (!this._needsRecursiveFeatureResolution) return this;
this._needsRecursiveFeatureResolution = false;
edition = this._edition || edition;
ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);
this.nestedArray.forEach(nested => {
nested._resolveFeaturesRecursive(edition);
});
return this;
};
/**
* Recursively looks up the reflection object matching the specified path in the scope of this namespace.
* @param {string|string[]} path Path to look up
* @param {*|Array.<*>} filterTypes Filter types, any combination of the constructors of `protobuf.Type`, `protobuf.Enum`, `protobuf.Service` etc.
* @param {boolean} [parentAlreadyChecked=false] If known, whether the parent has already been checked
* @returns {ReflectionObject|null} Looked up object or `null` if none could be found
*/
Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChecked) {
/* istanbul ignore next */
if (typeof filterTypes === "boolean") {
parentAlreadyChecked = filterTypes;
filterTypes = undefined;
} else if (filterTypes && !Array.isArray(filterTypes))
filterTypes = [ filterTypes ];
if (util.isString(path) && path.length) {
if (path === ".")
return this.root;
path = path.split(".");
} else if (!path.length)
return this;
var flatPath = path.join(".");
// Start at root if path is absolute
if (path[0] === "")
return this.root.lookup(path.slice(1), filterTypes);
// Lookup at this namespace and below
var found = this._lookupImpl(path, flatPath);
if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
return found;
}
// Fall back to respective absolute path once relative scope has been checked (non-standard)
found = this.root._fullyQualifiedObjects && this.root._fullyQualifiedObjects["." + flatPath];
if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
return found;
}
if (parentAlreadyChecked)
return null;
// If there hasn't been a match, walk up the tree and look more broadly
var current = this;
while (current.parent) {
found = current.parent._lookupImpl(path, flatPath);
if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) {
return found;
}
current = current.parent;
}
return null;
};
/**
* Internal helper for lookup that handles searching just at this namespace and below along with caching.
* @param {string[]} path Path to look up
* @param {string} flatPath Flattened version of the path to use as a cache key
* @returns {ReflectionObject|null} Looked up object or `null` if none could be found
* @private
*/
Namespace.prototype._lookupImpl = function lookup(path, flatPath) {
if(Object.prototype.hasOwnProperty.call(this._lookupCache, flatPath)) {
return this._lookupCache[flatPath];
}
// Test if the first part matches any nested object, and if so, traverse if path contains more
var found = this.get(path[0]);
var exact = null;
if (found) {
if (path.length === 1) {
exact = found;
} else if (found instanceof Namespace) {
path = path.slice(1);
exact = found._lookupImpl(path, path.join("."));
}
// Otherwise try each nested namespace
} else {
for (var i = 0; i < this.nestedArray.length; ++i)
if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path, flatPath))) {
exact = found;
break;
}
}
// Set this even when null, so that when we walk up the tree we can quickly bail on repeated checks back down.
this._lookupCache[flatPath] = exact;
return exact;
};
/**
* Looks up the reflection object at the specified path, relative to this namespace.
* @name NamespaceBase#lookup
* @function
* @param {string|string[]} path Path to look up
* @param {boolean} [parentAlreadyChecked=false] Whether the parent has already been checked
* @returns {ReflectionObject|null} Looked up object or `null` if none could be found
* @variation 2
*/
// lookup(path: string, [parentAlreadyChecked: boolean])
/**
* Looks up the {@link Type|type} at the specified path, relative to this namespace.
* Besides its signature, this methods differs from {@link Namespace#lookup|lookup} in that it throws instead of returning `null`.
* @param {string|string[]} path Path to look up
* @returns {Type} Looked up type
* @throws {Error} If `path` does not point to a type
*/
Namespace.prototype.lookupType = function lookupType(path) {
var found = this.lookup(path, [ Type ]);
if (!found)
throw Error("no such type: " + path);
return found;
};
/**
* Looks up the values of the {@link Enum|enum} at the specified path, relative to this namespace.
* Besides its signature, this methods differs from {@link Namespace#lookup|lookup} in that it throws instead of returning `null`.
* @param {string|string[]} path Path to look up
* @returns {Enum} Looked up enum
* @throws {Error} If `path` does not point to an enum
*/
Namespace.prototype.lookupEnum = function lookupEnum(path) {
var found = this.lookup(path, [ Enum ]);
if (!found)
throw Error("no such Enum '" + path + "' in " + this);
return found;
};
/**
* Looks up the {@link Type|type} or {@link Enum|enum} at the specified path, relative to this namespace.
* Besides its signature, this methods differs from {@link Namespace#lookup|lookup} in that it throws instead of returning `null`.
* @param {string|string[]} path Path to look up
* @returns {Type} Looked up type or enum
* @throws {Error} If `path` does not point to a type or enum
*/
Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path) {
var found = this.lookup(path, [ Type, Enum ]);
if (!found)
throw Error("no such Type or Enum '" + path + "' in " + this);
return found;
};
/**
* Looks up the {@link Service|service} at the specified path, relative to this namespace.
* Besides its signature, this methods differs from {@link Namespace#lookup|lookup} in that it throws instead of returning `null`.
* @param {string|string[]} path Path to look up
* @returns {Service} Looked up service
* @throws {Error} If `path` does not point to a service
*/
Namespace.prototype.lookupService = function lookupService(path) {
var found = this.lookup(path, [ Service ]);
if (!found)
throw Error("no such Service '" + path + "' in " + this);
return found;
};
// Sets up cyclic dependencies (called in index-light)
Namespace._configure = function(Type_, Service_, Enum_) {
Type = Type_;
Service = Service_;
Enum = Enum_;
};
+392
View File
@@ -0,0 +1,392 @@
"use strict";
module.exports = ReflectionObject;
ReflectionObject.className = "ReflectionObject";
const OneOf = require("./oneof");
var util = require("./util");
var Root; // cyclic
/* eslint-disable no-warning-comments */
// TODO: Replace with embedded proto.
var editions2024Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE2024", default_symbol_visibility: "EXPORT_TOP_LEVEL" };
var editions2023Defaults = {enum_type: "OPEN", field_presence: "EXPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE_LEGACY", default_symbol_visibility: "EXPORT_ALL" };
var proto2Defaults = {enum_type: "CLOSED", field_presence: "EXPLICIT", json_format: "LEGACY_BEST_EFFORT", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "EXPANDED", utf8_validation: "NONE", enforce_naming_style: "STYLE_LEGACY", default_symbol_visibility: "EXPORT_ALL" };
var proto3Defaults = {enum_type: "OPEN", field_presence: "IMPLICIT", json_format: "ALLOW", message_encoding: "LENGTH_PREFIXED", repeated_field_encoding: "PACKED", utf8_validation: "VERIFY", enforce_naming_style: "STYLE_LEGACY", default_symbol_visibility: "EXPORT_ALL" };
/**
* Constructs a new reflection object instance.
* @classdesc Base class of all reflection objects.
* @constructor
* @param {string} name Object name
* @param {Object.<string,*>} [options] Declared options
* @abstract
*/
function ReflectionObject(name, options) {
if (!util.isString(name))
throw TypeError("name must be a string");
if (options && !util.isObject(options))
throw TypeError("options must be an object");
/**
* Options.
* @type {Object.<string,*>|undefined}
*/
this.options = options; // toJSON
/**
* Parsed Options.
* @type {Array.<Object.<string,*>>|undefined}
*/
this.parsedOptions = null;
/**
* Unique name within its namespace.
* @type {string}
*/
this.name = name;
/**
* The edition specified for this object. Only relevant for top-level objects.
* @type {string}
* @private
*/
this._edition = null;
/**
* The default edition to use for this object if none is specified. For legacy reasons,
* this is proto2 except in the JSON parsing case where it was proto3.
* @type {string}
* @private
*/
this._defaultEdition = "proto2";
/**
* Resolved Features.
* @type {object}
* @private
*/
this._features = {};
/**
* Whether or not features have been resolved.
* @type {boolean}
* @private
*/
this._featuresResolved = false;
/**
* Parent namespace.
* @type {Namespace|null}
*/
this.parent = null;
/**
* Whether already resolved or not.
* @type {boolean}
*/
this.resolved = false;
/**
* Comment text, if any.
* @type {string|null}
*/
this.comment = null;
/**
* Defining file name.
* @type {string|null}
*/
this.filename = null;
}
Object.defineProperties(ReflectionObject.prototype, {
/**
* Reference to the root namespace.
* @name ReflectionObject#root
* @type {Root}
* @readonly
*/
root: {
get: function() {
var ptr = this;
while (ptr.parent !== null)
ptr = ptr.parent;
return ptr;
}
},
/**
* Full name including leading dot.
* @name ReflectionObject#fullName
* @type {string}
* @readonly
*/
fullName: {
get: function() {
var path = [ this.name ],
ptr = this.parent;
while (ptr) {
path.unshift(ptr.name);
ptr = ptr.parent;
}
return path.join(".");
}
}
});
/**
* Converts this reflection object to its descriptor representation.
* @returns {Object.<string,*>} Descriptor
*/
ReflectionObject.prototype.toJSON = /* istanbul ignore next */ function toJSON() {
throw Error(); // not implemented, shouldn't happen
};
/**
* Called when this object is added to a parent.
* @param {ReflectionObject} parent Parent added to
* @returns {undefined}
*/
ReflectionObject.prototype.onAdd = function onAdd(parent) {
if (this.parent && this.parent !== parent)
this.parent.remove(this);
this.parent = parent;
this.resolved = false;
var root = parent.root;
if (root instanceof Root)
root._handleAdd(this);
};
/**
* Called when this object is removed from a parent.
* @param {ReflectionObject} parent Parent removed from
* @returns {undefined}
*/
ReflectionObject.prototype.onRemove = function onRemove(parent) {
var root = parent.root;
if (root instanceof Root)
root._handleRemove(this);
this.parent = null;
this.resolved = false;
};
/**
* Resolves this objects type references.
* @returns {ReflectionObject} `this`
*/
ReflectionObject.prototype.resolve = function resolve() {
if (this.resolved)
return this;
if (this.root instanceof Root)
this.resolved = true; // only if part of a root
return this;
};
/**
* Resolves this objects editions features.
* @param {string} edition The edition we're currently resolving for.
* @returns {ReflectionObject} `this`
*/
ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
return this._resolveFeatures(this._edition || edition);
};
/**
* Resolves child features from parent features
* @param {string} edition The edition we're currently resolving for.
* @returns {undefined}
*/
ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
if (this._featuresResolved) {
return;
}
var defaults = {};
/* istanbul ignore if */
if (!edition) {
throw new Error("Unknown edition for " + this.fullName);
}
var protoFeatures = util.merge({}, this.options && this.options.features,
this._inferLegacyProtoFeatures(edition));
if (this._edition) {
// For a namespace marked with a specific edition, reset defaults.
/* istanbul ignore else */
if (edition === "proto2") {
defaults = Object.assign({}, proto2Defaults);
} else if (edition === "proto3") {
defaults = Object.assign({}, proto3Defaults);
} else if (edition === "2023") {
defaults = Object.assign({}, editions2023Defaults);
} else if (edition === "2024") {
defaults = Object.assign({}, editions2024Defaults);
} else {
throw new Error("Unknown edition: " + edition);
}
this._features = util.merge(defaults, protoFeatures);
} else {
// fields in Oneofs aren't actually children of them, so we have to
// special-case it
/* istanbul ignore else */
if (this.partOf instanceof OneOf) {
var lexicalParentFeaturesCopy = util.merge({}, this.partOf._features);
this._features = util.merge(lexicalParentFeaturesCopy, protoFeatures);
} else if (this.declaringField) {
// Skip feature resolution of sister fields.
} else if (this.parent) {
var parentFeaturesCopy = util.merge({}, this.parent._features);
this._features = util.merge(parentFeaturesCopy, protoFeatures);
} else {
throw new Error("Unable to find a parent for " + this.fullName);
}
}
if (this.extensionField) {
// Sister fields should have the same features as their extensions.
this.extensionField._features = this._features;
}
this._featuresResolved = true;
};
/**
* Infers features from legacy syntax that may have been specified differently.
* in older editions.
* @param {string|undefined} edition The edition this proto is on, or undefined if pre-editions
* @returns {object} The feature values to override
*/
ReflectionObject.prototype._inferLegacyProtoFeatures = function _inferLegacyProtoFeatures(/*edition*/) {
return {};
};
/**
* Gets an option value.
* @param {string} name Option name
* @returns {*} Option value or `undefined` if not set
*/
ReflectionObject.prototype.getOption = function getOption(name) {
if (this.options && Object.prototype.hasOwnProperty.call(this.options, name))
return this.options[name];
return undefined;
};
/**
* Sets an option.
* @param {string} name Option name
* @param {*} value Option value
* @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
* @returns {ReflectionObject} `this`
*/
ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) {
if (name === "__proto__")
return this;
if (!this.options)
this.options = {};
if (/^features\./.test(name)) {
util.setProperty(this.options, name, value, ifNotSet);
} else {
var prev = this.getOption(name);
if (!ifNotSet || prev === undefined) {
if (prev !== value) this.resolved = false;
this.options[name] = value;
}
}
return this;
};
/**
* Sets a parsed option.
* @param {string} name parsed Option name
* @param {*} value Option value
* @param {string} propName dot '.' delimited full path of property within the option to set. if undefined\empty, will add a new option with that value
* @returns {ReflectionObject} `this`
*/
ReflectionObject.prototype.setParsedOption = function setParsedOption(name, value, propName) {
if (name === "__proto__")
return this;
if (!this.parsedOptions) {
this.parsedOptions = [];
}
var parsedOptions = this.parsedOptions;
if (propName) {
// If setting a sub property of an option then try to merge it
// with an existing option
var opt = parsedOptions.find(function (opt) {
return Object.prototype.hasOwnProperty.call(opt, name);
});
if (opt) {
// If we found an existing option - just merge the property value
// (If it's a feature, will just write over)
var newValue = opt[name];
util.setProperty(newValue, propName, value);
} else {
// otherwise, create a new option, set its property and add it to the list
opt = {};
opt[name] = util.setProperty({}, propName, value);
parsedOptions.push(opt);
}
} else {
// Always create a new option when setting the value of the option itself
var newOpt = {};
newOpt[name] = value;
parsedOptions.push(newOpt);
}
return this;
};
/**
* Sets multiple options.
* @param {Object.<string,*>} options Options to set
* @param {boolean} [ifNotSet] Sets an option only if it isn't currently set
* @returns {ReflectionObject} `this`
*/
ReflectionObject.prototype.setOptions = function setOptions(options, ifNotSet) {
if (options)
for (var keys = Object.keys(options), i = 0; i < keys.length; ++i)
this.setOption(keys[i], options[keys[i]], ifNotSet);
return this;
};
/**
* Converts this instance to its string representation.
* @name ReflectionObject#toString
* @function
* @returns {string} Class name[, space, full name]
*/
Object.defineProperty(ReflectionObject.prototype, "toString", {
value: function toString() {
var className = this.constructor.className,
fullName = this.fullName;
if (fullName.length)
return className + " " + fullName;
return className;
},
writable: true,
enumerable: false,
configurable: true
});
/**
* Converts the edition this object is pinned to for JSON format.
* @returns {string|undefined} The edition string for JSON representation
*/
ReflectionObject.prototype._editionToJSON = function _editionToJSON() {
if (!this._edition || this._edition === "proto3") {
// Avoid emitting proto3 since we need to default to it for backwards
// compatibility anyway.
return undefined;
}
return this._edition;
};
// Sets up cyclic dependencies (called in index-light)
ReflectionObject._configure = function(Root_) {
Root = Root_;
};
+233
View File
@@ -0,0 +1,233 @@
"use strict";
module.exports = OneOf;
// extends ReflectionObject
var ReflectionObject = require("./object");
OneOf.prototype = Object.create(ReflectionObject.prototype, {
constructor: {
value: OneOf,
writable: true,
enumerable: false,
configurable: true
}
});
OneOf.className = "OneOf";
var Field = require("./field"),
util = require("./util");
/**
* Constructs a new oneof instance.
* @classdesc Reflected oneof.
* @extends ReflectionObject
* @constructor
* @param {string} name Oneof name
* @param {string[]|Object.<string,*>} [fieldNames] Field names
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] Comment associated with this field
*/
function OneOf(name, fieldNames, options, comment) {
if (!Array.isArray(fieldNames)) {
options = fieldNames;
fieldNames = undefined;
}
ReflectionObject.call(this, name, options);
/* istanbul ignore if */
if (!(fieldNames === undefined || Array.isArray(fieldNames)))
throw TypeError("fieldNames must be an Array");
/**
* Field names that belong to this oneof.
* @type {string[]}
*/
this.oneof = fieldNames || []; // toJSON, marker
/**
* Fields that belong to this oneof as an array for iteration.
* @type {Field[]}
* @readonly
*/
this.fieldsArray = []; // declared readonly for conformance, possibly not yet added to parent
/**
* Comment for this field.
* @type {string|null}
*/
this.comment = comment;
}
/**
* Oneof descriptor.
* @interface IOneOf
* @property {Array.<string>} oneof Oneof field names
* @property {Object.<string,*>} [options] Oneof options
* @property {string|null} [comment] Oneof comment
*/
/**
* Constructs a oneof from a oneof descriptor.
* @param {string} name Oneof name
* @param {IOneOf} json Oneof descriptor
* @returns {OneOf} Created oneof
* @throws {TypeError} If arguments are invalid
*/
OneOf.fromJSON = function fromJSON(name, json) {
return new OneOf(name, json.oneof, json.options, json.comment);
};
/**
* Converts this oneof to a oneof descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IOneOf} Oneof descriptor
*/
OneOf.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"options" , this.options,
"oneof" , this.oneof,
"comment" , keepComments ? this.comment : undefined
]);
};
/**
* Adds the fields of the specified oneof to the parent if not already done so.
* @param {OneOf} oneof The oneof
* @returns {undefined}
* @inner
* @ignore
*/
function addFieldsToParent(oneof) {
if (oneof.parent)
for (var i = 0; i < oneof.fieldsArray.length; ++i)
if (!oneof.fieldsArray[i].parent)
oneof.parent.add(oneof.fieldsArray[i]);
}
/**
* Adds a field to this oneof and removes it from its current parent, if any.
* @param {Field} field Field to add
* @returns {OneOf} `this`
*/
OneOf.prototype.add = function add(field) {
/* istanbul ignore if */
if (!(field instanceof Field))
throw TypeError("field must be a Field");
if (field.parent && field.parent !== this.parent)
field.parent.remove(field);
this.oneof.push(field.name);
this.fieldsArray.push(field);
field.partOf = this; // field.parent remains null
addFieldsToParent(this);
return this;
};
/**
* Removes a field from this oneof and puts it back to the oneof's parent.
* @param {Field} field Field to remove
* @returns {OneOf} `this`
*/
OneOf.prototype.remove = function remove(field) {
/* istanbul ignore if */
if (!(field instanceof Field))
throw TypeError("field must be a Field");
var index = this.fieldsArray.indexOf(field);
/* istanbul ignore if */
if (index < 0)
throw Error(field + " is not a member of " + this);
this.fieldsArray.splice(index, 1);
index = this.oneof.indexOf(field.name);
/* istanbul ignore else */
if (index > -1) // theoretical
this.oneof.splice(index, 1);
field.partOf = null;
return this;
};
/**
* @override
*/
OneOf.prototype.onAdd = function onAdd(parent) {
ReflectionObject.prototype.onAdd.call(this, parent);
var self = this;
// Collect present fields
for (var i = 0; i < this.oneof.length; ++i) {
var field = parent.get(this.oneof[i]);
if (field && !field.partOf) {
field.partOf = self;
self.fieldsArray.push(field);
}
}
// Add not yet present fields
addFieldsToParent(this);
};
/**
* @override
*/
OneOf.prototype.onRemove = function onRemove(parent) {
for (var i = 0, field; i < this.fieldsArray.length; ++i)
if ((field = this.fieldsArray[i]).parent)
field.parent.remove(field);
ReflectionObject.prototype.onRemove.call(this, parent);
};
/**
* Determines whether this field corresponds to a synthetic oneof created for
* a proto3 optional field. No behavioral logic should depend on this, but it
* can be relevant for reflection.
* @name OneOf#isProto3Optional
* @type {boolean}
* @readonly
*/
Object.defineProperty(OneOf.prototype, "isProto3Optional", {
get: function() {
if (this.fieldsArray == null || this.fieldsArray.length !== 1) {
return false;
}
var field = this.fieldsArray[0];
return field.options != null && field.options["proto3_optional"] === true;
}
});
/**
* Decorator function as returned by {@link OneOf.d} (TypeScript).
* @typedef OneOfDecorator
* @type {function}
* @param {Object} prototype Target prototype
* @param {string} oneofName OneOf name
* @returns {undefined}
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
/**
* OneOf decorator (TypeScript).
* @function
* @param {...string} fieldNames Field names
* @returns {OneOfDecorator} Decorator function
* @template T extends string
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
OneOf.d = function decorateOneOf() {
var fieldNames = new Array(arguments.length),
index = 0;
while (index < arguments.length)
fieldNames[index] = arguments[index++];
return function oneOfDecorator(prototype, oneofName) {
util.decorateType(prototype.constructor)
.add(new OneOf(oneofName, fieldNames));
Object.defineProperty(prototype, oneofName, {
get: util.oneOfGetter(fieldNames),
set: util.oneOfSetter(fieldNames)
});
};
};
+1111
View File
File diff suppressed because it is too large Load Diff
+788
View File
@@ -0,0 +1,788 @@
"use strict";
module.exports = Reader;
var util = require("./util/minimal");
var BufferReader; // cyclic
var LongBits = util.LongBits,
utf8 = util.utf8;
/* istanbul ignore next */
function indexOutOfRange(reader, writeLength) {
return RangeError("index out of range: " + reader.pos + " + " + (writeLength || 1) + " > " + reader.len);
}
/**
* Constructs a new reader instance using the specified buffer.
* @classdesc Wire format reader using `Uint8Array`.
* @constructor
* @param {Uint8Array} buffer Buffer to read from
*/
function Reader(buffer) {
/**
* Read buffer.
* @type {Uint8Array}
*/
this.buf = buffer;
/**
* Read buffer position.
* @type {number}
*/
this.pos = 0;
/**
* Read buffer length.
* @type {number}
*/
this.len = buffer.length;
/**
* Cached DataView for packed reads.
* @type {DataView|null}
*/
this.view = null;
/**
* Whether to discard unknown fields while decoding.
* @type {boolean}
*/
this.discardUnknown = Reader.discardUnknown;
}
function create_array(buffer) {
// TODO: Remove plain array reader support in the next major release.
if (Array.isArray(buffer))
buffer = new Uint8Array(buffer);
if (buffer instanceof Uint8Array)
return new Reader(buffer);
throw Error("illegal buffer");
}
var create = function create() {
return util.Buffer
? function create_buffer_setup(buffer) {
return (Reader.create = function create_buffer(buffer) {
return util.Buffer.isBuffer(buffer)
? new BufferReader(buffer)
/* istanbul ignore next */
: create_array(buffer);
})(buffer);
}
/* istanbul ignore next */
: create_array;
};
/**
* Creates a new reader using the specified buffer.
* @function
* @param {Uint8Array|Buffer} buffer Buffer to read from
* @returns {Reader|BufferReader} A {@link BufferReader} if `buffer` is a Buffer, otherwise a {@link Reader}
* @throws {Error} If `buffer` is not a valid buffer
*/
Reader.create = create();
/**
* Returns raw bytes from the backing buffer without advancing the reader.
* @param {number} start Start offset
* @param {number} end End offset
* @returns {Uint8Array} Raw bytes
*/
Reader.prototype.raw = function read_raw(start, end) {
return this.buf.subarray(start, end);
};
/**
* Reads a varint as an unsigned 32 bit value.
* @function
* @returns {number} Value read
*/
Reader.prototype.uint32 = function read_uint32() {
var buf = this.buf,
pos = this.pos,
value = (buf[pos] & 127) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
value = (value | (buf[pos] & 127) << 7) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
value = (value | (buf[pos] & 127) << 14) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
value = (value | (buf[pos] & 127) << 21) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
value = (value | (buf[pos] & 15) << 28) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
for (var i = 0; i < 5; ++i) {
/* istanbul ignore if */
if (pos >= this.len) {
this.pos = pos;
throw indexOutOfRange(this);
}
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
}
/* istanbul ignore next */
this.pos = pos;
throw Error("invalid varint encoding");
};
/**
* Reads a field tag.
* @function
* @returns {number} Tag read
*/
Reader.prototype.tag = function read_tag() {
var buf = this.buf,
pos = this.pos,
value = (buf[pos] & 127) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
value = (value | (buf[pos] & 127) << 7) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
value = (value | (buf[pos] & 127) << 14) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
value = (value | (buf[pos] & 127) << 21) >>> 0;
if (buf[pos++] < 128) {
this.pos = pos;
return value;
}
value = (value | (buf[pos] & 15) << 28) >>> 0;
if (buf[pos] < 128 && (buf[pos] & 112) === 0) {
this.pos = pos + 1;
return value;
}
this.pos = pos + 1;
throw Error("invalid tag encoding");
};
/**
* Reads a varint as a signed 32 bit value.
* @returns {number} Value read
*/
Reader.prototype.int32 = function read_int32() {
return this.uint32() | 0;
};
/**
* Reads a zig-zag encoded varint as a signed 32 bit value.
* @returns {number} Value read
*/
Reader.prototype.sint32 = function read_sint32() {
var value = this.uint32();
return value >>> 1 ^ -(value & 1) | 0;
};
/* eslint-disable no-invalid-this */
function readLongVarint() {
// tends to deopt with local vars for octet etc.
var bits = new LongBits(0, 0);
var i = 0;
if (this.len - this.pos > 4) { // fast route (lo)
for (; i < 4; ++i) {
// 1st..4th
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
}
// 5th
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << 28) >>> 0;
bits.hi = (bits.hi | (this.buf[this.pos] & 127) >> 4) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
i = 0;
} else {
for (; i < 4; ++i) {
/* istanbul ignore if */
if (this.pos >= this.len)
throw indexOutOfRange(this);
// 1st..4th
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
}
throw indexOutOfRange(this);
}
if (this.len - this.pos > 4) { // fast route (hi)
for (; i < 5; ++i) {
// 6th..10th
bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
}
} else {
for (; i < 5; ++i) {
/* istanbul ignore if */
if (this.pos >= this.len)
throw indexOutOfRange(this);
// 6th..10th
bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
}
}
/* istanbul ignore next */
throw Error("invalid varint encoding");
}
/* eslint-enable no-invalid-this */
/**
* Reads a varint as a signed 64 bit value.
* @name Reader#int64
* @function
* @returns {Long} Value read
*/
/**
* Reads a varint as an unsigned 64 bit value.
* @name Reader#uint64
* @function
* @returns {Long} Value read
*/
/**
* Reads a zig-zag encoded varint as a signed 64 bit value.
* @name Reader#sint64
* @function
* @returns {Long} Value read
*/
/**
* Reads a varint as a boolean.
* @returns {boolean} Value read
*/
Reader.prototype.bool = function read_bool() {
var value = false,
b;
for (var i = 0; i < 10; ++i) {
/* istanbul ignore if */
if (this.pos >= this.len)
throw indexOutOfRange(this);
b = this.buf[this.pos++];
if (b & 127)
value = true;
if (b < 128)
return value;
}
/* istanbul ignore next */
throw Error("invalid varint encoding");
};
function readFixed32_end(buf, end) { // note that this uses `end`, not `pos`
return (buf[end - 4]
| buf[end - 3] << 8
| buf[end - 2] << 16
| buf[end - 1] << 24) >>> 0;
}
/**
* Reads fixed 32 bits as an unsigned 32 bit integer.
* @returns {number} Value read
*/
Reader.prototype.fixed32 = function read_fixed32() {
/* istanbul ignore if */
if (this.pos + 4 > this.len)
throw indexOutOfRange(this, 4);
return readFixed32_end(this.buf, this.pos += 4);
};
/**
* Reads fixed 32 bits as a signed 32 bit integer.
* @returns {number} Value read
*/
Reader.prototype.sfixed32 = function read_sfixed32() {
/* istanbul ignore if */
if (this.pos + 4 > this.len)
throw indexOutOfRange(this, 4);
return readFixed32_end(this.buf, this.pos += 4) | 0;
};
/* eslint-disable no-invalid-this */
function readFixed64(/* this: Reader */) {
/* istanbul ignore if */
if (this.pos + 8 > this.len)
throw indexOutOfRange(this, 8);
return new LongBits(readFixed32_end(this.buf, this.pos += 4), readFixed32_end(this.buf, this.pos += 4));
}
/* eslint-enable no-invalid-this */
/**
* Reads fixed 64 bits.
* @name Reader#fixed64
* @function
* @returns {Long} Value read
*/
/**
* Reads zig-zag encoded fixed 64 bits.
* @name Reader#sfixed64
* @function
* @returns {Long} Value read
*/
/**
* Reads a float (32 bit) as a number.
* @function
* @returns {number} Value read
*/
Reader.prototype.float = function read_float() {
/* istanbul ignore if */
if (this.pos + 4 > this.len)
throw indexOutOfRange(this, 4);
var value = util.float.readFloatLE(this.buf, this.pos);
this.pos += 4;
return value;
};
/**
* Reads a double (64 bit float) as a number.
* @function
* @returns {number} Value read
*/
Reader.prototype.double = function read_double() {
/* istanbul ignore if */
if (this.pos + 8 > this.len)
throw indexOutOfRange(this, 4);
var value = util.float.readDoubleLE(this.buf, this.pos);
this.pos += 8;
return value;
};
/**
* Reads a packed repeated field of unsigned 32 bit varints.
* @param {number[]} [array] Array to read into; a new one is created if omitted
* @returns {number[]} Array read into
*/
Reader.prototype.uint32s = function read_uint32s(array) {
if (array === undefined) array = [];
var end = this.uint32() + this.pos;
while (this.pos < end)
array.push(this.uint32());
return array;
};
/**
* Reads a packed repeated field of signed 32 bit varints.
* @param {number[]} [array] Array to read into; a new one is created if omitted
* @returns {number[]} Array read into
*/
Reader.prototype.int32s = function read_int32s(array) {
if (array === undefined) array = [];
var end = this.uint32() + this.pos;
while (this.pos < end)
array.push(this.int32());
return array;
};
/**
* Reads a packed repeated field of zig-zag encoded signed 32 bit varints.
* @param {number[]} [array] Array to read into; a new one is created if omitted
* @returns {number[]} Array read into
*/
Reader.prototype.sint32s = function read_sint32s(array) {
if (array === undefined) array = [];
var end = this.uint32() + this.pos;
while (this.pos < end)
array.push(this.sint32());
return array;
};
/**
* Reads a packed repeated field of booleans.
* @param {boolean[]} [array] Array to read into; a new one is created if omitted
* @returns {boolean[]} Array read into
*/
Reader.prototype.bools = function read_bools(array) {
if (array === undefined) array = [];
var end = this.uint32() + this.pos;
while (this.pos < end)
array.push(this.bool());
return array;
};
// The view allocation only pays off when amortized over enough reads
var VIEW_THRESHOLD_FLOAT = 8,
VIEW_THRESHOLD_INT = 128;
function getLazyView(reader, count, threshold) {
var view = reader.view;
if (view || count < threshold)
return view;
var buf = reader.buf;
return reader.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
}
/**
* Reads a packed repeated field of unsigned 32 bit fixed values.
* @param {number[]} [array] Array to read into; a new one is created if omitted
* @returns {number[]} Array read into
*/
Reader.prototype.fixed32s = function read_fixed32s(array) {
if (array === undefined) array = [];
var len = this.uint32(), end = this.pos + len;
/* istanbul ignore if */
if (end > this.len) throw indexOutOfRange(this, len);
var count = len >>> 2, i = array.length, pos = this.pos;
array.length = i + count;
var dv = getLazyView(this, count, VIEW_THRESHOLD_INT);
if (dv)
for (var k = 0; k < count; ++k, pos += 4) array[i++] = dv.getUint32(pos, true);
else {
var buf = this.buf;
for (var j = 0; j < count; ++j, pos += 4) array[i++] = readFixed32_end(buf, pos + 4);
}
this.pos = pos;
if (pos !== end) throw indexOutOfRange(this, 4);
return array;
};
/**
* Reads a packed repeated field of signed 32 bit fixed values.
* @param {number[]} [array] Array to read into; a new one is created if omitted
* @returns {number[]} Array read into
*/
Reader.prototype.sfixed32s = function read_sfixed32s(array) {
if (array === undefined) array = [];
var len = this.uint32(), end = this.pos + len;
/* istanbul ignore if */
if (end > this.len) throw indexOutOfRange(this, len);
var count = len >>> 2, i = array.length, pos = this.pos;
array.length = i + count;
var dv = getLazyView(this, count, VIEW_THRESHOLD_INT);
if (dv)
for (var k = 0; k < count; ++k, pos += 4) array[i++] = dv.getInt32(pos, true);
else {
var buf = this.buf;
for (var j = 0; j < count; ++j, pos += 4) array[i++] = readFixed32_end(buf, pos + 4) | 0;
}
this.pos = pos;
if (pos !== end) throw indexOutOfRange(this, 4);
return array;
};
/**
* Reads a packed repeated field of floats (32 bit).
* @param {number[]} [array] Array to read into; a new one is created if omitted
* @returns {number[]} Array read into
*/
Reader.prototype.floats = function read_floats(array) {
if (array === undefined) array = [];
var len = this.uint32(), end = this.pos + len;
/* istanbul ignore if */
if (end > this.len) throw indexOutOfRange(this, len);
var count = len >>> 2, i = array.length, pos = this.pos;
array.length = i + count;
var dv = getLazyView(this, count, VIEW_THRESHOLD_FLOAT);
if (dv)
for (var k = 0; k < count; ++k, pos += 4) array[i++] = dv.getFloat32(pos, true);
else {
var buf = this.buf;
for (var j = 0; j < count; ++j, pos += 4) array[i++] = util.float.readFloatLE(buf, pos);
}
this.pos = pos;
if (pos !== end) throw indexOutOfRange(this, 4);
return array;
};
/**
* Reads a packed repeated field of doubles (64 bit float).
* @param {number[]} [array] Array to read into; a new one is created if omitted
* @returns {number[]} Array read into
*/
Reader.prototype.doubles = function read_doubles(array) {
if (array === undefined) array = [];
var len = this.uint32(), end = this.pos + len;
/* istanbul ignore if */
if (end > this.len) throw indexOutOfRange(this, len);
var count = len >>> 3, i = array.length, pos = this.pos;
array.length = i + count;
var dv = getLazyView(this, count, VIEW_THRESHOLD_FLOAT);
if (dv)
for (var k = 0; k < count; ++k, pos += 8) array[i++] = dv.getFloat64(pos, true);
else {
var buf = this.buf;
for (var j = 0; j < count; ++j, pos += 8) array[i++] = util.float.readDoubleLE(buf, pos);
}
this.pos = pos;
if (pos !== end) throw indexOutOfRange(this, 8);
return array;
};
/**
* Reads a packed repeated field of unsigned 64 bit varints.
* @param {Array.<Long|number>} [array] Array to read into; a new one is created if omitted
* @returns {Array.<Long|number>} Array read into
*/
Reader.prototype.uint64s = function read_uint64s(array) {
if (array === undefined) array = [];
var end = this.uint32() + this.pos;
while (this.pos < end)
array.push(this.uint64());
return array;
};
/**
* Reads a packed repeated field of signed 64 bit varints.
* @param {Array.<Long|number>} [array] Array to read into; a new one is created if omitted
* @returns {Array.<Long|number>} Array read into
*/
Reader.prototype.int64s = function read_int64s(array) {
if (array === undefined) array = [];
var end = this.uint32() + this.pos;
while (this.pos < end)
array.push(this.int64());
return array;
};
/**
* Reads a packed repeated field of zig-zag encoded signed 64 bit varints.
* @param {Array.<Long|number>} [array] Array to read into; a new one is created if omitted
* @returns {Array.<Long|number>} Array read into
*/
Reader.prototype.sint64s = function read_sint64s(array) {
if (array === undefined) array = [];
var end = this.uint32() + this.pos;
while (this.pos < end)
array.push(this.sint64());
return array;
};
/**
* Reads a packed repeated field of unsigned 64 bit fixed values.
* @param {Array.<Long|number>} [array] Array to read into; a new one is created if omitted
* @returns {Array.<Long|number>} Array read into
*/
Reader.prototype.fixed64s = function read_fixed64s(array) {
if (array === undefined) array = [];
var len = this.uint32(), end = this.pos + len, i = array.length;
/* istanbul ignore if */
if (end > this.len) throw indexOutOfRange(this, len);
var count = len >>> 3;
array.length = i + count; // 8 bytes per value, count is known
for (var j = 0; j < count; ++j)
array[i++] = this.fixed64();
if (this.pos !== end) throw indexOutOfRange(this, 8);
return array;
};
/**
* Reads a packed repeated field of signed 64 bit fixed values.
* @param {Array.<Long|number>} [array] Array to read into; a new one is created if omitted
* @returns {Array.<Long|number>} Array read into
*/
Reader.prototype.sfixed64s = function read_sfixed64s(array) {
if (array === undefined) array = [];
var len = this.uint32(), end = this.pos + len, i = array.length;
/* istanbul ignore if */
if (end > this.len) throw indexOutOfRange(this, len);
var count = len >>> 3;
array.length = i + count; // 8 bytes per value, count is known
for (var j = 0; j < count; ++j)
array[i++] = this.sfixed64();
if (this.pos !== end) throw indexOutOfRange(this, 8);
return array;
};
/**
* Reads a sequence of bytes preceeded by its length as a varint.
* @returns {Uint8Array} Value read
*/
Reader.prototype.bytes = function read_bytes() {
var length = this.uint32(),
start = this.pos,
end = this.pos + length;
/* istanbul ignore if */
if (end > this.len)
throw indexOutOfRange(this, length);
this.pos = end;
return this.raw(start, end);
};
/**
* Reads a string preceeded by its byte length as a varint.
* @returns {string} Value read
*/
Reader.prototype.string = function read_string() {
var length = this.uint32(),
start = this.pos,
end = this.pos + length;
/* istanbul ignore if */
if (end > this.len)
throw indexOutOfRange(this, length);
this.pos = end;
return utf8.read(this.buf, start, end);
};
/**
* Reads a string preceeded by its byte length as a varint, rejecting invalid UTF8.
* @returns {string} Value read
*/
Reader.prototype.stringVerify = function read_string_verify() {
var length = this.uint32(),
start = this.pos,
end = this.pos + length;
/* istanbul ignore if */
if (end > this.len)
throw indexOutOfRange(this, length);
this.pos = end;
return utf8.readStrict(this.buf, start, end);
};
/**
* Skips the specified number of bytes if specified, otherwise skips a varint.
* @param {number} [length] Length if known, otherwise a varint is assumed
* @returns {Reader} `this`
*/
Reader.prototype.skip = function skip(length) {
if (typeof length === "number") {
/* istanbul ignore if */
if (this.pos + length > this.len)
throw indexOutOfRange(this, length);
this.pos += length;
} else {
do {
/* istanbul ignore if */
if (this.pos >= this.len)
throw indexOutOfRange(this);
} while (this.buf[this.pos++] & 128);
}
return this;
};
/**
* Recursion limit.
* @type {number}
*/
Reader.recursionLimit = util.recursionLimit;
/**
* Whether readers discard unknown fields while decoding.
* @type {boolean}
*/
Reader.discardUnknown = true;
/**
* Skips the next element of the specified wire type.
* @param {number} wireType Wire type received
* @param {number} [depth] Depth of recursion to control nested calls; 0 if omitted
* @param {number} [fieldNumber] Field number for validating group end tags
* @returns {Reader} `this`
*/
Reader.prototype.skipType = function(wireType, depth, fieldNumber) {
if (depth === undefined) depth = 0;
if (depth > Reader.recursionLimit)
throw Error("max depth exceeded");
if (fieldNumber === 0)
throw Error("illegal tag: field number 0");
switch (wireType) {
case 0:
this.skip();
break;
case 1:
this.skip(8);
break;
case 2:
this.skip(this.uint32());
break;
case 3:
while (true) {
var tag = this.tag();
var nestedField = tag >>> 3;
wireType = tag & 7;
if (!nestedField)
throw Error("illegal tag: field number 0");
if (wireType === 4) {
if (fieldNumber !== undefined && nestedField !== fieldNumber)
throw Error("invalid end group tag");
break;
}
this.skipType(wireType, depth + 1, nestedField);
}
break;
case 5:
this.skip(4);
break;
/* istanbul ignore next */
default:
throw Error("invalid wire type " + wireType + " at offset " + this.pos);
}
return this;
};
Reader._configure = function(BufferReader_) {
BufferReader = BufferReader_;
Reader.create = create();
BufferReader._configure();
var fn = util.Long ? "toLong" : /* istanbul ignore next */ "toNumber";
util.merge(Reader.prototype, {
int64: function read_int64() {
return readLongVarint.call(this)[fn](false);
},
uint64: function read_uint64() {
return readLongVarint.call(this)[fn](true);
},
sint64: function read_sint64() {
return readLongVarint.call(this).zzDecode()[fn](false);
},
fixed64: function read_fixed64() {
return readFixed64.call(this)[fn](true);
},
sfixed64: function read_sfixed64() {
return readFixed64.call(this)[fn](false);
}
});
};
+77
View File
@@ -0,0 +1,77 @@
"use strict";
module.exports = BufferReader;
// extends Reader
var Reader = require("./reader");
BufferReader.prototype = Object.create(Reader.prototype, {
constructor: {
value: BufferReader,
writable: true,
enumerable: false,
configurable: true
}
});
var util = require("./util/minimal");
/**
* Constructs a new buffer reader instance.
* @classdesc Wire format reader using node buffers.
* @extends Reader
* @constructor
* @param {Buffer} buffer Buffer to read from
*/
function BufferReader(buffer) {
Reader.call(this, buffer);
/**
* Read buffer.
* @name BufferReader#buf
* @type {Buffer}
*/
}
BufferReader._configure = function () {
/* istanbul ignore else */
if (util.Buffer)
BufferReader.prototype._slice = util.Buffer.prototype.slice;
};
/**
* Returns raw bytes from the backing buffer without advancing the reader.
* @name BufferReader#raw
* @function
* @param {number} start Start offset
* @param {number} end End offset
* @returns {Buffer} Raw bytes
*/
BufferReader.prototype.raw = function read_raw_buffer(start, end) {
return this._slice.call(this.buf, start, end);
};
/**
* @override
*/
BufferReader.prototype.string = function read_string_buffer() {
var len = this.uint32(), // modifies pos
start = this.pos,
end = this.pos + len;
/* istanbul ignore if */
if (end > this.len)
throw RangeError("index out of range: " + this.pos + " + " + len + " > " + this.len);
this.pos = end;
return this.buf.utf8Slice
? this.buf.utf8Slice(start, end)
: this.buf.toString("utf-8", start, end);
};
/**
* Reads a sequence of bytes preceeded by its length as a varint.
* @name BufferReader#bytes
* @function
* @returns {Buffer} Value read
*/
BufferReader._configure();
+424
View File
@@ -0,0 +1,424 @@
"use strict";
module.exports = Root;
// extends Namespace
var Namespace = require("./namespace");
Root.prototype = Object.create(Namespace.prototype, {
constructor: {
value: Root,
writable: true,
enumerable: false,
configurable: true
}
});
Root.className = "Root";
var Field = require("./field"),
Enum = require("./enum"),
OneOf = require("./oneof"),
util = require("./util");
var Type, // cyclic
parse, // might be excluded
common; // "
/**
* Constructs a new root namespace instance.
* @classdesc Root namespace wrapping all types, enums, services, sub-namespaces etc. that belong together.
* @extends NamespaceBase
* @constructor
* @param {Object.<string,*>} [options] Top level options
*/
function Root(options) {
Namespace.call(this, "", options);
/**
* Deferred extension fields.
* @type {Field[]}
*/
this.deferred = [];
/**
* Resolved file names of loaded files.
* @type {string[]}
*/
this.files = [];
/**
* Edition, defaults to proto2 if unspecified.
* @type {string}
* @private
*/
this._edition = "proto2";
/**
* Global lookup cache of fully qualified names.
* @type {Object.<string,ReflectionObject>}
* @private
*/
this._fullyQualifiedObjects = {};
}
/**
* Loads a namespace descriptor into a root namespace.
* @param {INamespace} json Namespace descriptor
* @param {Root} [root] Root namespace, defaults to create a new one if omitted
* @param {number} [depth] Current nesting depth, defaults to `0`
* @returns {Root} Root namespace
*/
Root.fromJSON = function fromJSON(json, root, depth) {
if (depth === undefined)
depth = 0;
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
if (!root)
root = new Root();
if (json.options)
root.setOptions(json.options);
return root.addJSON(json.nested, depth).resolveAll();
};
/**
* Resolves the path of an imported file, relative to the importing origin.
* This method exists so you can override it with your own logic in case your imports are scattered over multiple directories.
* @function
* @param {string} origin The file name of the importing file
* @param {string} target The file name being imported
* @returns {string|null} Resolved path to `target` or `null` to skip the file
*/
Root.prototype.resolvePath = util.path.resolve;
/**
* Fetch content from file path or url
* This method exists so you can override it with your own logic.
* @function
* @param {string} path File path or url
* @param {FetchCallback} callback Callback function
* @returns {undefined}
*/
Root.prototype.fetch = util.fetch;
// A symbol-like function to safely signal synchronous loading
/* istanbul ignore next */
function SYNC() {} // eslint-disable-line no-empty-function
/**
* Loads one or multiple .proto or preprocessed .json files into this root namespace and calls the callback.
* @param {string|string[]} filename Names of one or multiple files to load
* @param {IParseOptions} options Parse options
* @param {LoadCallback} callback Callback function
* @returns {undefined}
*/
Root.prototype.load = function load(filename, options, callback) {
if (typeof options === "function") {
callback = options;
options = undefined;
}
var self = this;
if (!callback) {
return util.asPromise(load, self, filename, options);
}
var sync = callback === SYNC; // undocumented
// Finishes loading by calling the callback (exactly once)
function finish(err, root) {
/* istanbul ignore if */
if (!callback) {
return;
}
if (sync) {
throw err;
}
if (root) {
root.resolveAll();
}
var cb = callback;
callback = null;
cb(err, root);
}
// Bundled definition existence checking
function getBundledFileName(filename) {
var idx = filename.lastIndexOf("google/protobuf/");
if (idx > -1) {
var altname = filename.substring(idx);
if (Object.prototype.hasOwnProperty.call(common, altname)) return altname;
}
if (Object.prototype.hasOwnProperty.call(common, filename)) return filename;
return null;
}
// Processes a single file
function process(filename, source, depth) {
if (depth === undefined)
depth = 0;
try {
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
if (util.isString(source) && source.charAt(0) === "{")
source = JSON.parse(source);
if (!util.isString(source))
self.setOptions(source.options).addJSON(source.nested);
else {
parse.filename = filename;
var parsed = parse(source, self, options),
resolved,
i = 0;
if (parsed.imports)
for (; i < parsed.imports.length; ++i)
if (resolved = getBundledFileName(parsed.imports[i]) || self.resolvePath(filename, parsed.imports[i]))
fetch(resolved, false, depth + 1);
if (parsed.weakImports)
for (i = 0; i < parsed.weakImports.length; ++i)
if (resolved = getBundledFileName(parsed.weakImports[i]) || self.resolvePath(filename, parsed.weakImports[i]))
fetch(resolved, true, depth + 1);
}
} catch (err) {
finish(err);
}
if (!sync && !queued) {
finish(null, self); // only once anyway
}
}
// Fetches a single file
function fetch(filename, weak, depth) {
if (depth === undefined)
depth = 0;
filename = getBundledFileName(filename) || filename;
// Skip if already loaded / attempted
if (self.files.indexOf(filename) > -1) {
return;
}
self.files.push(filename);
// Shortcut bundled definitions
if (Object.prototype.hasOwnProperty.call(common, filename)) {
if (sync) {
process(filename, common[filename], depth);
} else {
++queued;
setTimeout(function() {
--queued;
process(filename, common[filename], depth);
});
}
return;
}
// Otherwise fetch from disk or network
if (sync) {
var source;
try {
source = util.fs.readFileSync(filename).toString("utf8");
} catch (err) {
if (!weak)
finish(err);
return;
}
process(filename, source, depth);
} else {
++queued;
self.fetch(filename, function(err, source) {
--queued;
/* istanbul ignore if */
if (!callback) {
return; // terminated meanwhile
}
if (err) {
/* istanbul ignore else */
if (!weak)
finish(err);
else if (!queued) // can't be covered reliably
finish(null, self);
return;
}
process(filename, source, depth);
});
}
}
var queued = 0;
// Assembling the root namespace doesn't require working type
// references anymore, so we can load everything in parallel
if (util.isString(filename)) {
filename = [ filename ];
}
for (var i = 0, resolved; i < filename.length; ++i)
if (resolved = self.resolvePath("", filename[i]))
fetch(resolved);
if (sync) {
self.resolveAll();
return self;
}
if (!queued) {
finish(null, self);
}
return self;
};
// function load(filename:string, options:IParseOptions, callback:LoadCallback):undefined
/**
* Loads one or multiple .proto or preprocessed .json files into this root namespace and calls the callback.
* @function Root#load
* @param {string|string[]} filename Names of one or multiple files to load
* @param {LoadCallback} callback Callback function
* @returns {undefined}
* @variation 2
*/
// function load(filename:string, callback:LoadCallback):undefined
/**
* Loads one or multiple .proto or preprocessed .json files into this root namespace and returns a promise.
* @function Root#load
* @param {string|string[]} filename Names of one or multiple files to load
* @param {IParseOptions} [options] Parse options. Defaults to {@link parse.defaults} when omitted.
* @returns {Promise<Root>} Promise
* @variation 3
*/
// function load(filename:string, [options:IParseOptions]):Promise<Root>
/**
* Synchronously loads one or multiple .proto or preprocessed .json files into this root namespace (node only).
* @function Root#loadSync
* @param {string|string[]} filename Names of one or multiple files to load
* @param {IParseOptions} [options] Parse options. Defaults to {@link parse.defaults} when omitted.
* @returns {Root} Root namespace
* @throws {Error} If synchronous fetching is not supported (i.e. in browsers) or if a file's syntax is invalid
*/
Root.prototype.loadSync = function loadSync(filename, options) {
if (!util.isNode)
throw Error("not supported");
return this.load(filename, options, SYNC);
};
/**
* @override
*/
Root.prototype.resolveAll = function resolveAll() {
if (!this._needsRecursiveResolve) return this;
if (this.deferred.length)
throw Error("unresolvable extensions: " + this.deferred.map(function(field) {
return "'extend " + field.extend + "' in " + field.parent.fullName;
}).join(", "));
return Namespace.prototype.resolveAll.call(this);
};
// only uppercased (and thus conflict-free) children are exposed, see below
var exposeRe = /^[A-Z]/;
/**
* Handles a deferred declaring extension field by creating a sister field to represent it within its extended type.
* @param {Root} root Root instance
* @param {Field} field Declaring extension field witin the declaring type
* @returns {boolean} `true` if successfully added to the extended type, `false` otherwise
* @inner
* @ignore
*/
function tryHandleExtension(root, field) {
var extendedType = field.parent.lookup(field.extend);
if (extendedType) {
var sisterField = new Field(field.fullName, field.id, field.type, field.rule, undefined, field.options);
//do not allow to extend same field twice to prevent the error
if (extendedType.get(sisterField.name)) {
return true;
}
sisterField.declaringField = field;
field.extensionField = sisterField;
extendedType.add(sisterField);
return true;
}
return false;
}
/**
* Called when any object is added to this root or its sub-namespaces.
* @param {ReflectionObject} object Object added
* @returns {undefined}
* @private
*/
Root.prototype._handleAdd = function _handleAdd(object) {
if (object instanceof Field) {
if (/* an extension field (implies not part of a oneof) */ object.extend !== undefined && /* not already handled */ !object.extensionField)
if (!tryHandleExtension(this, object))
this.deferred.push(object);
} else if (object instanceof Enum) {
if (exposeRe.test(object.name))
object.parent[object.name] = object.values; // expose enum values as property of its parent
} else if (!(object instanceof OneOf)) /* everything else is a namespace */ {
if (object instanceof Type) // Try to handle any deferred extensions
for (var i = 0; i < this.deferred.length;)
if (tryHandleExtension(this, this.deferred[i]))
this.deferred.splice(i, 1);
else
++i;
for (var j = 0; j < /* initializes */ object.nestedArray.length; ++j) // recurse into the namespace
this._handleAdd(object._nestedArray[j]);
if (exposeRe.test(object.name))
object.parent[object.name] = object; // expose namespace as property of its parent
}
if (object instanceof Type || object instanceof Enum || object instanceof Field) {
// Only store types and enums for quick lookup during resolve.
this._fullyQualifiedObjects[object.fullName] = object;
}
// The above also adds uppercased (and thus conflict-free) nested types, services and enums as
// properties of namespaces just like static code does. This allows using a .d.ts generated for
// a static module with reflection-based solutions where the condition is met.
};
/**
* Called when any object is removed from this root or its sub-namespaces.
* @param {ReflectionObject} object Object removed
* @returns {undefined}
* @private
*/
Root.prototype._handleRemove = function _handleRemove(object) {
if (object instanceof Field) {
if (/* an extension field */ object.extend !== undefined) {
if (/* already handled */ object.extensionField) { // remove its sister field
object.extensionField.parent.remove(object.extensionField);
object.extensionField = null;
} else { // cancel the extension
var index = this.deferred.indexOf(object);
/* istanbul ignore else */
if (index > -1)
this.deferred.splice(index, 1);
}
}
} else if (object instanceof Enum) {
if (exposeRe.test(object.name))
delete object.parent[object.name]; // unexpose enum values
} else if (object instanceof Namespace) {
for (var i = 0; i < /* initializes */ object.nestedArray.length; ++i) // recurse into the namespace
this._handleRemove(object._nestedArray[i]);
if (exposeRe.test(object.name))
delete object.parent[object.name]; // unexpose namespaces
}
delete this._fullyQualifiedObjects[object.fullName];
};
// Sets up cyclic dependencies (called in index-light)
Root._configure = function(Type_, parse_, common_) {
Type = Type_;
parse = parse_;
common = common_;
};
+18
View File
@@ -0,0 +1,18 @@
"use strict";
module.exports = Object.create(null);
/**
* Named roots.
* This is where pbjs stores generated structures (the option `-r, --root` specifies a name).
* Can also be used manually to make roots available across modules.
* @name roots
* @type {Object.<string,Root>}
* @example
* // pbjs -r myroot -o compiled.js ...
*
* // in another module:
* require("./compiled.js");
*
* // in any subsequent module:
* var root = protobuf.roots["myroot"];
*/
+36
View File
@@ -0,0 +1,36 @@
"use strict";
/**
* Streaming RPC helpers.
* @namespace
*/
var rpc = exports;
/**
* RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets.
* @typedef RPCImpl
* @type {function}
* @param {Method|rpc.ServiceMethod<Message<{}>,Message<{}>>} method Reflected or static method being called
* @param {Uint8Array} requestData Request data
* @param {RPCImplCallback} callback Callback function
* @returns {undefined}
* @example
* function rpcImpl(method, requestData, callback) {
* if (protobuf.util.lcFirst(method.name) !== "myMethod") // compatible with static code
* throw Error("no such method");
* asynchronouslyObtainAResponse(requestData, function(err, responseData) {
* callback(err, responseData);
* });
* }
*/
/**
* Node-style callback as used by {@link RPCImpl}.
* @typedef RPCImplCallback
* @type {function}
* @param {Error|null} error Error, if any, otherwise `null`
* @param {Uint8Array|null} [response] Response data or `null` to signal end of stream, if there hasn't been an error
* @returns {undefined}
*/
rpc.Service = require("./rpc/service");
+155
View File
@@ -0,0 +1,155 @@
"use strict";
module.exports = Service;
var util = require("../util/minimal");
// Extends EventEmitter
Service.prototype = Object.create(util.EventEmitter.prototype, {
constructor: {
value: Service,
writable: true,
enumerable: false,
configurable: true
}
});
/**
* A service method callback as used by {@link rpc.ServiceMethod|ServiceMethod}.
*
* Differs from {@link RPCImplCallback} in that it is an actual callback of a service method which may not return `response = null`.
* @typedef rpc.ServiceMethodCallback
* @template TRes extends Message<TRes>
* @type {function}
* @param {Error|null} error Error, if any
* @param {TRes} [response] Response message
* @returns {undefined}
*/
/**
* A service method part of a {@link rpc.Service} as created by {@link Service.create}.
* @typedef rpc.ServiceMethod
* @template TReq extends Message<TReq>
* @template TRes extends Message<TRes>
* @type {{
* (request: TReq|Properties<TReq>, callback: rpc.ServiceMethodCallback<TRes>): void;
* (request: TReq|Properties<TReq>): Promise<TRes>;
* readonly name: string;
* readonly path: string;
* readonly requestType: string;
* readonly responseType: string;
* readonly requestStream: true|undefined;
* readonly responseStream: true|undefined;
* }}
*/
/**
* Constructs a new RPC service instance.
* @classdesc An RPC service as returned by {@link Service#create}.
* @exports rpc.Service
* @extends util.EventEmitter
* @constructor
* @param {RPCImpl} rpcImpl RPC implementation
* @param {boolean} [requestDelimited=false] Whether requests are length-delimited
* @param {boolean} [responseDelimited=false] Whether responses are length-delimited
*/
function Service(rpcImpl, requestDelimited, responseDelimited) {
if (typeof rpcImpl !== "function")
throw TypeError("rpcImpl must be a function");
util.EventEmitter.call(this);
/**
* RPC implementation. Becomes `null` once the service is ended.
* @type {RPCImpl|null}
*/
this.rpcImpl = rpcImpl;
/**
* Whether requests are length-delimited.
* @type {boolean}
*/
this.requestDelimited = Boolean(requestDelimited);
/**
* Whether responses are length-delimited.
* @type {boolean}
*/
this.responseDelimited = Boolean(responseDelimited);
}
/**
* Calls a service method through {@link rpc.Service#rpcImpl|rpcImpl}.
* @param {Method|rpc.ServiceMethod<TReq,TRes>} method Reflected or static method
* @param {Constructor<TReq>} requestCtor Request constructor
* @param {Constructor<TRes>} responseCtor Response constructor
* @param {TReq|Properties<TReq>} request Request message or plain object
* @param {rpc.ServiceMethodCallback<TRes>} callback Service callback
* @returns {undefined}
* @template TReq extends Message<TReq>
* @template TRes extends Message<TRes>
*/
Service.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request, callback) {
if (!request)
throw TypeError("request must be specified");
var self = this;
if (!callback)
return util.asPromise(rpcCall, self, method, requestCtor, responseCtor, request);
if (!self.rpcImpl) {
setTimeout(function() { callback(Error("already ended")); }, 0);
return undefined;
}
try {
return self.rpcImpl(
method,
requestCtor[self.requestDelimited ? "encodeDelimited" : "encode"](request).finish(),
function rpcCallback(err, response) {
if (err) {
self.emit("error", err, method);
return callback(err);
}
if (response === null) {
self.end(/* endedByRPC */ true);
return undefined;
}
if (!(response instanceof responseCtor)) {
try {
response = responseCtor[self.responseDelimited ? "decodeDelimited" : "decode"](response);
} catch (err) {
self.emit("error", err, method);
return callback(err);
}
}
self.emit("data", response, method);
return callback(null, response);
}
);
} catch (err) {
self.emit("error", err, method);
setTimeout(function() { callback(err); }, 0);
return undefined;
}
};
/**
* Ends this service and emits the `end` event.
* @param {boolean} [endedByRPC=false] Whether the service has been ended by the RPC implementation.
* @returns {rpc.Service} `this`
*/
Service.prototype.end = function end(endedByRPC) {
if (this.rpcImpl) {
if (!endedByRPC) // signal end to rpcImpl
this.rpcImpl(null, null, null);
this.rpcImpl = null;
this.emit("end").off();
}
return this;
};
+206
View File
@@ -0,0 +1,206 @@
"use strict";
module.exports = Service;
// extends Namespace
var Namespace = require("./namespace");
Service.prototype = Object.create(Namespace.prototype, {
constructor: {
value: Service,
writable: true,
enumerable: false,
configurable: true
}
});
Service.className = "Service";
var Method = require("./method"),
util = require("./util"),
rpc = require("./rpc");
/**
* Constructs a new service instance.
* @classdesc Reflected service.
* @extends NamespaceBase
* @constructor
* @param {string} name Service name
* @param {Object.<string,*>} [options] Service options
* @throws {TypeError} If arguments are invalid
*/
function Service(name, options) {
Namespace.call(this, name, options);
/**
* Service methods.
* @type {Object.<string,Method>}
*/
this.methods = {}; // toJSON, marker
/**
* Cached methods as an array.
* @type {Method[]|null}
* @private
*/
this._methodsArray = null;
}
/**
* Service descriptor.
* @interface IService
* @extends INamespace
* @property {string} [edition] Edition
* @property {Object.<string,IMethod>} methods Method descriptors
* @property {string|null} [comment] Service comment
*/
/**
* Constructs a service from a service descriptor.
* @param {string} name Service name
* @param {IService} json Service descriptor
* @param {number} [depth] Current nesting depth, defaults to `0`
* @returns {Service} Created service
* @throws {TypeError} If arguments are invalid
*/
Service.fromJSON = function fromJSON(name, json, depth) {
if (depth === undefined)
depth = 0;
if (depth > util.recursionLimit)
throw Error("max depth exceeded");
var service = new Service(name, json.options);
/* istanbul ignore else */
if (json.methods)
for (var names = Object.keys(json.methods), i = 0; i < names.length; ++i)
service.add(Method.fromJSON(names[i], json.methods[names[i]]));
if (json.nested)
service.addJSON(json.nested, depth);
if (json.edition)
service._edition = json.edition;
service.comment = json.comment;
service._defaultEdition = "proto3"; // For backwards-compatibility.
return service;
};
/**
* Converts this service to a service descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IService} Service descriptor
*/
Service.prototype.toJSON = function toJSON(toJSONOptions) {
var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"edition" , this._editionToJSON(),
"options" , inherited && inherited.options || undefined,
"methods" , Namespace.arrayToJSON(this.methodsArray, toJSONOptions) || /* istanbul ignore next */ {},
"nested" , inherited && inherited.nested || undefined,
"comment" , keepComments ? this.comment : undefined
]);
};
/**
* Methods of this service as an array for iteration.
* @name Service#methodsArray
* @type {Method[]}
* @readonly
*/
Object.defineProperty(Service.prototype, "methodsArray", {
get: function() {
return this._methodsArray || (this._methodsArray = util.toArray(this.methods));
}
});
function clearCache(service) {
service._methodsArray = null;
return service;
}
/**
* @override
*/
Service.prototype.get = function get(name) {
return Object.prototype.hasOwnProperty.call(this.methods, name)
? this.methods[name]
: Namespace.prototype.get.call(this, name);
};
/**
* @override
*/
Service.prototype.resolveAll = function resolveAll() {
if (!this._needsRecursiveResolve) return this;
Namespace.prototype.resolve.call(this);
var methods = this.methodsArray;
for (var i = 0; i < methods.length; ++i)
methods[i].resolve();
return this;
};
/**
* @override
*/
Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
if (!this._needsRecursiveFeatureResolution) return this;
edition = this._edition || edition;
Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
this.methodsArray.forEach(method => {
method._resolveFeaturesRecursive(edition);
});
return this;
};
/**
* @override
*/
Service.prototype.add = function add(object) {
/* istanbul ignore if */
if (this.get(object.name))
throw Error("duplicate name '" + object.name + "' in " + this);
if (object instanceof Method) {
if (object.name === "__proto__")
return this;
this.methods[object.name] = object;
object.parent = this;
return clearCache(this);
}
return Namespace.prototype.add.call(this, object);
};
/**
* @override
*/
Service.prototype.remove = function remove(object) {
if (object instanceof Method) {
/* istanbul ignore if */
if (this.methods[object.name] !== object)
throw Error(object + " is not a member of " + this);
delete this.methods[object.name];
object.parent = null;
return clearCache(this);
}
return Namespace.prototype.remove.call(this, object);
};
/**
* Creates a runtime service using the specified rpc implementation.
* @param {RPCImpl} rpcImpl RPC implementation
* @param {boolean} [requestDelimited=false] Whether requests are length-delimited
* @param {boolean} [responseDelimited=false] Whether responses are length-delimited
* @returns {rpc.Service} RPC service. Useful where requests and/or responses are streamed.
*/
Service.prototype.create = function create(rpcImpl, requestDelimited, responseDelimited) {
var rpcService = new rpc.Service(rpcImpl, requestDelimited, responseDelimited);
for (var i = 0, method; i < /* initializes */ this.methodsArray.length; ++i) {
var methodName = util.lcFirst((method = this._methodsArray[i]).resolve().name).replace(/[^$\w_]/g, "");
rpcService[methodName] = (function(method, requestType, responseType) {
return function rpcMethod(request, callback) {
return rpc.Service.prototype.rpcCall.call(this, method, requestType, responseType, request, callback);
};
})(method, method.resolvedRequestType.ctor, method.resolvedResponseType.ctor);
}
return rpcService;
};
+421
View File
@@ -0,0 +1,421 @@
"use strict";
module.exports = tokenize;
var delimRe = /[\s{}=;:[\],'"()<>]/g,
stringDoubleRe = /(?:"([^"\\]*(?:\\.[^"\\]*)*)")/g,
stringSingleRe = /(?:'([^'\\]*(?:\\.[^'\\]*)*)')/g;
var setCommentRe = /^ *[*/]+ */,
setCommentAltRe = /^\s*\*?\/*/,
setCommentSplitRe = /\n/g,
whitespaceRe = /\s/,
unescapeRe = /\\(.?)/g;
var unescapeMap = {
"0": "\0",
"r": "\r",
"n": "\n",
"t": "\t"
};
/**
* Unescapes a string.
* @param {string} str String to unescape
* @returns {string} Unescaped string
* @property {Object.<string,string>} map Special characters map
* @memberof tokenize
*/
function unescape(str) {
return str.replace(unescapeRe, function($0, $1) {
switch ($1) {
case "\\":
case "":
return $1;
default:
return unescapeMap[$1] || "";
}
});
}
tokenize.unescape = unescape;
/**
* Gets the next token and advances.
* @typedef TokenizerHandleNext
* @type {function}
* @returns {string|null} Next token or `null` on eof
*/
/**
* Peeks for the next token.
* @typedef TokenizerHandlePeek
* @type {function}
* @returns {string|null} Next token or `null` on eof
*/
/**
* Pushes a token back to the stack.
* @typedef TokenizerHandlePush
* @type {function}
* @param {string} token Token
* @returns {undefined}
*/
/**
* Skips the next token.
* @typedef TokenizerHandleSkip
* @type {function}
* @param {string} expected Expected token
* @param {boolean} [optional=false] If optional
* @returns {boolean} Whether the token matched
* @throws {Error} If the token didn't match and is not optional
*/
/**
* Gets the comment on the previous line or, alternatively, the line comment on the specified line.
* @typedef TokenizerHandleCmnt
* @type {function}
* @param {number} [line] Line number
* @returns {string|null} Comment text or `null` if none
*/
/**
* Handle object returned from {@link tokenize}.
* @interface ITokenizerHandle
* @property {TokenizerHandleNext} next Gets the next token and advances (`null` on eof)
* @property {TokenizerHandlePeek} peek Peeks for the next token (`null` on eof)
* @property {TokenizerHandlePush} push Pushes a token back to the stack
* @property {TokenizerHandleSkip} skip Skips a token, returns its presence and advances or, if non-optional and not present, throws
* @property {TokenizerHandleCmnt} cmnt Gets the comment on the previous line or the line comment on the specified line, if any
* @property {number} line Current line number
*/
/**
* Tokenizes the given .proto source and returns an object with useful utility functions.
* @param {string} source Source contents
* @param {boolean} alternateCommentMode Whether we should activate alternate comment parsing mode.
* @returns {ITokenizerHandle} Tokenizer handle
*/
function tokenize(source, alternateCommentMode) {
/* eslint-disable callback-return */
source = source.toString();
var offset = 0,
length = source.length,
line = 1,
lastCommentLine = 0,
comments = {};
var stack = [];
var stringDelim = null;
/* istanbul ignore next */
/**
* Creates an error for illegal syntax.
* @param {string} subject Subject
* @returns {Error} Error created
* @inner
*/
function illegal(subject) {
return Error("illegal " + subject + " (line " + line + ")");
}
/**
* Reads a string till its end.
* @returns {string} String read
* @inner
*/
function readString() {
var re = stringDelim === "'" ? stringSingleRe : stringDoubleRe;
re.lastIndex = offset - 1;
var match = re.exec(source);
if (!match)
throw illegal("string");
offset = re.lastIndex;
push(stringDelim);
stringDelim = null;
return unescape(match[1]);
}
/**
* Gets the character at `pos` within the source.
* @param {number} pos Position
* @returns {string} Character
* @inner
*/
function charAt(pos) {
return source.charAt(pos);
}
/**
* Sets the current comment text.
* @param {number} start Start offset
* @param {number} end End offset
* @param {boolean} isLeading set if a leading comment
* @returns {undefined}
* @inner
*/
function setComment(start, end, isLeading) {
var comment = {
type: source.charAt(start++),
lineEmpty: false,
leading: isLeading,
};
var lookback;
if (alternateCommentMode) {
lookback = 2; // alternate comment parsing: "//" or "/*"
} else {
lookback = 3; // "///" or "/**"
}
var commentOffset = start - lookback,
c;
do {
if (--commentOffset < 0 ||
(c = source.charAt(commentOffset)) === "\n") {
comment.lineEmpty = true;
break;
}
} while (c === " " || c === "\t");
var lines = source
.substring(start, end)
.split(setCommentSplitRe);
for (var i = 0; i < lines.length; ++i)
lines[i] = lines[i]
.replace(alternateCommentMode ? setCommentAltRe : setCommentRe, "")
.trim();
comment.text = lines
.join("\n")
.trim();
comments[line] = comment;
lastCommentLine = line;
}
function isDoubleSlashCommentLine(startOffset) {
var endOffset = findEndOfLine(startOffset);
// see if remaining line matches comment pattern
var lineText = source.substring(startOffset, endOffset);
var isComment = /^\s*\/\//.test(lineText);
return isComment;
}
function findEndOfLine(cursor) {
// find end of cursor's line
var endOffset = cursor;
while (endOffset < length && charAt(endOffset) !== "\n") {
endOffset++;
}
return endOffset;
}
/**
* Obtains the next token.
* @returns {string|null} Next token or `null` on eof
* @inner
*/
function next() {
if (stack.length > 0)
return stack.shift();
if (stringDelim)
return readString();
var repeat,
prev,
curr,
start,
isDoc,
nextLineIsComment,
isLeadingComment = offset === 0;
do {
if (offset === length)
return null;
repeat = false;
while (whitespaceRe.test(curr = charAt(offset))) {
if (curr === "\n") {
isLeadingComment = true;
++line;
}
if (++offset === length)
return null;
}
if (charAt(offset) === "/") {
if (++offset === length) {
throw illegal("comment");
}
if (charAt(offset) === "/") { // Line
if (!alternateCommentMode) {
// check for triple-slash comment
isDoc = charAt(start = offset + 1) === "/";
while (charAt(++offset) !== "\n") {
if (offset === length) {
return null;
}
}
++offset;
if (isDoc) {
setComment(start, offset - 1, isLeadingComment);
// Trailing comment cannot not be multi-line,
// so leading comment state should be reset to handle potential next comments
isLeadingComment = true;
}
++line;
repeat = true;
} else {
// check for double-slash comments, consolidating consecutive lines
start = offset;
isDoc = false;
if (isDoubleSlashCommentLine(offset - 1)) {
isDoc = true;
do {
offset = findEndOfLine(offset);
if (offset === length) {
break;
}
offset++;
if (!isLeadingComment) {
// Trailing comment cannot not be multi-line
break;
}
nextLineIsComment = isDoubleSlashCommentLine(offset);
if (nextLineIsComment) {
line++;
}
} while (nextLineIsComment);
} else {
offset = Math.min(length, findEndOfLine(offset) + 1);
}
if (isDoc) {
setComment(start, offset, isLeadingComment);
isLeadingComment = true;
}
line++;
repeat = true;
}
} else if ((curr = charAt(offset)) === "*") { /* Block */
// check for /** (regular comment mode) or /* (alternate comment mode)
start = offset + 1;
isDoc = alternateCommentMode || charAt(start) === "*";
do {
if (curr === "\n") {
++line;
}
if (++offset === length) {
throw illegal("comment");
}
prev = curr;
curr = charAt(offset);
} while (prev !== "*" || curr !== "/");
++offset;
if (isDoc) {
setComment(start, offset - 2, isLeadingComment);
isLeadingComment = true;
}
repeat = true;
} else {
return "/";
}
}
} while (repeat);
// offset !== length if we got here
var end = offset;
delimRe.lastIndex = 0;
var delim = delimRe.test(charAt(end++));
if (!delim)
while (end < length && !delimRe.test(charAt(end)))
++end;
var token = source.substring(offset, offset = end);
if (token === "\"" || token === "'")
stringDelim = token;
return token;
}
/**
* Pushes a token back to the stack.
* @param {string} token Token
* @returns {undefined}
* @inner
*/
function push(token) {
stack.push(token);
}
/**
* Peeks for the next token.
* @returns {string|null} Token or `null` on eof
* @inner
*/
function peek() {
if (!stack.length) {
var token = next();
if (token === null)
return null;
push(token);
}
return stack[0];
}
/**
* Skips a token.
* @param {string} expected Expected token
* @param {boolean} [optional=false] Whether the token is optional
* @returns {boolean} `true` when skipped, `false` if not
* @throws {Error} When a required token is not present
* @inner
*/
function skip(expected, optional) {
var actual = peek(),
equals = actual === expected;
if (equals) {
next();
return true;
}
if (!optional)
throw illegal("token '" + actual + "', '" + expected + "' expected");
return false;
}
/**
* Gets a comment.
* @param {number} [trailingLine] Line number if looking for a trailing comment
* @returns {string|null} Comment text
* @inner
*/
function cmnt(trailingLine) {
var ret = null;
var comment;
if (trailingLine === undefined) {
comment = comments[line - 1];
delete comments[line - 1];
if (comment && (alternateCommentMode || comment.type === "*" || comment.lineEmpty)) {
ret = comment.leading ? comment.text : null;
}
} else {
/* istanbul ignore else */
if (lastCommentLine < trailingLine) {
peek();
}
comment = comments[trailingLine];
delete comments[trailingLine];
if (comment && !comment.lineEmpty && (alternateCommentMode || comment.type === "/")) {
ret = comment.leading ? null : comment.text;
}
}
return ret;
}
return Object.defineProperty({
next: next,
peek: peek,
push: push,
skip: skip,
cmnt: cmnt
}, "line", {
get: function() { return line; }
});
/* eslint-enable callback-return */
}
+676
View File
@@ -0,0 +1,676 @@
"use strict";
module.exports = Type;
// extends Namespace
var Namespace = require("./namespace");
Type.prototype = Object.create(Namespace.prototype, {
constructor: {
value: Type,
writable: true,
enumerable: false,
configurable: true
}
});
Type.className = "Type";
var Enum = require("./enum"),
OneOf = require("./oneof"),
Field = require("./field"),
MapField = require("./mapfield"),
Service = require("./service"),
Message = require("./message"),
Reader = require("./reader"),
Writer = require("./writer"),
util = require("./util"),
encoder = require("./encoder"),
decoder = require("./decoder"),
verifier = require("./verifier"),
converter = require("./converter"),
wrappers = require("./wrappers");
/**
* Constructs a new reflected message type instance.
* @classdesc Reflected message type.
* @extends NamespaceBase
* @constructor
* @param {string} name Message name
* @param {Object.<string,*>} [options] Declared options
*/
function Type(name, options) {
name = name.replace(/\W/g, "");
Namespace.call(this, name, options);
/**
* Message fields.
* @type {Object.<string,Field>}
*/
this.fields = {}; // toJSON, marker
/**
* Oneofs declared within this namespace, if any.
* @type {Object.<string,OneOf>}
*/
this.oneofs = undefined; // toJSON
/**
* Extension ranges, if any.
* @type {number[][]}
*/
this.extensions = undefined; // toJSON
/**
* Reserved ranges, if any.
* @type {Array.<number[]|string>}
*/
this.reserved = undefined; // toJSON
/*?
* Whether this type is a legacy group.
* @type {boolean|undefined}
*/
this.group = undefined; // toJSON
/**
* Cached fields by id.
* @type {Object.<number,Field>|null}
* @private
*/
this._fieldsById = null;
/**
* Cached fields as an array.
* @type {Field[]|null}
* @private
*/
this._fieldsArray = null;
/**
* Cached oneofs as an array.
* @type {OneOf[]|null}
* @private
*/
this._oneofsArray = null;
/**
* Cached constructor.
* @type {Constructor<{}>}
* @private
*/
this._ctor = null;
/**
* Cached fields by JSON name.
* @type {Object.<string,Field>|null}
* @private
*/
this._fieldsByJsonName = null; // used by ext/protojson
}
Object.defineProperties(Type.prototype, {
/**
* Message fields by id.
* @name Type#fieldsById
* @type {Object.<number,Field>}
* @readonly
*/
fieldsById: {
get: function() {
/* istanbul ignore if */
if (this._fieldsById)
return this._fieldsById;
this._fieldsById = {};
for (var names = Object.keys(this.fields), i = 0; i < names.length; ++i) {
var field = this.fields[names[i]],
id = field.id;
/* istanbul ignore if */
if (this._fieldsById[id])
throw Error("duplicate id " + id + " in " + this);
this._fieldsById[id] = field;
}
return this._fieldsById;
}
},
/**
* Fields of this message as an array for iteration.
* @name Type#fieldsArray
* @type {Field[]}
* @readonly
*/
fieldsArray: {
get: function() {
return this._fieldsArray || (this._fieldsArray = util.toArray(this.fields));
}
},
/**
* Oneofs of this message as an array for iteration.
* @name Type#oneofsArray
* @type {OneOf[]}
* @readonly
*/
oneofsArray: {
get: function() {
return this._oneofsArray || (this._oneofsArray = util.toArray(this.oneofs));
}
},
/**
* The registered constructor, if any registered, otherwise a generic constructor.
* Assigning a function replaces the internal constructor. If the function does not extend {@link Message} yet, its prototype will be setup accordingly and static methods will be populated. If it already extends {@link Message}, it will just replace the internal constructor.
* When assigning manually, add the type to its parent namespace/root first if fields reference other reflected types, because constructor setup resolves field defaults.
* @name Type#ctor
* @type {Constructor<{}>}
*/
ctor: {
get: function() {
return this._ctor || (this.ctor = Type.generateConstructor(this)());
},
set: function(ctor) {
// Ensure proper prototype
var prototype = ctor.prototype;
if (!(prototype instanceof Message)) {
ctor.prototype = new Message();
Object.defineProperty(ctor.prototype, "constructor", {
value: ctor,
writable: true,
enumerable: false,
configurable: true
});
util.merge(ctor.prototype, prototype);
}
// Classes and messages reference their reflected type
ctor.$type = ctor.prototype.$type = this;
// Mix in static methods
util.merge(ctor, Message, true);
this._ctor = ctor;
delete this.decode;
delete this.fromObject;
// Messages have non-enumerable default values on their prototype
var i = 0;
for (var field; i < /* initializes */ this.fieldsArray.length; ++i) {
field = this._fieldsArray[i].resolve(); // ensures a proper value
ctor.prototype[field.name] = field.defaultValue;
}
// Messages have non-enumerable getters and setters for each virtual oneof field
var ctorProperties = {};
for (i = 0; i < /* initializes */ this.oneofsArray.length; ++i)
ctorProperties[this._oneofsArray[i].resolve().name] = {
get: util.oneOfGetter(this._oneofsArray[i].oneof),
set: util.oneOfSetter(this._oneofsArray[i].oneof)
};
if (i)
Object.defineProperties(ctor.prototype, ctorProperties);
}
}
});
/**
* Generates a constructor function for the specified type.
* @param {Type} mtype Message type
* @returns {Codegen} Codegen instance
*/
Type.generateConstructor = function generateConstructor(mtype) {
/* eslint-disable no-unexpected-multiline */
var gen = util.codegen(["p"]);
// explicitly initialize mutable object/array fields so that these aren't just inherited from the prototype
for (var i = 0, field; i < mtype.fieldsArray.length; ++i)
if ((field = mtype._fieldsArray[i]).map) gen
("this%s={}", util.safeProp(field.name));
else if (field.repeated) gen
("this%s=[]", util.safeProp(field.name));
return gen
("if(p)for(var ks=Object.keys(p),i=0;i<ks.length;++i)if(p[ks[i]]!=null&&ks[i]!==\"__proto__\")") // omit undefined or null
("this[ks[i]]=p[ks[i]]");
/* eslint-enable no-unexpected-multiline */
};
function clearCache(type) {
type._fieldsById = type._fieldsArray = type._oneofsArray = type._fieldsByJsonName = null;
delete type.encode;
delete type.decode;
delete type.verify;
return type;
}
/**
* Message type descriptor.
* @interface IType
* @extends INamespace
* @property {string} [edition] Edition
* @property {Object.<string,IOneOf>} [oneofs] Oneof descriptors
* @property {Object.<string,IField>} fields Field descriptors
* @property {number[][]} [extensions] Extension ranges
* @property {Array.<number[]|string>} [reserved] Reserved ranges
* @property {boolean} [group=false] Whether a legacy group or not
* @property {string|null} [comment] Message type comment
*/
/**
* Creates a message type from a message type descriptor.
* @param {string} name Message name
* @param {IType} json Message type descriptor
* @param {number} [depth] Current nesting depth, defaults to `0`
* @returns {Type} Created message type
*/
Type.fromJSON = function fromJSON(name, json, depth) {
if (depth === undefined)
depth = 0;
if (depth > util.nestingLimit)
throw Error("max depth exceeded");
var type = new Type(name, json.options);
type.extensions = json.extensions;
type.reserved = json.reserved;
var names = Object.keys(json.fields),
i = 0;
for (; i < names.length; ++i)
type.add(
( typeof json.fields[names[i]].keyType !== "undefined"
? MapField.fromJSON
: Field.fromJSON )(names[i], json.fields[names[i]])
);
if (json.oneofs)
for (names = Object.keys(json.oneofs), i = 0; i < names.length; ++i)
type.add(OneOf.fromJSON(names[i], json.oneofs[names[i]]));
if (json.nested)
for (names = Object.keys(json.nested), i = 0; i < names.length; ++i) {
var nested = json.nested[names[i]];
type.add( // most to least likely
( nested.id !== undefined
? Field.fromJSON
: nested.fields !== undefined
? Type.fromJSON
: nested.values !== undefined
? Enum.fromJSON
: nested.methods !== undefined
? Service.fromJSON
: Namespace.fromJSON )(names[i], nested, depth + 1)
);
}
if (json.extensions && json.extensions.length)
type.extensions = json.extensions;
if (json.reserved && json.reserved.length)
type.reserved = json.reserved;
if (json.group)
type.group = true;
if (json.comment)
type.comment = json.comment;
if (json.edition)
type._edition = json.edition;
type._defaultEdition = "proto3"; // For backwards-compatibility.
return type;
};
/**
* Converts this message type to a message type descriptor.
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
* @returns {IType} Message type descriptor
*/
Type.prototype.toJSON = function toJSON(toJSONOptions) {
var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"edition" , this._editionToJSON(),
"options" , inherited && inherited.options || undefined,
"oneofs" , Namespace.arrayToJSON(this.oneofsArray, toJSONOptions),
"fields" , Namespace.arrayToJSON(this.fieldsArray.filter(function(obj) { return !obj.declaringField; }), toJSONOptions) || {},
"extensions" , this.extensions && this.extensions.length ? this.extensions : undefined,
"reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
"group" , this.group || undefined,
"nested" , inherited && inherited.nested || undefined,
"comment" , keepComments ? this.comment : undefined
]);
};
/**
* @override
*/
Type.prototype.resolveAll = function resolveAll() {
if (!this._needsRecursiveResolve) return this;
Namespace.prototype.resolveAll.call(this);
var oneofs = this.oneofsArray; i = 0;
while (i < oneofs.length)
oneofs[i++].resolve();
var fields = this.fieldsArray, i = 0;
while (i < fields.length)
fields[i++].resolve();
return this;
};
/**
* @override
*/
Type.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
if (!this._needsRecursiveFeatureResolution) return this;
edition = this._edition || edition;
Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
this.oneofsArray.forEach(oneof => {
oneof._resolveFeatures(edition);
});
this.fieldsArray.forEach(field => {
field._resolveFeatures(edition);
});
return this;
};
/**
* @override
*/
Type.prototype.get = function get(name) {
if (Object.prototype.hasOwnProperty.call(this.fields, name))
return this.fields[name];
if (this.oneofs && Object.prototype.hasOwnProperty.call(this.oneofs, name))
return this.oneofs[name];
if (this.nested && Object.prototype.hasOwnProperty.call(this.nested, name))
return this.nested[name];
return null;
};
/**
* Adds a nested object to this type.
* @param {ReflectionObject} object Nested object to add
* @returns {Type} `this`
* @throws {TypeError} If arguments are invalid
* @throws {Error} If there is already a nested object with this name or, if a field, when there is already a field with this id
*/
Type.prototype.add = function add(object) {
if (this.get(object.name))
throw Error("duplicate name '" + object.name + "' in " + this);
if (object instanceof Field && object.extend === undefined) {
// NOTE: Extension fields aren't actual fields on the declaring type, but nested objects.
// The root object takes care of adding distinct sister-fields to the respective extended
// type instead.
// avoids calling the getter if not absolutely necessary because it's called quite frequently
if (this._fieldsById ? /* istanbul ignore next */ this._fieldsById[object.id] : this.fieldsById[object.id])
throw Error("duplicate id " + object.id + " in " + this);
if (this.isReservedId(object.id))
throw Error("id " + object.id + " is reserved in " + this);
if (this.isReservedName(object.name) || object.name.charAt(0) === "$")
throw Error("name '" + object.name + "' is reserved in " + this);
if (object.name === "__proto__")
return this;
if (object.parent)
object.parent.remove(object);
this.fields[object.name] = object;
object.message = this;
object.onAdd(this);
return clearCache(this);
}
if (object instanceof OneOf) {
if (object.name.charAt(0) === "$")
throw Error("name '" + object.name + "' is reserved in " + this);
if (object.name === "__proto__")
return this;
if (!this.oneofs)
this.oneofs = {};
this.oneofs[object.name] = object;
object.onAdd(this);
return clearCache(this);
}
return Namespace.prototype.add.call(this, object);
};
/**
* Removes a nested object from this type.
* @param {ReflectionObject} object Nested object to remove
* @returns {Type} `this`
* @throws {TypeError} If arguments are invalid
* @throws {Error} If `object` is not a member of this type
*/
Type.prototype.remove = function remove(object) {
if (object instanceof Field && object.extend === undefined) {
// See Type#add for the reason why extension fields are excluded here.
/* istanbul ignore if */
if (!util.remove(this.fields, object, object.name))
throw Error(object + " is not a member of " + this);
object.parent = null;
object.onRemove(this);
return clearCache(this);
}
if (object instanceof OneOf) {
/* istanbul ignore if */
if (!util.remove(this.oneofs, object, object.name))
throw Error(object + " is not a member of " + this);
object.parent = null;
object.onRemove(this);
return clearCache(this);
}
return Namespace.prototype.remove.call(this, object);
};
/**
* Tests if the specified id is reserved.
* @param {number} id Id to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
Type.prototype.isReservedId = function isReservedId(id) {
return Namespace.isReservedId(this.reserved, id);
};
/**
* Tests if the specified name is reserved.
* @param {string} name Name to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
Type.prototype.isReservedName = function isReservedName(name) {
return Namespace.isReservedName(this.reserved, name);
};
/**
* Creates a new message of this type using the specified properties.
* @param {Object.<string,*>} [properties] Properties to set
* @returns {ReflectedMessage} Message instance
*/
Type.prototype.create = function create(properties) {
return new this.ctor(properties);
};
/**
* Sets up {@link Type#encode|encode}, {@link Type#decode|decode} and {@link Type#verify|verify}.
* @returns {Type} `this`
*/
Type.prototype.setup = function setup() {
// Sets up everything at once so that the prototype chain does not have to be re-evaluated
// multiple times (V8, soft-deopt prototype-check).
// Resolve feature defaults incl. field presence before generating codecs
var root = this.root;
if (root && root._needsRecursiveFeatureResolution) {
var edition = root._edition || this._edition;
if (edition)
root._resolveFeaturesRecursive(edition);
}
var fullName = this.fullName,
types = [];
for (var i = 0; i < /* initializes */ this.fieldsArray.length; ++i)
types.push(this._fieldsArray[i].resolve().resolvedType);
// Replace setup methods with type-specific generated functions
this.encode = encoder(this)({
Writer : Writer,
types : types,
util : util
});
this.decode = decoder(this)({
Reader : Reader,
types : types,
util : util,
C : this.ctor
});
this.verify = verifier(this)({
types : types,
util : util
});
this.fromObject = converter.fromObject(this)({
types : types,
util : util,
C : this.ctor
});
this.toObject = converter.toObject(this)({
types : types,
util : util
});
// Inject custom wrappers for common types
var wrapper = wrappers[fullName];
if (wrapper) {
var wrapperThis = Object.create(this);
// Reuse this type's runtime constructor in wrapper fromObject/toObject
wrapperThis._ctor = this.ctor;
wrapperThis.fromObject = this.fromObject;
this.fromObject = wrapper.fromObject.bind(wrapperThis);
wrapperThis.toObject = this.toObject;
this.toObject = wrapper.toObject.bind(wrapperThis);
}
return this;
};
/**
* Encodes a message of this type. Does not implicitly {@link Type#verify|verify} messages.
* @param {Message<{}>|Object.<string,*>} message Message instance or plain object
* @param {Writer} [writer] Writer to encode to
* @returns {Writer} writer
*/
Type.prototype.encode = function encode_setup(message, writer) { // eslint-disable-line no-unused-vars
return this.setup().encode.apply(this, arguments); // overrides this method
};
/**
* Encodes a message of this type preceeded by its byte length as a varint. Does not implicitly {@link Type#verify|verify} messages.
* @param {Message<{}>|Object.<string,*>} message Message instance or plain object
* @param {Writer} [writer] Writer to encode to
* @returns {Writer} writer
*/
Type.prototype.encodeDelimited = function encodeDelimited(message, writer) {
return this.encode(message, (writer || Writer.create()).fork()).ldelim();
};
/**
* Decodes a message of this type.
* @param {Reader|Uint8Array} reader Reader or buffer to decode from
* @param {number} [length] Length of the message, if known beforehand
* @returns {ReflectedMessage} Decoded message
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {util.ProtocolError<{}>} If required fields are missing
*/
Type.prototype.decode = function decode_setup(reader, length) { // eslint-disable-line no-unused-vars
return this.setup().decode.apply(this, arguments); // overrides this method
};
/**
* Decodes a message of this type preceeded by its byte length as a varint.
* @param {Reader|Uint8Array} reader Reader or buffer to decode from
* @returns {ReflectedMessage} Decoded message
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {util.ProtocolError} If required fields are missing
*/
Type.prototype.decodeDelimited = function decodeDelimited(reader) {
if (!(reader instanceof Reader))
reader = Reader.create(reader);
return this.decode(reader, reader.uint32());
};
/**
* Verifies that field values are valid and that required fields are present.
* @param {Object.<string,*>} message Plain object to verify
* @returns {null|string} `null` if valid, otherwise the reason why it is not
*/
Type.prototype.verify = function verify_setup(message) { // eslint-disable-line no-unused-vars
return this.setup().verify.apply(this, arguments); // overrides this method
};
/**
* Creates a new message of this type from a plain object. Also converts values to their respective internal types.
* @param {Object.<string,*>} object Plain object to convert
* @returns {ReflectedMessage} Message instance
*/
Type.prototype.fromObject = function fromObject(object) { // eslint-disable-line no-unused-vars
return this.setup().fromObject.apply(this, arguments);
};
/**
* Conversion options as used by {@link Type#toObject} and {@link Message.toObject}.
* @interface IConversionOptions
* @property {Function} [longs] Long conversion type.
* Valid values are `BigInt`, `String` and `Number` (the global types).
* Defaults to copy the present value, which is a possibly unsafe number without and a {@link Long} with a long library.
* @property {Function} [enums] Enum value conversion type.
* Only valid value is `String` (the global type).
* Defaults to copy the present value, which is the numeric id.
* @property {Function} [bytes] Bytes value conversion type.
* Valid values are `Array` and (a base64 encoded) `String` (the global types).
* Defaults to copy the present value, which usually is a Buffer under node and an Uint8Array in the browser.
* @property {boolean} [defaults=false] Also sets default values on the resulting object
* @property {boolean} [arrays=false] Sets empty arrays for missing repeated fields even if `defaults=false`
* @property {boolean} [objects=false] Sets empty objects for missing map fields even if `defaults=false`
* @property {boolean} [oneofs=false] Includes virtual oneof properties set to the present field's name, if any
* @property {boolean} [json=false] Performs additional JSON compatibility conversions, i.e. NaN and Infinity to strings
*/
/**
* Creates a plain object from a message of this type. Also converts values to other types if specified.
* @param {Message<{}>} message Message instance
* @param {IConversionOptions} [options] Conversion options
* @returns {Object.<string,*>} Plain object
*/
Type.prototype.toObject = function toObject(message, options) { // eslint-disable-line no-unused-vars
return this.setup().toObject.apply(this, arguments);
};
/**
* Gets the type url for this type.
* @param {string} [prefix] Custom type url prefix, defaults to `"type.googleapis.com"`
* @returns {string} The type url
*/
Type.prototype.getTypeUrl = function getTypeUrl(prefix) {
if (prefix === undefined)
prefix = "type.googleapis.com";
var fullName = this.fullName;
return prefix + "/" + (fullName.charAt(0) === "." ? fullName.substring(1) : fullName);
};
/**
* Decorator function as returned by {@link Type.d} (TypeScript).
* @typedef TypeDecorator
* @type {function}
* @param {Constructor<T>} target Target constructor
* @returns {undefined}
* @template T extends Message<T>
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
/**
* Type decorator (TypeScript).
* @param {string} [typeName] Type name, defaults to the constructor's name
* @returns {TypeDecorator<T>} Decorator function
* @template T extends Message<T>
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
Type.d = function decorateType(typeName) {
return function typeDecorator(target) {
util.decorateType(target, typeName);
};
};
+196
View File
@@ -0,0 +1,196 @@
"use strict";
/**
* Common type constants.
* @namespace
*/
var types = exports;
var util = require("./util");
var s = [
"double", // 0
"float", // 1
"int32", // 2
"uint32", // 3
"sint32", // 4
"fixed32", // 5
"sfixed32", // 6
"int64", // 7
"uint64", // 8
"sint64", // 9
"fixed64", // 10
"sfixed64", // 11
"bool", // 12
"string", // 13
"bytes" // 14
];
function bake(values, offset) {
var i = 0, o = Object.create(null);
offset |= 0;
while (i < values.length) o[s[i + offset]] = values[i++];
return o;
}
/**
* Basic type wire types.
* @type {Object.<string,number>}
* @const
* @property {number} double=1 Fixed64 wire type
* @property {number} float=5 Fixed32 wire type
* @property {number} int32=0 Varint wire type
* @property {number} uint32=0 Varint wire type
* @property {number} sint32=0 Varint wire type
* @property {number} fixed32=5 Fixed32 wire type
* @property {number} sfixed32=5 Fixed32 wire type
* @property {number} int64=0 Varint wire type
* @property {number} uint64=0 Varint wire type
* @property {number} sint64=0 Varint wire type
* @property {number} fixed64=1 Fixed64 wire type
* @property {number} sfixed64=1 Fixed64 wire type
* @property {number} bool=0 Varint wire type
* @property {number} string=2 Ldelim wire type
* @property {number} bytes=2 Ldelim wire type
*/
types.basic = bake([
/* double */ 1,
/* float */ 5,
/* int32 */ 0,
/* uint32 */ 0,
/* sint32 */ 0,
/* fixed32 */ 5,
/* sfixed32 */ 5,
/* int64 */ 0,
/* uint64 */ 0,
/* sint64 */ 0,
/* fixed64 */ 1,
/* sfixed64 */ 1,
/* bool */ 0,
/* string */ 2,
/* bytes */ 2
]);
/**
* Basic type defaults.
* @type {Object.<string,*>}
* @const
* @property {number} double=0 Double default
* @property {number} float=0 Float default
* @property {number} int32=0 Int32 default
* @property {number} uint32=0 Uint32 default
* @property {number} sint32=0 Sint32 default
* @property {number} fixed32=0 Fixed32 default
* @property {number} sfixed32=0 Sfixed32 default
* @property {number} int64=0 Int64 default
* @property {number} uint64=0 Uint64 default
* @property {number} sint64=0 Sint32 default
* @property {number} fixed64=0 Fixed64 default
* @property {number} sfixed64=0 Sfixed64 default
* @property {boolean} bool=false Bool default
* @property {string} string="" String default
* @property {Array.<number>} bytes=Array(0) Bytes default
* @property {null} message=null Message default
*/
types.defaults = bake([
/* double */ 0,
/* float */ 0,
/* int32 */ 0,
/* uint32 */ 0,
/* sint32 */ 0,
/* fixed32 */ 0,
/* sfixed32 */ 0,
/* int64 */ 0,
/* uint64 */ 0,
/* sint64 */ 0,
/* fixed64 */ 0,
/* sfixed64 */ 0,
/* bool */ false,
/* string */ "",
/* bytes */ util.emptyArray,
/* message */ null
]);
/**
* Basic long type wire types.
* @type {Object.<string,number>}
* @const
* @property {number} int64=0 Varint wire type
* @property {number} uint64=0 Varint wire type
* @property {number} sint64=0 Varint wire type
* @property {number} fixed64=1 Fixed64 wire type
* @property {number} sfixed64=1 Fixed64 wire type
*/
types.long = bake([
/* int64 */ 0,
/* uint64 */ 0,
/* sint64 */ 0,
/* fixed64 */ 1,
/* sfixed64 */ 1
], 7);
/**
* Allowed types for map keys with their associated wire type.
* @type {Object.<string,number>}
* @const
* @property {number} int32=0 Varint wire type
* @property {number} uint32=0 Varint wire type
* @property {number} sint32=0 Varint wire type
* @property {number} fixed32=5 Fixed32 wire type
* @property {number} sfixed32=5 Fixed32 wire type
* @property {number} int64=0 Varint wire type
* @property {number} uint64=0 Varint wire type
* @property {number} sint64=0 Varint wire type
* @property {number} fixed64=1 Fixed64 wire type
* @property {number} sfixed64=1 Fixed64 wire type
* @property {number} bool=0 Varint wire type
* @property {number} string=2 Ldelim wire type
*/
types.mapKey = bake([
/* int32 */ 0,
/* uint32 */ 0,
/* sint32 */ 0,
/* fixed32 */ 5,
/* sfixed32 */ 5,
/* int64 */ 0,
/* uint64 */ 0,
/* sint64 */ 0,
/* fixed64 */ 1,
/* sfixed64 */ 1,
/* bool */ 0,
/* string */ 2
], 2);
/**
* Allowed types for packed repeated fields with their associated wire type.
* @type {Object.<string,number>}
* @const
* @property {number} double=1 Fixed64 wire type
* @property {number} float=5 Fixed32 wire type
* @property {number} int32=0 Varint wire type
* @property {number} uint32=0 Varint wire type
* @property {number} sint32=0 Varint wire type
* @property {number} fixed32=5 Fixed32 wire type
* @property {number} sfixed32=5 Fixed32 wire type
* @property {number} int64=0 Varint wire type
* @property {number} uint64=0 Varint wire type
* @property {number} sint64=0 Varint wire type
* @property {number} fixed64=1 Fixed64 wire type
* @property {number} sfixed64=1 Fixed64 wire type
* @property {number} bool=0 Varint wire type
*/
types.packed = bake([
/* double */ 1,
/* float */ 5,
/* int32 */ 0,
/* uint32 */ 0,
/* sint32 */ 0,
/* fixed32 */ 5,
/* sfixed32 */ 5,
/* int64 */ 0,
/* uint64 */ 0,
/* sint64 */ 0,
/* fixed64 */ 1,
/* sfixed64 */ 1,
/* bool */ 0
]);
+25
View File
@@ -0,0 +1,25 @@
"use strict";
/* eslint-disable no-unused-vars */
// Global TypeScript helper typedefs. The unused vars anchor these typedefs so
// both TypeScript checkJs and pbts can discover them from this script file.
/**
* Constructor type.
* @template T
* @typedef {Function & { new(...params: any[]): T; prototype: T }} Constructor
*/
var Constructor;
/**
* Properties type.
* @template T
* @typedef {{ [P in keyof T]?: T[P] }} Properties
*/
var Properties;
/**
* Dynamically reflected message type.
* @typedef {Message<{}> & { [k: string]: any }} ReflectedMessage
*/
var ReflectedMessage;
+264
View File
@@ -0,0 +1,264 @@
"use strict";
/**
* Various utility functions.
* @namespace
*/
var util = module.exports = require("./util/minimal");
var roots = require("./roots");
var Type, // cyclic
Enum;
util.codegen = require("./util/codegen");
util.fetch = require("./util/fetch");
util.path = require("./util/path");
util.patterns = require("./util/patterns");
var reservedRe = util.patterns.reservedRe;
/**
* Node's fs module if available.
* @type {Object.<string,*>}
*/
util.fs = require("./util/fs");
/**
* Converts an object's values to an array.
* @param {Object.<string,*>} object Object to convert
* @returns {Array.<*>} Converted array
*/
util.toArray = function toArray(object) {
if (object) {
var keys = Object.keys(object),
array = new Array(keys.length),
index = 0;
while (index < keys.length)
array[index] = object[keys[index++]];
return array;
}
return [];
};
/**
* Converts an array of keys immediately followed by their respective value to an object, omitting undefined values.
* @param {Array.<*>} array Array to convert
* @returns {Object.<string,*>} Converted object
*/
util.toObject = function toObject(array) {
var object = {},
index = 0;
while (index < array.length) {
var key = array[index++],
val = array[index++];
if (val !== undefined)
object[key] = val;
}
return object;
};
/**
* Removes the first matching value from an object.
* @param {Object.<string,*>|undefined} object Object to remove from
* @param {*} value Value to remove
* @param {string} [key] Optional key for fast path removal
* @returns {boolean} `true` if removed, otherwise `false`
*/
util.remove = function remove(object, value, key) {
if (!object)
return false;
if (key !== undefined && Object.prototype.hasOwnProperty.call(object, key) && object[key] === value) {
delete object[key];
return true;
}
for (var names = Object.keys(object), i = 0; i < names.length; ++i)
if (object[names[i]] === value) {
delete object[names[i]];
return true;
}
return false;
};
/**
* Tests whether the specified name is a reserved word in JS.
* @param {string} name Name to test
* @returns {boolean} `true` if reserved, otherwise `false`
*/
util.isReserved = function isReserved(name) {
return reservedRe.test(name);
};
/**
* Returns a safe property accessor for the specified property name.
* @param {string} prop Property name
* @returns {string} Safe accessor
*/
util.safeProp = function safeProp(prop) {
if (!/^[$\w_]+$/.test(prop) || reservedRe.test(prop))
return "[" + JSON.stringify(prop) + "]";
return "." + prop;
};
/**
* Converts the first character of a string to upper case.
* @param {string} str String to convert
* @returns {string} Converted string
*/
util.ucFirst = function ucFirst(str) {
return str.charAt(0).toUpperCase() + str.substring(1);
};
var camelCaseRe = /_([a-z])/g;
/**
* Converts a string to camel case.
* @param {string} str String to convert
* @returns {string} Converted string
* @deprecated Use {@link util.jsonName} for protobuf field JSON names.
*/
util.camelCase = function camelCase(str) {
return str.substring(0, 1)
+ str.substring(1)
.replace(camelCaseRe, function($0, $1) { return $1.toUpperCase(); });
};
/**
* Converts a proto field name to its protoc-compatible JSON name.
* @param {string} str Proto field name
* @returns {string} JSON name
*/
util.jsonName = function jsonName(str) {
var result = "",
upperNext = false,
i = 0;
for (; i < str.length; ++i) {
var ch = str.charAt(i);
if (ch === "_")
upperNext = true;
else if (upperNext) {
result += ch.toUpperCase();
upperNext = false;
} else
result += ch;
}
return result;
};
/**
* Compares reflected fields by id.
* @param {Field} a First field
* @param {Field} b Second field
* @returns {number} Comparison value
*/
util.compareFieldsById = function compareFieldsById(a, b) {
return a.id - b.id;
};
/**
* Decorator helper for types (TypeScript).
* @param {Constructor<T>} ctor Constructor function
* @param {string} [typeName] Type name, defaults to the constructor's name
* @returns {Type} Reflected type
* @template T extends Message<T>
* @property {Root} root Decorators root
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
util.decorateType = function decorateType(ctor, typeName) {
/* istanbul ignore if */
if (ctor.$type) {
if (typeName && ctor.$type.name !== typeName) {
util.decorateRoot.remove(ctor.$type);
ctor.$type.name = typeName;
util.decorateRoot.add(ctor.$type);
}
return ctor.$type;
}
/* istanbul ignore next */
if (!Type)
Type = require("./type");
var type = new Type(typeName || ctor.name);
util.decorateRoot.add(type);
type.ctor = ctor; // sets up .encode, .decode etc.
Object.defineProperty(ctor, "$type", { value: type, enumerable: false });
Object.defineProperty(ctor.prototype, "$type", { value: type, enumerable: false });
return type;
};
var decorateEnumIndex = 0;
/**
* Decorator helper for enums (TypeScript).
* @param {Object} object Enum object
* @returns {Enum} Reflected enum
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
util.decorateEnum = function decorateEnum(object) {
/* istanbul ignore if */
if (object.$type)
return object.$type;
/* istanbul ignore next */
if (!Enum)
Enum = require("./enum");
var enm = new Enum("Enum" + decorateEnumIndex++, object);
util.decorateRoot.add(enm);
Object.defineProperty(object, "$type", { value: enm, enumerable: false });
return enm;
};
/**
* Sets the value of a property by property path. If a value already exists, it is turned to an array
* @param {Object.<string,*>} dst Destination object
* @param {string} path dot '.' delimited path of the property to set
* @param {Object} value the value to set
* @param {boolean|undefined} [ifNotSet] Sets the option only if it isn't currently set
* @returns {Object.<string,*>} Destination object
*/
util.setProperty = function setProperty(dst, path, value, ifNotSet) {
function setProp(dst, path, value) {
var part = path.shift();
if (util.isUnsafeProperty(part))
return dst;
if (path.length > 0) {
dst[part] = setProp(dst[part] || {}, path, value);
} else {
var prevValue = dst[part];
if (prevValue && ifNotSet)
return dst;
if (prevValue)
value = [].concat(prevValue).concat(value);
dst[part] = value;
}
return dst;
}
if (typeof dst !== "object")
throw TypeError("dst must be an object");
if (!path)
throw TypeError("path must be specified");
path = path.split(".");
if (path.length > util.recursionLimit)
throw Error("max depth exceeded");
return setProp(dst, path, value);
};
/**
* Decorator root (TypeScript).
* @name util.decorateRoot
* @type {Root}
* @readonly
* @deprecated Legacy TypeScript decorator support. Will be removed in a future release.
*/
Object.defineProperty(util, "decorateRoot", {
get: function() {
return roots["decorated"] || (roots["decorated"] = new (require("./root"))());
}
});
+13
View File
@@ -0,0 +1,13 @@
export = asPromise;
type asPromiseCallback = (error: Error | null, ...params: any[]) => {};
/**
* Returns a promise from a node-style callback function.
* @memberof util
* @param {asPromiseCallback} fn Function to call
* @param {*} ctx Function context
* @param {...*} params Function arguments
* @returns {Promise<*>} Promisified function
*/
declare function asPromise(fn: asPromiseCallback, ctx: any, ...params: any[]): Promise<any>;
+52
View File
@@ -0,0 +1,52 @@
"use strict";
module.exports = asPromise;
/**
* Callback as used by {@link util.asPromise}.
* @typedef asPromiseCallback
* @type {function}
* @param {Error|null} error Error, if any
* @param {...*} params Additional arguments
* @returns {undefined}
*/
/**
* Returns a promise from a node-style callback function.
* @memberof util
* @param {asPromiseCallback} fn Function to call
* @param {*} ctx Function context
* @param {...*} params Function arguments
* @returns {Promise<*>} Promisified function
*/
function asPromise(fn, ctx/*, varargs */) {
var params = new Array(arguments.length - 1),
offset = 0,
index = 2,
pending = true;
while (index < arguments.length)
params[offset++] = arguments[index++];
return new Promise(function executor(resolve, reject) {
params[offset] = function callback(err/*, varargs */) {
if (pending) {
pending = false;
if (err)
reject(err);
else {
var params = new Array(arguments.length - 1),
offset = 0;
while (offset < params.length)
params[offset++] = arguments[offset];
resolve.apply(null, params);
}
}
};
try {
fn.apply(ctx || null, params);
} catch (err) {
if (pending) {
pending = false;
reject(err);
}
}
});
}
+32
View File
@@ -0,0 +1,32 @@
/**
* Calculates the byte length of a base64 encoded string.
* @param {string} string Base64 encoded string
* @returns {number} Byte length
*/
export function length(string: string): number;
/**
* Encodes a buffer to a base64 encoded string.
* @param {Uint8Array} buffer Source buffer
* @param {number} start Source start
* @param {number} end Source end
* @returns {string} Base64 encoded string
*/
export function encode(buffer: Uint8Array, start: number, end: number): string;
/**
* Decodes a base64 encoded string to a buffer.
* @param {string} string Source string
* @param {Uint8Array} buffer Destination buffer
* @param {number} offset Destination offset
* @returns {number} Number of bytes written
* @throws {Error} If encoding is invalid
*/
export function decode(string: string, buffer: Uint8Array, offset: number): number;
/**
* Tests if the specified string appears to be base64 encoded.
* @param {string} string String to test
* @returns {boolean} `true` if it appears to be base64 encoded, otherwise false
*/
export function test(string: string): boolean;
+146
View File
@@ -0,0 +1,146 @@
"use strict";
/**
* A minimal base64 implementation for number arrays.
* @memberof util
* @namespace
*/
var base64 = exports;
/**
* Calculates the byte length of a base64 encoded string.
* @param {string} string Base64 encoded string
* @returns {number} Byte length
*/
base64.length = function length(string) {
var p = string.length;
if (!p)
return 0;
while (p > 0 && string.charAt(p - 1) === "=")
--p;
return Math.floor(p * 3 / 4);
};
// Base64 encoding table
var b64 = new Array(64);
// Base64 decoding table
var s64 = new Array(123);
// 65..90, 97..122, 48..57, 43, 47
for (var i = 0; i < 64;)
s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;
s64[45] = 62; // - -> +
s64[95] = 63; // _ -> /
/**
* Encodes a buffer to a base64 encoded string.
* @param {Uint8Array} buffer Source buffer
* @param {number} start Source start
* @param {number} end Source end
* @returns {string} Base64 encoded string
*/
base64.encode = function encode(buffer, start, end) {
var parts = null,
chunk = [];
var i = 0, // output index
j = 0, // goto index
t; // temporary
while (start < end) {
var b = buffer[start++];
switch (j) {
case 0:
chunk[i++] = b64[b >> 2];
t = (b & 3) << 4;
j = 1;
break;
case 1:
chunk[i++] = b64[t | b >> 4];
t = (b & 15) << 2;
j = 2;
break;
case 2:
chunk[i++] = b64[t | b >> 6];
chunk[i++] = b64[b & 63];
j = 0;
break;
}
if (i > 8191) {
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
i = 0;
}
}
if (j) {
chunk[i++] = b64[t];
chunk[i++] = 61;
if (j === 1)
chunk[i++] = 61;
}
if (parts) {
if (i)
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
return parts.join("");
}
return String.fromCharCode.apply(String, chunk.slice(0, i));
};
var invalidEncoding = "invalid encoding";
/**
* Decodes a base64 encoded string to a buffer.
* @param {string} string Source string
* @param {Uint8Array} buffer Destination buffer
* @param {number} offset Destination offset
* @returns {number} Number of bytes written
* @throws {Error} If encoding is invalid
*/
base64.decode = function decode(string, buffer, offset) {
var start = offset;
var j = 0, // goto index
t; // temporary
for (var i = 0; i < string.length;) {
var c = string.charCodeAt(i++);
if (c === 61 && j > 1)
break;
if ((c = s64[c]) === undefined)
throw Error(invalidEncoding);
switch (j) {
case 0:
t = c;
j = 1;
break;
case 1:
buffer[offset++] = t << 2 | (c & 48) >> 4;
t = c;
j = 2;
break;
case 2:
buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
t = c;
j = 3;
break;
case 3:
buffer[offset++] = (t & 3) << 6 | c;
j = 0;
break;
}
}
if (j === 1)
throw Error(invalidEncoding);
return offset - start;
};
var base64Re = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,
base64UrlRe = /[-_]/,
base64UrlNoPaddingRe = /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2}(?:==)?|[A-Za-z0-9_-]{3}=?)?$/;
/**
* Tests if the specified string appears to be base64 encoded.
* @param {string} string String to test
* @returns {boolean} `true` if probably base64 encoded, otherwise false
*/
base64.test = function test(string) {
return base64Re.test(string)
|| base64UrlRe.test(string) && base64UrlNoPaddingRe.test(string);
};
+31
View File
@@ -0,0 +1,31 @@
export = codegen;
/**
* Appends code to the function's body.
* @param [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any
* @param [formatParams] Format parameters
* @returns Itself or the generated function if finished
* @throws {Error} If format parameter counts do not match
*/
type Codegen = (formatStringOrScope?: (string|{ [k: string]: any }), ...formatParams: any[]) => (Codegen|Function);
/**
* Begins generating a function.
* @param functionParams Function parameter names
* @param [functionName] Function name if not anonymous
* @returns Appender that appends code to the function's body
*/
declare function codegen(functionParams: string[], functionName?: string): Codegen;
/**
* Begins generating a function.
* @param [functionName] Function name if not anonymous
* @returns Appender that appends code to the function's body
*/
declare function codegen(functionName?: string): Codegen;
declare namespace codegen {
/** When set to `true`, codegen will log generated code to console. Useful for debugging. */
let verbose: boolean;
}
+118
View File
@@ -0,0 +1,118 @@
"use strict";
module.exports = codegen;
var patterns = require("./patterns");
var reservedRe = patterns.reservedRe;
/**
* Begins generating a function.
* @memberof util
* @param {string[]} functionParams Function parameter names
* @param {string} [functionName] Function name if not anonymous
* @returns {Codegen} Appender that appends code to the function's body
*/
function codegen(functionParams, functionName) {
/* istanbul ignore if */
if (typeof functionParams === "string") {
functionName = functionParams;
functionParams = undefined;
}
var body = [];
/**
* Appends code to the function's body or finishes generation.
* @typedef Codegen
* @type {function}
* @param {string|Object.<string,*>} [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any
* @param {...*} [formatParams] Format parameters
* @returns {Codegen|Function} Itself or the generated function if finished
* @throws {Error} If format parameter counts do not match
*/
function Codegen(formatStringOrScope) {
// note that explicit array handling below makes this ~50% faster
// finish the function
if (typeof formatStringOrScope !== "string") {
var source = toString();
if (codegen.verbose)
console.log("codegen: " + source); // eslint-disable-line no-console
source = "return " + source;
if (formatStringOrScope) {
var scopeKeys = Object.keys(formatStringOrScope),
scopeParams = new Array(scopeKeys.length + 1),
scopeValues = new Array(scopeKeys.length),
scopeOffset = 0;
while (scopeOffset < scopeKeys.length) {
scopeParams[scopeOffset] = scopeKeys[scopeOffset];
scopeValues[scopeOffset] = formatStringOrScope[scopeKeys[scopeOffset++]];
}
scopeParams[scopeOffset] = source;
return Function.apply(null, scopeParams).apply(null, scopeValues); // eslint-disable-line no-new-func
}
return Function(source)(); // eslint-disable-line no-new-func
}
// otherwise append to body
var formatParams = new Array(arguments.length - 1),
formatOffset = 0;
while (formatOffset < formatParams.length)
formatParams[formatOffset] = arguments[++formatOffset];
formatOffset = 0;
formatStringOrScope = formatStringOrScope.replace(/%([%dfijs])/g, function replace($0, $1) {
var value = formatParams[formatOffset++];
switch ($1) {
case "d": case "f": return String(Number(value));
case "i": return String(Math.floor(value));
case "j": return JSON.stringify(value);
case "s": return String(value);
}
return "%";
});
if (formatOffset !== formatParams.length)
throw Error("parameter count mismatch");
body.push(formatStringOrScope);
return Codegen;
}
function toString(functionNameOverride) {
return "function " + safeFunctionName(functionNameOverride || functionName) + "(" + (functionParams && functionParams.join(",") || "") + "){\n " + body.join("\n ") + "\n}";
}
Object.defineProperty(Codegen, "toString", {
value: toString,
writable: true,
enumerable: true,
configurable: true
});
return Codegen;
}
/**
* Begins generating a function.
* @memberof util
* @function codegen
* @param {string} [functionName] Function name if not anonymous
* @returns {Codegen} Appender that appends code to the function's body
* @variation 2
*/
/**
* When set to `true`, codegen will log generated code to console. Useful for debugging.
* @name util.codegen.verbose
* @type {boolean}
*/
codegen.verbose = false;
function safeFunctionName(name) {
if (!name)
return "";
name = String(name).replace(/[^\w$]/g, "");
if (!name)
return "";
if (/^\d/.test(name))
name = "_" + name;
return reservedRe.test(name) ? name + "_" : name;
}
+45
View File
@@ -0,0 +1,45 @@
export = EventEmitter;
type EventEmitterListener = (...args: any[]) => {};
/**
* Constructs a new event emitter instance.
* @classdesc A minimal event emitter.
* @memberof util
* @constructor
*/
declare class EventEmitter {
/**
* Constructs a new event emitter instance.
* @classdesc A minimal event emitter.
* @memberof util
* @constructor
*/
constructor();
/**
* Registers an event listener.
* @param {string} evt Event name
* @param {EventEmitterListener} fn Listener
* @param {*} [ctx] Listener context
* @returns {this} `this`
*/
public on(evt: string, fn: EventEmitterListener, ctx?: any): EventEmitter;
/**
* Removes an event listener or any matching listeners if arguments are omitted.
* @param {string} [evt] Event name. Removes all listeners if omitted.
* @param {EventEmitterListener} [fn] Listener to remove. Removes all listeners of `evt` if omitted.
* @returns {this} `this`
*/
public off(evt?: string, fn?: EventEmitterListener): EventEmitter;
/**
* Emits an event by calling its listeners with the specified arguments.
* @param {string} evt Event name
* @param {...*} args Arguments
* @returns {this} `this`
*/
public emit(evt: string, ...args: any[]): EventEmitter;
}
+86
View File
@@ -0,0 +1,86 @@
"use strict";
module.exports = EventEmitter;
/**
* Constructs a new event emitter instance.
* @classdesc A minimal event emitter.
* @memberof util
* @constructor
*/
function EventEmitter() {
/**
* Registered listeners.
* @type {Object.<string,*>}
* @private
*/
this._listeners = Object.create(null);
}
/**
* Event listener as used by {@link util.EventEmitter}.
* @typedef EventEmitterListener
* @type {function}
* @param {...*} args Arguments
* @returns {undefined}
*/
/**
* Registers an event listener.
* @param {string} evt Event name
* @param {EventEmitterListener} fn Listener
* @param {*} [ctx] Listener context
* @returns {this} `this`
*/
EventEmitter.prototype.on = function on(evt, fn, ctx) {
(this._listeners[evt] || (this._listeners[evt] = [])).push({
fn : fn,
ctx : ctx || this
});
return this;
};
/**
* Removes an event listener or any matching listeners if arguments are omitted.
* @param {string} [evt] Event name. Removes all listeners if omitted.
* @param {EventEmitterListener} [fn] Listener to remove. Removes all listeners of `evt` if omitted.
* @returns {this} `this`
*/
EventEmitter.prototype.off = function off(evt, fn) {
if (evt === undefined)
this._listeners = Object.create(null);
else {
if (fn === undefined)
this._listeners[evt] = [];
else {
var listeners = this._listeners[evt];
if (!listeners)
return this;
for (var i = 0; i < listeners.length;)
if (listeners[i].fn === fn)
listeners.splice(i, 1);
else
++i;
}
}
return this;
};
/**
* Emits an event by calling its listeners with the specified arguments.
* @param {string} evt Event name
* @param {...*} args Arguments
* @returns {this} `this`
*/
EventEmitter.prototype.emit = function emit(evt) {
var listeners = this._listeners[evt];
if (listeners) {
var args = [],
i = 1;
for (; i < arguments.length;)
args.push(arguments[i++]);
for (i = 0; i < listeners.length;)
listeners[i].fn.apply(listeners[i++].ctx, args);
}
return this;
};
+56
View File
@@ -0,0 +1,56 @@
export = fetch;
/**
* Node-style callback as used by {@link util.fetch}.
* @typedef FetchCallback
* @type {function}
* @param {?Error} error Error, if any, otherwise `null`
* @param {string} [contents] File contents, if there hasn't been an error
* @returns {undefined}
*/
type FetchCallback = (error: Error, contents?: string) => void;
/**
* Options as used by {@link util.fetch}.
* @typedef IFetchOptions
* @type {Object}
* @property {boolean} [binary=false] Whether expecting a binary response
* @property {boolean} [xhr=false] If `true`, forces the use of XMLHttpRequest
*/
interface IFetchOptions {
binary?: boolean;
xhr?: boolean;
}
/**
* Fetches the contents of a file.
* @memberof util
* @param {string} filename File path or url
* @param {IFetchOptions} options Fetch options
* @param {FetchCallback} callback Callback function
* @returns {undefined}
*/
declare function fetch(filename: string, options: IFetchOptions, callback: FetchCallback): void;
/**
* Fetches the contents of a file.
* @name util.fetch
* @function
* @param {string} path File path or url
* @param {FetchCallback} callback Callback function
* @returns {undefined}
* @variation 2
*/
declare function fetch(path: string, callback: FetchCallback): void;
/**
* Fetches the contents of a file.
* @name util.fetch
* @function
* @param {string} path File path or url
* @param {IFetchOptions} [options] Fetch options
* @returns {Promise<string|Uint8Array>} Promise
* @variation 3
*/
declare function fetch(path: string, options?: IFetchOptions): Promise<(string|Uint8Array)>;
+112
View File
@@ -0,0 +1,112 @@
"use strict";
module.exports = fetch;
var asPromise = require("./aspromise"),
fs = require("./fs");
/**
* Node-style callback as used by {@link util.fetch}.
* @typedef FetchCallback
* @type {function}
* @param {?Error} error Error, if any, otherwise `null`
* @param {string} [contents] File contents, if there hasn't been an error
* @returns {undefined}
*/
/**
* Options as used by {@link util.fetch}.
* @interface IFetchOptions
* @property {boolean} [binary=false] Whether expecting a binary response
* @property {boolean} [xhr=false] If `true`, forces the use of XMLHttpRequest
*/
/**
* Fetches the contents of a file.
* @memberof util
* @param {string} filename File path or url
* @param {IFetchOptions} options Fetch options
* @param {FetchCallback} callback Callback function
* @returns {undefined}
*/
function fetch(filename, options, callback) {
if (typeof options === "function") {
callback = options;
options = {};
} else if (!options)
options = {};
if (!callback)
return asPromise(fetch, this, filename, options); // eslint-disable-line no-invalid-this
// if a node-like filesystem is present, try it first but fall back to XHR if nothing is found.
if (!options.xhr && fs && fs.readFile)
return fs.readFile(filename, function fetchReadFileCallback(err, contents) {
return err && typeof XMLHttpRequest !== "undefined"
? fetch.xhr(filename, options, callback)
: err
? callback(err)
: callback(null, options.binary ? contents : contents.toString("utf8"));
});
// use the XHR version otherwise.
return fetch.xhr(filename, options, callback);
}
/**
* Fetches the contents of a file.
* @name util.fetch
* @function
* @param {string} path File path or url
* @param {FetchCallback} callback Callback function
* @returns {undefined}
* @variation 2
*/
/**
* Fetches the contents of a file.
* @name util.fetch
* @function
* @param {string} path File path or url
* @param {IFetchOptions} [options] Fetch options
* @returns {Promise<string|Uint8Array>} Promise
* @variation 3
*/
/**/
fetch.xhr = function fetch_xhr(filename, options, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange /* works everywhere */ = function fetchOnReadyStateChange() {
if (xhr.readyState !== 4)
return undefined;
// local cors security errors return status 0 / empty string, too. afaik this cannot be
// reliably distinguished from an actually empty file for security reasons. feel free
// to send a pull request if you are aware of a solution.
if (xhr.status !== 0 && xhr.status !== 200)
return callback(Error("status " + xhr.status));
// if binary data is expected, make sure that some sort of array is returned, even if
// ArrayBuffers are not supported. the binary string fallback, however, is unsafe.
if (options.binary) {
var buffer = xhr.response;
if (!buffer) {
buffer = [];
for (var i = 0; i < xhr.responseText.length; ++i)
buffer.push(xhr.responseText.charCodeAt(i) & 255);
}
return callback(null, typeof Uint8Array !== "undefined" ? new Uint8Array(buffer) : buffer);
}
return callback(null, xhr.responseText);
};
if (options.binary) {
// ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Receiving_binary_data_in_older_browsers
if ("overrideMimeType" in xhr)
xhr.overrideMimeType("text/plain; charset=x-user-defined");
xhr.responseType = "arraybuffer";
}
xhr.open("GET", filename);
xhr.send();
};
+83
View File
@@ -0,0 +1,83 @@
/**
* Writes a 32 bit float to a buffer using little endian byte order.
* @name writeFloatLE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
export function writeFloatLE(val: number, buf: Uint8Array, pos: number): void;
/**
* Writes a 32 bit float to a buffer using big endian byte order.
* @name writeFloatBE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
export function writeFloatBE(val: number, buf: Uint8Array, pos: number): void;
/**
* Reads a 32 bit float from a buffer using little endian byte order.
* @name readFloatLE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
export function readFloatLE(buf: Uint8Array, pos: number): number;
/**
* Reads a 32 bit float from a buffer using big endian byte order.
* @name readFloatBE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
export function readFloatBE(buf: Uint8Array, pos: number): number;
/**
* Writes a 64 bit double to a buffer using little endian byte order.
* @name writeDoubleLE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
export function writeDoubleLE(val: number, buf: Uint8Array, pos: number): void;
/**
* Writes a 64 bit double to a buffer using big endian byte order.
* @name writeDoubleBE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
export function writeDoubleBE(val: number, buf: Uint8Array, pos: number): void;
/**
* Reads a 64 bit double from a buffer using little endian byte order.
* @name readDoubleLE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
export function readDoubleLE(buf: Uint8Array, pos: number): number;
/**
* Reads a 64 bit double from a buffer using big endian byte order.
* @name readDoubleBE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
export function readDoubleBE(buf: Uint8Array, pos: number): number;
+335
View File
@@ -0,0 +1,335 @@
"use strict";
module.exports = factory(factory);
/**
* Reads / writes floats / doubles from / to buffers.
* @name util.float
* @namespace
*/
/**
* Writes a 32 bit float to a buffer using little endian byte order.
* @name util.float.writeFloatLE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
/**
* Writes a 32 bit float to a buffer using big endian byte order.
* @name util.float.writeFloatBE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
/**
* Reads a 32 bit float from a buffer using little endian byte order.
* @name util.float.readFloatLE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
/**
* Reads a 32 bit float from a buffer using big endian byte order.
* @name util.float.readFloatBE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
/**
* Writes a 64 bit double to a buffer using little endian byte order.
* @name util.float.writeDoubleLE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
/**
* Writes a 64 bit double to a buffer using big endian byte order.
* @name util.float.writeDoubleBE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
/**
* Reads a 64 bit double from a buffer using little endian byte order.
* @name util.float.readDoubleLE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
/**
* Reads a 64 bit double from a buffer using big endian byte order.
* @name util.float.readDoubleBE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
// Factory function for the purpose of node-based testing in modified global environments
function factory(exports) {
// float: typed array
if (typeof Float32Array !== "undefined") (function() {
var f32 = new Float32Array([ -0 ]),
f8b = new Uint8Array(f32.buffer),
le = f8b[3] === 128;
function writeFloat_f32_cpy(val, buf, pos) {
f32[0] = val;
buf[pos ] = f8b[0];
buf[pos + 1] = f8b[1];
buf[pos + 2] = f8b[2];
buf[pos + 3] = f8b[3];
}
function writeFloat_f32_rev(val, buf, pos) {
f32[0] = val;
buf[pos ] = f8b[3];
buf[pos + 1] = f8b[2];
buf[pos + 2] = f8b[1];
buf[pos + 3] = f8b[0];
}
/* istanbul ignore next */
exports.writeFloatLE = le ? writeFloat_f32_cpy : writeFloat_f32_rev;
/* istanbul ignore next */
exports.writeFloatBE = le ? writeFloat_f32_rev : writeFloat_f32_cpy;
function readFloat_f32_cpy(buf, pos) {
f8b[0] = buf[pos ];
f8b[1] = buf[pos + 1];
f8b[2] = buf[pos + 2];
f8b[3] = buf[pos + 3];
return f32[0];
}
function readFloat_f32_rev(buf, pos) {
f8b[3] = buf[pos ];
f8b[2] = buf[pos + 1];
f8b[1] = buf[pos + 2];
f8b[0] = buf[pos + 3];
return f32[0];
}
/* istanbul ignore next */
exports.readFloatLE = le ? readFloat_f32_cpy : readFloat_f32_rev;
/* istanbul ignore next */
exports.readFloatBE = le ? readFloat_f32_rev : readFloat_f32_cpy;
// float: ieee754
})(); else (function() {
function writeFloat_ieee754(writeUint, val, buf, pos) {
var sign = val < 0 ? 1 : 0;
if (sign)
val = -val;
if (val === 0)
writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos);
else if (isNaN(val))
writeUint(2143289344, buf, pos);
else if (val > 3.4028234663852886e+38) // +-Infinity
writeUint((sign << 31 | 2139095040) >>> 0, buf, pos);
else if (val < 1.1754943508222875e-38) // denormal
writeUint((sign << 31 | Math.round(val / 1.401298464324817e-45)) >>> 0, buf, pos);
else {
var exponent = Math.floor(Math.log(val) / Math.LN2),
mantissa = Math.round(val * Math.pow(2, -exponent) * 8388608) & 8388607;
writeUint((sign << 31 | exponent + 127 << 23 | mantissa) >>> 0, buf, pos);
}
}
exports.writeFloatLE = writeFloat_ieee754.bind(null, writeUintLE);
exports.writeFloatBE = writeFloat_ieee754.bind(null, writeUintBE);
function readFloat_ieee754(readUint, buf, pos) {
var uint = readUint(buf, pos),
sign = (uint >> 31) * 2 + 1,
exponent = uint >>> 23 & 255,
mantissa = uint & 8388607;
return exponent === 255
? mantissa
? NaN
: sign * Infinity
: exponent === 0 // denormal
? sign * 1.401298464324817e-45 * mantissa
: sign * Math.pow(2, exponent - 150) * (mantissa + 8388608);
}
exports.readFloatLE = readFloat_ieee754.bind(null, readUintLE);
exports.readFloatBE = readFloat_ieee754.bind(null, readUintBE);
})();
// double: typed array
if (typeof Float64Array !== "undefined") (function() {
var f64 = new Float64Array([-0]),
f8b = new Uint8Array(f64.buffer),
le = f8b[7] === 128;
function writeDouble_f64_cpy(val, buf, pos) {
f64[0] = val;
buf[pos ] = f8b[0];
buf[pos + 1] = f8b[1];
buf[pos + 2] = f8b[2];
buf[pos + 3] = f8b[3];
buf[pos + 4] = f8b[4];
buf[pos + 5] = f8b[5];
buf[pos + 6] = f8b[6];
buf[pos + 7] = f8b[7];
}
function writeDouble_f64_rev(val, buf, pos) {
f64[0] = val;
buf[pos ] = f8b[7];
buf[pos + 1] = f8b[6];
buf[pos + 2] = f8b[5];
buf[pos + 3] = f8b[4];
buf[pos + 4] = f8b[3];
buf[pos + 5] = f8b[2];
buf[pos + 6] = f8b[1];
buf[pos + 7] = f8b[0];
}
/* istanbul ignore next */
exports.writeDoubleLE = le ? writeDouble_f64_cpy : writeDouble_f64_rev;
/* istanbul ignore next */
exports.writeDoubleBE = le ? writeDouble_f64_rev : writeDouble_f64_cpy;
function readDouble_f64_cpy(buf, pos) {
f8b[0] = buf[pos ];
f8b[1] = buf[pos + 1];
f8b[2] = buf[pos + 2];
f8b[3] = buf[pos + 3];
f8b[4] = buf[pos + 4];
f8b[5] = buf[pos + 5];
f8b[6] = buf[pos + 6];
f8b[7] = buf[pos + 7];
return f64[0];
}
function readDouble_f64_rev(buf, pos) {
f8b[7] = buf[pos ];
f8b[6] = buf[pos + 1];
f8b[5] = buf[pos + 2];
f8b[4] = buf[pos + 3];
f8b[3] = buf[pos + 4];
f8b[2] = buf[pos + 5];
f8b[1] = buf[pos + 6];
f8b[0] = buf[pos + 7];
return f64[0];
}
/* istanbul ignore next */
exports.readDoubleLE = le ? readDouble_f64_cpy : readDouble_f64_rev;
/* istanbul ignore next */
exports.readDoubleBE = le ? readDouble_f64_rev : readDouble_f64_cpy;
// double: ieee754
})(); else (function() {
function writeDouble_ieee754(writeUint, off0, off1, val, buf, pos) {
var sign = val < 0 ? 1 : 0;
if (sign)
val = -val;
if (val === 0) {
writeUint(0, buf, pos + off0);
writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos + off1);
} else if (isNaN(val)) {
writeUint(0, buf, pos + off0);
writeUint(2146959360, buf, pos + off1);
} else if (val > 1.7976931348623157e+308) { // +-Infinity
writeUint(0, buf, pos + off0);
writeUint((sign << 31 | 2146435072) >>> 0, buf, pos + off1);
} else {
var mantissa;
if (val < 2.2250738585072014e-308) { // denormal
mantissa = val / 5e-324;
writeUint(mantissa >>> 0, buf, pos + off0);
writeUint((sign << 31 | mantissa / 4294967296) >>> 0, buf, pos + off1);
} else {
var exponent = Math.floor(Math.log(val) / Math.LN2);
if (exponent === 1024)
exponent = 1023;
mantissa = val * Math.pow(2, -exponent);
writeUint(mantissa * 4503599627370496 >>> 0, buf, pos + off0);
writeUint((sign << 31 | exponent + 1023 << 20 | mantissa * 1048576 & 1048575) >>> 0, buf, pos + off1);
}
}
}
exports.writeDoubleLE = writeDouble_ieee754.bind(null, writeUintLE, 0, 4);
exports.writeDoubleBE = writeDouble_ieee754.bind(null, writeUintBE, 4, 0);
function readDouble_ieee754(readUint, off0, off1, buf, pos) {
var lo = readUint(buf, pos + off0),
hi = readUint(buf, pos + off1);
var sign = (hi >> 31) * 2 + 1,
exponent = hi >>> 20 & 2047,
mantissa = 4294967296 * (hi & 1048575) + lo;
return exponent === 2047
? mantissa
? NaN
: sign * Infinity
: exponent === 0 // denormal
? sign * 5e-324 * mantissa
: sign * Math.pow(2, exponent - 1075) * (mantissa + 4503599627370496);
}
exports.readDoubleLE = readDouble_ieee754.bind(null, readUintLE, 0, 4);
exports.readDoubleBE = readDouble_ieee754.bind(null, readUintBE, 4, 0);
})();
return exports;
}
// uint helpers
function writeUintLE(val, buf, pos) {
buf[pos ] = val & 255;
buf[pos + 1] = val >>> 8 & 255;
buf[pos + 2] = val >>> 16 & 255;
buf[pos + 3] = val >>> 24;
}
function writeUintBE(val, buf, pos) {
buf[pos ] = val >>> 24;
buf[pos + 1] = val >>> 16 & 255;
buf[pos + 2] = val >>> 8 & 255;
buf[pos + 3] = val & 255;
}
function readUintLE(buf, pos) {
return (buf[pos ]
| buf[pos + 1] << 8
| buf[pos + 2] << 16
| buf[pos + 3] << 24) >>> 0;
}
function readUintBE(buf, pos) {
return (buf[pos ] << 24
| buf[pos + 1] << 16
| buf[pos + 2] << 8
| buf[pos + 3]) >>> 0;
}
+11
View File
@@ -0,0 +1,11 @@
"use strict";
var fs = null;
try {
fs = require(/* webpackIgnore: true */ "fs");
if (!fs || !fs.readFile || !fs.readFileSync)
fs = null;
} catch (e) {
// `fs` is unavailable in browsers and browser-like bundles.
}
module.exports = fs;
+204
View File
@@ -0,0 +1,204 @@
"use strict";
module.exports = LongBits;
var Long;
/**
* Constructs new long bits.
* @classdesc Helper class for working with the low and high bits of a 64 bit value.
* @memberof util
* @constructor
* @param {number} lo Low 32 bits, unsigned
* @param {number} hi High 32 bits, unsigned
*/
function LongBits(lo, hi) {
// note that the casts below are theoretically unnecessary as of today, but older statically
// generated converter code might still call the ctor with signed 32bits. kept for compat.
/**
* Low bits.
* @type {number}
*/
this.lo = lo >>> 0;
/**
* High bits.
* @type {number}
*/
this.hi = hi >>> 0;
}
/**
* Zero bits.
* @memberof util.LongBits
* @type {util.LongBits}
*/
var zero = LongBits.zero = new LongBits(0, 0);
zero.toNumber = function() { return 0; };
zero.zzEncode = zero.zzDecode = function() { return this; };
zero.length = function() { return 1; };
/**
* Zero hash.
* @memberof util.LongBits
* @type {string}
*/
var zeroHash = LongBits.zeroHash = "\0\0\0\0\0\0\0\0";
/**
* Constructs new long bits from the specified number.
* @param {number} value Value
* @returns {util.LongBits} Instance
*/
LongBits.fromNumber = function fromNumber(value) {
if (value === 0)
return zero;
var sign = value < 0;
if (sign)
value = -value;
var lo = value >>> 0,
hi = (value - lo) / 4294967296 >>> 0;
if (sign) {
hi = ~hi >>> 0;
lo = ~lo >>> 0;
if (++lo > 4294967295) {
lo = 0;
if (++hi > 4294967295)
hi = 0;
}
}
return new LongBits(lo, hi);
};
/**
* Constructs new long bits from a number, long or string.
* @param {Long|number|string} value Value
* @returns {util.LongBits} Instance
*/
LongBits.from = function from(value) {
if (typeof value === "number")
return LongBits.fromNumber(value);
if (typeof value === "string" || value instanceof String) {
/* istanbul ignore else */
if (Long)
value = Long.fromString(value);
else
return LongBits.fromNumber(parseInt(value, 10));
}
return value.low || value.high ? new LongBits(value.low >>> 0, value.high >>> 0) : zero;
};
/**
* Converts this long bits to a possibly unsafe JavaScript number.
* @param {boolean} [unsigned=false] Whether unsigned or not
* @returns {number} Possibly unsafe number
*/
LongBits.prototype.toNumber = function toNumber(unsigned) {
if (!unsigned && this.hi >>> 31) {
var lo = ~this.lo + 1 >>> 0,
hi = ~this.hi >>> 0;
if (!lo)
hi = hi + 1 >>> 0;
return -(lo + hi * 4294967296);
}
return this.lo + this.hi * 4294967296;
};
/**
* Converts this long bits to a long.
* @param {boolean} [unsigned=false] Whether unsigned or not
* @returns {Long} Long
*/
LongBits.prototype.toLong = function toLong(unsigned) {
return Long
? new Long(this.lo | 0, this.hi | 0, Boolean(unsigned))
/* istanbul ignore next */
: { low: this.lo | 0, high: this.hi | 0, unsigned: Boolean(unsigned) };
};
var charCodeAt = String.prototype.charCodeAt;
/**
* Constructs new long bits from the specified 8 characters long hash.
* @param {string} hash Hash
* @returns {util.LongBits} Bits
*/
LongBits.fromHash = function fromHash(hash) {
if (hash === zeroHash)
return zero;
return new LongBits(
( charCodeAt.call(hash, 0)
| charCodeAt.call(hash, 1) << 8
| charCodeAt.call(hash, 2) << 16
| charCodeAt.call(hash, 3) << 24) >>> 0
,
( charCodeAt.call(hash, 4)
| charCodeAt.call(hash, 5) << 8
| charCodeAt.call(hash, 6) << 16
| charCodeAt.call(hash, 7) << 24) >>> 0
);
};
/**
* Converts this long bits to a 8 characters long hash.
* @returns {string} Hash
*/
LongBits.prototype.toHash = function toHash() {
return String.fromCharCode(
this.lo & 255,
this.lo >>> 8 & 255,
this.lo >>> 16 & 255,
this.lo >>> 24 ,
this.hi & 255,
this.hi >>> 8 & 255,
this.hi >>> 16 & 255,
this.hi >>> 24
);
};
/**
* Zig-zag encodes this long bits.
* @returns {util.LongBits} `this`
*/
LongBits.prototype.zzEncode = function zzEncode() {
var mask = this.hi >> 31;
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask) >>> 0;
this.lo = ( this.lo << 1 ^ mask) >>> 0;
return this;
};
/**
* Zig-zag decodes this long bits.
* @returns {util.LongBits} `this`
*/
LongBits.prototype.zzDecode = function zzDecode() {
var mask = -(this.lo & 1);
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask) >>> 0;
this.hi = ( this.hi >>> 1 ^ mask) >>> 0;
return this;
};
/**
* Calculates the length of this longbits when encoded as a varint.
* @returns {number} Length
*/
LongBits.prototype.length = function length() {
var part0 = this.lo,
part1 = (this.lo >>> 28 | this.hi << 4) >>> 0,
part2 = this.hi >>> 24;
return part2 === 0
? part1 === 0
? part0 < 16384
? part0 < 128 ? 1 : 2
: part0 < 2097152 ? 3 : 4
: part1 < 16384
? part1 < 128 ? 5 : 6
: part1 < 2097152 ? 7 : 8
: part2 < 128 ? 9 : 10;
};
LongBits._configure = function(Long_) {
Long = Long_;
};
+511
View File
@@ -0,0 +1,511 @@
"use strict";
/* global globalThis */
var util = exports;
// used to return a Promise where callback is omitted
util.asPromise = require("./aspromise");
// converts to / from base64 encoded strings
util.base64 = require("./base64");
// base class of rpc.Service
util.EventEmitter = require("./eventemitter");
// float handling accross browsers
util.float = require("./float");
// converts to / from utf8 encoded strings
util.utf8 = require("./utf8");
// provides a node-like buffer pool in the browser
util.pool = require("./pool");
// utility to work with the low and high bits of a 64 bit value
util.LongBits = require("./longbits");
/**
* Tests if the specified key can affect object prototypes.
* @memberof util
* @param {string} key Key to test
* @returns {boolean} `true` if the key is unsafe
*/
function isUnsafeProperty(key) {
return key === "__proto__" || key === "prototype" || key === "constructor";
}
util.isUnsafeProperty = isUnsafeProperty;
/**
* Whether running within node or not.
* @memberof util
* @type {boolean}
*/
util.isNode = Boolean(typeof global !== "undefined"
&& global
&& global.process
&& global.process.versions
&& global.process.versions.node);
/**
* Global object reference.
* @memberof util
* @type {Object}
*/
util.global = util.isNode && global
|| typeof window !== "undefined" && window
|| typeof self !== "undefined" && self
|| typeof globalThis !== "undefined" && globalThis
|| this; // eslint-disable-line no-invalid-this
/**
* An immuable empty array.
* @memberof util
* @type {Array.<*>}
* @const
*/
util.emptyArray = Object.freeze ? Object.freeze([]) : /* istanbul ignore next */ []; // used on prototypes
/**
* An immutable empty object.
* @type {Object}
* @const
*/
util.emptyObject = Object.freeze ? Object.freeze({}) : /* istanbul ignore next */ {}; // used on prototypes
/**
* Tests if the specified value is an integer.
* @function
* @param {*} value Value to test
* @returns {boolean} `true` if the value is an integer
*/
util.isInteger = Number.isInteger || /* istanbul ignore next */ function isInteger(value) {
return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
};
/**
* Tests if the specified value is a string.
* @param {*} value Value to test
* @returns {boolean} `true` if the value is a string
*/
util.isString = function isString(value) {
return typeof value === "string" || value instanceof String;
};
/**
* Tests if the specified value is a non-null object.
* @param {*} value Value to test
* @returns {boolean} `true` if the value is a non-null object
*/
util.isObject = function isObject(value) {
return value && typeof value === "object";
};
/**
* Checks if a property on a message is considered to be present.
* This is an alias of {@link util.isSet}.
* @function
* @param {Object} obj Plain object or message instance
* @param {string} prop Property name
* @returns {boolean} `true` if considered to be present, otherwise `false`
*/
util.isset =
/**
* Checks if a property on a message is considered to be present.
* @param {Object} obj Plain object or message instance
* @param {string} prop Property name
* @returns {boolean} `true` if considered to be present, otherwise `false`
*/
util.isSet = function isSet(obj, prop) {
var value = obj[prop];
if (value != null && Object.hasOwnProperty.call(obj, prop)) // eslint-disable-line eqeqeq
return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0;
return false;
};
/**
* Any compatible Buffer instance.
* This is a minimal stand-alone definition of a Buffer instance. The actual type is that exported by node's typings.
* @interface Buffer
* @extends Uint8Array
*/
/**
* Node's Buffer class if available.
* @type {Constructor<Buffer>}
*/
util.Buffer = (function() {
try {
var Buffer = util.global.Buffer;
// refuse to use non-node buffers if not explicitly assigned (perf reasons)
return Buffer.prototype.utf8Write || util.isNode ? Buffer : /* istanbul ignore next */ null;
} catch (e) {
/* istanbul ignore next */
return null;
}
})();
/**
* Creates a new buffer of whatever type supported by the environment.
* @param {number|number[]} [sizeOrArray=0] Buffer size or number array
* @returns {Uint8Array|Buffer} Buffer
*/
util.newBuffer = function newBuffer(sizeOrArray) {
var Buffer = util.Buffer;
/* istanbul ignore next */
return typeof sizeOrArray === "number"
? Buffer
? Buffer.allocUnsafe(sizeOrArray)
: new Uint8Array(sizeOrArray)
: Buffer
? Buffer.from(sizeOrArray)
: new Uint8Array(sizeOrArray);
};
/**
* Prepends a raw field tag to raw field data.
* @param {number} id Field id
* @param {number} wireType Wire type
* @param {Uint8Array} data Raw field data
* @returns {Uint8Array|Buffer} Raw field bytes
* @ignore
*/
util.rawField = function rawField(id, wireType, data) {
var out = [],
tag = id << 3 | wireType;
tag >>>= 0;
while (tag > 127) {
out.push(tag & 127 | 128);
tag >>>= 7;
}
out.push(tag);
for (var i = 0; i < data.length; ++i)
out.push(data[i]);
return util.newBuffer(out);
};
/**
* Array implementation used in the browser.
* @type {Constructor<Uint8Array>}
* @deprecated Use `Uint8Array` instead.
*/
util.Array = Uint8Array;
/**
* Any compatible Long instance.
* This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js.
* @interface Long
* @property {number} low Low bits
* @property {number} high High bits
* @property {boolean} unsigned Whether unsigned or not
*/
/**
* Long.js's Long class if available.
* @type {Constructor<Long>}
*/
util.Long = /* istanbul ignore next */ util.global.dcodeIO && /* istanbul ignore next */ util.global.dcodeIO.Long
|| /* istanbul ignore next */ util.global.Long
|| (function() {
try {
var Long = require("long");
return Long && Long.isLong ? Long : null;
} catch (e) {
/* istanbul ignore next */
return null;
}
})();
/**
* Regular expression used to verify 2 bit (`bool`) map keys.
* @type {RegExp}
* @const
*/
util.key2Re = /^(?:true|false|0|1)$/;
/**
* Regular expression used to verify 32 bit (`int32` etc.) map keys.
* @type {RegExp}
* @const
*/
util.key32Re = /^-?(?:0|[1-9][0-9]*)$/;
/**
* Regular expression used to verify 64 bit (`int64` etc.) map keys.
* @type {RegExp}
* @const
*/
util.key64Re = /^(?:[\x00-\xff]{8}|-?(?:0|[1-9][0-9]*))$/; // eslint-disable-line no-control-regex
/**
* Converts a number or long to an 8 characters long hash string.
* @param {Long|number} value Value to convert
* @returns {string} Hash
*/
util.longToHash = function longToHash(value) {
return value
? util.LongBits.from(value).toHash()
: util.LongBits.zeroHash;
};
/**
* Converts an 8 characters long hash string to a long or number.
* @param {string} hash Hash
* @param {boolean} [unsigned=false] Whether unsigned or not
* @returns {Long|number} Original value
*/
util.longFromHash = function longFromHash(hash, unsigned) {
var bits = util.LongBits.fromHash(hash);
if (util.Long)
return util.Long.fromBits(bits.lo, bits.hi, unsigned);
return bits.toNumber(Boolean(unsigned));
};
/**
* Converts a 64 bit key to a long or number if it is an 8 characters long hash string.
* @param {string} key Map key
* @param {boolean} [unsigned=false] Whether unsigned or not
* @returns {Long|number|string} Original value
*/
util.longFromKey = function longFromKey(key, unsigned) {
return util.key64Re.test(key) && !util.key32Re.test(key)
? util.longFromHash(key, unsigned)
: key;
};
/**
* Converts a boolean key to a boolean value.
* @param {string} key Map key
* @returns {boolean} Boolean value
*/
util.boolFromKey = function boolFromKey(key) {
return key === "true" || key === "1";
};
/**
* Merges the properties of the source object into the destination object.
* @memberof util
* @param {Object.<string,*>} dst Destination object
* @param {...(Object.<string,*>|boolean)} src Source objects, optionally followed by an `ifNotSet` flag
* @returns {Object.<string,*>} Destination object
*/
function merge(dst) { // used by converters
var ifNotSet = typeof arguments[arguments.length - 1] === "boolean",
limit = ifNotSet ? arguments.length - 1 : arguments.length;
ifNotSet = ifNotSet && arguments[arguments.length - 1];
for (var a = 1; a < limit; ++a) {
var src = arguments[a];
if (!src)
continue;
for (var keys = Object.keys(src), i = 0; i < keys.length; ++i)
if (!isUnsafeProperty(keys[i]) && (!ifNotSet || !Object.prototype.hasOwnProperty.call(dst, keys[i]) || dst[keys[i]] === undefined))
dst[keys[i]] = src[keys[i]];
}
return dst;
}
util.merge = merge;
/**
* Schema declaration nesting limit.
* @memberof util
* @type {number}
*/
util.nestingLimit = 32; // protoc: MaxMessageDeclarationNestingDepth
/**
* Recursion limit.
* @memberof util
* @type {number}
*/
util.recursionLimit = 100; // protoc: CodedInputStream::default_recursion_limit_
/**
* Makes a property safe for assignment as an own property.
* @memberof util
* @param {Object.<string,*>} obj Object
* @param {string} key Property key
* @param {boolean} [enumerable=true] Whether the property should be enumerable
* @returns {undefined}
*/
util.makeProp = function makeProp(obj, key, enumerable) {
if (Object.prototype.hasOwnProperty.call(obj, key))
return;
Object.defineProperty(obj, key, {
enumerable: enumerable === undefined ? true : enumerable,
configurable: true,
writable: true
});
};
/**
* Converts the first character of a string to lower case.
* @param {string} str String to convert
* @returns {string} Converted string
*/
util.lcFirst = function lcFirst(str) {
return str.charAt(0).toLowerCase() + str.substring(1);
};
/**
* Creates a custom error constructor.
* @memberof util
* @param {string} name Error name
* @returns {Constructor<Error>} Custom error constructor
*/
function newError(name) {
function CustomError(message, properties) {
if (!(this instanceof CustomError))
return new CustomError(message, properties);
// Error.call(this, message);
// ^ just returns a new error instance because the ctor can be called as a function
Object.defineProperty(this, "message", { get: function() { return message; } });
/* istanbul ignore next */
if (Error.captureStackTrace) // node
Error.captureStackTrace(this, CustomError);
else
Object.defineProperty(this, "stack", { value: new Error().stack || "" });
if (properties)
merge(this, properties);
}
CustomError.prototype = Object.create(Error.prototype, {
constructor: {
value: CustomError,
writable: true,
enumerable: false,
configurable: true,
},
name: {
get: function get() { return name; },
set: undefined,
enumerable: false,
// configurable: false would accurately preserve the behavior of
// the original, but I'm guessing that was not intentional.
// For an actual error subclass, this property would
// be configurable.
configurable: true,
},
toString: {
value: function value() { return this.name + ": " + this.message; },
writable: true,
enumerable: false,
configurable: true,
},
});
return CustomError;
}
util.newError = newError;
/**
* Constructs a new protocol error.
* @classdesc Error subclass indicating a protocol specifc error.
* @memberof util
* @extends Error
* @template T extends Message<T>
* @constructor
* @param {string} message Error message
* @param {Object.<string,*>} [properties] Additional properties
* @example
* try {
* MyMessage.decode(someBuffer); // throws if required fields are missing
* } catch (e) {
* if (e instanceof ProtocolError && e.instance)
* console.log("decoded so far: " + JSON.stringify(e.instance));
* }
*/
util.ProtocolError = newError("ProtocolError");
/**
* So far decoded message instance.
* @name util.ProtocolError#instance
* @type {Message<T>}
*/
/**
* A OneOf getter as returned by {@link util.oneOfGetter}.
* @typedef OneOfGetter
* @type {function}
* @returns {string|undefined} Set field name, if any
*/
/**
* Builds a getter for a oneof's present field name.
* @param {string[]} fieldNames Field names
* @returns {OneOfGetter} Unbound getter
*/
util.oneOfGetter = function getOneOf(fieldNames) {
var fieldMap = {};
for (var i = 0; i < fieldNames.length; ++i)
fieldMap[fieldNames[i]] = 1;
/**
* @returns {string|undefined} Set field name, if any
* @this Object
* @ignore
*/
return function() { // eslint-disable-line consistent-return
for (var keys = Object.keys(this), i = keys.length - 1; i > -1; --i)
if (fieldMap[keys[i]] === 1 && this[keys[i]] !== undefined && this[keys[i]] !== null)
return keys[i];
};
};
/**
* A OneOf setter as returned by {@link util.oneOfSetter}.
* @typedef OneOfSetter
* @type {function}
* @param {string|undefined} value Field name
* @returns {undefined}
*/
/**
* Builds a setter for a oneof's present field name.
* @param {string[]} fieldNames Field names
* @returns {OneOfSetter} Unbound setter
*/
util.oneOfSetter = function setOneOf(fieldNames) {
/**
* @param {string} name Field name
* @returns {undefined}
* @this Object
* @ignore
*/
return function(name) {
for (var i = 0; i < fieldNames.length; ++i)
if (fieldNames[i] !== name)
delete this[fieldNames[i]];
};
};
/**
* Default conversion options used for {@link Message#toJSON} implementations.
*
* These options are close to proto3's JSON mapping with the exception that internal types like Any are handled just like messages. More precisely:
*
* - Longs become strings
* - Enums become string keys
* - Bytes become base64 encoded strings
* - (Sub-)Messages become plain objects
* - Maps become plain objects with all string keys
* - Repeated fields become arrays
* - NaN and Infinity for float and double fields become strings
*
* @type {IConversionOptions}
* @see https://developers.google.com/protocol-buffers/docs/proto3?hl=en#json
*/
util.toJSONOptions = {
longs: String,
enums: String,
bytes: String,
json: true
};
+22
View File
@@ -0,0 +1,22 @@
/**
* Tests if the specified path is absolute.
* @param {string} path Path to test
* @returns {boolean} `true` if path is absolute
*/
export function isAbsolute(path: string): boolean;
/**
* Normalizes the specified path.
* @param {string} path Path to normalize
* @returns {string} Normalized path
*/
export function normalize(path: string): string;
/**
* Resolves the specified include path against the specified origin path.
* @param {string} originPath Path to the origin file
* @param {string} includePath Include path relative to origin path
* @param {boolean} [alreadyNormalized=false] `true` if both paths are already known to be normalized
* @returns {string} Path to the include file
*/
export function resolve(originPath: string, includePath: string, alreadyNormalized?: boolean): string;
+100
View File
@@ -0,0 +1,100 @@
"use strict";
/**
* A minimal path module to resolve Unix, Windows and URL paths alike.
* @memberof util
* @namespace
*/
var path = exports;
var urlRe = /^[a-zA-Z][a-zA-Z0-9+.-]+:\/\//;
function normalizeUrl(path) {
if (typeof URL === "undefined" || !urlRe.test(path))
return null;
try {
return new URL(path).href;
} catch (e) {
return null;
}
}
function resolveUrl(originPath, includePath) {
if (typeof URL === "undefined" || !urlRe.test(originPath) || urlRe.test(includePath))
return null;
try {
return new URL(includePath, originPath).href;
} catch (e) {
return null;
}
}
var isAbsolute =
/**
* Tests if the specified path is absolute.
* @param {string} path Path to test
* @returns {boolean} `true` if path is absolute
*/
path.isAbsolute = function isAbsolute(path) {
return /^(?:\/|\w+:|\\\\\w+)/.test(path);
};
var normalize =
/**
* Normalizes the specified path.
* @param {string} path Path to normalize
* @returns {string} Normalized path
*/
path.normalize = function normalize(path) {
var normalizedUrl = normalizeUrl(path);
if (normalizedUrl)
return normalizedUrl;
var firstTwoCharacters = path.substring(0,2);
var uncPrefix = "";
if (firstTwoCharacters === "\\\\") {
uncPrefix = firstTwoCharacters;
path = path.substring(2);
}
path = path.replace(/\\/g, "/")
.replace(/\/{2,}/g, "/");
var parts = path.split("/"),
absolute = isAbsolute(path),
prefix = "";
if (absolute)
prefix = parts.shift() + "/";
for (var i = 0; i < parts.length;) {
if (parts[i] === "..") {
if (i > 0 && parts[i - 1] !== "..")
parts.splice(--i, 2);
else if (absolute)
parts.splice(i, 1);
else
++i;
} else if (parts[i] === ".")
parts.splice(i, 1);
else
++i;
}
return uncPrefix + prefix + parts.join("/");
};
/**
* Resolves the specified include path against the specified origin path.
* @param {string} originPath Path to the origin file
* @param {string} includePath Include path relative to origin path
* @param {boolean} [alreadyNormalized=false] `true` if both paths are already known to be normalized
* @returns {string} Path to the include file
*/
path.resolve = function resolve(originPath, includePath, alreadyNormalized) {
var resolvedUrl = resolveUrl(originPath, includePath);
if (resolvedUrl)
return resolvedUrl;
if (!alreadyNormalized)
includePath = normalize(includePath); // path or absolute url
if (isAbsolute(includePath))
return includePath;
if (!alreadyNormalized)
originPath = normalize(originPath);
return (originPath = originPath.replace(/(?:\/|^)[^/]+$/, "")).length ? normalize(originPath + "/" + includePath) : includePath;
};
+7
View File
@@ -0,0 +1,7 @@
"use strict";
var patterns = exports;
patterns.numberRe = /^(?![eE])[0-9]*(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?$/;
patterns.typeRefRe = /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*$/;
patterns.reservedRe = /^(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$/;
+32
View File
@@ -0,0 +1,32 @@
export = pool;
/**
* An allocator as used by {@link util.pool}.
* @typedef PoolAllocator
* @type {function}
* @param {number} size Buffer size
* @returns {Uint8Array} Buffer
*/
type PoolAllocator = (size: number) => Uint8Array;
/**
* A slicer as used by {@link util.pool}.
* @typedef PoolSlicer
* @type {function}
* @param {number} start Start offset
* @param {number} end End offset
* @returns {Uint8Array} Buffer slice
* @this {Uint8Array}
*/
type PoolSlicer = (this: Uint8Array, start: number, end: number) => Uint8Array;
/**
* A general purpose buffer pool.
* @memberof util
* @function
* @param {PoolAllocator} alloc Allocator
* @param {PoolSlicer} slice Slicer
* @param {number} [size=8192] Slab size
* @returns {PoolAllocator} Pooled allocator
*/
declare function pool(alloc: PoolAllocator, slice: PoolSlicer, size?: number): PoolAllocator;

Some files were not shown because too many files have changed in this diff Show More