UNPKG

voluptasmollitia

Version:
110 lines (106 loc) 3.46 kB
/** * @license * Copyright 2017 Google LLC * * 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. */ const LONG_TYPE = 'type.googleapis.com/google.protobuf.Int64Value'; const UNSIGNED_LONG_TYPE = 'type.googleapis.com/google.protobuf.UInt64Value'; function mapValues( // { [k: string]: unknown } is no longer a wildcard assignment target after typescript 3.5 // eslint-disable-next-line @typescript-eslint/no-explicit-any o: { [key: string]: any }, f: (arg0: unknown) => unknown ): object { const result: { [key: string]: unknown } = {}; for (const key in o) { if (o.hasOwnProperty(key)) { result[key] = f(o[key]); } } return result; } /** * Takes data and encodes it in a JSON-friendly way, such that types such as * Date are preserved. * @internal * @param data - Data to encode. */ export function encode(data: unknown): unknown { if (data == null) { return null; } if (data instanceof Number) { data = data.valueOf(); } if (typeof data === 'number' && isFinite(data)) { // Any number in JS is safe to put directly in JSON and parse as a double // without any loss of precision. return data; } if (data === true || data === false) { return data; } if (Object.prototype.toString.call(data) === '[object String]') { return data; } if (data instanceof Date) { return data.toISOString(); } if (Array.isArray(data)) { return data.map(x => encode(x)); } if (typeof data === 'function' || typeof data === 'object') { return mapValues(data!, x => encode(x)); } // If we got this far, the data is not encodable. throw new Error('Data cannot be encoded in JSON: ' + data); } /** * Takes data that's been encoded in a JSON-friendly form and returns a form * with richer datatypes, such as Dates, etc. * @internal * @param json - JSON to convert. */ export function decode(json: unknown): unknown { if (json == null) { return json; } if ((json as { [key: string]: unknown })['@type']) { switch ((json as { [key: string]: unknown })['@type']) { case LONG_TYPE: // Fall through and handle this the same as unsigned. case UNSIGNED_LONG_TYPE: { // Technically, this could work return a valid number for malformed // data if there was a number followed by garbage. But it's just not // worth all the extra code to detect that case. const value = Number((json as { [key: string]: unknown })['value']); if (isNaN(value)) { throw new Error('Data cannot be decoded from JSON: ' + json); } return value; } default: { throw new Error('Data cannot be decoded from JSON: ' + json); } } } if (Array.isArray(json)) { return json.map(x => decode(x)); } if (typeof json === 'function' || typeof json === 'object') { return mapValues(json!, x => decode(x)); } // Anything else is safe to return. return json; }