pessimism
Version:
A fast HAMT Map intended for KV caching and optimistic updates
282 lines (249 loc) • 7.17 kB
JavaScript
"use strict";
function __(e, r) {
return r.tag = e, r;
}
var e = Math.imul || function(e, r) {
return ((e >> 16) * (r |= 0) << 16) + (65535 & e) * r | 0;
}, r = [ 0 ];
function mask(r, t) {
return 1 << (r >>> e(t, 5) & 31);
}
function hash(e) {
for (var r = e.length - 1 | 0, t = 5381, i = 0; i <= r; ++i) {
t = ((t << 5) + t | 0) + e.charCodeAt(i) | 0;
}
return t >>> 1 & 1073741824 | -1073741825 & t;
}
function indexBit(e, r) {
var t = e & (r - 1 | 0);
return 127 & ((t = (t = (t = (858993459 & (t = t - (t >> 1 & 1431655765) | 0)) + (t >> 2 & 858993459) | 0) + (t >> 4) & 252645135) + (t >> 8) | 0) + (t >> 16) | 0);
}
function copyIndex(e, t) {
var i, a;
return i = t, a = e[2], i === r || i !== a ? [ e[0], e[1].slice(), t ] : e;
}
function traverseCopy(e, r, t) {
for (var i = e, a = 0; ;) {
var n = a, o = i, c = o[0], s = o[1], u = mask(r, n);
if ((c | u) !== c) {
return [ n, o ];
}
var v = indexBit(c, u), f = s[v];
if (f.tag) {
return [ n, o ];
}
var d = copyIndex(f[0], t);
s[v] = __(0, [ d ]), a = n + 1 | 0, i = d;
}
}
function resolveConflict(e, r, t, i, a, n) {
var o = mask(e, a), c = mask(r, a), s = o | c;
return __(0, [ [ s, o === c ? [ resolveConflict(e, r, t, i, a + 1 | 0, n) ] : 0 !== indexBit(s, o) ? [ i, t ] : [ t, i ], n ] ]);
}
function removeFromIndex(e, r, t) {
var i = e[0], a = i ^ r;
if (a !== i) {
var n = copyIndex(e, t);
return n[1].splice(indexBit(i, r), 1), n[0] = a, n;
}
return e;
}
function clearBox(e, r) {
for (;;) {
var t = e, i = t[3], a = t[2];
if (void 0 !== i) {
var n = i;
if (a === r) {
e = n;
continue;
}
return [ t[0], t[1], t[2], clearBox(n, r) ];
}
return a === r ? void 0 : t;
}
}
function clearOptimisticNode(e, r) {
switch (0 | e.tag) {
case 2:
var t = e[0];
if (0 === t[2]) {
return e;
}
var i = e[1], a = clearBox(t, r);
return void 0 !== a ? __(2, [ a, i ]) : __(4, [ i ]);
case 3:
for (var n = e[1], o = e[0], c = o.length, s = [], u = 0; u < c; ) {
var v = o[u];
if (0 === v[2]) {
s.push(v);
} else {
var f = clearBox(v, r);
void 0 !== f && s.push(f);
}
u = u + 1 | 0;
}
return s.length > 0 ? __(3, [ s, n ]) : __(4, [ n ]);
default:
return e;
}
}
function addToBucket(e, r) {
for (var t = e.slice(), i = t.length, a = 0 !== r[2], n = 0, o = !1; n < i && !o; ) {
var c = t[n];
c[0] === r[0] && (a && (r[3] = c), t[n] = r, o = !0), n = n + 1 | 0;
}
return o || t.push(r), t;
}
function removeFromBucket(e, r) {
for (var t = e.length, i = [], a = 0; a < t; ) {
var n = e[a];
n[0] !== r && i.push(n), a = a + 1 | 0;
}
return i;
}
function rebuildWithStack(e, r, t, i, a) {
for (;;) {
var n = t, o = r, c = e, s = mask(i, n);
if (!c) {
return o;
}
var u = c[1], v = c[0];
if (0 !== o[0]) {
var f = copyIndex(v, a), d = indexBit(f[0], s);
f[1][d] = __(0, [ o ]), t = n - 1 | 0, r = f, e = u;
} else {
t = n - 1 | 0, r = removeFromIndex(v, s, a), e = u;
}
}
}
function setOptimistic(e, r, t, i) {
var a = e[2], n = copyIndex(e, a), o = hash(r), c = traverseCopy(n, o, a), s = c[1], u = c[0], v = 0 !== i, f = mask(o, u), d = s[0] | f, l = indexBit(d, f);
if (d !== s[0]) {
s[1].splice(l, 0, __(1, [ r, t, o ])), s[0] = d;
} else {
var _, m, p, x = s[1][l], h = 0;
switch (0 | x.tag) {
case 0:
_ = x;
break;
case 1:
var k = x[2], B = x[1], b = x[0];
b === r && v ? _ = __(2, [ [ r, t, i, [ b, B, 0, void 0 ] ], o ]) : b === r ? _ = __(1, [ r, t, o ]) : k === o ? _ = __(3, [ [ [ b, B, 0, void 0 ], [ r, t, 0, void 0 ] ], o ]) : (m = k,
p = x, h = 1);
break;
case 2:
var g = x[0];
if (g[0] === r && v) {
_ = __(2, [ [ r, t, i, g ], o ]);
} else if (g[0] === r) {
_ = __(2, [ [ r, t, 0, void 0 ], o ]);
} else {
var I = x[1];
I === o ? _ = __(3, [ [ g, [ r, t, 0, void 0 ] ], o ]) : (m = I, p = x, h = 1);
}
break;
case 3:
var y = x[1];
if (y === o) {
var O = [ r, t, i, void 0 ];
_ = __(3, [ addToBucket(x[0], O), o ]);
} else {
m = y, p = x, h = 1;
}
break;
case 4:
_ = v ? __(2, [ [ r, t, i, void 0 ], o ]) : __(1, [ r, t, o ]);
}
1 === h && (_ = resolveConflict(m, o, p, v ? __(2, [ [ r, t, i, void 0 ], o ]) : __(1, [ r, t, o ]), u + 1 | 0, a)),
s[1][l] = _;
}
return n;
}
exports.asImmutable = function asImmutable(e) {
return e[2] = r, e;
}, exports.asMutable = function asMutable(e) {
return e[2] === r ? [ e[0], e[1], [ 0 ] ] : e;
}, exports.clearOptimistic = function clearOptimistic(e, r) {
for (var t = copyIndex(e, e[2]), i = 0; i <= 31; ++i) {
var a = 1 << i;
if (0 != (a & t[0])) {
var n = indexBit(t[0], a), o = clearOptimisticNode(t[1][n], r);
switch (0 | o.tag) {
case 0:
var c = clearOptimistic(o[0], r);
0 === c[0] ? (t[1].splice(n, 1), t[0] = t[0] ^ a) : t[1][n] = __(0, [ c ]);
break;
case 4:
t[1].splice(n, 1), t[0] = t[0] ^ a;
break;
default:
t[1][n] = o;
}
}
}
return t;
}, exports.get = function getUndefined(e, r) {
for (var t = hash(r), i = e, a = 0; ;) {
var n = a, o = i, c = o[0], s = o[1], u = mask(t, n);
if ((c | u) !== c) {
return;
}
var v = s[indexBit(c, u)];
switch (0 | v.tag) {
case 0:
a = n + 1 | 0, i = v[0];
continue;
case 1:
return v[0] === r ? v[1] : void 0;
case 2:
var f = v[0];
return f[0] === r ? f[1] : void 0;
case 3:
for (var d = v[0], l = r, _ = d.length, m = void 0, p = 0; void 0 === m && p < _; ) {
var x = d[p];
x[0] === l && (m = x[1]), p = p + 1 | 0;
}
return m;
case 4:
return;
}
}
}, exports.make = function make(e) {
return [ 0, [], r ];
}, exports.remove = function remove(e, r) {
for (var t = e[2], i = hash(r), a = 0, n = e, o = 0; ;) {
var c = o, s = n, u = a, v = s[0], f = s[1], d = mask(i, c);
if ((v | d) !== v) {
return e;
}
var l, _ = indexBit(v, d), m = f[_], p = 0;
switch (0 | m.tag) {
case 0:
o = c + 1 | 0, n = m[0], a = [ s, u ];
continue;
case 1:
l = m[0], p = 1;
break;
case 2:
l = m[0][0], p = 1;
break;
case 3:
if (m[1] === i) {
var x = removeFromBucket(m[0], r);
if (0 === x.length) {
return rebuildWithStack(u, removeFromIndex(s, d, t), c - 1 | 0, i, t);
}
var h = copyIndex(s, t);
return h[1][_] = __(3, [ x, i ]), rebuildWithStack(u, h, c - 1 | 0, i, t);
}
return e;
case 4:
return e;
}
if (1 === p) {
return l === r ? rebuildWithStack(u, removeFromIndex(s, d, t), c - 1 | 0, i, t) : e;
}
}
}, exports.set = function set(e, r, t) {
return setOptimistic(e, r, t, 0);
}, exports.setOptimistic = setOptimistic;