@lionweb/delta-protocol-client 0.7.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,94 @@
1
+ //
2
+ // Licensed under the Apache License, Version 2.0 (the "License")
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ //
14
+ // SPDX-FileCopyrightText: 2025 TRUMPF Laser SE and other contributors
15
+ // SPDX-License-Identifier: Apache-2.0
16
+
17
+ import { Procedure } from "@lionweb/delta-protocol-common"
18
+
19
+
20
+ /**
21
+ * @return the index at which `t` should be inserted to keep the array `ts` sorted in the numeric order determined by applying `valueFunc` to its members.
22
+ * In case `t` has the same numeric value as existing members of `ts`, the lowest index having that numeric value is returned.
23
+ * (Exported for testing purposes only!)
24
+ */
25
+ export const insertionIndex = <T>(ts: T[], valueFunc: (t: T) => number, tToInsert: T): number => {
26
+ const valueToInsert = valueFunc(tToInsert)
27
+ let low = 0
28
+ let high = ts.length - 1
29
+
30
+ while (low <= high) {
31
+ const mid = low + ((high - low) >>> 1) // not buggy! ;D
32
+ const midValue = valueFunc(ts[mid])
33
+
34
+ if (midValue < valueToInsert) {
35
+ low = mid + 1
36
+ } else if (valueToInsert < midValue) {
37
+ high = mid - 1
38
+ } else {
39
+ return mid
40
+ }
41
+ }
42
+
43
+ return low
44
+ }
45
+
46
+
47
+ /**
48
+ * Type def. for a function that takes a `t` and either processes it directly if `t` has the next expected priority,
49
+ * or enqueues it for later processing.
50
+ *
51
+ * (Technically, this can be considered to be a modified {@link https://en.wikipedia.org/wiki/Priority_queue *“monotone priority queue”*}.)
52
+ */
53
+ export type PriorityQueueAcceptor<T> = (t: T) => void
54
+
55
+ /**
56
+ * @return a {@link PriorityQueueAcceptor} function that accepts instances of `T`,
57
+ * passing them to the `process` function in (min-max) priority order,
58
+ * as computed by the `priorityFunc`, starting with the `firstPriority`.
59
+ * @throws an {@link Error error} when a `T` is passed with a priority that has already been processed.
60
+ */
61
+ export const priorityQueueAcceptor = <T>(priorityFunc: (t: T) => number, firstPriority: number, process: Procedure<T>): PriorityQueueAcceptor<T> => {
62
+ const ts: T[] = []
63
+ let nextPriority = firstPriority
64
+ return (t: T) => {
65
+ const priority = priorityFunc(t)
66
+ if (priority < nextPriority) {
67
+ throw new Error(`priority ${priority} has already been processed; (next expected priority: ${nextPriority})`)
68
+ }
69
+ const index0 = insertionIndex(ts, priorityFunc, t)
70
+ if (priority === nextPriority) {
71
+ nextPriority++
72
+ process(t)
73
+ let index = index0
74
+ let stop = false
75
+ while (index < ts.length && !stop) {
76
+ const currentT = ts[index]
77
+ const currentPriority = priorityFunc(currentT)
78
+ if (currentPriority === nextPriority) {
79
+ nextPriority++
80
+ process(currentT)
81
+ index++
82
+ } else {
83
+ stop = true
84
+ }
85
+ }
86
+ if (index > index0) {
87
+ ts.splice(index0, index - index0)
88
+ }
89
+ } else {
90
+ ts.splice(index0, 0, t)
91
+ }
92
+ }
93
+ }
94
+