UNPKG

@hazae41/kdbx

Version:

Rust-like KeePass (KDBX 4) file format for TypeScript

376 lines (375 loc) 11.5 kB
// deno-lint-ignore-file no-namespace import { Readable, Unknown, Writable } from "@hazae41/binary"; import { Cursor } from "@hazae41/cursor"; export class Dictionary { version; entries; constructor(version, entries) { this.version = version; this.entries = entries; } sizeOrThrow() { return this.version.sizeOrThrow() + this.entries.sizeOrThrow() + 1; } writeOrThrow(cursor) { this.version.writeOrThrow(cursor); this.entries.writeOrThrow(cursor); cursor.writeUint8OrThrow(0x00); } cloneOrThrow() { return new Dictionary(this.version.cloneOrThrow(), this.entries.cloneOrThrow()); } } (function (Dictionary) { class Version { minor; major; constructor(minor, major) { this.minor = minor; this.major = major; } sizeOrThrow() { return 1 + 1; } writeOrThrow(cursor) { cursor.writeUint8OrThrow(this.minor); cursor.writeUint8OrThrow(this.major); } cloneOrThrow() { return this; } } Dictionary.Version = Version; (function (Version) { function readOrThrow(cursor) { const minor = cursor.readUint8OrThrow(); const major = cursor.readUint8OrThrow(); return new Version(minor, major); } Version.readOrThrow = readOrThrow; })(Version = Dictionary.Version || (Dictionary.Version = {})); function initOrThrow(version, entries) { return new Dictionary(version, Entries.initOrThrow(entries)); } Dictionary.initOrThrow = initOrThrow; function readOrThrow(cursor) { const version = Version.readOrThrow(cursor); if (version.major !== 1) throw new Error(); const entries = Entries.readOrThrow(cursor); return new Dictionary(version, entries); } Dictionary.readOrThrow = readOrThrow; })(Dictionary || (Dictionary = {})); export class Entries { bytes; value; constructor(bytes, value) { this.bytes = bytes; this.value = value; } sizeOrThrow() { return this.bytes.bytes.length; } writeOrThrow(cursor) { cursor.writeOrThrow(this.bytes.bytes); } cloneOrThrow() { return Readable.readFromBytesOrThrow(Entries, Writable.writeToBytesOrThrow(this)); } } (function (Entries) { function initOrThrow(value) { const entries = new Array(); for (const key in value) entries.push(new Entry(Key.initOrThrow(key), value[key])); const sized = entries.reduce((x, r) => x + r.sizeOrThrow(), 0); const bytes = new Unknown(new Uint8Array(sized)); const cursor = new Cursor(bytes.bytes); for (const entry of entries) entry.writeOrThrow(cursor); return new Entries(bytes, value); } Entries.initOrThrow = initOrThrow; function readOrThrow(cursor) { const start = cursor.offset; const entries = new Array(); const indexed = {}; while (true) { const record = Entry.readOrThrow(cursor); if (record == null) break; entries.push(record); indexed[record.key.value] = record.val; continue; } const bytes = new Unknown(cursor.bytes.subarray(start, cursor.offset)); return new Entries(bytes, indexed); } Entries.readOrThrow = readOrThrow; })(Entries || (Entries = {})); export class Entry { key; val; constructor(key, val) { this.key = key; this.val = val; } sizeOrThrow() { return 1 + 4 + this.key.sizeOrThrow() + 4 + this.val.sizeOrThrow(); } writeOrThrow(cursor) { cursor.writeUint8OrThrow(this.val.type); const klength = this.key.sizeOrThrow(); cursor.writeUint32OrThrow(klength, true); this.key.writeOrThrow(cursor); const vlength = this.val.sizeOrThrow(); cursor.writeUint32OrThrow(vlength, true); this.val.writeOrThrow(cursor); } } (function (Entry) { function readOrThrow(cursor) { const type = cursor.readUint8OrThrow(); if (type === 0) return; const klength = cursor.readUint32OrThrow(true); const kbytes = cursor.readOrThrow(klength); const kstring = new TextDecoder().decode(kbytes); const vlength = cursor.readUint32OrThrow(true); const vbytes = cursor.readOrThrow(vlength); const key = new Key(new Unknown(kbytes), kstring); const value = Value.parseOrThrow(type, new Unknown(vbytes)); return new Entry(key, value); } Entry.readOrThrow = readOrThrow; })(Entry || (Entry = {})); export class Key { bytes; value; constructor(bytes, value) { this.bytes = bytes; this.value = value; } sizeOrThrow() { return this.bytes.bytes.length; } writeOrThrow(cursor) { cursor.writeOrThrow(this.bytes.bytes); } } (function (Key) { function initOrThrow(value) { const bytes = new TextEncoder().encode(value); return new Key(new Unknown(bytes), value); } Key.initOrThrow = initOrThrow; })(Key || (Key = {})); export var Value; (function (Value) { var _a, _b, _c, _d, _e, _f, _g; function parseOrThrow(type, value) { if (type === UInt32.type) return Readable.readFromBytesOrThrow(UInt32, value.bytes); if (type === UInt64.type) return Readable.readFromBytesOrThrow(UInt64, value.bytes); if (type === Boolean.type) return Readable.readFromBytesOrThrow(Boolean, value.bytes); if (type === Int32.type) return Readable.readFromBytesOrThrow(Int32, value.bytes); if (type === Int64.type) return Readable.readFromBytesOrThrow(Int64, value.bytes); if (type === String.type) return Readable.readFromBytesOrThrow(String, value.bytes); if (type === Bytes.type) return Readable.readFromBytesOrThrow(Bytes, value.bytes); throw new Error(); } Value.parseOrThrow = parseOrThrow; class UInt32 { value; #class = _a; constructor(value) { this.value = value; } get type() { return this.#class.type; } sizeOrThrow() { return 4; } writeOrThrow(cursor) { cursor.writeUint32OrThrow(this.value, true); } } _a = UInt32; Value.UInt32 = UInt32; (function (UInt32) { UInt32.type = 0x04; function readOrThrow(cursor) { return new UInt32(cursor.readUint32OrThrow(true)); } UInt32.readOrThrow = readOrThrow; })(UInt32 = Value.UInt32 || (Value.UInt32 = {})); class UInt64 { value; #class = _b; constructor(value) { this.value = value; } get type() { return this.#class.type; } sizeOrThrow() { return 8; } writeOrThrow(cursor) { cursor.writeBigUint64OrThrow(this.value, true); } } _b = UInt64; Value.UInt64 = UInt64; (function (UInt64) { UInt64.type = 0x05; function readOrThrow(cursor) { return new UInt64(cursor.readBigUint64OrThrow(true)); } UInt64.readOrThrow = readOrThrow; })(UInt64 = Value.UInt64 || (Value.UInt64 = {})); class Boolean { value; #class = _c; constructor(value) { this.value = value; } get type() { return this.#class.type; } sizeOrThrow() { return 1; } writeOrThrow(cursor) { cursor.writeUint8OrThrow(this.value ? 1 : 0); } } _c = Boolean; Value.Boolean = Boolean; (function (Boolean) { Boolean.type = 0x08; function readOrThrow(cursor) { const value = cursor.readUint8OrThrow(); if (value !== 0 && value !== 1) throw new Error(); return new Boolean(value === 1); } Boolean.readOrThrow = readOrThrow; })(Boolean = Value.Boolean || (Value.Boolean = {})); class Int32 { value; #class = _d; constructor(value) { this.value = value; } get type() { return this.#class.type; } sizeOrThrow() { return 4; } writeOrThrow(cursor) { cursor.writeUint32OrThrow(this.value < 0 ? this.value + (2 ** 32) : this.value, true); } } _d = Int32; Value.Int32 = Int32; (function (Int32) { Int32.type = 0x0C; function readOrThrow(cursor) { const uint = cursor.readUint32OrThrow(true); const sint = uint > ((2 ** 31) - 1) ? uint - (2 ** 32) : uint; return new Int32(sint); } Int32.readOrThrow = readOrThrow; })(Int32 = Value.Int32 || (Value.Int32 = {})); class Int64 { value; #class = _e; constructor(value) { this.value = value; } get type() { return this.#class.type; } sizeOrThrow() { return 8; } writeOrThrow(cursor) { cursor.writeBigUint64OrThrow(this.value < 0n ? this.value + (2n ** 64n) : this.value, true); } } _e = Int64; Value.Int64 = Int64; (function (Int64) { Int64.type = 0x0D; function readOrThrow(cursor) { const uint = cursor.readBigUint64OrThrow(true); const sint = uint > ((2n ** 63n) - 1n) ? uint - (2n ** 64n) : uint; return new Int64(sint); } Int64.readOrThrow = readOrThrow; })(Int64 = Value.Int64 || (Value.Int64 = {})); class String { bytes; value; #class = _f; constructor(bytes, value) { this.bytes = bytes; this.value = value; } get type() { return this.#class.type; } sizeOrThrow() { return this.bytes.bytes.length; } writeOrThrow(cursor) { cursor.writeOrThrow(this.bytes.bytes); } } _f = String; Value.String = String; (function (String) { String.type = 0x18; function readOrThrow(cursor) { const bytes = cursor.readOrThrow(cursor.remaining); const value = new TextDecoder().decode(bytes); return new String(new Unknown(bytes), value); } String.readOrThrow = readOrThrow; })(String = Value.String || (Value.String = {})); class Bytes { value; #class = _g; constructor(value) { this.value = value; } get type() { return this.#class.type; } sizeOrThrow() { return this.value.bytes.length; } writeOrThrow(cursor) { cursor.writeOrThrow(this.value.bytes); } } _g = Bytes; Value.Bytes = Bytes; (function (Bytes) { Bytes.type = 0x42; function readOrThrow(cursor) { return new Bytes(new Unknown(cursor.readOrThrow(cursor.remaining))); } Bytes.readOrThrow = readOrThrow; })(Bytes = Value.Bytes || (Value.Bytes = {})); })(Value || (Value = {}));