Skip to main content
Glama
ssv445

Lorem Ipsum MCP Server

by ssv445
node.ts9.38 kB
import { equals } from "../../Equal.js" import type { HashMap } from "../../HashMap.js" import * as O from "../../Option.js" import { isTagged } from "../../Predicate.js" import * as Stack from "../stack.js" import { arraySpliceIn, arraySpliceOut, arrayUpdate } from "./array.js" import { fromBitmap, hashFragment, toBitmap } from "./bitwise.js" import { MAX_INDEX_NODE, MIN_ARRAY_NODE, SIZE } from "./config.js" /** @internal */ export type Node<K, V> = | EmptyNode<K, V> | LeafNode<K, V> | CollisionNode<K, V> | IndexedNode<K, V> | ArrayNode<K, V> /** @internal */ export interface SizeRef { value: number // mutable by design } /** @internal */ export class EmptyNode<out K, out V> { readonly _tag = "EmptyNode" modify( edit: number, _shift: number, f: HashMap.UpdateFn<V>, hash: number, key: K, size: SizeRef ): Node<K, V> { const v = f(O.none()) if (O.isNone(v)) return new EmptyNode() ;++size.value return new LeafNode(edit, hash, key, v) } } /** @internal */ export function isEmptyNode(a: unknown): a is EmptyNode<unknown, unknown> { return isTagged(a, "EmptyNode") } /** @internal */ export function isLeafNode<K, V>( node: Node<K, V> ): node is EmptyNode<K, V> | LeafNode<K, V> | CollisionNode<K, V> { return isEmptyNode(node) || node._tag === "LeafNode" || node._tag === "CollisionNode" } /** @internal */ export function canEditNode<K, V>(node: Node<K, V>, edit: number): boolean { return isEmptyNode(node) ? false : edit === node.edit } /** @internal */ export class LeafNode<out K, out V> { readonly _tag = "LeafNode" constructor( readonly edit: number, readonly hash: number, readonly key: K, public value: O.Option<V> ) {} modify( edit: number, shift: number, f: HashMap.UpdateFn<V>, hash: number, key: K, size: SizeRef ): Node<K, V> { if (equals(key, this.key)) { const v = f(this.value) if (v === this.value) return this else if (O.isNone(v)) { ;--size.value return new EmptyNode() } if (canEditNode(this, edit)) { this.value = v return this } return new LeafNode(edit, hash, key, v) } const v = f(O.none()) if (O.isNone(v)) return this ;++size.value return mergeLeaves( edit, shift, this.hash, this, hash, new LeafNode(edit, hash, key, v) ) } } /** @internal */ export class CollisionNode<out K, out V> { readonly _tag = "CollisionNode" constructor( readonly edit: number, readonly hash: number, readonly children: Array<Node<K, V>> ) {} modify( edit: number, shift: number, f: HashMap.UpdateFn<V>, hash: number, key: K, size: SizeRef ): Node<K, V> { if (hash === this.hash) { const canEdit = canEditNode(this, edit) const list = this.updateCollisionList( canEdit, edit, this.hash, this.children, f, key, size ) if (list === this.children) return this return list.length > 1 ? new CollisionNode(edit, this.hash, list) : list[0]! // collapse single element collision list } const v = f(O.none()) if (O.isNone(v)) return this ;++size.value return mergeLeaves( edit, shift, this.hash, this, hash, new LeafNode(edit, hash, key, v) ) } updateCollisionList( mutate: boolean, edit: number, hash: number, list: Array<Node<K, V>>, f: HashMap.UpdateFn<V>, key: K, size: SizeRef ) { const len = list.length for (let i = 0; i < len; ++i) { const child = list[i]! if ("key" in child && equals(key, child.key)) { const value = child.value const newValue = f(value) if (newValue === value) return list if (O.isNone(newValue)) { ;--size.value return arraySpliceOut(mutate, i, list) } return arrayUpdate(mutate, i, new LeafNode(edit, hash, key, newValue), list) } } const newValue = f(O.none()) if (O.isNone(newValue)) return list ;++size.value return arrayUpdate(mutate, len, new LeafNode(edit, hash, key, newValue), list) } } /** @internal */ export class IndexedNode<out K, out V> { readonly _tag = "IndexedNode" constructor( readonly edit: number, public mask: number, public children: Array<Node<K, V>> ) {} modify( edit: number, shift: number, f: HashMap.UpdateFn<V>, hash: number, key: K, size: SizeRef ): Node<K, V> { const mask = this.mask const children = this.children const frag = hashFragment(shift, hash) const bit = toBitmap(frag) const indx = fromBitmap(mask, bit) const exists = mask & bit const canEdit = canEditNode(this, edit) if (!exists) { const _newChild = new EmptyNode<K, V>().modify(edit, shift + SIZE, f, hash, key, size) if (!_newChild) return this return children.length >= MAX_INDEX_NODE ? expand(edit, frag, _newChild, mask, children) : new IndexedNode(edit, mask | bit, arraySpliceIn(canEdit, indx, _newChild, children)) } const current = children[indx]! const child = current.modify(edit, shift + SIZE, f, hash, key, size) if (current === child) return this let bitmap = mask let newChildren if (isEmptyNode(child)) { // remove bitmap &= ~bit if (!bitmap) return new EmptyNode() if (children.length <= 2 && isLeafNode(children[indx ^ 1]!)) { return children[indx ^ 1]! // collapse } newChildren = arraySpliceOut(canEdit, indx, children) } else { // modify newChildren = arrayUpdate(canEdit, indx, child, children) } if (canEdit) { this.mask = bitmap this.children = newChildren return this } return new IndexedNode(edit, bitmap, newChildren) } } /** @internal */ export class ArrayNode<out K, out V> { readonly _tag = "ArrayNode" constructor( readonly edit: number, public size: number, public children: Array<Node<K, V>> ) {} modify( edit: number, shift: number, f: HashMap.UpdateFn<V>, hash: number, key: K, size: SizeRef ): Node<K, V> { let count = this.size const children = this.children const frag = hashFragment(shift, hash) const child = children[frag] const newChild = (child || new EmptyNode<K, V>()).modify( edit, shift + SIZE, f, hash, key, size ) if (child === newChild) return this const canEdit = canEditNode(this, edit) let newChildren if (isEmptyNode(child) && !isEmptyNode(newChild)) { // add ;++count newChildren = arrayUpdate(canEdit, frag, newChild, children) } else if (!isEmptyNode(child) && isEmptyNode(newChild)) { // remove ;--count if (count <= MIN_ARRAY_NODE) { return pack(edit, count, frag, children) } newChildren = arrayUpdate(canEdit, frag, new EmptyNode<K, V>(), children) } else { // modify newChildren = arrayUpdate(canEdit, frag, newChild, children) } if (canEdit) { this.size = count this.children = newChildren return this } return new ArrayNode(edit, count, newChildren) } } function pack<K, V>( edit: number, count: number, removed: number, elements: Array<Node<K, V>> ) { const children = new Array<Node<K, V>>(count - 1) let g = 0 let bitmap = 0 for (let i = 0, len = elements.length; i < len; ++i) { if (i !== removed) { const elem = elements[i] if (elem && !isEmptyNode(elem)) { children[g++] = elem bitmap |= 1 << i } } } return new IndexedNode(edit, bitmap, children) } function expand<K, V>( edit: number, frag: number, child: Node<K, V>, bitmap: number, subNodes: Array<Node<K, V>> ) { const arr = [] let bit = bitmap let count = 0 for (let i = 0; bit; ++i) { if (bit & 1) arr[i] = subNodes[count++]! bit >>>= 1 } arr[frag] = child return new ArrayNode(edit, count + 1, arr) } function mergeLeavesInner<K, V>( edit: number, shift: number, h1: number, n1: Node<K, V>, h2: number, n2: Node<K, V> ): Node<K, V> | ((child: Node<K, V>) => Node<K, V>) { if (h1 === h2) return new CollisionNode(edit, h1, [n2, n1]) const subH1 = hashFragment(shift, h1) const subH2 = hashFragment(shift, h2) if (subH1 === subH2) { return (child) => new IndexedNode(edit, toBitmap(subH1) | toBitmap(subH2), [child]) } else { const children = subH1 < subH2 ? [n1, n2] : [n2, n1] return new IndexedNode(edit, toBitmap(subH1) | toBitmap(subH2), children) } } function mergeLeaves<K, V>( edit: number, shift: number, h1: number, n1: Node<K, V>, h2: number, n2: Node<K, V> ): Node<K, V> { let stack: Stack.Stack<(node: Node<K, V>) => Node<K, V>> | undefined = undefined let currentShift = shift while (true) { const res = mergeLeavesInner(edit, currentShift, h1, n1, h2, n2) if (typeof res === "function") { stack = Stack.make(res, stack) currentShift = currentShift + SIZE } else { let final = res while (stack != null) { final = stack.value(final) stack = stack.previous } return final } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ssv445/lorem-ipsum-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server