UNPKG

pessimism

Version:

A fast HAMT Map intended for KV caching and optimistic updates

323 lines (304 loc) 8.64 kB
import * as Block from "bs-platform/lib/es6/block.js"; import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; import * as Js_undefined from "bs-platform/lib/es6/js_undefined.js"; function hash(x) { var length = x.length; var explode = function (_h, _i) { while(true) { var i = _i; var h = _h; if (i < length) { var h2 = ((h << 5) + h | 0) + x.charCodeAt(i) | 0; _i = i + 1 | 0; _h = h2; continue ; } else { return h; } }; }; var x$1 = explode(5381, 0); return (x$1 >>> 1) & 1073741824 | x$1 & -1073741825; } function arrayRemove(arr, index) { arr.splice(index, 1); return /* () */0; } function make(param) { return new Map(); } function getUndefined(map, k) { var item = map.get(hash(k)); if (Js_undefined.testAny(item)) { return undefined; } else { switch (item.tag | 0) { case 0 : var value = item[/* value */1]; if (item[/* key */0] === k) { return value; } else { return undefined; } case 1 : var match = item[0]; var value$1 = match[/* value */2]; if (match[/* key */0] === k) { return value$1; } else { return undefined; } case 2 : var match$1 = item[0].find((function (param) { return param[/* key */0] === k; })); if (match$1 !== undefined) { return match$1[/* value */2]; } else { return undefined; } } } } function get(map, k) { return Caml_option.undefined_to_opt(getUndefined(map, k)); } function setOptimistic(map, k, v, id) { var code = hash(k); var optimistic = id !== 0; var item = map.get(code); var newItem; if (Js_undefined.testAny(item)) { newItem = optimistic ? /* Chain */Block.__(1, [/* record */[ /* key */k, /* id */id, /* value */v, /* prev */undefined ]]) : /* Raw */Block.__(0, [ /* key */k, /* value */v ]); } else { switch (item.tag | 0) { case 0 : var key = item[/* key */0]; var value = item[/* value */1]; if (key === k && !optimistic) { item[/* value */1] = v; newItem = item; } else if (key === k) { var prev = /* record */[ /* key */key, /* id */0, /* value */value, /* prev */undefined ]; var box = /* record */[ /* key */key, /* id */id, /* value */v, /* prev */prev ]; newItem = /* Chain */Block.__(1, [box]); } else { var box$1 = /* record */[ /* key */k, /* id */id, /* value */v, /* prev */undefined ]; var other = /* record */[ /* key */key, /* id */0, /* value */value, /* prev */undefined ]; newItem = /* Collision */Block.__(2, [/* array */[ box$1, other ]]); } break; case 1 : var prev$1 = item[0]; var key$1 = prev$1[/* key */0]; if (key$1 === k && !optimistic) { newItem = /* Raw */Block.__(0, [ /* key */key$1, /* value */v ]); } else if (key$1 === k) { var box$2 = /* record */[ /* key */key$1, /* id */id, /* value */v, /* prev */prev$1 ]; newItem = /* Chain */Block.__(1, [box$2]); } else { var box$3 = /* record */[ /* key */k, /* id */id, /* value */v, /* prev */undefined ]; newItem = /* Collision */Block.__(2, [/* array */[ box$3, prev$1 ]]); } break; case 2 : var bucket = item[0]; var index = bucket.findIndex((function (param) { return param[/* key */0] === k; })); if (index > -1) { var prev$2 = bucket[index]; var box$4 = /* record */[ /* key */k, /* id */id, /* value */v, /* prev */optimistic ? prev$2 : undefined ]; bucket[index] = box$4; } else { var box$5 = /* record */[ /* key */k, /* id */id, /* value */v, /* prev */undefined ]; bucket.push(box$5); } newItem = item; break; } } map.set(code, newItem); return map; } function set(map, k, v) { return setOptimistic(map, k, v, 0); } function remove(map, k) { var code = hash(k); var item = map.get(code); if (!Js_undefined.testAny(item)) { switch (item.tag | 0) { case 0 : if (item[/* key */0] === k) { map.delete(code); } break; case 1 : if (item[0][/* key */0] === k) { map.delete(code); } break; case 2 : var bucket = item[0]; var index = bucket.findIndex((function (param) { return param[/* key */0] === k; })); if (index > -1) { arrayRemove(bucket, index); } break; } } return map; } function clearBoxOptimistic(box, optid) { var filter = function (_x) { while(true) { var x = _x; if (x !== undefined) { var b = x; var prev = b[/* prev */3]; if (b[/* id */1] !== optid) { b[/* prev */3] = filter(b[/* prev */3]); return x; } else { _x = prev; continue ; } } else { return undefined; } }; }; return filter(box); } function clearOptimistic(map, optid) { map.forEach((function (node, code) { switch (node.tag | 0) { case 0 : return /* () */0; case 1 : var box = node[0]; if (box[/* id */1] !== 0) { var match = clearBoxOptimistic(box, optid); if (match !== undefined) { map.set(code, /* Chain */Block.__(1, [match])); return /* () */0; } else { map.delete(code); return /* () */0; } } else { return /* () */0; } case 2 : var bucket = node[0].reduce((function (acc, box) { if (box[/* id */1] !== 0) { var match = clearBoxOptimistic(box, optid); if (match !== undefined) { acc.push(match); return acc; } else { return acc; } } else { acc.push(box); return acc; } }), /* array */[]); var len = bucket.length; if (len !== 1) { if (len !== 0) { map.set(code, /* Collision */Block.__(2, [bucket])); return /* () */0; } else { map.delete(code); return /* () */0; } } else { var box$1 = bucket[0]; var match$1 = box$1[/* id */1]; if (match$1 !== 0) { map.set(code, /* Chain */Block.__(1, [box$1])); return /* () */0; } else { var value = box$1[/* value */2]; map.set(code, /* Raw */Block.__(0, [ /* key */box$1[/* key */0], /* value */value ])); return /* () */0; } } } })); return map; } export { make , get , getUndefined , remove , set , setOptimistic , clearOptimistic , } /* No side effect */