@aptos-labs/ts-sdk
Version:
Aptos TypeScript SDK
747 lines (745 loc) • 28.6 kB
JavaScript
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { MAX_U128_BIG_INT, MAX_U16_NUMBER, MAX_U32_NUMBER, MAX_U64_BIG_INT, MAX_U8_NUMBER, MAX_U256_BIG_INT, MIN_I8_NUMBER, MAX_I8_NUMBER, MIN_I16_NUMBER, MAX_I16_NUMBER, MIN_I32_NUMBER, MAX_I32_NUMBER, MIN_I64_BIG_INT, MAX_I64_BIG_INT, MIN_I128_BIG_INT, MAX_I128_BIG_INT, MIN_I256_BIG_INT, MAX_I256_BIG_INT, } from "./consts.js";
import { Hex } from "../core/hex.js";
import { TEXT_ENCODER } from "../utils/const.js";
/**
* This class serves as a base class for all serializable types. It facilitates
* composable serialization of complex types and enables the serialization of
* instances to their BCS (Binary Canonical Serialization) representation.
* @group Implementation
* @category BCS
*/
export class Serializable {
/**
* Serializes a `Serializable` value to its BCS representation.
* This function is the TypeScript SDK equivalent of `bcs::to_bytes` in Move.
* @returns the BCS representation of the Serializable instance as a byte buffer.
* @group Implementation
* @category BCS
*/
bcsToBytes() {
const serializer = new Serializer();
this.serialize(serializer);
return serializer.toUint8Array();
}
/**
* Converts the BCS-serialized bytes of a value into a Hex instance.
* This function provides a Hex representation of the BCS-serialized data for easier handling and manipulation.
* @returns A Hex instance with the BCS-serialized bytes loaded into its underlying Uint8Array.
* @group Implementation
* @category BCS
*/
bcsToHex() {
const bcsBytes = this.bcsToBytes();
return Hex.fromHexInput(bcsBytes);
}
/**
* Returns the hex string representation of the `Serializable` value without the 0x prefix.
* @returns the hex format as a string without `0x` prefix.
*/
toStringWithoutPrefix() {
return this.bcsToHex().toStringWithoutPrefix();
}
/**
* Returns the hex string representation of the `Serializable` value with the 0x prefix.
* @returns the hex format as a string prefixed by `0x`.
*/
toString() {
return `0x${this.toStringWithoutPrefix()}`;
}
}
/**
* Serialize a Serializable value as length-prefixed bytes into a Serializer,
* with backwards compatibility for older Serializer implementations that lack
* the `serializeAsBytes` method. This is critical for cross-version compatibility
* when SDK objects built with a newer SDK are serialized by an older SDK's Serializer
* (e.g., wallet extensions bundling an older SDK version).
*
* @param serializer - The serializer to write into (may be from any SDK version).
* @param value - The Serializable value to serialize as bytes.
*/
export function serializeEntryFunctionBytesCompat(serializer, value) {
if ("serializeAsBytes" in serializer && typeof serializer.serializeAsBytes === "function") {
serializer.serializeAsBytes(value);
}
else {
const bcsBytes = value.bcsToBytes();
serializer.serializeBytes(bcsBytes);
}
}
/**
* Minimum buffer growth increment to avoid too many small reallocations.
*/
const MIN_BUFFER_GROWTH = 256;
/**
* Pool of reusable Serializer instances for temporary serialization operations.
* This reduces allocations when using serializeAsBytes() repeatedly.
*/
const serializerPool = [];
const MAX_POOL_SIZE = 8;
/**
* Acquires a Serializer from the pool or creates a new one.
* @internal
*/
function acquireSerializer() {
const serializer = serializerPool.pop();
if (serializer) {
serializer.reset();
return serializer;
}
return new Serializer();
}
/**
* Returns a Serializer to the pool for reuse.
* @internal
*/
function releaseSerializer(serializer) {
if (serializerPool.length < MAX_POOL_SIZE) {
serializerPool.push(serializer);
}
}
/**
* A class for serializing various data types into a binary format.
* It provides methods to serialize strings, bytes, numbers, and other serializable objects
* using the Binary Coded Serialization (BCS) layout. The serialized data can be retrieved as a
* Uint8Array.
* @group Implementation
* @category BCS
*/
export class Serializer {
buffer;
offset;
/**
* Reusable DataView instance to reduce allocations during serialization.
* Recreated when buffer is resized.
*/
dataView;
/**
* Constructs a serializer with a buffer of size `length` bytes, 64 bytes by default.
* The `length` must be greater than 0.
*
* @param length - The size of the buffer in bytes.
* @group Implementation
* @category BCS
*/
constructor(length = 64) {
if (length <= 0) {
throw new Error("Length needs to be greater than 0");
}
this.buffer = new ArrayBuffer(length);
this.dataView = new DataView(this.buffer);
this.offset = 0;
}
/**
* Ensures that the internal buffer can accommodate the specified number of bytes.
* This function dynamically resizes the buffer using a growth factor of 1.5x with
* a minimum growth increment to balance memory usage and reallocation frequency.
*
* @param bytes - The number of bytes to ensure the buffer can handle.
* @group Implementation
* @category BCS
*/
ensureBufferWillHandleSize(bytes) {
const requiredSize = this.offset + bytes;
if (this.buffer.byteLength >= requiredSize) {
return;
}
// Calculate new size: max of (1.5x current size) or (current + required + MIN_GROWTH)
// Using 1.5x instead of 2x provides better memory efficiency
const growthSize = Math.max(Math.floor(this.buffer.byteLength * 1.5), requiredSize + MIN_BUFFER_GROWTH);
const newBuffer = new ArrayBuffer(growthSize);
new Uint8Array(newBuffer).set(new Uint8Array(this.buffer, 0, this.offset));
this.buffer = newBuffer;
this.dataView = new DataView(this.buffer);
}
/**
* Appends the specified values to the buffer, ensuring that the buffer can accommodate the new data.
*
* @param {Uint8Array} values - The values to be appended to the buffer.
* @group Implementation
* @category BCS
*/
appendToBuffer(values) {
this.ensureBufferWillHandleSize(values.length);
new Uint8Array(this.buffer, this.offset).set(values);
this.offset += values.length;
}
/**
* Serializes a value into the buffer using the provided function, ensuring the buffer can accommodate the size.
* Uses the cached DataView instance for better performance.
*
* @param fn - The function to serialize the value, which takes a byte offset, the value to serialize, and an optional little-endian flag.
* @param fn.byteOffset - The byte offset at which to write the value.
* @param fn.value - The numeric value to serialize into the buffer.
* @param fn.littleEndian - Optional flag indicating whether to use little-endian byte order (defaults to true).
* @group Implementation
* @category BCS
*/
// TODO: JSDoc bytesLength and value
serializeWithFunction(fn, bytesLength, value) {
this.ensureBufferWillHandleSize(bytesLength);
fn.apply(this.dataView, [this.offset, value, true]);
this.offset += bytesLength;
}
/**
* Serializes a string. UTF8 string is supported.
* The number of bytes in the string content is serialized first, as a uleb128-encoded u32 integer.
* Then the string content is serialized as UTF8 encoded bytes.
*
* BCS layout for "string": string_length | string_content
* where string_length is a u32 integer encoded as a uleb128 integer, equal to the number of bytes in string_content.
*
* @param value - The string to serialize.
*
* @example
* ```typescript
* const serializer = new Serializer();
* serializer.serializeStr("1234abcd");
* assert(serializer.toUint8Array() === new Uint8Array([8, 49, 50, 51, 52, 97, 98, 99, 100]));
* ```
* @group Implementation
* @category BCS
*/
serializeStr(value) {
this.serializeBytes(TEXT_ENCODER.encode(value));
}
/**
* Serializes an array of bytes.
*
* This function encodes the length of the byte array as a u32 integer in uleb128 format, followed by the byte array itself.
* BCS layout for "bytes": bytes_length | bytes
* where bytes_length is a u32 integer encoded as a uleb128 integer, equal to the length of the bytes array.
* @param value - The byte array to serialize.
* @group Implementation
* @category BCS
*/
serializeBytes(value) {
this.serializeU32AsUleb128(value.length);
this.appendToBuffer(value);
}
/**
* Serializes an array of bytes with a known length, allowing for efficient deserialization without needing to serialize the
* length itself.
* When deserializing, the number of bytes to deserialize needs to be passed in.
* @param value - The Uint8Array to be serialized.
* @group Implementation
* @category BCS
*/
serializeFixedBytes(value) {
this.appendToBuffer(value);
}
/**
* Serializes a boolean value into a byte representation.
*
* The BCS layout for a boolean uses one byte, where "0x01" represents true and "0x00" represents false.
*
* @param value - The boolean value to serialize.
* @group Implementation
* @category BCS
*/
serializeBool(value) {
/**
* Ensures that the provided value is a boolean.
* This function throws an error if the value is not a boolean, helping to enforce type safety in your code.
*
* @param value - The value to be checked for boolean type.
* @throws {Error} Throws an error if the value is not a boolean.
* @group Implementation
* @category BCS
*/
ensureBoolean(value);
const byteValue = value ? 1 : 0;
this.appendToBuffer(new Uint8Array([byteValue]));
}
/**
* Serializes a Uint8 value and appends it to the buffer.
* BCS layout for "uint8": One byte. Binary format in little-endian representation.
*
* @param value - The Uint8 value to serialize.
* @group Implementation
* @category BCS
*/
serializeU8(value) {
this.appendToBuffer(new Uint8Array([value]));
}
/**
* Serializes a uint16 number.
*
* @group Implementation
* @category BCS
*/
/**
* Serializes a 16-bit unsigned integer value into a binary format.
* BCS layout for "uint16": Two bytes. Binary format in little-endian representation.
*
* @param value - The 16-bit unsigned integer value to serialize.
* @example
* ```typescript
* const serializer = new Serializer();
* serializer.serializeU16(4660);
* assert(serializer.toUint8Array() === new Uint8Array([0x34, 0x12]));
* ```
* @group Implementation
* @category BCS
*/
serializeU16(value) {
this.serializeWithFunction(DataView.prototype.setUint16, 2, value);
}
/**
* Serializes a 32-bit unsigned integer value into a binary format.
* This function is useful for encoding data that needs to be stored or transmitted in a compact form.
* @example
* ```typescript
* const serializer = new Serializer();
* serializer.serializeU32(305419896);
* assert(serializer.toUint8Array() === new Uint8Array([0x78, 0x56, 0x34, 0x12]));
* ```
* @param value - The 32-bit unsigned integer value to serialize.
* @group Implementation
* @category BCS
*/
serializeU32(value) {
this.serializeWithFunction(DataView.prototype.setUint32, 4, value);
}
/**
* Serializes a 64-bit unsigned integer into a format suitable for storage or transmission.
* This function breaks down the value into two 32-bit components and writes them in little-endian order.
*
* @param value - The 64-bit unsigned integer to serialize, represented as a number.
* @example
* ```ts
* const serializer = new Serializer();
* serializer.serializeU64(1311768467750121216);
* assert(serializer.toUint8Array() === new Uint8Array([0x00, 0xEF, 0xCD, 0xAB, 0x78, 0x56, 0x34, 0x12]));
* ```
* @group Implementation
* @category BCS
*/
serializeU64(value) {
const low = BigInt(value) & BigInt(MAX_U32_NUMBER);
const high = BigInt(value) >> BigInt(32);
// write little endian number
this.serializeU32(Number(low));
this.serializeU32(Number(high));
}
/**
* Serializes a U128 value into a format suitable for storage or transmission.
*
* @param value - The U128 value to serialize, represented as a number.
* @group Implementation
* @category BCS
*/
serializeU128(value) {
const low = BigInt(value) & MAX_U64_BIG_INT;
const high = BigInt(value) >> BigInt(64);
// write little endian number
this.serializeU64(low);
this.serializeU64(high);
}
/**
* Serializes a U256 value into a byte representation.
* This function is essential for encoding large numbers in a compact format suitable for transmission or storage.
*
* @param value - The U256 value to serialize, represented as an AnyNumber.
* @group Implementation
* @category BCS
*/
serializeU256(value) {
const low = BigInt(value) & MAX_U128_BIG_INT;
const high = BigInt(value) >> BigInt(128);
// write little endian number
this.serializeU128(low);
this.serializeU128(high);
}
/**
* Serializes an 8-bit signed integer value.
* BCS layout for "int8": One byte. Binary format in little-endian representation.
*
* @param value - The 8-bit signed integer value to serialize.
* @group Implementation
* @category BCS
*/
serializeI8(value) {
this.serializeWithFunction(DataView.prototype.setInt8, 1, value);
}
/**
* Serializes a 16-bit signed integer value into a binary format.
* BCS layout for "int16": Two bytes. Binary format in little-endian representation.
*
* @param value - The 16-bit signed integer value to serialize.
* @group Implementation
* @category BCS
*/
serializeI16(value) {
this.serializeWithFunction(DataView.prototype.setInt16, 2, value);
}
/**
* Serializes a 32-bit signed integer value into a binary format.
*
* @param value - The 32-bit signed integer value to serialize.
* @group Implementation
* @category BCS
*/
serializeI32(value) {
this.serializeWithFunction(DataView.prototype.setInt32, 4, value);
}
/**
* Serializes a 64-bit signed integer into a format suitable for storage or transmission.
* This function uses two's complement representation for negative values.
*
* @param value - The 64-bit signed integer to serialize.
* @group Implementation
* @category BCS
*/
serializeI64(value) {
const val = BigInt(value);
// Convert to unsigned representation using two's complement
const unsigned = val < 0 ? (BigInt(1) << BigInt(64)) + val : val;
const low = unsigned & BigInt(MAX_U32_NUMBER);
const high = unsigned >> BigInt(32);
// write little endian number
this.serializeU32(Number(low));
this.serializeU32(Number(high));
}
/**
* Serializes a 128-bit signed integer value.
*
* @param value - The 128-bit signed integer value to serialize.
* @group Implementation
* @category BCS
*/
serializeI128(value) {
const val = BigInt(value);
// Convert to unsigned representation using two's complement
const unsigned = val < 0 ? (BigInt(1) << BigInt(128)) + val : val;
const low = unsigned & MAX_U64_BIG_INT;
const high = unsigned >> BigInt(64);
// write little endian number
this.serializeU64(low);
this.serializeU64(high);
}
/**
* Serializes a 256-bit signed integer value.
*
* @param value - The 256-bit signed integer value to serialize.
* @group Implementation
* @category BCS
*/
serializeI256(value) {
const val = BigInt(value);
// Convert to unsigned representation using two's complement
const unsigned = val < 0 ? (BigInt(1) << BigInt(256)) + val : val;
const low = unsigned & MAX_U128_BIG_INT;
const high = unsigned >> BigInt(128);
// write little endian number
this.serializeU128(low);
this.serializeU128(high);
}
/**
* Serializes a 32-bit unsigned integer as a variable-length ULEB128 encoded byte array.
* BCS uses uleb128 encoding in two cases: (1) lengths of variable-length sequences and (2) tags of enum values
*
* @param val - The 32-bit unsigned integer value to be serialized.
* @group Implementation
* @category BCS
*/
serializeU32AsUleb128(val) {
let value = val;
const valueArray = [];
while (value >>> 7 !== 0) {
valueArray.push((value & 0x7f) | 0x80);
value >>>= 7;
}
valueArray.push(value);
this.appendToBuffer(new Uint8Array(valueArray));
}
/**
* Returns the buffered bytes as a Uint8Array.
*
* This function allows you to retrieve the byte representation of the buffer up to the current offset.
* For better performance, returns a view when the buffer is exactly the right size, or copies
* only the used portion otherwise.
*
* @returns Uint8Array - The byte array representation of the buffer.
* @group Implementation
* @category BCS
*/
toUint8Array() {
// Return a copy of only the used portion of the buffer
// Using subarray + slice pattern for efficiency
return new Uint8Array(this.buffer, 0, this.offset).slice();
}
/**
* Resets the serializer to its initial state, allowing the buffer to be reused.
* This clears the buffer contents to prevent data leakage between uses.
*
* @group Implementation
* @category BCS
*/
reset() {
// Clear buffer contents to prevent data leakage when reusing pooled serializers
// Only clear the portion that was used (up to offset) for efficiency
if (this.offset > 0) {
new Uint8Array(this.buffer, 0, this.offset).fill(0);
}
this.offset = 0;
}
/**
* Returns the current number of bytes written to the serializer.
*
* @returns The number of bytes written.
* @group Implementation
* @category BCS
*/
getOffset() {
return this.offset;
}
/**
* Returns a view of the serialized bytes without copying.
* WARNING: The returned view is only valid until the next write operation.
* Use toUint8Array() if you need a persistent copy.
*
* @returns A Uint8Array view of the buffer (not a copy).
* @group Implementation
* @category BCS
*/
toUint8ArrayView() {
return new Uint8Array(this.buffer, 0, this.offset);
}
/**
* Serializes a `Serializable` value, facilitating composable serialization.
*
* @param value The Serializable value to serialize.
*
* @returns the serializer instance
* @group Implementation
* @category BCS
*/
serialize(value) {
// NOTE: The `serialize` method called by `value` is defined in `value`'s
// Serializable interface, not the one defined in this class.
value.serialize(this);
}
/**
* Serializes a Serializable value as a byte array with a length prefix.
* This is the optimized pattern for entry function argument serialization.
*
* Instead of:
* ```typescript
* const bcsBytes = value.bcsToBytes(); // Creates new Serializer, copies bytes
* serializer.serializeBytes(bcsBytes);
* ```
*
* Use:
* ```typescript
* serializer.serializeAsBytes(value); // Uses pooled Serializer, avoids extra copy
* ```
*
* This method uses a pooled Serializer instance to reduce allocations and
* directly appends the serialized bytes with a length prefix.
*
* @param value - The Serializable value to serialize as bytes.
* @group Implementation
* @category BCS
*/
serializeAsBytes(value) {
// Acquire a pooled serializer for temporary use
const tempSerializer = acquireSerializer();
try {
// Serialize the value to the temporary serializer
value.serialize(tempSerializer);
// Get the serialized bytes (as a view to avoid copying)
const bytes = tempSerializer.toUint8ArrayView();
// Serialize with length prefix to this serializer
this.serializeBytes(bytes);
}
finally {
// Return the serializer to the pool for reuse
releaseSerializer(tempSerializer);
}
}
/**
* Serializes an array of BCS Serializable values to a serializer instance.
* The bytes are added to the serializer instance's byte buffer.
*
* @param values The array of BCS Serializable values
* @example
* const addresses = new Array<AccountAddress>(
* AccountAddress.from("0x1"),
* AccountAddress.from("0x2"),
* AccountAddress.from("0xa"),
* AccountAddress.from("0xb"),
* );
* const serializer = new Serializer();
* serializer.serializeVector(addresses);
* const serializedBytes = serializer.toUint8Array();
* // serializedBytes is now the BCS-serialized bytes
* // The equivalent value in Move would be:
* // `bcs::to_bytes(&vector<address> [@0x1, @0x2, @0xa, @0xb])`;
* @group Implementation
* @category BCS
*/
serializeVector(values) {
this.serializeU32AsUleb128(values.length);
values.forEach((item) => {
item.serialize(this);
});
}
/**
* Serializes an optional value which can be a Serializable, string, or Uint8Array.
* For strings and Uint8Arrays, it uses the appropriate serialization method.
*
* @param value The value to serialize (Serializable, string, Uint8Array, or undefined)
* @param len Optional fixed length for Uint8Array serialization. If provided, uses serializeFixedBytes instead of serializeBytes
*
* @example
* ```typescript
* const serializer = new Serializer();
* serializer.serializeOption("hello"); // Serializes optional string
* serializer.serializeOption(new Uint8Array([1, 2, 3])); // Serializes optional bytes
* serializer.serializeOption(new Uint8Array([1, 2, 3]), 3); // Serializes optional fixed-length bytes
* serializer.serializeOption(new AccountAddress(...)); // Serializes optional Serializable
* serializer.serializeOption(undefined); // Serializes none case
* ```
* @group Implementation
* @category BCS
*/
serializeOption(value, len) {
const hasValue = value !== undefined;
this.serializeBool(hasValue);
if (hasValue) {
if (typeof value === "string") {
this.serializeStr(value);
}
else if (value instanceof Uint8Array) {
if (len !== undefined) {
this.serializeFixedBytes(value);
}
else {
this.serializeBytes(value);
}
}
else {
value.serialize(this);
}
}
}
/**
* @deprecated use `serializeOption` instead.
* Serializes an optional string, supporting UTF8 encoding.
* The function encodes the existence of the string first, followed by the length and content if it exists.
*
* BCS layout for optional "string": 1 | string_length | string_content
* where string_length is a u32 integer encoded as a uleb128 integer, equal to the number of bytes in string_content.
* BCS layout for undefined: 0
*
* @param value - The optional string to serialize. If undefined, it will serialize as 0.
* @group Implementation
* @category BCS
*/
serializeOptionStr(value) {
if (value === undefined) {
this.serializeU32AsUleb128(0);
}
else {
this.serializeU32AsUleb128(1);
this.serializeStr(value);
}
}
}
__decorate([
checkNumberRange(0, MAX_U8_NUMBER)
], Serializer.prototype, "serializeU8", null);
__decorate([
checkNumberRange(0, MAX_U16_NUMBER)
], Serializer.prototype, "serializeU16", null);
__decorate([
checkNumberRange(0, MAX_U32_NUMBER)
], Serializer.prototype, "serializeU32", null);
__decorate([
checkNumberRange(BigInt(0), MAX_U64_BIG_INT)
], Serializer.prototype, "serializeU64", null);
__decorate([
checkNumberRange(BigInt(0), MAX_U128_BIG_INT)
], Serializer.prototype, "serializeU128", null);
__decorate([
checkNumberRange(BigInt(0), MAX_U256_BIG_INT)
], Serializer.prototype, "serializeU256", null);
__decorate([
checkNumberRange(MIN_I8_NUMBER, MAX_I8_NUMBER)
], Serializer.prototype, "serializeI8", null);
__decorate([
checkNumberRange(MIN_I16_NUMBER, MAX_I16_NUMBER)
], Serializer.prototype, "serializeI16", null);
__decorate([
checkNumberRange(MIN_I32_NUMBER, MAX_I32_NUMBER)
], Serializer.prototype, "serializeI32", null);
__decorate([
checkNumberRange(MIN_I64_BIG_INT, MAX_I64_BIG_INT)
], Serializer.prototype, "serializeI64", null);
__decorate([
checkNumberRange(MIN_I128_BIG_INT, MAX_I128_BIG_INT)
], Serializer.prototype, "serializeI128", null);
__decorate([
checkNumberRange(MIN_I256_BIG_INT, MAX_I256_BIG_INT)
], Serializer.prototype, "serializeI256", null);
__decorate([
checkNumberRange(0, MAX_U32_NUMBER)
], Serializer.prototype, "serializeU32AsUleb128", null);
/**
* @group Implementation
* @category BCS
*/
export function ensureBoolean(value) {
if (typeof value !== "boolean") {
throw new Error(`${value} is not a boolean value`);
}
}
/**
* @group Implementation
* @category BCS
*/
export const outOfRangeErrorMessage = (value, min, max) => `${value} is out of range: [${min}, ${max}]`;
/**
* Validates that a given number is within a specified range.
* This function throws an error if the value is outside the defined minimum and maximum bounds.
*
* @param value - The number to validate.
* @param minValue - The minimum allowable value (inclusive).
* @param maxValue - The maximum allowable value (inclusive).
* @group Implementation
* @category BCS
*/
export function validateNumberInRange(value, minValue, maxValue) {
const valueBigInt = BigInt(value);
if (valueBigInt > BigInt(maxValue) || valueBigInt < BigInt(minValue)) {
throw new Error(outOfRangeErrorMessage(value, minValue, maxValue));
}
}
/**
* A decorator that validates that the input argument for a function is within a specified range.
* This ensures that the function is only called with valid input values, preventing potential errors.
*
* @param minValue - The input argument must be greater than or equal to this value.
* @param maxValue - The input argument must be less than or equal to this value.
* @group Implementation
* @category BCS
*/
function checkNumberRange(minValue, maxValue) {
return (target, propertyKey, descriptor) => {
const childFunction = descriptor.value;
descriptor.value = function deco(value) {
validateNumberInRange(value, minValue, maxValue);
return childFunction.apply(this, [value]);
};
return descriptor;
};
}
//# sourceMappingURL=serializer.js.map