anyid
Version:
A simple and flexible API to generate various kinds of string ID / code.
146 lines • 4.57 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
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 assert_1 = __importDefault(require("assert"));
const _ = __importStar(require("lodash"));
const encode_1 = require("./encode");
const utils_1 = require("./utils");
class Value {
constructor(owner) {
this.owner = owner;
}
set bits(n) {
this._bits = n;
}
get bits() {
if (!this._bits) {
this._bits = this.owner.sectionBitLength();
}
return this._bits;
}
returnValue(v) {
return this.bits ? utils_1.toBuffer(v, Math.ceil(this.bits / 8)) : utils_1.toBuffer(v);
}
}
exports.Value = Value;
class Delimiter {
constructor(delimiter) {
this.delimiter = delimiter;
}
id(_unused) { return this.delimiter; }
}
class AnyId {
constructor() {
this._sections = [];
this._values = [];
}
static use(mixin) {
const prototype = AnyId.prototype;
Object.getOwnPropertyNames(mixin.prototype).forEach((name) => {
prototype[name] = mixin.prototype[name];
});
}
get codec() {
try {
return this._codec ? this._codec : this._parent.codec;
}
catch (_a) {
throw new Error('Missing encode()');
}
}
id(arg) {
if (this.hasValue()) {
const { bits, buf } = _.reduceRight(this._values, (result, value) => {
const v = value.value(arg);
const b = value.bits || v.length * 8;
return {
bits: b + result.bits,
buf: utils_1.concatBits(v, b, result.buf, result.bits)
};
}, { bits: 0, buf: Buffer.alloc(0) });
const c = this.codec.encode(buf);
if (this._length) {
if (c.length > this._length) {
return c.substr(c.length - this._length);
}
if (c.length < this._length) {
return _.padStart(c, this._length, this.codec.padChar());
}
}
return c;
}
return this._sections.map((section) => section.id(arg)).join('');
}
section(anyid) {
assert_1.default(!this.hasValue(), 'Do not mix section with value');
anyid._parent = this;
this._sections.push(anyid);
return this;
}
delimiter(d) {
assert_1.default(!this.hasValue(), 'Do not mix delimiter with value');
this._sections.push(new Delimiter(d));
return this;
}
encode(charset) {
assert_1.default(!this._codec, 'Duplicated encode');
this._codec = encode_1.codec(charset);
return this;
}
length(n) {
assert_1.default(!this._length, 'Duplicated length');
assert_1.default(n > 0, 'Length must be larger than zero');
this._length = n;
return this;
}
bits(n) {
assert_1.default(n > 0, 'Bit must be larger than zero');
this._bits = n;
return this;
}
addValue(value) {
assert_1.default(!this.hasSection(), 'Section/delimiter already exist. Value need to be put inside section');
value.bits = this._bits;
this._bits = undefined;
this._values.push(value);
}
lastValue() {
return _.last(this._values);
}
findValueByType(type) {
for (const v of this._values) {
if (v.constructor.name === type) {
return v;
}
}
for (const s of this._sections) {
if (s instanceof AnyId) {
const v = s.findValueByType(type);
if (v) {
return v;
}
}
}
return this._parent ? this._parent.findValueByType(type) : undefined;
}
sectionBitLength() {
return this._length ? this.codec.bytesForLength(this._length) * 8 : undefined;
}
hasSection() {
return this._sections.length > 0;
}
hasValue() {
return this._values.length > 0;
}
}
exports.AnyId = AnyId;
//# sourceMappingURL=core.js.map