73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { embed, GenericEmbedded } from "./embedded";
|
|
import { Bytes } from "./bytes";
|
|
import { Record, Tuple } from "./record";
|
|
import { Value } from "./values";
|
|
import { Dictionary, Set } from "./dictionary";
|
|
|
|
export function fromJS<T = GenericEmbedded>(x: any): Value<T> {
|
|
switch (typeof x) {
|
|
case 'number':
|
|
if (!Number.isInteger(x)) {
|
|
// We require that clients be explicit about integer vs. non-integer types.
|
|
throw new TypeError("Refusing to autoconvert non-integer number to Double");
|
|
}
|
|
// FALL THROUGH
|
|
case 'bigint':
|
|
case 'string':
|
|
case 'symbol':
|
|
case 'boolean':
|
|
return x;
|
|
|
|
case 'undefined':
|
|
case 'function':
|
|
break;
|
|
|
|
case 'object':
|
|
if (x === null) {
|
|
break;
|
|
}
|
|
if (typeof x.__as_preserve__ === 'function') {
|
|
return x.__as_preserve__();
|
|
}
|
|
if (Record.isRecord<Value<T>, Tuple<Value<T>>, T>(x)) {
|
|
return x;
|
|
}
|
|
if (Array.isArray(x)) {
|
|
return x.map<Value<T>>(fromJS);
|
|
}
|
|
if (ArrayBuffer.isView(x) || x instanceof ArrayBuffer) {
|
|
return Bytes.from(x);
|
|
}
|
|
if (Map.isMap(x)) {
|
|
const d = new Dictionary<T>();
|
|
x.forEach((v, k) => d.set(fromJS(k), fromJS(v)));
|
|
return d;
|
|
}
|
|
if (Set.isSet(x)) {
|
|
const s = new Set<T>();
|
|
x.forEach(v => s.add(fromJS(v)));
|
|
return s;
|
|
}
|
|
// Just... assume it's a T.
|
|
return embed(x as T);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
throw new TypeError("Cannot represent JavaScript value as Preserves: " + x);
|
|
}
|
|
|
|
declare module "./dictionary" {
|
|
namespace Dictionary {
|
|
export function fromJS<T = GenericEmbedded, V = GenericEmbedded>(x: object): Dictionary<T, Value<V>>;
|
|
}
|
|
}
|
|
|
|
Dictionary.fromJS = function <T = GenericEmbedded, V = GenericEmbedded>(x: object): Dictionary<T, Value<V>> {
|
|
if (Dictionary.isDictionary<T, Value<V>>(x)) return x;
|
|
const d = new Dictionary<T, Value<V>>();
|
|
Object.entries(x).forEach(([key, value]) => d.set(key, fromJS(value)));
|
|
return d;
|
|
};
|