mirror of
https://github.com/pezkuwichain/pezkuwi-api.git
synced 2026-04-23 00:17:55 +00:00
31467f90d4
- @pezkuwi/papi-utils (rebrand of @polkadot-api/utils) - @pezkuwi/bizinikiwi-bindings (rebrand of @polkadot-api/substrate-bindings) - @pezkuwi/metadata-builders (rebrand of @polkadot-api/metadata-builders) - @pezkuwi/merkleize-metadata (rebrand of @polkadot-api/merkleize-metadata) All @polkadot-api references replaced with @pezkuwi equivalents.
162 lines
4.8 KiB
JavaScript
162 lines
4.8 KiB
JavaScript
function buildLookupGraph(lookupFn, lookupLength) {
|
|
const result = /* @__PURE__ */ new Map();
|
|
const visited = /* @__PURE__ */ new Set();
|
|
const addEdge = (from, to) => {
|
|
if (!result.has(from))
|
|
result.set(from, {
|
|
entry: lookupFn(from),
|
|
backRefs: /* @__PURE__ */ new Set(),
|
|
refs: /* @__PURE__ */ new Set()
|
|
});
|
|
if (!result.has(to))
|
|
result.set(to, {
|
|
entry: lookupFn(to),
|
|
backRefs: /* @__PURE__ */ new Set(),
|
|
refs: /* @__PURE__ */ new Set()
|
|
});
|
|
result.get(from).refs.add(to);
|
|
result.get(to).backRefs.add(from);
|
|
};
|
|
for (let i = 0; i < lookupLength; i++) {
|
|
const entry = lookupFn(i);
|
|
if (i !== entry.id) {
|
|
addEdge(i, entry.id);
|
|
}
|
|
if (visited.has(entry.id)) continue;
|
|
visited.add(entry.id);
|
|
switch (entry.type) {
|
|
case "array":
|
|
case "option":
|
|
case "sequence":
|
|
addEdge(entry.id, entry.value.id);
|
|
break;
|
|
case "enum":
|
|
Object.values(entry.value).forEach((enumEntry) => {
|
|
switch (enumEntry.type) {
|
|
case "array":
|
|
case "lookupEntry":
|
|
addEdge(entry.id, enumEntry.value.id);
|
|
break;
|
|
case "struct":
|
|
case "tuple":
|
|
Object.values(enumEntry.value).forEach(
|
|
(v) => addEdge(entry.id, v.id)
|
|
);
|
|
break;
|
|
}
|
|
});
|
|
break;
|
|
case "result":
|
|
addEdge(entry.id, entry.value.ok.id);
|
|
addEdge(entry.id, entry.value.ko.id);
|
|
break;
|
|
case "struct":
|
|
case "tuple":
|
|
Object.values(entry.value).forEach((v) => addEdge(entry.id, v.id));
|
|
break;
|
|
}
|
|
if (!result.has(entry.id)) {
|
|
result.set(entry.id, {
|
|
backRefs: /* @__PURE__ */ new Set(),
|
|
refs: /* @__PURE__ */ new Set(),
|
|
entry
|
|
});
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
const subgraphCache = /* @__PURE__ */ new WeakMap();
|
|
function _getSubgraph(id, graph, result, cache) {
|
|
if (result.has(id)) return;
|
|
const node = graph.get(id);
|
|
result.set(id, node);
|
|
cache.set(id, result);
|
|
node.refs.forEach((ref) => _getSubgraph(ref, graph, result, cache));
|
|
node.backRefs.forEach((ref) => _getSubgraph(ref, graph, result, cache));
|
|
}
|
|
function getSubgraph(id, graph) {
|
|
if (!subgraphCache.has(graph)) {
|
|
subgraphCache.set(graph, /* @__PURE__ */ new Map());
|
|
}
|
|
const cache = subgraphCache.get(graph);
|
|
if (cache.has(id)) return cache.get(id);
|
|
const result = /* @__PURE__ */ new Map();
|
|
_getSubgraph(id, graph, result, cache);
|
|
return result;
|
|
}
|
|
function getStronglyConnectedComponents(graph) {
|
|
const tarjanState = /* @__PURE__ */ new Map();
|
|
let index = 0;
|
|
const stack = [];
|
|
const result = [];
|
|
function strongConnect(v) {
|
|
const state = {
|
|
index,
|
|
lowLink: index,
|
|
onStack: true
|
|
};
|
|
tarjanState.set(v, state);
|
|
index++;
|
|
stack.push(v);
|
|
const edges = graph.get(v).refs;
|
|
for (let w of edges) {
|
|
const edgeState = tarjanState.get(w);
|
|
if (!edgeState) {
|
|
strongConnect(w);
|
|
state.lowLink = Math.min(state.lowLink, tarjanState.get(w).lowLink);
|
|
} else if (edgeState.onStack) {
|
|
state.lowLink = Math.min(state.lowLink, edgeState.index);
|
|
}
|
|
}
|
|
if (state.lowLink === state.index) {
|
|
const component = /* @__PURE__ */ new Set();
|
|
let poppedNode = -1;
|
|
do {
|
|
poppedNode = stack.pop();
|
|
tarjanState.get(poppedNode).onStack = false;
|
|
component.add(poppedNode);
|
|
} while (poppedNode !== v);
|
|
result.push(component);
|
|
}
|
|
}
|
|
for (const node of graph.keys()) {
|
|
if (!tarjanState.has(node)) {
|
|
strongConnect(node);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function mergeSCCsWithCommonNodes(stronglyConnectedComponents) {
|
|
const scc = stronglyConnectedComponents;
|
|
const ungroupedCycles = new Set(scc.map((_, i) => i));
|
|
const edges = new Map(scc.map((_, i) => [i, /* @__PURE__ */ new Set()]));
|
|
scc.forEach((cycle, i) => {
|
|
scc.slice(i + 1).forEach((otherCycle, _j) => {
|
|
const j = _j + i + 1;
|
|
const combined = /* @__PURE__ */ new Set([...cycle, ...otherCycle]);
|
|
if (combined.size !== cycle.size + otherCycle.size) {
|
|
edges.get(i).add(j);
|
|
edges.get(j).add(i);
|
|
}
|
|
});
|
|
});
|
|
const groups = [];
|
|
while (ungroupedCycles.size) {
|
|
const group = /* @__PURE__ */ new Set();
|
|
const toVisit = [ungroupedCycles.values().next().value];
|
|
while (toVisit.length) {
|
|
const idx = toVisit.pop();
|
|
if (!ungroupedCycles.has(idx)) continue;
|
|
ungroupedCycles.delete(idx);
|
|
const cycle = scc[idx];
|
|
cycle.forEach((v) => group.add(Number(v)));
|
|
edges.get(idx).forEach((n) => toVisit.push(n));
|
|
}
|
|
groups.push(group);
|
|
}
|
|
return groups;
|
|
}
|
|
|
|
export { buildLookupGraph, getStronglyConnectedComponents, getSubgraph, mergeSCCsWithCommonNodes };
|
|
//# sourceMappingURL=lookup-graph.mjs.map
|