-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathprotocol.js
More file actions
83 lines (73 loc) · 2.28 KB
/
protocol.js
File metadata and controls
83 lines (73 loc) · 2.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import Core from '../core';
// https://github.com/airportyh/protomorphism
class Protocol {
constructor(spec) {
this.registry = new Map();
this.fallback = null;
function createFun(funName) {
return function(...args) {
const thing = args[0];
let fun = null;
if (thing === null && this.hasImplementation(Symbol('null'))) {
fun = this.registry.get(Symbol)[funName];
} else if (
Number.isInteger(thing) &&
this.hasImplementation(Core.Integer)
) {
fun = this.registry.get(Core.Integer)[funName];
} else if (
typeof thing === 'number' &&
!Number.isInteger(thing) &&
this.hasImplementation(Core.Float)
) {
fun = this.registry.get(Core.Float)[funName];
} else if (
typeof thing === 'string' &&
this.hasImplementation(Core.BitString)
) {
fun = this.registry.get(Core.BitString)[funName];
} else if (
thing &&
thing.has(Symbol.for('__struct__')) &&
this.hasImplementation(thing)
) {
fun = this.registry.get(
thing.get(Symbol.for('__struct__')).__MODULE__
)[funName];
} else if (thing !== null && this.hasImplementation(thing)) {
fun = this.registry.get(thing.constructor)[funName];
} else if (this.fallback) {
fun = this.fallback[funName];
}
if (fun != null) {
const retval = fun.apply(this, args);
return retval;
}
throw new Error(`No implementation found for ${thing}`);
};
}
for (const funName in spec) {
this[funName] = createFun(funName).bind(this);
}
}
implementation(type, implementation) {
if (type === null) {
this.fallback = implementation;
} else {
this.registry.set(type, implementation);
}
}
hasImplementation(thing) {
if (
thing === Core.Integer ||
thing === Core.Float ||
thing === Core.BitString
) {
return this.registry.has(thing);
} else if (thing && thing.has(Symbol.for('__struct__'))) {
return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__);
}
return this.registry.has(thing.constructor);
}
}
export default Protocol;