Comparing version 0.0.3 to 0.1.0
100
index.d.ts
/// <reference types="node" /> | ||
import ByteBuffer from "bytebuffer"; | ||
import Long from "long"; | ||
@@ -91,5 +92,2 @@ import { Optional } from "typescript-optional"; | ||
namespace Persistence { | ||
interface ReadOptions { | ||
compressed?: boolean; | ||
} | ||
interface TypedObject { | ||
@@ -105,5 +103,59 @@ readonly __nbtPrototype__: CompoundSchema; | ||
} | ||
function serialize(object: TypedObject, compressed?: boolean): Promise<Buffer>; | ||
function deserialize(fileData: Buffer, compressed?: boolean): Promise<TypedObject>; | ||
function readTagSync(fileData: Buffer): NBT.TagCompound<any> | undefined; | ||
type TypeIdentity = Schema | string | TagType; | ||
class ReadContext { | ||
private scopeType; | ||
private reg; | ||
constructor(scopeType: TypeIdentity, reg: { | ||
[name: string]: string; | ||
}); | ||
type: TypeIdentity; | ||
findSchemaId(schema: Schema): string | undefined; | ||
fork(tagType: number): ReadContext; | ||
} | ||
class WriteContext { | ||
readonly type: Schema; | ||
private reg; | ||
constructor(type: Schema, reg: { | ||
[id: string]: Schema; | ||
}); | ||
findSchema(id: string): Schema | undefined; | ||
fork(type?: Schema): WriteContext; | ||
} | ||
interface IO { | ||
read(buf: ByteBuffer, context: ReadContext): any; | ||
write(buf: ByteBuffer, value: any, context: WriteContext): void; | ||
} | ||
interface SerializationOption { | ||
compressed?: boolean; | ||
/** | ||
* IO override for serialization | ||
*/ | ||
io?: { | ||
[tagType: number]: IO; | ||
}; | ||
} | ||
/** | ||
* Serialzie an nbt typed json object into NBT binary | ||
* @param object The json | ||
* @param compressed Should we compress it | ||
*/ | ||
function serialize(object: TypedObject, option?: SerializationOption): Promise<Buffer>; | ||
/** | ||
* Deserialize the nbt binary into json | ||
* @param fileData The nbt binary | ||
* @param compressed Should we compress it | ||
*/ | ||
function deserialize(fileData: Buffer, option?: SerializationOption): Promise<TypedObject>; | ||
/** | ||
* Serialzie an nbt typed json object into NBT binary | ||
* @param object The json | ||
* @param compressed Should we compress it | ||
*/ | ||
function serializeSync(object: TypedObject, option?: SerializationOption): Buffer; | ||
/** | ||
* Deserialize the nbt binary into json | ||
* @param fileData The nbt binary | ||
* @param compressed Should we compress it | ||
*/ | ||
function deserializeSync(fileData: Buffer, option?: SerializationOption): TypedObject; | ||
function createSerializer(): Serializer; | ||
@@ -113,7 +165,39 @@ class Serializer { | ||
private reversedRegistry; | ||
/** | ||
* Register a new type nbt schema to the serializer | ||
* @param type The type name | ||
* @param schema The schema | ||
*/ | ||
register(type: string, schema: CompoundSchema): this; | ||
serialize(object: object, type: string, compressed?: boolean): Promise<Buffer>; | ||
deserialize(fileData: Buffer, compressed?: boolean): { | ||
/** | ||
* Serialize the object into the specific type | ||
* @param object The json object | ||
* @param type The registered nbt type | ||
* @param option The serialize option | ||
*/ | ||
serialize(object: object, type: string, option?: SerializationOption): Promise<Buffer>; | ||
/** | ||
* Serialize the object into the specific type | ||
* @param object The json object | ||
* @param type The registered nbt type | ||
* @param compressed Should compress this nbt | ||
*/ | ||
serializeSync(object: object, type: string, option?: SerializationOption): any; | ||
/** | ||
* Deserialize the nbt to json object directly | ||
* @param fileData The nbt data | ||
* @param compressed Does the data compressed | ||
*/ | ||
deserialize(fileData: Buffer, option?: SerializationOption): Promise<{ | ||
value: any; | ||
type: any | string; | ||
}>; | ||
/** | ||
* Deserialize the nbt to json object directly | ||
* @param fileData The nbt data | ||
* @param compressed Does the data compressed | ||
*/ | ||
deserializeSync(fileData: Buffer, option?: SerializationOption): { | ||
value: any; | ||
type: any | string; | ||
}; | ||
@@ -120,0 +204,0 @@ } |
190
index.js
@@ -5,15 +5,7 @@ "use strict"; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||
result["default"] = mod; | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const bytebuffer_1 = __importDefault(require("bytebuffer")); | ||
const fileType = require("file-type"); | ||
const file_type_1 = __importDefault(require("file-type")); | ||
const long_1 = __importDefault(require("long")); | ||
const typescript_optional_1 = require("typescript-optional"); | ||
const zlib = __importStar(require("zlib")); | ||
const utils_1 = require("./utils"); | ||
@@ -58,6 +50,6 @@ var NBT; | ||
if (typeof tag.type !== "number") { | ||
return false; | ||
return true; | ||
} | ||
if (!Number.isInteger(tag.type) || tag.type > 12 || tag.type < 0) { | ||
return false; | ||
return true; | ||
} | ||
@@ -79,9 +71,9 @@ const tagType = tag.type; | ||
case TagType.ByteArray: | ||
return typeof value !== "object" || !(value instanceof Buffer); | ||
return typeof value !== "object" || !(value instanceof Uint8Array); | ||
case TagType.String: | ||
return typeof value !== "string"; | ||
case TagType.IntArray: | ||
return typeof value !== "object" || !(value instanceof Buffer) || value.length % 4 !== 0; | ||
return typeof value !== "object" || !(value instanceof Int32Array); | ||
case TagType.LongArray: | ||
return typeof value !== "object" || !(value instanceof Buffer) || value.length % 8 !== 0; | ||
return typeof value !== "object" || !(value instanceof Array); | ||
} | ||
@@ -248,2 +240,3 @@ return true; | ||
} | ||
Persistence.ReadContext = ReadContext; | ||
class WriteContext { | ||
@@ -257,2 +250,3 @@ constructor(type, reg) { | ||
} | ||
Persistence.WriteContext = WriteContext; | ||
const handlers = [ | ||
@@ -263,3 +257,3 @@ { read: (buf) => undefined, write(buf, v) { } }, | ||
{ read: (buf) => buf.readInt(), write(buf, v) { buf.writeInt(v ? v : 0); } }, | ||
{ read: (buf) => buf.readLong(), write(buf, v) { buf.writeInt64(v ? v : 0); } }, | ||
{ read: (buf) => buf.readInt64(), write(buf, v) { buf.writeInt64(v ? v : 0); } }, | ||
{ read: (buf) => buf.readFloat(), write(buf, v) { buf.writeFloat(v ? v : 0); } }, | ||
@@ -418,3 +412,3 @@ { read: (buf) => buf.readDouble(), write(buf, v) { buf.writeDouble(v ? v : 0); } }, | ||
for (let i = 0; i < len; i++) { | ||
arr[i] = buf.readLong(); | ||
arr[i] = buf.readInt64(); | ||
} | ||
@@ -431,8 +425,24 @@ return arr; | ||
]; | ||
async function serialize(object, compressed) { | ||
return writeRootTag(object, object.__nbtPrototype__, {}, "", compressed || false); | ||
/** | ||
* Serialzie an nbt typed json object into NBT binary | ||
* @param object The json | ||
* @param compressed Should we compress it | ||
*/ | ||
async function serialize(object, option = {}) { | ||
const buff = writeRootTag(object, object.__nbtPrototype__, {}, "", Object.assign({}, handlers, option.io)); | ||
if (!option.compressed) { | ||
return buff; | ||
} | ||
return utils_1.zlib.gzip(buff); | ||
} | ||
Persistence.serialize = serialize; | ||
async function deserialize(fileData, compressed) { | ||
const { value, type } = await readBuffer(fileData, compressed); | ||
/** | ||
* Deserialize the nbt binary into json | ||
* @param fileData The nbt binary | ||
* @param compressed Should we compress it | ||
*/ | ||
async function deserialize(fileData, option = {}) { | ||
const doUnzip = shouldUnzip(fileData, option.compressed); | ||
const bb = bytebuffer_1.default.wrap(doUnzip ? await utils_1.zlib.unzip(fileData) : fileData); | ||
const { value, type } = readRootTag(bb, undefined, Object.assign({}, handlers, option.io)); | ||
deepFreeze(type); | ||
@@ -443,10 +453,33 @@ Object.defineProperty(value, "__nbtPrototype__", { value: type }); | ||
Persistence.deserialize = deserialize; | ||
function readTagSync(fileData) { | ||
return undefined; | ||
/** | ||
* Serialzie an nbt typed json object into NBT binary | ||
* @param object The json | ||
* @param compressed Should we compress it | ||
*/ | ||
function serializeSync(object, option = {}) { | ||
const buff = writeRootTag(object, object.__nbtPrototype__, {}, "", Object.assign({}, handlers, option.io)); | ||
if (!option.compressed) { | ||
return buff; | ||
} | ||
return utils_1.zlib.gzipSync(buff); | ||
} | ||
Persistence.readTagSync = readTagSync; | ||
async function readBuffer(fileData, compressed) { | ||
Persistence.serializeSync = serializeSync; | ||
/** | ||
* Deserialize the nbt binary into json | ||
* @param fileData The nbt binary | ||
* @param compressed Should we compress it | ||
*/ | ||
function deserializeSync(fileData, option = {}) { | ||
const doUnzip = shouldUnzip(fileData, option.compressed); | ||
const bb = bytebuffer_1.default.wrap(doUnzip ? utils_1.zlib.unzipSync(fileData) : fileData); | ||
const { value, type } = readRootTag(bb, undefined, Object.assign({}, handlers, option.io)); | ||
deepFreeze(type); | ||
Object.defineProperty(value, "__nbtPrototype__", { value: type }); | ||
return value; | ||
} | ||
Persistence.deserializeSync = deserializeSync; | ||
function shouldUnzip(fileData, compressed) { | ||
let doUnzip; | ||
if (typeof compressed === "undefined") { | ||
const ft = fileType(fileData); | ||
const ft = file_type_1.default(fileData); | ||
doUnzip = ft !== undefined && ft.ext === "gz"; | ||
@@ -457,15 +490,5 @@ } | ||
} | ||
const bb = bytebuffer_1.default.wrap(doUnzip ? await new Promise((resolve, reject) => { | ||
zlib.unzip(fileData, (err, r) => { | ||
if (err) { | ||
reject(err); | ||
} | ||
else { | ||
resolve(r); | ||
} | ||
}); | ||
}) : fileData); | ||
return readRootTag(bb); | ||
return doUnzip; | ||
} | ||
function readRootTag(buffer, reg = {}) { | ||
function readRootTag(buffer, reg = {}, io = handlers) { | ||
const rootType = buffer.readByte(); | ||
@@ -480,6 +503,6 @@ if (rootType === TagType.End) { | ||
const context = new ReadContext(TagType.Compound, reg); | ||
const value = handlers[TagType.Compound].read(buffer, context); | ||
const value = io[TagType.Compound].read(buffer, context); | ||
return { type: context.type, value, name }; | ||
} | ||
async function writeRootTag(value, type, reg, filename, compressed) { | ||
function writeRootTag(value, type, reg, filename, io) { | ||
const buffer = new bytebuffer_1.default(); | ||
@@ -489,18 +512,4 @@ buffer.writeByte(NBT.TagType.Compound); | ||
const context = new WriteContext(type, reg); | ||
handlers[NBT.TagType.Compound].write(buffer, value, context); | ||
if (compressed) { | ||
return new Promise((resolve, reject) => { | ||
zlib.gzip(buffer.flip().buffer.slice(0, buffer.limit), (e, r) => { | ||
if (e) { | ||
reject(e); | ||
} | ||
else { | ||
resolve(r); | ||
} | ||
}); | ||
}); | ||
} | ||
else { | ||
return buffer.flip().buffer.slice(0, buffer.limit); | ||
} | ||
io[NBT.TagType.Compound].write(buffer, value, context); | ||
return buffer.flip().buffer.slice(0, buffer.limit); | ||
} | ||
@@ -516,2 +525,7 @@ function createSerializer() { | ||
} | ||
/** | ||
* Register a new type nbt schema to the serializer | ||
* @param type The type name | ||
* @param schema The schema | ||
*/ | ||
register(type, schema) { | ||
@@ -525,3 +539,9 @@ if (typeof schema !== "object" || schema === null) { | ||
} | ||
serialize(object, type, compressed = false) { | ||
/** | ||
* Serialize the object into the specific type | ||
* @param object The json object | ||
* @param type The registered nbt type | ||
* @param option The serialize option | ||
*/ | ||
async serialize(object, type, option = {}) { | ||
const schema = this.registry[type]; | ||
@@ -531,22 +551,56 @@ if (!schema) { | ||
} | ||
return writeRootTag(object, schema, this.registry, "", compressed); | ||
const buff = writeRootTag(object, schema, this.registry, "", Object.assign({}, handlers, option.io)); | ||
if (!option.compressed) { | ||
return buff; | ||
} | ||
return utils_1.zlib.gzip(buff); | ||
} | ||
deserialize(fileData, compressed = false) { | ||
let doUnzip; | ||
if (typeof compressed === "undefined") { | ||
const ft = fileType(fileData); | ||
doUnzip = ft !== undefined && ft.ext === "gz"; | ||
/** | ||
* Serialize the object into the specific type | ||
* @param object The json object | ||
* @param type The registered nbt type | ||
* @param compressed Should compress this nbt | ||
*/ | ||
serializeSync(object, type, option = {}) { | ||
const schema = this.registry[type]; | ||
if (!schema) { | ||
throw new Error(`Unknown type [${schema}]`); | ||
} | ||
const buff = writeRootTag(object, schema, this.registry, "", Object.assign({}, handlers, option.io)); | ||
if (!option.compressed) { | ||
return buff; | ||
} | ||
return utils_1.zlib.gzipSync(buff); | ||
} | ||
/** | ||
* Deserialize the nbt to json object directly | ||
* @param fileData The nbt data | ||
* @param compressed Does the data compressed | ||
*/ | ||
async deserialize(fileData, option = {}) { | ||
const doUnzip = shouldUnzip(fileData, option.compressed); | ||
let bytebuffer; | ||
if (doUnzip) { | ||
bytebuffer = bytebuffer_1.default.wrap(await utils_1.zlib.unzip(fileData)); | ||
} | ||
else { | ||
doUnzip = compressed; | ||
bytebuffer = bytebuffer_1.default.wrap(fileData); | ||
} | ||
return readRootTag(bytebuffer, this.reversedRegistry, Object.assign({}, handlers, option.io)); | ||
} | ||
/** | ||
* Deserialize the nbt to json object directly | ||
* @param fileData The nbt data | ||
* @param compressed Does the data compressed | ||
*/ | ||
deserializeSync(fileData, option = {}) { | ||
const doUnzip = shouldUnzip(fileData, option.compressed); | ||
let bytebuffer; | ||
if (doUnzip) { | ||
const zip = zlib.unzipSync(fileData); | ||
const bytebuffer = bytebuffer_1.default.wrap(zip); | ||
return readRootTag(bytebuffer, this.reversedRegistry); | ||
bytebuffer = bytebuffer_1.default.wrap(utils_1.zlib.unzipSync(fileData)); | ||
} | ||
else { | ||
const bytebuffer = bytebuffer_1.default.wrap(fileData); | ||
return readRootTag(bytebuffer, this.reversedRegistry); | ||
bytebuffer = bytebuffer_1.default.wrap(fileData); | ||
} | ||
return readRootTag(bytebuffer, this.reversedRegistry, Object.assign({}, handlers, option.io)); | ||
} | ||
@@ -553,0 +607,0 @@ } |
191
index.ts
import ByteBuffer from "bytebuffer"; | ||
import fileType = require("file-type"); | ||
import fileType from "file-type"; | ||
import Long from "long"; | ||
import { Optional } from "typescript-optional"; | ||
import * as zlib from "zlib"; | ||
import { readUTF8, writeUTF8 } from "./utils"; | ||
import { readUTF8, writeUTF8, zlib } from "./utils"; | ||
@@ -143,4 +142,4 @@ export namespace NBT { | ||
function badTag(tag: any): boolean { | ||
if (typeof tag.type !== "number") { return false; } | ||
if (!Number.isInteger(tag.type) || tag.type > 12 || tag.type < 0) { return false; } | ||
if (typeof tag.type !== "number") { return true; } | ||
if (!Number.isInteger(tag.type) || tag.type > 12 || tag.type < 0) { return true; } | ||
const tagType = tag.type; | ||
@@ -161,9 +160,9 @@ const value = tag.value; | ||
case TagType.ByteArray: | ||
return typeof value !== "object" || !(value instanceof Buffer); | ||
return typeof value !== "object" || !(value instanceof Uint8Array); | ||
case TagType.String: | ||
return typeof value !== "string"; | ||
case TagType.IntArray: | ||
return typeof value !== "object" || !(value instanceof Buffer) || value.length % 4 !== 0; | ||
return typeof value !== "object" || !(value instanceof Int32Array); | ||
case TagType.LongArray: | ||
return typeof value !== "object" || !(value instanceof Buffer) || value.length % 8 !== 0; | ||
return typeof value !== "object" || !(value instanceof Array); | ||
} | ||
@@ -298,6 +297,2 @@ return true; | ||
export namespace Persistence { | ||
export interface ReadOptions { | ||
compressed?: boolean; | ||
} | ||
interface TypedObject { | ||
@@ -314,3 +309,3 @@ readonly __nbtPrototype__: CompoundSchema; | ||
class ReadContext { | ||
export class ReadContext { | ||
constructor(private scopeType: TypeIdentity, private reg: { [name: string]: string }) { } | ||
@@ -325,3 +320,3 @@ set type(s: TypeIdentity) { this.scopeType = s; } | ||
} | ||
class WriteContext { | ||
export class WriteContext { | ||
constructor(readonly type: Schema, private reg: { [id: string]: Schema }) { } | ||
@@ -332,8 +327,8 @@ findSchema(id: string): Schema | undefined { return this.reg[id]; } | ||
interface IO { | ||
export interface IO { | ||
read(buf: ByteBuffer, context: ReadContext): any; | ||
write(buf: ByteBuffer, value: any, context: WriteContext): void; | ||
readTag?(buf: ByteBuffer): Tags; | ||
writeTag?(buf: ByteBuffer, tags: Tags): void; | ||
// readTag?(buf: ByteBuffer): Tags; | ||
// writeTag?(buf: ByteBuffer, tags: Tags): void; | ||
} | ||
@@ -346,3 +341,3 @@ | ||
{ read: (buf) => buf.readInt(), write(buf, v) { buf.writeInt(v ? v : 0); } }, // int | ||
{ read: (buf) => buf.readLong(), write(buf, v) { buf.writeInt64(v ? v : 0); } }, // long | ||
{ read: (buf) => buf.readInt64(), write(buf, v) { buf.writeInt64(v ? v : 0); } }, // long | ||
{ read: (buf) => buf.readFloat(), write(buf, v) { buf.writeFloat(v ? v : 0); } }, // float | ||
@@ -475,3 +470,3 @@ { read: (buf) => buf.readDouble(), write(buf, v) { buf.writeDouble(v ? v : 0); } }, // double | ||
const arr: Long[] = new Array(len); | ||
for (let i = 0; i < len; i++) { arr[i] = buf.readLong(); } | ||
for (let i = 0; i < len; i++) { arr[i] = buf.readInt64(); } | ||
return arr; | ||
@@ -486,8 +481,33 @@ }, | ||
export async function serialize(object: TypedObject, compressed?: boolean): Promise<Buffer> { | ||
return writeRootTag(object, object.__nbtPrototype__, {}, "", compressed || false); | ||
export interface SerializationOption { | ||
compressed?: boolean; | ||
/** | ||
* IO override for serialization | ||
*/ | ||
io?: { [tagType: number]: IO }; | ||
} | ||
export async function deserialize(fileData: Buffer, compressed?: boolean): Promise<TypedObject> { | ||
const { value, type } = await readBuffer(fileData, compressed); | ||
/** | ||
* Serialzie an nbt typed json object into NBT binary | ||
* @param object The json | ||
* @param compressed Should we compress it | ||
*/ | ||
export async function serialize(object: TypedObject, option: SerializationOption = {}): Promise<Buffer> { | ||
const buff = writeRootTag(object, object.__nbtPrototype__, {}, "", Object.assign({}, handlers, option.io)); | ||
if (!option.compressed) { | ||
return buff; | ||
} | ||
return zlib.gzip(buff) as any; | ||
} | ||
/** | ||
* Deserialize the nbt binary into json | ||
* @param fileData The nbt binary | ||
* @param compressed Should we compress it | ||
*/ | ||
export async function deserialize(fileData: Buffer, option: SerializationOption = {}): Promise<TypedObject> { | ||
const doUnzip: boolean = shouldUnzip(fileData, option.compressed); | ||
const bb = ByteBuffer.wrap(doUnzip ? await zlib.unzip(fileData) : fileData); | ||
const { value, type } = readRootTag(bb, undefined, Object.assign({}, handlers, option.io)); | ||
deepFreeze(type); | ||
@@ -498,7 +518,31 @@ Object.defineProperty(value, "__nbtPrototype__", { value: type }); | ||
export function readTagSync(fileData: Buffer): NBT.TagCompound<any> | undefined { | ||
return undefined; | ||
/** | ||
* Serialzie an nbt typed json object into NBT binary | ||
* @param object The json | ||
* @param compressed Should we compress it | ||
*/ | ||
export function serializeSync(object: TypedObject, option: SerializationOption = {}): Buffer { | ||
const buff = writeRootTag(object, object.__nbtPrototype__, {}, "", Object.assign({}, handlers, option.io)); | ||
if (!option.compressed) { | ||
return buff; | ||
} | ||
return zlib.gzipSync(buff); | ||
} | ||
async function readBuffer(fileData: Buffer, compressed?: boolean) { | ||
/** | ||
* Deserialize the nbt binary into json | ||
* @param fileData The nbt binary | ||
* @param compressed Should we compress it | ||
*/ | ||
export function deserializeSync(fileData: Buffer, option: SerializationOption = {}): TypedObject { | ||
const doUnzip: boolean = shouldUnzip(fileData, option.compressed); | ||
const bb = ByteBuffer.wrap(doUnzip ? zlib.unzipSync(fileData) : fileData); | ||
const { value, type } = readRootTag(bb, undefined, Object.assign({}, handlers, option.io)); | ||
deepFreeze(type); | ||
Object.defineProperty(value, "__nbtPrototype__", { value: type }); | ||
return value; | ||
} | ||
function shouldUnzip(fileData: Buffer, compressed?: boolean) { | ||
let doUnzip: boolean; | ||
@@ -511,11 +555,6 @@ if (typeof compressed === "undefined") { | ||
} | ||
const bb = ByteBuffer.wrap(doUnzip ? await new Promise((resolve, reject) => { | ||
zlib.unzip(fileData, (err, r) => { | ||
if (err) { reject(err); } else { resolve(r); } | ||
}); | ||
}) : fileData); | ||
return readRootTag(bb); | ||
return doUnzip; | ||
} | ||
function readRootTag(buffer: ByteBuffer, reg: { [id: string]: string } = {}) { | ||
function readRootTag(buffer: ByteBuffer, reg: { [id: string]: string } = {}, io: IO[] = handlers) { | ||
const rootType = buffer.readByte(); | ||
@@ -526,7 +565,7 @@ if (rootType === TagType.End) { throw new Error("NBTEnd"); } | ||
const context = new ReadContext(TagType.Compound, reg); | ||
const value = handlers[TagType.Compound].read(buffer, context); | ||
const value = io[TagType.Compound].read(buffer, context); | ||
return { type: context.type, value, name }; | ||
} | ||
async function writeRootTag(value: any, type: Schema, reg: { [id: string]: Schema }, filename?: string, compressed?: boolean): Promise<Buffer> { | ||
function writeRootTag(value: any, type: Schema, reg: { [id: string]: Schema }, filename: string, io: IO[]): Buffer { | ||
const buffer = new ByteBuffer(); | ||
@@ -537,13 +576,5 @@ buffer.writeByte(NBT.TagType.Compound); | ||
const context = new WriteContext(type, reg); | ||
handlers[NBT.TagType.Compound].write(buffer, value, context); | ||
io[NBT.TagType.Compound].write(buffer, value, context); | ||
if (compressed) { | ||
return new Promise((resolve, reject) => { | ||
zlib.gzip(buffer.flip().buffer.slice(0, buffer.limit), (e, r) => { | ||
if (e) { reject(e); } else { resolve(r); } | ||
}); | ||
}); | ||
} else { | ||
return buffer.flip().buffer.slice(0, buffer.limit); | ||
} | ||
return buffer.flip().buffer.slice(0, buffer.limit); | ||
} | ||
@@ -558,2 +589,7 @@ | ||
private reversedRegistry: { [shape: string]: string } = {}; | ||
/** | ||
* Register a new type nbt schema to the serializer | ||
* @param type The type name | ||
* @param schema The schema | ||
*/ | ||
register(type: string, schema: CompoundSchema): this { | ||
@@ -565,24 +601,63 @@ if (typeof schema !== "object" || schema === null) { throw new Error(); } | ||
} | ||
serialize(object: object, type: string, compressed: boolean = false) { | ||
/** | ||
* Serialize the object into the specific type | ||
* @param object The json object | ||
* @param type The registered nbt type | ||
* @param option The serialize option | ||
*/ | ||
async serialize(object: object, type: string, option: SerializationOption = {}) { | ||
const schema = this.registry[type]; | ||
if (!schema) { throw new Error(`Unknown type [${schema}]`); } | ||
return writeRootTag(object, schema, this.registry, "", compressed); | ||
const buff = writeRootTag(object, schema, this.registry, "", Object.assign({}, handlers, option.io)); | ||
if (!option.compressed) { | ||
return buff; | ||
} | ||
return zlib.gzip(buff) as Promise<Buffer>; | ||
} | ||
deserialize(fileData: Buffer, compressed: boolean = false): { value: any, type: any | string } { | ||
let doUnzip: boolean; | ||
if (typeof compressed === "undefined") { | ||
const ft = fileType(fileData); | ||
doUnzip = ft !== undefined && ft.ext === "gz"; | ||
/** | ||
* Serialize the object into the specific type | ||
* @param object The json object | ||
* @param type The registered nbt type | ||
* @param compressed Should compress this nbt | ||
*/ | ||
serializeSync(object: object, type: string, option: SerializationOption = {}) { | ||
const schema = this.registry[type]; | ||
if (!schema) { throw new Error(`Unknown type [${schema}]`); } | ||
const buff = writeRootTag(object, schema, this.registry, "", Object.assign({}, handlers, option.io)); | ||
if (!option.compressed) { | ||
return buff; | ||
} | ||
return zlib.gzipSync(buff); | ||
} | ||
/** | ||
* Deserialize the nbt to json object directly | ||
* @param fileData The nbt data | ||
* @param compressed Does the data compressed | ||
*/ | ||
async deserialize(fileData: Buffer, option: SerializationOption = {}): Promise<{ value: any, type: any | string }> { | ||
const doUnzip: boolean = shouldUnzip(fileData, option.compressed); | ||
let bytebuffer: ByteBuffer; | ||
if (doUnzip) { | ||
bytebuffer = ByteBuffer.wrap(await zlib.unzip(fileData)); | ||
} else { | ||
doUnzip = compressed; | ||
bytebuffer = ByteBuffer.wrap(fileData); | ||
} | ||
return readRootTag(bytebuffer, this.reversedRegistry, Object.assign({}, handlers, option.io)); | ||
} | ||
/** | ||
* Deserialize the nbt to json object directly | ||
* @param fileData The nbt data | ||
* @param compressed Does the data compressed | ||
*/ | ||
deserializeSync(fileData: Buffer, option: SerializationOption = {}): { value: any, type: any | string } { | ||
const doUnzip: boolean = shouldUnzip(fileData, option.compressed); | ||
let bytebuffer: ByteBuffer; | ||
if (doUnzip) { | ||
const zip = zlib.unzipSync(fileData); | ||
const bytebuffer = ByteBuffer.wrap(zip); | ||
return readRootTag(bytebuffer, this.reversedRegistry); | ||
bytebuffer = ByteBuffer.wrap(zlib.unzipSync(fileData)); | ||
} else { | ||
const bytebuffer = ByteBuffer.wrap(fileData); | ||
return readRootTag(bytebuffer, this.reversedRegistry); | ||
bytebuffer = ByteBuffer.wrap(fileData); | ||
} | ||
return readRootTag(bytebuffer, this.reversedRegistry, Object.assign({}, handlers, option.io)); | ||
} | ||
@@ -589,0 +664,0 @@ } |
{ | ||
"name": "@xmcl/nbt", | ||
"version": "0.0.3", | ||
"main": "./index.js", | ||
"types": "./index.d.ts", | ||
"description": "NBT serialization and deserialization", | ||
"engines": { | ||
"node": ">=10.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"build": "tsc --build tsconfig.json" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ci010/ts-minecraft.git" | ||
}, | ||
"author": "cijhn@hotmail.com", | ||
"keywords": [ | ||
"minecraft", | ||
"typescript", | ||
"minecraft-launcher", | ||
"nodejs", | ||
"electron" | ||
], | ||
"license": "MIT", | ||
"dependencies": { | ||
"bytebuffer": "^5.0.1", | ||
"file-type": "^11.0.0", | ||
"long": "^3.2.0", | ||
"typescript-optional": "^2.0.1" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/ci010/ts-minecraft/issues" | ||
}, | ||
"homepage": "https://github.com/ci010/ts-minecraft#readme", | ||
"gitHead": "0d8e76d0276d653052ccb24d000e0c679296f39c" | ||
"name": "@xmcl/nbt", | ||
"version": "0.1.0", | ||
"main": "./index.js", | ||
"types": "./index.d.ts", | ||
"description": "NBT serialization and deserialization", | ||
"engines": { | ||
"node": ">=10.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"compile": "tsc --build tsconfig.json", | ||
"build": "npm run compile" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/ci010/ts-minecraft.git" | ||
}, | ||
"author": "cijhn@hotmail.com", | ||
"keywords": [ | ||
"minecraft", | ||
"typescript", | ||
"minecraft-launcher", | ||
"nodejs", | ||
"electron" | ||
], | ||
"license": "MIT", | ||
"optionalDependencies": { | ||
"pako": "^1.0.10" | ||
}, | ||
"dependencies": { | ||
"bytebuffer": "^5.0.1", | ||
"file-type": "^11.0.0", | ||
"long": "^3.2.0", | ||
"typescript-optional": "^2.0.1" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/ci010/ts-minecraft/issues" | ||
}, | ||
"homepage": "https://github.com/ci010/ts-minecraft#readme", | ||
"gitHead": "5bf361647f9726c870c17effba3b540d1edc1582" | ||
} |
@@ -5,3 +5,3 @@ # Nbt Module | ||
[![npm](https://img.shields.io/npm/l/@xmcl/minecraft-launcher-core.svg)](https://github.com/voxelum/minecraft-launcher-core-node/blob/master/LICENSE) | ||
[![Build Status](https://travis-ci.org/voxelum/minecraft-launcher-core-node.svg)](https://travis-ci.org/voxelum/minecraft-launcher-core-node) | ||
[![Build Status](https://github.com/voxelum/minecraft-launcher-core-node/workflows/Release%20Pre-Check/badge.svg)](https://github.com/voxelum/minecraft-launcher-core-node/workflows/Release%20Pre-Check/badge.svg) | ||
@@ -8,0 +8,0 @@ This is a sub-module belong to [minecraft-launcher-core](https://www.npmjs.com/package/@xmcl/minecraft-launcher-core) module. You can still use this individually. |
{ | ||
"files": [ | ||
"index.ts", | ||
"utils.ts", | ||
"test.ts" | ||
"utils.ts" | ||
], | ||
@@ -7,0 +6,0 @@ "compilerOptions": { |
@@ -0,3 +1,13 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="bytebuffer" /> | ||
export declare type ZippingData = Uint8Array | number[] | string | Buffer; | ||
export declare let zlib: ZLib<any>; | ||
export declare function setZlib<BUF>(lib: ZLib<BUF>): void; | ||
export interface ZLib<BUF> { | ||
gzip(buffer: BUF): Promise<BUF>; | ||
gzipSync(buffer: BUF): BUF; | ||
unzip(buffer: BUF): Promise<BUF>; | ||
unzipSync(buffer: BUF): BUF; | ||
} | ||
export declare function writeUTF8(out: ByteBuffer, str: string): number; | ||
export declare function readUTF8(buff: ByteBuffer): string; |
39
utils.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
function setZlib(lib) { exports.zlib = lib; } | ||
exports.setZlib = setZlib; | ||
try { | ||
// tslint:disable-next-line: no-var-requires | ||
const lib = require("zlib"); | ||
setZlib({ | ||
gzip(buf) { | ||
return new Promise((resolve, reject) => { | ||
lib.gzip(buf, (e, r) => { | ||
if (e) { | ||
reject(e); | ||
} | ||
else { | ||
resolve(r); | ||
} | ||
}); | ||
}); | ||
}, | ||
unzip(buff) { | ||
return new Promise((resolve, reject) => { | ||
lib.gunzip(buff, (err, r) => { | ||
if (err) { | ||
reject(err); | ||
} | ||
else { | ||
resolve(r); | ||
} | ||
}); | ||
}); | ||
}, | ||
gzipSync(buff) { return lib.gzipSync(buff); }, | ||
unzipSync(buff) { return lib.unzipSync(buff); }, | ||
}); | ||
} | ||
catch (e) { | ||
console.error(e); | ||
// tslint:disable-next-line: no-var-requires | ||
require("pako"); | ||
} | ||
function writeUTF8(out, str) { | ||
@@ -4,0 +43,0 @@ const strlen = str.length; |
40
utils.ts
@@ -0,2 +1,42 @@ | ||
export type ZippingData = Uint8Array | number[] | string | Buffer; | ||
export let zlib: ZLib<any>; | ||
export function setZlib<BUF>(lib: ZLib<BUF>) { zlib = lib; } | ||
export interface ZLib<BUF> { | ||
gzip(buffer: BUF): Promise<BUF>; | ||
gzipSync(buffer: BUF): BUF; | ||
unzip(buffer: BUF): Promise<BUF>; | ||
unzipSync(buffer: BUF): BUF; | ||
} | ||
try { | ||
// tslint:disable-next-line: no-var-requires | ||
const lib: typeof import("zlib") = require("zlib"); | ||
setZlib({ | ||
gzip(buf) { | ||
return new Promise((resolve, reject) => { | ||
lib.gzip(buf, (e, r) => { | ||
if (e) { reject(e); } else { resolve(r); } | ||
}); | ||
}); | ||
}, | ||
unzip(buff) { | ||
return new Promise((resolve, reject) => { | ||
lib.gunzip(buff, (err, r) => { | ||
if (err) { reject(err); } else { resolve(r); } | ||
}); | ||
}); | ||
}, | ||
gzipSync(buff) { return lib.gzipSync(buff); }, | ||
unzipSync(buff) { return lib.unzipSync(buff); }, | ||
} as ZLib<Buffer>); | ||
} catch (e) { | ||
console.error(e); | ||
// tslint:disable-next-line: no-var-requires | ||
require("pako"); | ||
} | ||
export function writeUTF8(out: ByteBuffer, str: string) { | ||
@@ -3,0 +43,0 @@ const strlen = str.length; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
108783
1782
5