@mysten/bcs
Version:
BCS - Canonical Binary Serialization implementation for JavaScript
407 lines (406 loc) • 12.4 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var bcs_exports = {};
__export(bcs_exports, {
bcs: () => bcs
});
module.exports = __toCommonJS(bcs_exports);
var import_bcs_type = require("./bcs-type.js");
var import_uleb = require("./uleb.js");
function fixedArray(size, type, options) {
return new import_bcs_type.BcsType({
read: (reader) => {
const result = new Array(size);
for (let i = 0; i < size; i++) {
result[i] = type.read(reader);
}
return result;
},
write: (value, writer) => {
for (const item of value) {
type.write(item, writer);
}
},
...options,
name: options?.name ?? `${type.name}[${size}]`,
validate: (value) => {
options?.validate?.(value);
if (!value || typeof value !== "object" || !("length" in value)) {
throw new TypeError(`Expected array, found ${typeof value}`);
}
if (value.length !== size) {
throw new TypeError(`Expected array of length ${size}, found ${value.length}`);
}
}
});
}
function option(type) {
return bcs.enum(`Option<${type.name}>`, {
None: null,
Some: type
}).transform({
input: (value) => {
if (value == null) {
return { None: true };
}
return { Some: value };
},
output: (value) => {
if (value.$kind === "Some") {
return value.Some;
}
return null;
}
});
}
function vector(type, options) {
return new import_bcs_type.BcsType({
read: (reader) => {
const length = reader.readULEB();
const result = new Array(length);
for (let i = 0; i < length; i++) {
result[i] = type.read(reader);
}
return result;
},
write: (value, writer) => {
writer.writeULEB(value.length);
for (const item of value) {
type.write(item, writer);
}
},
...options,
name: options?.name ?? `vector<${type.name}>`,
validate: (value) => {
options?.validate?.(value);
if (!value || typeof value !== "object" || !("length" in value)) {
throw new TypeError(`Expected array, found ${typeof value}`);
}
}
});
}
function map(keyType, valueType) {
return bcs.vector(bcs.tuple([keyType, valueType])).transform({
name: `Map<${keyType.name}, ${valueType.name}>`,
input: (value) => {
return [...value.entries()];
},
output: (value) => {
const result = /* @__PURE__ */ new Map();
for (const [key, val] of value) {
result.set(key, val);
}
return result;
}
});
}
const bcs = {
/**
* Creates a BcsType that can be used to read and write an 8-bit unsigned integer.
* @example
* bcs.u8().serialize(255).toBytes() // Uint8Array [ 255 ]
*/
u8(options) {
return (0, import_bcs_type.uIntBcsType)({
readMethod: "read8",
writeMethod: "write8",
size: 1,
maxValue: 2 ** 8 - 1,
...options,
name: options?.name ?? "u8"
});
},
/**
* Creates a BcsType that can be used to read and write a 16-bit unsigned integer.
* @example
* bcs.u16().serialize(65535).toBytes() // Uint8Array [ 255, 255 ]
*/
u16(options) {
return (0, import_bcs_type.uIntBcsType)({
readMethod: "read16",
writeMethod: "write16",
size: 2,
maxValue: 2 ** 16 - 1,
...options,
name: options?.name ?? "u16"
});
},
/**
* Creates a BcsType that can be used to read and write a 32-bit unsigned integer.
* @example
* bcs.u32().serialize(4294967295).toBytes() // Uint8Array [ 255, 255, 255, 255 ]
*/
u32(options) {
return (0, import_bcs_type.uIntBcsType)({
readMethod: "read32",
writeMethod: "write32",
size: 4,
maxValue: 2 ** 32 - 1,
...options,
name: options?.name ?? "u32"
});
},
/**
* Creates a BcsType that can be used to read and write a 64-bit unsigned integer.
* @example
* bcs.u64().serialize(1).toBytes() // Uint8Array [ 1, 0, 0, 0, 0, 0, 0, 0 ]
*/
u64(options) {
return (0, import_bcs_type.bigUIntBcsType)({
readMethod: "read64",
writeMethod: "write64",
size: 8,
maxValue: 2n ** 64n - 1n,
...options,
name: options?.name ?? "u64"
});
},
/**
* Creates a BcsType that can be used to read and write a 128-bit unsigned integer.
* @example
* bcs.u128().serialize(1).toBytes() // Uint8Array [ 1, ..., 0 ]
*/
u128(options) {
return (0, import_bcs_type.bigUIntBcsType)({
readMethod: "read128",
writeMethod: "write128",
size: 16,
maxValue: 2n ** 128n - 1n,
...options,
name: options?.name ?? "u128"
});
},
/**
* Creates a BcsType that can be used to read and write a 256-bit unsigned integer.
* @example
* bcs.u256().serialize(1).toBytes() // Uint8Array [ 1, ..., 0 ]
*/
u256(options) {
return (0, import_bcs_type.bigUIntBcsType)({
readMethod: "read256",
writeMethod: "write256",
size: 32,
maxValue: 2n ** 256n - 1n,
...options,
name: options?.name ?? "u256"
});
},
/**
* Creates a BcsType that can be used to read and write boolean values.
* @example
* bcs.bool().serialize(true).toBytes() // Uint8Array [ 1 ]
*/
bool(options) {
return (0, import_bcs_type.fixedSizeBcsType)({
size: 1,
read: (reader) => reader.read8() === 1,
write: (value, writer) => writer.write8(value ? 1 : 0),
...options,
name: options?.name ?? "bool",
validate: (value) => {
options?.validate?.(value);
if (typeof value !== "boolean") {
throw new TypeError(`Expected boolean, found ${typeof value}`);
}
}
});
},
/**
* Creates a BcsType that can be used to read and write unsigned LEB encoded integers
* @example
*
*/
uleb128(options) {
return (0, import_bcs_type.dynamicSizeBcsType)({
read: (reader) => reader.readULEB(),
serialize: (value) => {
return Uint8Array.from((0, import_uleb.ulebEncode)(value));
},
...options,
name: options?.name ?? "uleb128"
});
},
/**
* Creates a BcsType representing a fixed length byte array
* @param size The number of bytes this types represents
* @example
* bcs.bytes(3).serialize(new Uint8Array([1, 2, 3])).toBytes() // Uint8Array [1, 2, 3]
*/
bytes(size, options) {
return (0, import_bcs_type.fixedSizeBcsType)({
size,
read: (reader) => reader.readBytes(size),
write: (value, writer) => {
writer.writeBytes(new Uint8Array(value));
},
...options,
name: options?.name ?? `bytes[${size}]`,
validate: (value) => {
options?.validate?.(value);
if (!value || typeof value !== "object" || !("length" in value)) {
throw new TypeError(`Expected array, found ${typeof value}`);
}
if (value.length !== size) {
throw new TypeError(`Expected array of length ${size}, found ${value.length}`);
}
}
});
},
/**
* Creates a BcsType representing a variable length byte array
*
* @example
* bcs.byteVector().serialize([1, 2, 3]).toBytes() // Uint8Array [3, 1, 2, 3]
*/
byteVector(options) {
return new import_bcs_type.BcsType({
read: (reader) => {
const length = reader.readULEB();
return reader.readBytes(length);
},
write: (value, writer) => {
const array = new Uint8Array(value);
writer.writeULEB(array.length);
writer.writeBytes(array);
},
...options,
name: options?.name ?? "vector<u8>",
serializedSize: (value) => {
const length = "length" in value ? value.length : null;
return length == null ? null : (0, import_uleb.ulebEncode)(length).length + length;
},
validate: (value) => {
options?.validate?.(value);
if (!value || typeof value !== "object" || !("length" in value)) {
throw new TypeError(`Expected array, found ${typeof value}`);
}
}
});
},
/**
* Creates a BcsType that can ser/de string values. Strings will be UTF-8 encoded
* @example
* bcs.string().serialize('a').toBytes() // Uint8Array [ 1, 97 ]
*/
string(options) {
return (0, import_bcs_type.stringLikeBcsType)({
toBytes: (value) => new TextEncoder().encode(value),
fromBytes: (bytes) => new TextDecoder().decode(bytes),
...options,
name: options?.name ?? "string"
});
},
/**
* Creates a BcsType that represents a fixed length array of a given type
* @param size The number of elements in the array
* @param type The BcsType of each element in the array
* @example
* bcs.fixedArray(3, bcs.u8()).serialize([1, 2, 3]).toBytes() // Uint8Array [ 1, 2, 3 ]
*/
fixedArray,
/**
* Creates a BcsType representing an optional value
* @param type The BcsType of the optional value
* @example
* bcs.option(bcs.u8()).serialize(null).toBytes() // Uint8Array [ 0 ]
* bcs.option(bcs.u8()).serialize(1).toBytes() // Uint8Array [ 1, 1 ]
*/
option,
/**
* Creates a BcsType representing a variable length vector of a given type
* @param type The BcsType of each element in the vector
*
* @example
* bcs.vector(bcs.u8()).toBytes([1, 2, 3]) // Uint8Array [ 3, 1, 2, 3 ]
*/
vector,
/**
* Creates a BcsType representing a tuple of a given set of types
* @param types The BcsTypes for each element in the tuple
*
* @example
* const tuple = bcs.tuple([bcs.u8(), bcs.string(), bcs.bool()])
* tuple.serialize([1, 'a', true]).toBytes() // Uint8Array [ 1, 1, 97, 1 ]
*/
tuple(fields, options) {
return new import_bcs_type.BcsTuple({
fields,
...options
});
},
/**
* Creates a BcsType representing a struct of a given set of fields
* @param name The name of the struct
* @param fields The fields of the struct. The order of the fields affects how data is serialized and deserialized
*
* @example
* const struct = bcs.struct('MyStruct', {
* a: bcs.u8(),
* b: bcs.string(),
* })
* struct.serialize({ a: 1, b: 'a' }).toBytes() // Uint8Array [ 1, 1, 97 ]
*/
struct(name, fields, options) {
return new import_bcs_type.BcsStruct({
name,
fields,
...options
});
},
/**
* Creates a BcsType representing an enum of a given set of options
* @param name The name of the enum
* @param values The values of the enum. The order of the values affects how data is serialized and deserialized.
* null can be used to represent a variant with no data.
*
* @example
* const enum = bcs.enum('MyEnum', {
* A: bcs.u8(),
* B: bcs.string(),
* C: null,
* })
* enum.serialize({ A: 1 }).toBytes() // Uint8Array [ 0, 1 ]
* enum.serialize({ B: 'a' }).toBytes() // Uint8Array [ 1, 1, 97 ]
* enum.serialize({ C: true }).toBytes() // Uint8Array [ 2 ]
*/
enum(name, fields, options) {
return new import_bcs_type.BcsEnum({
name,
fields,
...options
});
},
/**
* Creates a BcsType representing a map of a given key and value type
* @param keyType The BcsType of the key
* @param valueType The BcsType of the value
* @example
* const map = bcs.map(bcs.u8(), bcs.string())
* map.serialize(new Map([[2, 'a']])).toBytes() // Uint8Array [ 1, 2, 1, 97 ]
*/
map,
/**
* Creates a BcsType that wraps another BcsType which is lazily evaluated. This is useful for creating recursive types.
* @param cb A callback that returns the BcsType
*/
lazy(cb) {
return (0, import_bcs_type.lazyBcsType)(cb);
}
};
//# sourceMappingURL=bcs.js.map