pessimism
Version:
A fast HAMT Map intended for KV caching and optimistic updates
294 lines (255 loc) • 7.1 kB
JavaScript
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, c = i, o = c[0], u = c[1], v = mask(r, n);
if ((o | v) !== o) {
return [ n, c ];
}
var s = indexBit(o, v), f = u[s];
if (f.tag) {
return [ n, c ];
}
var d = copyIndex(f[0], t);
u[s] = __(0, [ d ]), a = n + 1 | 0, i = d;
}
}
function resolveConflict(e, r, t, i, a, n) {
var c = mask(e, a), o = mask(r, a), u = c | o;
return __(0, [ [ u, c === o ? [ resolveConflict(e, r, t, i, a + 1 | 0, n) ] : 0 !== indexBit(u, c) ? [ 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], c = e[0], o = c.length, u = [], v = 0; v < o; ) {
var s = c[v];
if (0 === s[2]) {
u.push(s);
} else {
var f = clearBox(s, r);
void 0 !== f && u.push(f);
}
v = v + 1 | 0;
}
return u.length > 0 ? __(3, [ u, n ]) : __(4, [ n ]);
default:
return e;
}
}
function addToBucket(e, r) {
for (var t = e.slice(), i = t.length, a = 0 !== r[2], n = 0, c = !1; n < i && !c; ) {
var o = t[n];
o[0] === r[0] && (a && (r[3] = o), t[n] = r, c = !0), n = n + 1 | 0;
}
return c || 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, c = r, o = e, u = mask(i, n);
if (!o) {
return c;
}
var v = o[1], s = o[0];
if (0 !== c[0]) {
var f = copyIndex(s, a), d = indexBit(f[0], u);
f[1][d] = __(0, [ c ]), t = n - 1 | 0, r = f, e = v;
} else {
t = n - 1 | 0, r = removeFromIndex(s, u, a), e = v;
}
}
}
function make(e) {
return [ 0, [], r ];
}
function asMutable(e) {
return e[2] === r ? [ e[0], e[1], [ 0 ] ] : e;
}
function asImmutable(e) {
return e[2] = r, e;
}
function getUndefined(e, r) {
for (var t = hash(r), i = e, a = 0; ;) {
var n = a, c = i, o = c[0], u = c[1], v = mask(t, n);
if ((o | v) !== o) {
return;
}
var s = u[indexBit(o, v)];
switch (0 | s.tag) {
case 0:
a = n + 1 | 0, i = s[0];
continue;
case 1:
return s[0] === r ? s[1] : void 0;
case 2:
var f = s[0];
return f[0] === r ? f[1] : void 0;
case 3:
for (var d = s[0], l = r, _ = d.length, m = void 0, h = 0; void 0 === m && h < _; ) {
var k = d[h];
k[0] === l && (m = k[1]), h = h + 1 | 0;
}
return m;
case 4:
return;
}
}
}
function setOptimistic(e, r, t, i) {
var a = e[2], n = copyIndex(e, a), c = hash(r), o = traverseCopy(n, c, a), u = o[1], v = o[0], s = 0 !== i, f = mask(c, v), d = u[0] | f, l = indexBit(d, f);
if (d !== u[0]) {
u[1].splice(l, 0, __(1, [ r, t, c ])), u[0] = d;
} else {
var _, m, h, k = u[1][l], p = 0;
switch (0 | k.tag) {
case 0:
_ = k;
break;
case 1:
var x = k[2], g = k[1], B = k[0];
B === r && s ? _ = __(2, [ [ r, t, i, [ B, g, 0, void 0 ] ], c ]) : B === r ? _ = __(1, [ r, t, c ]) : x === c ? _ = __(3, [ [ [ B, g, 0, void 0 ], [ r, t, 0, void 0 ] ], c ]) : (m = x,
h = k, p = 1);
break;
case 2:
var b = k[0];
if (b[0] === r && s) {
_ = __(2, [ [ r, t, i, b ], c ]);
} else if (b[0] === r) {
_ = __(2, [ [ r, t, 0, void 0 ], c ]);
} else {
var I = k[1];
I === c ? _ = __(3, [ [ b, [ r, t, 0, void 0 ] ], c ]) : (m = I, h = k, p = 1);
}
break;
case 3:
var y = k[1];
if (y === c) {
var O = [ r, t, i, void 0 ];
_ = __(3, [ addToBucket(k[0], O), c ]);
} else {
m = y, h = k, p = 1;
}
break;
case 4:
_ = s ? __(2, [ [ r, t, i, void 0 ], c ]) : __(1, [ r, t, c ]);
}
1 === p && (_ = resolveConflict(m, c, h, s ? __(2, [ [ r, t, i, void 0 ], c ]) : __(1, [ r, t, c ]), v + 1 | 0, a)),
u[1][l] = _;
}
return n;
}
function set(e, r, t) {
return setOptimistic(e, r, t, 0);
}
function remove(e, r) {
for (var t = e[2], i = hash(r), a = 0, n = e, c = 0; ;) {
var o = c, u = n, v = a, s = u[0], f = u[1], d = mask(i, o);
if ((s | d) !== s) {
return e;
}
var l, _ = indexBit(s, d), m = f[_], h = 0;
switch (0 | m.tag) {
case 0:
c = o + 1 | 0, n = m[0], a = [ u, v ];
continue;
case 1:
l = m[0], h = 1;
break;
case 2:
l = m[0][0], h = 1;
break;
case 3:
if (m[1] === i) {
var k = removeFromBucket(m[0], r);
if (0 === k.length) {
return rebuildWithStack(v, removeFromIndex(u, d, t), o - 1 | 0, i, t);
}
var p = copyIndex(u, t);
return p[1][_] = __(3, [ k, i ]), rebuildWithStack(v, p, o - 1 | 0, i, t);
}
return e;
case 4:
return e;
}
if (1 === h) {
return l === r ? rebuildWithStack(v, removeFromIndex(u, d, t), o - 1 | 0, i, t) : e;
}
}
}
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), c = clearOptimisticNode(t[1][n], r);
switch (0 | c.tag) {
case 0:
var o = clearOptimistic(c[0], r);
0 === o[0] ? (t[1].splice(n, 1), t[0] = t[0] ^ a) : t[1][n] = __(0, [ o ]);
break;
case 4:
t[1].splice(n, 1), t[0] = t[0] ^ a;
break;
default:
t[1][n] = c;
}
}
}
return t;
}
export { asImmutable, asMutable, clearOptimistic, getUndefined as get, make, remove, set, setOptimistic };