Dorian 0d073fa89e Add comprehensive installation and setup documentation
- Add GETTING_STARTED.md with quick start guide and development modes
- Add INSTALL.sh automated installation script
- Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md
- Add QUICK_REFERENCE.md for common commands
- Add SETUP_GUIDE.md with detailed setup instructions
- Update README.md with improved project overview
- Add did-wallet app dependencies and node_modules
2026-01-27 17:18:21 +00:00

246 lines
7.1 KiB
JavaScript

import { is } from './is.js';
import {
Token,
Type
} from './token.js';
import { Bl } from './bl.js';
import { encodeErrPrefix } from './common.js';
import { quickEncodeToken } from './jump.js';
import { asU8A } from './byte-utils.js';
import { encodeUint } from './0uint.js';
import { encodeNegint } from './1negint.js';
import { encodeBytes } from './2bytes.js';
import { encodeString } from './3string.js';
import { encodeArray } from './4array.js';
import { encodeMap } from './5map.js';
import { encodeTag } from './6tag.js';
import { encodeFloat } from './7float.js';
const defaultEncodeOptions = {
float64: false,
mapSorter,
quickEncodeToken
};
export function makeCborEncoders() {
const encoders = [];
encoders[Type.uint.major] = encodeUint;
encoders[Type.negint.major] = encodeNegint;
encoders[Type.bytes.major] = encodeBytes;
encoders[Type.string.major] = encodeString;
encoders[Type.array.major] = encodeArray;
encoders[Type.map.major] = encodeMap;
encoders[Type.tag.major] = encodeTag;
encoders[Type.float.major] = encodeFloat;
return encoders;
}
const cborEncoders = makeCborEncoders();
const buf = new Bl();
class Ref {
constructor(obj, parent) {
this.obj = obj;
this.parent = parent;
}
includes(obj) {
let p = this;
do {
if (p.obj === obj) {
return true;
}
} while (p = p.parent);
return false;
}
static createCheck(stack, obj) {
if (stack && stack.includes(obj)) {
throw new Error(`${ encodeErrPrefix } object contains circular references`);
}
return new Ref(obj, stack);
}
}
const simpleTokens = {
null: new Token(Type.null, null),
undefined: new Token(Type.undefined, undefined),
true: new Token(Type.true, true),
false: new Token(Type.false, false),
emptyArray: new Token(Type.array, 0),
emptyMap: new Token(Type.map, 0)
};
const typeEncoders = {
number(obj, _typ, _options, _refStack) {
if (!Number.isInteger(obj) || !Number.isSafeInteger(obj)) {
return new Token(Type.float, obj);
} else if (obj >= 0) {
return new Token(Type.uint, obj);
} else {
return new Token(Type.negint, obj);
}
},
bigint(obj, _typ, _options, _refStack) {
if (obj >= BigInt(0)) {
return new Token(Type.uint, obj);
} else {
return new Token(Type.negint, obj);
}
},
Uint8Array(obj, _typ, _options, _refStack) {
return new Token(Type.bytes, obj);
},
string(obj, _typ, _options, _refStack) {
return new Token(Type.string, obj);
},
boolean(obj, _typ, _options, _refStack) {
return obj ? simpleTokens.true : simpleTokens.false;
},
null(_obj, _typ, _options, _refStack) {
return simpleTokens.null;
},
undefined(_obj, _typ, _options, _refStack) {
return simpleTokens.undefined;
},
ArrayBuffer(obj, _typ, _options, _refStack) {
return new Token(Type.bytes, new Uint8Array(obj));
},
DataView(obj, _typ, _options, _refStack) {
return new Token(Type.bytes, new Uint8Array(obj.buffer, obj.byteOffset, obj.byteLength));
},
Array(obj, _typ, options, refStack) {
if (!obj.length) {
if (options.addBreakTokens === true) {
return [
simpleTokens.emptyArray,
new Token(Type.break)
];
}
return simpleTokens.emptyArray;
}
refStack = Ref.createCheck(refStack, obj);
const entries = [];
let i = 0;
for (const e of obj) {
entries[i++] = objectToTokens(e, options, refStack);
}
if (options.addBreakTokens) {
return [
new Token(Type.array, obj.length),
entries,
new Token(Type.break)
];
}
return [
new Token(Type.array, obj.length),
entries
];
},
Object(obj, typ, options, refStack) {
const isMap = typ !== 'Object';
const keys = isMap ? obj.keys() : Object.keys(obj);
const length = isMap ? obj.size : keys.length;
if (!length) {
if (options.addBreakTokens === true) {
return [
simpleTokens.emptyMap,
new Token(Type.break)
];
}
return simpleTokens.emptyMap;
}
refStack = Ref.createCheck(refStack, obj);
const entries = [];
let i = 0;
for (const key of keys) {
entries[i++] = [
objectToTokens(key, options, refStack),
objectToTokens(isMap ? obj.get(key) : obj[key], options, refStack)
];
}
sortMapEntries(entries, options);
if (options.addBreakTokens) {
return [
new Token(Type.map, length),
entries,
new Token(Type.break)
];
}
return [
new Token(Type.map, length),
entries
];
}
};
typeEncoders.Map = typeEncoders.Object;
typeEncoders.Buffer = typeEncoders.Uint8Array;
for (const typ of 'Uint8Clamped Uint16 Uint32 Int8 Int16 Int32 BigUint64 BigInt64 Float32 Float64'.split(' ')) {
typeEncoders[`${ typ }Array`] = typeEncoders.DataView;
}
function objectToTokens(obj, options = {}, refStack) {
const typ = is(obj);
const customTypeEncoder = options && options.typeEncoders && options.typeEncoders[typ] || typeEncoders[typ];
if (typeof customTypeEncoder === 'function') {
const tokens = customTypeEncoder(obj, typ, options, refStack);
if (tokens != null) {
return tokens;
}
}
const typeEncoder = typeEncoders[typ];
if (!typeEncoder) {
throw new Error(`${ encodeErrPrefix } unsupported type: ${ typ }`);
}
return typeEncoder(obj, typ, options, refStack);
}
function sortMapEntries(entries, options) {
if (options.mapSorter) {
entries.sort(options.mapSorter);
}
}
function mapSorter(e1, e2) {
const keyToken1 = Array.isArray(e1[0]) ? e1[0][0] : e1[0];
const keyToken2 = Array.isArray(e2[0]) ? e2[0][0] : e2[0];
if (keyToken1.type !== keyToken2.type) {
return keyToken1.type.compare(keyToken2.type);
}
const major = keyToken1.type.major;
const tcmp = cborEncoders[major].compareTokens(keyToken1, keyToken2);
if (tcmp === 0) {
console.warn('WARNING: complex key types used, CBOR key sorting guarantees are gone');
}
return tcmp;
}
function tokensToEncoded(buf, tokens, encoders, options) {
if (Array.isArray(tokens)) {
for (const token of tokens) {
tokensToEncoded(buf, token, encoders, options);
}
} else {
encoders[tokens.type.major](buf, tokens, options);
}
}
function encodeCustom(data, encoders, options) {
const tokens = objectToTokens(data, options);
if (!Array.isArray(tokens) && options.quickEncodeToken) {
const quickBytes = options.quickEncodeToken(tokens);
if (quickBytes) {
return quickBytes;
}
const encoder = encoders[tokens.type.major];
if (encoder.encodedSize) {
const size = encoder.encodedSize(tokens, options);
const buf = new Bl(size);
encoder(buf, tokens, options);
if (buf.chunks.length !== 1) {
throw new Error(`Unexpected error: pre-calculated length for ${ tokens } was wrong`);
}
return asU8A(buf.chunks[0]);
}
}
buf.reset();
tokensToEncoded(buf, tokens, encoders, options);
return buf.toBytes(true);
}
function encode(data, options) {
options = Object.assign({}, defaultEncodeOptions, options);
return encodeCustom(data, cborEncoders, options);
}
export {
objectToTokens,
encode,
encodeCustom,
Ref
};