aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/undici/lib/core/tree.js
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
commit76cb9c2a39d477a64824a985ade40507e3bbade1 (patch)
tree41e997aa9c6f538d3a136af61dae9424db2005a9 /vanilla/node_modules/undici/lib/core/tree.js
parent819a39a21ac992b1393244a4c283bbb125208c69 (diff)
downloadneko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.gz
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.bz2
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.zip
feat(vanilla): add testing infrastructure and tests (NK-wjnczv)
Diffstat (limited to 'vanilla/node_modules/undici/lib/core/tree.js')
-rw-r--r--vanilla/node_modules/undici/lib/core/tree.js160
1 files changed, 160 insertions, 0 deletions
diff --git a/vanilla/node_modules/undici/lib/core/tree.js b/vanilla/node_modules/undici/lib/core/tree.js
new file mode 100644
index 0000000..6eed58a
--- /dev/null
+++ b/vanilla/node_modules/undici/lib/core/tree.js
@@ -0,0 +1,160 @@
+'use strict'
+
+const {
+ wellknownHeaderNames,
+ headerNameLowerCasedRecord
+} = require('./constants')
+
+class TstNode {
+ /** @type {any} */
+ value = null
+ /** @type {null | TstNode} */
+ left = null
+ /** @type {null | TstNode} */
+ middle = null
+ /** @type {null | TstNode} */
+ right = null
+ /** @type {number} */
+ code
+ /**
+ * @param {string} key
+ * @param {any} value
+ * @param {number} index
+ */
+ constructor (key, value, index) {
+ if (index === undefined || index >= key.length) {
+ throw new TypeError('Unreachable')
+ }
+ const code = this.code = key.charCodeAt(index)
+ // check code is ascii string
+ if (code > 0x7F) {
+ throw new TypeError('key must be ascii string')
+ }
+ if (key.length !== ++index) {
+ this.middle = new TstNode(key, value, index)
+ } else {
+ this.value = value
+ }
+ }
+
+ /**
+ * @param {string} key
+ * @param {any} value
+ * @returns {void}
+ */
+ add (key, value) {
+ const length = key.length
+ if (length === 0) {
+ throw new TypeError('Unreachable')
+ }
+ let index = 0
+ /**
+ * @type {TstNode}
+ */
+ let node = this
+ while (true) {
+ const code = key.charCodeAt(index)
+ // check code is ascii string
+ if (code > 0x7F) {
+ throw new TypeError('key must be ascii string')
+ }
+ if (node.code === code) {
+ if (length === ++index) {
+ node.value = value
+ break
+ } else if (node.middle !== null) {
+ node = node.middle
+ } else {
+ node.middle = new TstNode(key, value, index)
+ break
+ }
+ } else if (node.code < code) {
+ if (node.left !== null) {
+ node = node.left
+ } else {
+ node.left = new TstNode(key, value, index)
+ break
+ }
+ } else if (node.right !== null) {
+ node = node.right
+ } else {
+ node.right = new TstNode(key, value, index)
+ break
+ }
+ }
+ }
+
+ /**
+ * @param {Uint8Array} key
+ * @returns {TstNode | null}
+ */
+ search (key) {
+ const keylength = key.length
+ let index = 0
+ /**
+ * @type {TstNode|null}
+ */
+ let node = this
+ while (node !== null && index < keylength) {
+ let code = key[index]
+ // A-Z
+ // First check if it is bigger than 0x5a.
+ // Lowercase letters have higher char codes than uppercase ones.
+ // Also we assume that headers will mostly contain lowercase characters.
+ if (code <= 0x5a && code >= 0x41) {
+ // Lowercase for uppercase.
+ code |= 32
+ }
+ while (node !== null) {
+ if (code === node.code) {
+ if (keylength === ++index) {
+ // Returns Node since it is the last key.
+ return node
+ }
+ node = node.middle
+ break
+ }
+ node = node.code < code ? node.left : node.right
+ }
+ }
+ return null
+ }
+}
+
+class TernarySearchTree {
+ /** @type {TstNode | null} */
+ node = null
+
+ /**
+ * @param {string} key
+ * @param {any} value
+ * @returns {void}
+ * */
+ insert (key, value) {
+ if (this.node === null) {
+ this.node = new TstNode(key, value, 0)
+ } else {
+ this.node.add(key, value)
+ }
+ }
+
+ /**
+ * @param {Uint8Array} key
+ * @returns {any}
+ */
+ lookup (key) {
+ return this.node?.search(key)?.value ?? null
+ }
+}
+
+const tree = new TernarySearchTree()
+
+for (let i = 0; i < wellknownHeaderNames.length; ++i) {
+ const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]]
+ tree.insert(key, key)
+}
+
+module.exports = {
+ TernarySearchTree,
+ tree
+}