@esri/arcgis-rest-feature-service
Version:
Feature layer query and edit helpers for @esri/arcgis-rest-js
1,452 lines (1,371 loc) • 94 kB
JavaScript
/* @preserve
* @esri/arcgis-rest-feature-service - v4.10.2 - Apache-2.0
* Copyright (c) 2017-2026 Esri, Inc.
* Tue Apr 07 2026 14:52:39 GMT+0000 (Coordinated Universal Time)
*/
import { cleanUrl, appendCustomParams, request, ArcGISRequestError, ArcGISAuthError } from '@esri/arcgis-rest-request';
import { determineOwner, getPortalUrl } from '@esri/arcgis-rest-portal';
/* Copyright (c) 2017 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Add features request. See the [REST Documentation](https://developers.arcgis.com/rest/services-reference/add-features.htm) for more information.
*
* ```js
* import { addFeatures } from '@esri/arcgis-rest-feature-service';
* //
* addFeatures({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0",
* features: [{
* geometry: { x: -120, y: 45, spatialReference: { wkid: 4326 } },
* attributes: { status: "alive" }
* }]
* })
* .then(response)
* ```
*
* @param requestOptions - Options for the request.
* @returns A Promise that will resolve with the addFeatures response.
*/
function addFeatures(requestOptions) {
const url = `${cleanUrl(requestOptions.url)}/addFeatures`;
// edit operations are POST only
const options = appendCustomParams(requestOptions, ["features", "gdbVersion", "returnEditMoment", "rollbackOnFailure"], { params: Object.assign({}, requestOptions.params) });
return request(url, options);
}
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Attach a file to a feature by id. See [Add Attachment](https://developers.arcgis.com/rest/services-reference/add-attachment.htm) for more information.
*
* ```js
* import { addAttachment } from '@esri/arcgis-rest-feature-service';
* //
* addAttachment({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0",
* featureId: 8484,
* attachment: myFileInput.files[0]
* })
* .then(response)
* ```
*
* @param requestOptions - Options for the request.
* @returns A Promise that will resolve with the `addAttachment()` response.
*/
function addAttachment(requestOptions) {
const options = Object.assign({ params: {} }, requestOptions);
// `attachment` --> params: {}
options.params.attachment = requestOptions.attachment;
return request(`${cleanUrl(options.url)}/${options.featureId}/addAttachment`, options);
}
/* Copyright (c) 2018-2019 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Add layer(s) and/or table(s) to a hosted feature service. See the [REST Documentation](https://developers.arcgis.com/rest/services-reference/add-to-definition-feature-service-.htm) for more information.
*
* ```js
* import { addToServiceDefinition } from '@esri/arcgis-rest-feature-service';
* //
* addToServiceDefinition(serviceurl, {
* authentication: ArcGISIdentityManager,
* layers: [],
* tables: []
* });
* ```
*
* @param url - URL of feature service
* @param requestOptions - Options for the request
* @returns A Promise that resolves with service layer and/or table details once the definition
* has been updated
*/
function addToServiceDefinition(url, requestOptions) {
const adminUrl = `${cleanUrl(url).replace(`/rest/services`, `/rest/admin/services`)}/addToDefinition`;
requestOptions.params = Object.assign({ addToDefinition: {} }, requestOptions.params);
if (requestOptions.layers && requestOptions.layers.length > 0) {
requestOptions.params.addToDefinition.layers = requestOptions.layers;
}
if (requestOptions.tables && requestOptions.tables.length > 0) {
requestOptions.params.addToDefinition.tables = requestOptions.tables;
}
return request(adminUrl, requestOptions);
}
/* Copyright (c) 2017-2019 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Apply edits request. See the [REST Documentation](https://developers.arcgis.com/rest/services-reference/apply-edits-feature-service-layer-.htm) for more information.
*
* ```js
* import { applyEdits } from '@esri/arcgis-rest-feature-service';
* //
* applyEdits({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0",
* adds: [{
* geometry: { x: -120, y: 45, spatialReference: { wkid: 4326 } },
* attributes: { status: "alive" }
* }],
* updates: [{
* attributes: { OBJECTID: 1004, status: "alive" }
* }],
* deletes: [862, 1548]
* })
* .then(response)
* ```
*
* @param requestOptions - Options for the request.
* @returns A Promise that will resolve with the applyEdits response.
*/
function applyEdits(requestOptions) {
const url = `${cleanUrl(requestOptions.url)}/applyEdits`;
// edit operations are POST only
const options = appendCustomParams(requestOptions, [
"adds",
"updates",
"deletes",
"useGlobalIds",
"attachments",
"gdbVersion",
"returnEditMoment",
"rollbackOnFailure",
"trueCurveClient"
], { params: Object.assign({}, requestOptions.params) });
return request(url, options);
}
/* Copyright (c) 2018-2019 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Create a new [hosted feature service](https://developers.arcgis.com/rest/users-groups-and-items/create-service.htm). After the service has been created, call {@linkcode addToServiceDefinition} if you'd like to update it's schema.
*
* ```js
* import {
* createFeatureService,
* addToServiceDefinition
* } from '@esri/arcgis-rest-feature-service';
* //
* createFeatureService({
* authentication: ArcGISIdentityManager,
* item: {
* "name": "NewEmptyService",
* "capabilities": "Create,Delete,Query,Update,Editing"
* }
* });
* ```
*
* @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
* @returns A Promise that resolves with service details once the service has been created
*/
function createFeatureService(requestOptions) {
return determineOwner(requestOptions).then((owner) => {
const options = Object.assign(Object.assign({}, requestOptions), { rawResponse: false });
const baseUrl = `${getPortalUrl(requestOptions)}/content/users/${owner}`;
const folder = !options.folderId || options.folderId === "/"
? ""
: "/" + options.folderId;
const url = `${baseUrl}${folder}/createService`;
// Create the service
options.params = Object.assign({ createParameters: options.item, outputType: "featureService" }, options.params);
return request(url, options);
});
}
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Layer (Feature Service) request. See the [REST Documentation](https://developers.arcgis.com/rest/services-reference/layer-feature-service-.htm) for more information.
*
* ```js
* import { getLayer } from '@esri/arcgis-rest-feature-service';
* //
* getLayer({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0"
* })
* .then(response) // { name: "311", id: 0, ... }
* ```
*
* @param options - Options for the request.
* @returns A Promise that will resolve with the addFeatures response.
*/
function getLayer(options) {
return request(cleanUrl(options.url), options);
}
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* ```js
* import { queryFeatures, decodeValues } from '@esri/arcgis-rest-feature-service';
* //
* const url = `https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0`
* queryFeatures({ url })
* .then(queryResponse => {
* decodeValues({
* url,
* queryResponse
* })
* .then(decodedResponse)
* })
* ```
* Replaces the raw coded domain values in a query response with descriptions (for legibility).
*
* @param requestOptions - Options for the request.
* @returns A Promise that will resolve with the addFeatures response.
*/
function decodeValues(requestOptions) {
let prms;
if (requestOptions.fields) {
prms = Promise.resolve(requestOptions.fields);
}
else {
prms = getLayer({ url: requestOptions.url }).then((metadata) => {
return metadata.fields;
});
}
return prms.then((fields) => {
// extract coded value domains
const domains = extractCodedValueDomains(fields);
if (Object.keys(domains).length < 1) {
// no values to decode
return requestOptions.queryResponse;
}
// don't mutate original features
const decodedFeatures = requestOptions.queryResponse.features.map((feature) => {
const decodedAttributes = {};
for (const key in feature.attributes) {
if (!Object.prototype.hasOwnProperty.call(feature.attributes, key))
continue;
const value = feature.attributes[key];
const domain = domains[key];
decodedAttributes[key] =
value !== null && domain ? decodeValue(value, domain) : value;
}
// merge decoded attributes into the feature
return Object.assign(Object.assign({}, feature), { attributes: decodedAttributes });
});
// merge decoded features into the response
return Object.assign(Object.assign({}, requestOptions.queryResponse), { features: decodedFeatures });
});
}
function extractCodedValueDomains(fields) {
return fields.reduce((domains, field) => {
const domain = field.domain;
if (domain && domain.type === "codedValue") {
domains[field.name] = domain;
}
return domains;
}, {});
}
// TODO: add type for domain?
function decodeValue(value, domain) {
const codedValue = domain.codedValues.find((d) => {
return value === d.code;
});
return codedValue ? codedValue.name : value;
}
/* Copyright (c) 2017 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Delete features request. See the [REST Documentation](https://developers.arcgis.com/rest/services-reference/delete-features.htm) for more information.
*
* ```js
* import { deleteFeatures } from '@esri/arcgis-rest-feature-service';
* //
* deleteFeatures({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0",
* objectIds: [1,2,3]
* });
* ```
*
* @param requestOptions - Options for the request.
* @returns A Promise that will resolve with the deleteFeatures response.
*/
function deleteFeatures(requestOptions) {
const url = `${cleanUrl(requestOptions.url)}/deleteFeatures`;
// edit operations POST only
const options = appendCustomParams(requestOptions, [
"where",
"objectIds",
"gdbVersion",
"returnEditMoment",
"rollbackOnFailure"
], { params: Object.assign({}, requestOptions.params) });
return request(url, options);
}
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Delete existing attachment files of a feature by id. See [Delete Attachments](https://developers.arcgis.com/rest/services-reference/delete-attachments.htm) for more information.
*
* ```js
* import { deleteAttachments } from '@esri/arcgis-rest-feature-service';
* //
* deleteAttachments({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0",
* featureId: 8484,
* attachmentIds: [306]
* });
* ```
*
* @param requestOptions - Options for the request.
* @returns A Promise that will resolve with the `deleteAttachments()` response.
*/
function deleteAttachments(requestOptions) {
const options = Object.assign({ params: {} }, requestOptions);
// `attachmentIds` --> params: {}
options.params.attachmentIds = requestOptions.attachmentIds;
return request(`${cleanUrl(options.url)}/${options.featureId}/deleteAttachments`, options);
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
/* Copyright (c) 2017-2019 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
const serviceRegex = new RegExp(/.+(?:map|feature|image)server/i);
/**
* Return the service url. If not matched, returns what was passed in
*/
function parseServiceUrl(url) {
const match = url.match(serviceRegex);
if (match) {
return match[0];
}
else {
return stripQueryString(url);
}
}
function stripQueryString(url) {
const stripped = url.split("?")[0];
return cleanUrl(stripped);
}
/**
* * Fetches all the layers and tables associated with a given layer service.
* Wrapper for https://developers.arcgis.com/rest/services-reference/all-layers-and-tables.htm
*
* ```js
* import { getAllLayersAndTables } from '@esri/arcgis-rest-feature-service';
* getAllLayersAndTables({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0"
* })
* .then(response) // { layers: [...], tables: [...] }
* ```
*
* @param options - Request options, including the url for the layer service
* @returns A Promise that will resolve with the layers and tables for the given service
*/
// TODO: should we expand this to support other valid params of the endpoint?
function getAllLayersAndTables(options) {
const { url } = options, requestOptions = __rest(options, ["url"]);
const layersUrl = `${parseServiceUrl(url)}/layers`;
return request(layersUrl, requestOptions);
}
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Request `attachmentInfos` of a feature by id. See [Attachment Infos](https://developers.arcgis.com/rest/services-reference/attachment-infos-feature-service-.htm) for more information.
*
* ```js
* import { getAttachments } from '@esri/arcgis-rest-feature-service';
* //
* getAttachments({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0",
* featureId: 8484
* });
* ```
*
* @param requestOptions - Options for the request.
* @returns A Promise that will resolve with the `getAttachments()` response.
*/
function getAttachments(requestOptions) {
const options = Object.assign({ httpMethod: "GET" }, requestOptions);
// pass through
return request(`${cleanUrl(options.url)}/${options.featureId}/attachments`, options);
}
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Feature Service request. See the [REST Documentation](https://developers.arcgis.com/rest/services-reference/feature-service.htm) for more information.
*
* ```js
* import { getService } from '@esri/arcgis-rest-feature-service';
* //
* getService({
* url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer"
* })
* .then(response) // { name: "311", id: 0, ... }
* ```
*
* @param options - Options for the request.
* @returns A Promise that will resolve with the getService response.
*/
function getService(options) {
return request(cleanUrl(options.url), options);
}
/* Copyright (c) 2018-2020 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Given a Feature Service URL, fetch the service admin information.
*
* The response from this call includes all the detailed information
* for each layer/table in the service as well as some admin properties
*
* @param {string} serviceUrl
* @param {ArcGISIdentityManager} session
* @return {*} {Promise<IServiceInfo>}
*/
function getServiceAdminInfo(serviceUrl, session) {
const serviceAdminUrl = serviceUrl.replace("/rest/services", "/rest/admin/services");
return request(serviceAdminUrl, {
authentication: session,
params: {
f: "json"
}
});
}
/* Copyright (c) 2018-2020 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
/**
* Return the sources response for a view service item
*
* @param {string} viewServiceUrl
* @param {ArcGISIdentityManager} session
* @return {*} {Promise<Record<string, unknown>>}
*/
function getViewSources(viewServiceUrl, session) {
return request(`${viewServiceUrl}/sources`, { authentication: session });
}
/* istanbul ignore file --@preserve */
// generated from https://github.com/Esri/arcgis-pbf/blob/main/proto/FeatureCollection/FeatureCollection.proto
// code generated by pbf v4.0.1
function readFeatureCollectionPBuffer(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferField, { version: "", queryResult: undefined }, end);
}
function _readFeatureCollectionPBufferField(tag, obj, pbf) {
if (tag === 1)
obj.version = pbf.readString();
else if (tag === 2)
obj.queryResult = readFeatureCollectionPBufferQueryResult(pbf, pbf.readVarint() + pbf.pos);
}
const FeatureCollectionPBufferFieldType = {
esriFieldTypeSmallInteger: 0,
esriFieldTypeInteger: 1,
esriFieldTypeSingle: 2,
esriFieldTypeDouble: 3,
esriFieldTypeString: 4,
esriFieldTypeDate: 5,
esriFieldTypeOID: 6,
esriFieldTypeGeometry: 7,
esriFieldTypeBlob: 8,
esriFieldTypeRaster: 9,
esriFieldTypeGUID: 10,
esriFieldTypeGlobalID: 11,
esriFieldTypeXML: 12,
esriFieldTypeBigInteger: 13,
esriFieldTypeDateOnly: 14,
esriFieldTypeTimeOnly: 15,
esriFieldTypeTimestampOffset: 16
};
const FeatureCollectionPBufferSQLType = {
sqlTypeBigInt: 0,
sqlTypeBinary: 1,
sqlTypeBit: 2,
sqlTypeChar: 3,
sqlTypeDate: 4,
sqlTypeDecimal: 5,
sqlTypeDouble: 6,
sqlTypeFloat: 7,
sqlTypeGeometry: 8,
sqlTypeGUID: 9,
sqlTypeInteger: 10,
sqlTypeLongNVarchar: 11,
sqlTypeLongVarbinary: 12,
sqlTypeLongVarchar: 13,
sqlTypeNChar: 14,
sqlTypeNVarchar: 15,
sqlTypeOther: 16,
sqlTypeReal: 17,
sqlTypeSmallInt: 18,
sqlTypeSqlXml: 19,
sqlTypeTime: 20,
sqlTypeTimestamp: 21,
sqlTypeTimestamp2: 22,
sqlTypeTinyInt: 23,
sqlTypeVarbinary: 24,
sqlTypeVarchar: 25,
sqlTypeTimestampWithTimezone: 26
};
function readFeatureCollectionPBufferSpatialReference(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferSpatialReferenceField, { wkid: 0, latestWkid: 0, vcsWkid: 0, latestVcsWkid: 0, wkt: "", wkt2: "" }, end);
}
function _readFeatureCollectionPBufferSpatialReferenceField(tag, obj, pbf) {
if (tag === 1)
obj.wkid = pbf.readVarint();
else if (tag === 2)
obj.latestWkid = pbf.readVarint();
else if (tag === 3)
obj.vcsWkid = pbf.readVarint();
else if (tag === 4)
obj.latestVcsWkid = pbf.readVarint();
else if (tag === 5)
obj.wkt = pbf.readString();
else if (tag === 6)
obj.wkt2 = pbf.readString();
}
function readFeatureCollectionPBufferField(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferFieldField, {
name: "",
fieldType: 0,
alias: "",
sqlType: 0,
domain: "",
defaultValue: ""
}, end);
}
function _readFeatureCollectionPBufferFieldField(tag, obj, pbf) {
if (tag === 1)
obj.name = pbf.readString();
else if (tag === 2)
obj.fieldType = pbf.readVarint();
else if (tag === 3)
obj.alias = pbf.readString();
else if (tag === 4)
obj.sqlType = pbf.readVarint();
else if (tag === 5)
obj.domain = pbf.readString();
else if (tag === 6)
obj.defaultValue = pbf.readString();
}
function readFeatureCollectionPBufferGeometryField(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferGeometryFieldField, { field: undefined, geometryType: 0 }, end);
}
function _readFeatureCollectionPBufferGeometryFieldField(tag, obj, pbf) {
if (tag === 1)
obj.field = readFeatureCollectionPBufferField(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 2)
obj.geometryType = pbf.readVarint();
}
function readFeatureCollectionPBufferEnvelope(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferEnvelopeField, { XMin: 0, YMin: 0, XMax: 0, YMax: 0, SpatialReference: undefined }, end);
}
function _readFeatureCollectionPBufferEnvelopeField(tag, obj, pbf) {
if (tag === 1)
obj.XMin = pbf.readDouble();
else if (tag === 2)
obj.YMin = pbf.readDouble();
else if (tag === 3)
obj.XMax = pbf.readDouble();
else if (tag === 4)
obj.YMax = pbf.readDouble();
else if (tag === 5)
obj.SpatialReference = readFeatureCollectionPBufferSpatialReference(pbf, pbf.readVarint() + pbf.pos);
}
function readFeatureCollectionPBufferValue(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferValueField, {
string_value: "",
value_type: undefined,
float_value: 0,
double_value: 0,
sint_value: 0,
uint_value: 0,
int64_value: 0,
uint64_value: 0,
sint64_value: 0,
bool_value: false,
null_value: false,
index: 0
}, end);
}
function _readFeatureCollectionPBufferValueField(tag, obj, pbf) {
if (tag === 1) {
obj.string_value = pbf.readString();
obj.value_type = "string_value";
}
else if (tag === 2) {
obj.float_value = pbf.readFloat();
obj.value_type = "float_value";
}
else if (tag === 3) {
obj.double_value = pbf.readDouble();
obj.value_type = "double_value";
}
else if (tag === 4) {
obj.sint_value = pbf.readSVarint();
obj.value_type = "sint_value";
}
else if (tag === 5) {
obj.uint_value = pbf.readVarint();
obj.value_type = "uint_value";
}
else if (tag === 6) {
obj.int64_value = pbf.readVarint(true);
obj.value_type = "int64_value";
}
else if (tag === 7) {
obj.uint64_value = pbf.readVarint();
obj.value_type = "uint64_value";
}
else if (tag === 8) {
obj.sint64_value = pbf.readSVarint();
obj.value_type = "sint64_value";
}
else if (tag === 9) {
obj.bool_value = pbf.readBoolean();
obj.value_type = "bool_value";
}
else if (tag === 10) {
obj.null_value = pbf.readBoolean();
obj.value_type = "null_value";
}
else if (tag === 11)
obj.index = pbf.readVarint();
}
function readFeatureCollectionPBufferGeometry(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferGeometryField, { geometryType: 0, lengths: [], coords: [], ids: [] }, end);
}
function _readFeatureCollectionPBufferGeometryField(tag, obj, pbf) {
if (tag === 1)
obj.geometryType = pbf.readVarint();
else if (tag === 2)
pbf.readPackedVarint(obj.lengths);
else if (tag === 3)
pbf.readPackedSVarint(obj.coords);
else if (tag === 4)
pbf.readPackedSVarint(obj.ids);
}
function readFeatureCollectionPBufferCurveGeometry(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferCurveGeometryField, { geometryType: 0, parts: [], segmentSets: [], coords: [] }, end);
}
function _readFeatureCollectionPBufferCurveGeometryField(tag, obj, pbf) {
if (tag === 1)
obj.geometryType = pbf.readVarint();
else if (tag === 2)
pbf.readPackedVarint(obj.parts);
else if (tag === 3)
obj.segmentSets.push(readFeatureCollectionPBufferSegmentSet(pbf, pbf.readVarint() + pbf.pos));
else if (tag === 4)
pbf.readPackedSVarint(obj.coords);
}
function readFeatureCollectionPBufferSegmentSet(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferSegmentSetField, { type: 0, count: 0, parameters: [] }, end);
}
function _readFeatureCollectionPBufferSegmentSetField(tag, obj, pbf) {
if (tag === 1)
obj.type = pbf.readVarint();
else if (tag === 2)
obj.count = pbf.readVarint();
else if (tag === 3)
pbf.readPackedDouble(obj.parameters);
}
function readFeatureCollectionPBufferesriShapeBuffer(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferesriShapeBufferField, { bytes: undefined }, end);
}
function _readFeatureCollectionPBufferesriShapeBufferField(tag, obj, pbf) {
if (tag === 1)
obj.bytes = pbf.readBytes();
}
function readFeatureCollectionPBufferFeature(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferFeatureField, {
attributes: [],
geometry: undefined,
compressed_geometry: undefined,
shapeBuffer: undefined,
curveGeometry: undefined,
centroid: undefined,
aggregateGeometries: [],
envelope: undefined
}, end);
}
function _readFeatureCollectionPBufferFeatureField(tag, obj, pbf) {
if (tag === 1)
obj.attributes.push(readFeatureCollectionPBufferValue(pbf, pbf.readVarint() + pbf.pos));
else if (tag === 2) {
obj.geometry = readFeatureCollectionPBufferGeometry(pbf, pbf.readVarint() + pbf.pos);
obj.compressed_geometry = "geometry";
}
else if (tag === 3) {
obj.shapeBuffer = readFeatureCollectionPBufferesriShapeBuffer(pbf, pbf.readVarint() + pbf.pos);
obj.compressed_geometry = "shapeBuffer";
}
else if (tag === 7) {
obj.curveGeometry = readFeatureCollectionPBufferCurveGeometry(pbf, pbf.readVarint() + pbf.pos);
obj.compressed_geometry = "curveGeometry";
}
else if (tag === 4)
obj.centroid = readFeatureCollectionPBufferGeometry(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 5)
obj.aggregateGeometries.push(readFeatureCollectionPBufferGeometry(pbf, pbf.readVarint() + pbf.pos));
else if (tag === 6)
obj.envelope = readFeatureCollectionPBufferEnvelope(pbf, pbf.readVarint() + pbf.pos);
}
function readFeatureCollectionPBufferUniqueIdField(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferUniqueIdFieldField, { name: "", isSystemMaintained: false }, end);
}
function _readFeatureCollectionPBufferUniqueIdFieldField(tag, obj, pbf) {
if (tag === 1)
obj.name = pbf.readString();
else if (tag === 2)
obj.isSystemMaintained = pbf.readBoolean();
}
function readFeatureCollectionPBufferGeometryProperties(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferGeometryPropertiesField, { shapeAreaFieldName: "", shapeLengthFieldName: "", units: "" }, end);
}
function _readFeatureCollectionPBufferGeometryPropertiesField(tag, obj, pbf) {
if (tag === 1)
obj.shapeAreaFieldName = pbf.readString();
else if (tag === 2)
obj.shapeLengthFieldName = pbf.readString();
else if (tag === 3)
obj.units = pbf.readString();
}
function readFeatureCollectionPBufferServerGens(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferServerGensField, { minServerGen: 0, serverGen: 0 }, end);
}
function _readFeatureCollectionPBufferServerGensField(tag, obj, pbf) {
if (tag === 1)
obj.minServerGen = pbf.readVarint();
else if (tag === 2)
obj.serverGen = pbf.readVarint();
}
function readFeatureCollectionPBufferScale(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferScaleField, { xScale: 0, yScale: 0, mScale: 0, zScale: 0 }, end);
}
function _readFeatureCollectionPBufferScaleField(tag, obj, pbf) {
if (tag === 1)
obj.xScale = pbf.readDouble();
else if (tag === 2)
obj.yScale = pbf.readDouble();
else if (tag === 3)
obj.mScale = pbf.readDouble();
else if (tag === 4)
obj.zScale = pbf.readDouble();
}
function readFeatureCollectionPBufferTranslate(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferTranslateField, { xTranslate: 0, yTranslate: 0, mTranslate: 0, zTranslate: 0 }, end);
}
function _readFeatureCollectionPBufferTranslateField(tag, obj, pbf) {
if (tag === 1)
obj.xTranslate = pbf.readDouble();
else if (tag === 2)
obj.yTranslate = pbf.readDouble();
else if (tag === 3)
obj.mTranslate = pbf.readDouble();
else if (tag === 4)
obj.zTranslate = pbf.readDouble();
}
function readFeatureCollectionPBufferTransform(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferTransformField, { quantizeOriginPostion: 0, scale: undefined, translate: undefined }, end);
}
function _readFeatureCollectionPBufferTransformField(tag, obj, pbf) {
if (tag === 1)
obj.quantizeOriginPostion = pbf.readVarint();
else if (tag === 2)
obj.scale = readFeatureCollectionPBufferScale(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 3)
obj.translate = readFeatureCollectionPBufferTranslate(pbf, pbf.readVarint() + pbf.pos);
}
function readFeatureCollectionPBufferFeatureResult(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferFeatureResultField, {
objectIdFieldName: "",
uniqueIdField: undefined,
globalIdFieldName: "",
geohashFieldName: "",
geometryProperties: undefined,
serverGens: undefined,
geometryType: 0,
spatialReference: undefined,
exceededTransferLimit: false,
hasZ: false,
hasM: false,
transform: undefined,
fields: [],
values: [],
features: [],
geometryFields: []
}, end);
}
function _readFeatureCollectionPBufferFeatureResultField(tag, obj, pbf) {
if (tag === 1)
obj.objectIdFieldName = pbf.readString();
else if (tag === 2)
obj.uniqueIdField = readFeatureCollectionPBufferUniqueIdField(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 3)
obj.globalIdFieldName = pbf.readString();
else if (tag === 4)
obj.geohashFieldName = pbf.readString();
else if (tag === 5)
obj.geometryProperties = readFeatureCollectionPBufferGeometryProperties(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 6)
obj.serverGens = readFeatureCollectionPBufferServerGens(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 7)
obj.geometryType = pbf.readVarint();
else if (tag === 8)
obj.spatialReference = readFeatureCollectionPBufferSpatialReference(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 9)
obj.exceededTransferLimit = pbf.readBoolean();
else if (tag === 10)
obj.hasZ = pbf.readBoolean();
else if (tag === 11)
obj.hasM = pbf.readBoolean();
else if (tag === 12)
obj.transform = readFeatureCollectionPBufferTransform(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 13)
obj.fields.push(readFeatureCollectionPBufferField(pbf, pbf.readVarint() + pbf.pos));
else if (tag === 14)
obj.values.push(readFeatureCollectionPBufferValue(pbf, pbf.readVarint() + pbf.pos));
else if (tag === 15)
obj.features.push(readFeatureCollectionPBufferFeature(pbf, pbf.readVarint() + pbf.pos));
else if (tag === 16)
obj.geometryFields.push(readFeatureCollectionPBufferGeometryField(pbf, pbf.readVarint() + pbf.pos));
}
function readFeatureCollectionPBufferCountResult(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferCountResultField, { count: 0 }, end);
}
function _readFeatureCollectionPBufferCountResultField(tag, obj, pbf) {
if (tag === 1)
obj.count = pbf.readVarint();
}
function readFeatureCollectionPBufferObjectIdsResult(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferObjectIdsResultField, { objectIdFieldName: "", serverGens: undefined, objectIds: [] }, end);
}
function _readFeatureCollectionPBufferObjectIdsResultField(tag, obj, pbf) {
if (tag === 1)
obj.objectIdFieldName = pbf.readString();
else if (tag === 2)
obj.serverGens = readFeatureCollectionPBufferServerGens(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 3)
pbf.readPackedVarint(obj.objectIds);
}
function readFeatureCollectionPBufferExtentCountResult(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferExtentCountResultField, { extent: undefined, count: 0 }, end);
}
function _readFeatureCollectionPBufferExtentCountResultField(tag, obj, pbf) {
if (tag === 1)
obj.extent = readFeatureCollectionPBufferEnvelope(pbf, pbf.readVarint() + pbf.pos);
else if (tag === 2)
obj.count = pbf.readVarint();
}
function readFeatureCollectionPBufferQueryResult(pbf, end) {
return pbf.readFields(_readFeatureCollectionPBufferQueryResultField, {
featureResult: undefined,
Results: undefined,
countResult: undefined,
idsResult: undefined,
extentCountResult: undefined
}, end);
}
function _readFeatureCollectionPBufferQueryResultField(tag, obj, pbf) {
if (tag === 1) {
obj.featureResult = readFeatureCollectionPBufferFeatureResult(pbf, pbf.readVarint() + pbf.pos);
obj.Results = "featureResult";
}
else if (tag === 2) {
obj.countResult = readFeatureCollectionPBufferCountResult(pbf, pbf.readVarint() + pbf.pos);
obj.Results = "countResult";
}
else if (tag === 3) {
obj.idsResult = readFeatureCollectionPBufferObjectIdsResult(pbf, pbf.readVarint() + pbf.pos);
obj.Results = "idsResult";
}
else if (tag === 4) {
obj.extentCountResult = readFeatureCollectionPBufferExtentCountResult(pbf, pbf.readVarint() + pbf.pos);
obj.Results = "extentCountResult";
}
}
const SHIFT_LEFT_32 = (1 << 16) * (1 << 16);
const SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
// Threshold chosen based on both benchmarking and knowledge about browser string
// data structures (which currently switch structure types at 12 bytes or more)
const TEXT_DECODER_MIN_LENGTH = 12;
const utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8');
const PBF_VARINT = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
const PBF_FIXED64 = 1; // 64-bit: double, fixed64, sfixed64
const PBF_BYTES = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
const PBF_FIXED32 = 5; // 32-bit: float, fixed32, sfixed32
class Pbf {
/**
* @param {Uint8Array | ArrayBuffer} [buf]
*/
constructor(buf = new Uint8Array(16)) {
this.buf = ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf);
this.dataView = new DataView(this.buf.buffer);
this.pos = 0;
this.type = 0;
this.length = this.buf.length;
}
// === READING =================================================================
/**
* @template T
* @param {(tag: number, result: T, pbf: Pbf) => void} readField
* @param {T} result
* @param {number} [end]
*/
readFields(readField, result, end = this.length) {
while (this.pos < end) {
const val = this.readVarint(),
tag = val >> 3,
startPos = this.pos;
this.type = val & 0x7;
readField(tag, result, this);
if (this.pos === startPos) this.skip(val);
}
return result;
}
/**
* @template T
* @param {(tag: number, result: T, pbf: Pbf) => void} readField
* @param {T} result
*/
readMessage(readField, result) {
return this.readFields(readField, result, this.readVarint() + this.pos);
}
readFixed32() {
const val = this.dataView.getUint32(this.pos, true);
this.pos += 4;
return val;
}
readSFixed32() {
const val = this.dataView.getInt32(this.pos, true);
this.pos += 4;
return val;
}
// 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
readFixed64() {
const val = this.dataView.getUint32(this.pos, true) + this.dataView.getUint32(this.pos + 4, true) * SHIFT_LEFT_32;
this.pos += 8;
return val;
}
readSFixed64() {
const val = this.dataView.getUint32(this.pos, true) + this.dataView.getInt32(this.pos + 4, true) * SHIFT_LEFT_32;
this.pos += 8;
return val;
}
readFloat() {
const val = this.dataView.getFloat32(this.pos, true);
this.pos += 4;
return val;
}
readDouble() {
const val = this.dataView.getFloat64(this.pos, true);
this.pos += 8;
return val;
}
/**
* @param {boolean} [isSigned]
*/
readVarint(isSigned) {
const buf = this.buf;
let val, b;
b = buf[this.pos++]; val = b & 0x7f; if (b < 0x80) return val;
b = buf[this.pos++]; val |= (b & 0x7f) << 7; if (b < 0x80) return val;
b = buf[this.pos++]; val |= (b & 0x7f) << 14; if (b < 0x80) return val;
b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) return val;
b = buf[this.pos]; val |= (b & 0x0f) << 28;
return readVarintRemainder(val, isSigned, this);
}
readVarint64() { // for compatibility with v2.0.1
return this.readVarint(true);
}
readSVarint() {
const num = this.readVarint();
return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
}
readBoolean() {
return Boolean(this.readVarint());
}
readString() {
const end = this.readVarint() + this.pos;
const pos = this.pos;
this.pos = end;
if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {
// longer strings are fast with the built-in browser TextDecoder API
return utf8TextDecoder.decode(this.buf.subarray(pos, end));
}
// short strings are fast with our custom implementation
return readUtf8(this.buf, pos, end);
}
readBytes() {
const end = this.readVarint() + this.pos,
buffer = this.buf.subarray(this.pos, end);
this.pos = end;
return buffer;
}
// verbose for performance reasons; doesn't affect gzipped size
/**
* @param {number[]} [arr]
* @param {boolean} [isSigned]
*/
readPackedVarint(arr = [], isSigned) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readVarint(isSigned));
return arr;
}
/** @param {number[]} [arr] */
readPackedSVarint(arr = []) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readSVarint());
return arr;
}
/** @param {boolean[]} [arr] */
readPackedBoolean(arr = []) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readBoolean());
return arr;
}
/** @param {number[]} [arr] */
readPackedFloat(arr = []) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readFloat());
return arr;
}
/** @param {number[]} [arr] */
readPackedDouble(arr = []) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readDouble());
return arr;
}
/** @param {number[]} [arr] */
readPackedFixed32(arr = []) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readFixed32());
return arr;
}
/** @param {number[]} [arr] */
readPackedSFixed32(arr = []) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readSFixed32());
return arr;
}
/** @param {number[]} [arr] */
readPackedFixed64(arr = []) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readFixed64());
return arr;
}
/** @param {number[]} [arr] */
readPackedSFixed64(arr = []) {
const end = this.readPackedEnd();
while (this.pos < end) arr.push(this.readSFixed64());
return arr;
}
readPackedEnd() {
return this.type === PBF_BYTES ? this.readVarint() + this.pos : this.pos + 1;
}
/** @param {number} val */
skip(val) {
const type = val & 0x7;
if (type === PBF_VARINT) while (this.buf[this.pos++] > 0x7f) {}
else if (type === PBF_BYTES) this.pos = this.readVarint() + this.pos;
else if (type === PBF_FIXED32) this.pos += 4;
else if (type === PBF_FIXED64) this.pos += 8;
else throw new Error(`Unimplemented type: ${type}`);
}
// === WRITING =================================================================
/**
* @param {number} tag
* @param {number} type
*/
writeTag(tag, type) {
this.writeVarint((tag << 3) | type);
}
/** @param {number} min */
realloc(min) {
let length = this.length || 16;
while (length < this.pos + min) length *= 2;
if (length !== this.length) {
const buf = new Uint8Array(length);
buf.set(this.buf);
this.buf = buf;
this.dataView = new DataView(buf.buffer);
this.length = length;
}
}
finish() {
this.length = this.pos;
this.pos = 0;
return this.buf.subarray(0, this.length);
}
/** @param {number} val */
writeFixed32(val) {
this.realloc(4);
this.dataView.setInt32(this.pos, val, true);
this.pos += 4;
}
/** @param {number} val */
writeSFixed32(val) {
this.realloc(4);
this.dataView.setInt32(this.pos, val, true);
this.pos += 4;
}
/** @param {number} val */
writeFixed64(val) {
this.realloc(8);
this.dataView.setInt32(this.pos, val & -1, true);
this.dataView.setInt32(this.pos + 4, Math.floor(val * SHIFT_RIGHT_32), true);
this.pos += 8;
}
/** @param {number} val */
writeSFixed64(val) {
this.realloc(8);
this.dataView.setInt32(this.pos, val & -1, true);
this.dataView.setInt32(this.pos + 4, Math.floor(val * SHIFT_RIGHT_32), true);
this.pos += 8;
}
/** @param {number} val */
writeVarint(val) {
val = +val || 0;
if (val > 0xfffffff || val < 0) {
writeBigVarint(val, this);
return;
}
this.realloc(4);
this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
this.buf[this.pos++] = (val >>> 7) & 0x7f;
}
/** @param {number} val */
writeSVarint(val) {
this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
}
/** @param {boolean} val */
writeBoolean(val) {
this.writeVarint(+val);
}
/** @param {string} str */
writeString(str) {
str = String(str);
this.realloc(str.length * 4);
this.pos++; // reserve 1 byte for short string length
const startPos = this.pos;
// write the string directly to the buffer and see how much was written
this.pos = writeUtf8(this.buf, str, this.pos);
const len = this.pos - startPos;
if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);
// finally, write the message length in the reserved place and restore the position
this.pos = startPos - 1;
this.writeVarint(len);
this.pos += len;
}
/** @param {number} val */
writeFloat(val) {
this.realloc(4);
this.dataView.setFloat32(this.pos, val, true);
this.pos += 4;
}
/** @param {number} val */
writeDouble(val) {
this.realloc(8);
this.dataView.setFloat64(this.pos, val, true);
this.pos += 8;
}
/** @param {Uint8Array} buffer */
writeBytes(buffer) {
const len = buffer.length;
this.writeVarint(len);
this.realloc(len);
for (let i = 0; i < len; i++) this.buf[this.pos++] = buffer[i];
}
/**
* @template T
* @param {(obj: T, pbf: Pbf) => void} fn
* @param {T} obj
*/
writeRawMessage(fn, obj) {
this.pos++; // reserve 1 byte for short message length
// write the message directly to the buffer and see how much was written
const startPos = this.pos;
fn(obj, this);
const len = this.pos - startPos;
if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);
// finally, write the message length in the reserved place and restore the position
this.pos = startPos - 1;
this.writeVarint(len);
this.pos += len;
}
/**
* @template T
* @param {number} tag
* @param {(obj: T, pbf: Pbf) => void} fn
* @param {T} obj
*/
writeMessage(tag, fn, obj) {
this.writeTag(tag, PBF_BYTES);
this.writeRawMessage(fn, obj);
}
/**
* @param {number} tag
* @param {number[]} arr
*/
writePackedVarint(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedVarint, arr);
}
/**
* @param {number} tag
* @param {number[]} arr
*/
writePackedSVarint(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedSVarint, arr);
}
/**
* @param {number} tag
* @param {boolean[]} arr
*/
writePackedBoolean(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedBoolean, arr);
}
/**
* @param {number} tag
* @param {number[]} arr
*/
writePackedFloat(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedFloat, arr);
}
/**
* @param {number} tag
* @param {number[]} arr
*/
writePackedDouble(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedDouble, arr);
}
/**
* @param {number} tag
* @param {number[]} arr
*/
writePackedFixed32(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedFixed32, arr);
}
/**
* @param {number} tag
* @param {number[]} arr
*/
writePackedSFixed32(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedSFixed32, arr);
}
/**
* @param {number} tag
* @param {number[]} arr
*/
writePackedFixed64(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedFixed64, arr);
}
/**
* @param {number} tag
* @param {number[]} arr
*/
writePackedSFixed64(tag, arr) {
if (arr.length) this.writeMessage(tag, writePackedSFixed64, arr);
}
/**
* @param {number} tag
* @param {Uint8Array} buffer
*/
writeBytesField(tag, buffer) {
this.writeTag(tag, PBF_BYTES);
this.writeBytes(buffer);
}
/**
* @param {number} tag
* @param {number} val
*/
writeFixed32Field(tag, val) {
this.writeTag(tag, PBF_FIXED32);
this.writeFixed32(val);
}
/**
* @param {number} tag
* @param {number} val
*/
writeSFixed32Field(tag, val) {
this.writeTag(tag, PBF_FIXED32);
this.writeSFixed32(val);
}
/**
* @param {number} tag
* @param {number} val
*/
writeFixed64Field(tag, val) {
this.writeTag(tag, PBF_FIXED64);
this.writeFixed64(val);
}
/**
* @param {number} tag
* @param {number} val
*/
writeSFixed64Field(tag, val) {
this.writeTag(tag, PBF_FIXED64);
this.writeSFixed64(val);
}
/**
* @param {number} tag
* @param {number} val
*/
writeVarintField(tag, val) {
this.writeTag(tag, PBF_VARINT);
this.writeVarint(val);
}
/**
* @param {number} tag
* @param {number} val
*/
writeSVarintField(tag, val) {
this.writeTag(tag, PBF_VARINT);
this.writeSVarint(val);
}
/**
* @param {number} tag
* @param {string} str
*/
writeStringField(tag, str) {
this.writeTag(tag, PBF_BYTES);
this.writeString(str);
}
/**
* @param {number} tag
* @param {number} val
*/
writeFloatField(tag, val) {
this.writeTag(tag, PBF_FIXED32);
this.writeFloat(val);
}
/**
* @param {number} tag
* @param {number} val
*/
writeDoubleField(tag, val) {
this.writeTag(tag, PBF_FIXED64);
this.writeDouble(val);
}
/**
* @param {number} tag
* @param {boolean} val
*/
writeBooleanField(tag, val) {
this.writeVarintField(tag, +val);
}
}
/**
* @param {number} l
* @param {boolean | undefined} s
* @param {Pbf} p
*/
function readVarintRemainder(l, s, p) {
const buf = p.buf;
let h, b;
b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) return toNum(l, h, s);
b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) return toNum(l, h, s);
b = buf