• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16package escompat;
17
18export interface ReadonlySet<T> extends Iterable<T> {
19    /**
20     * Checks if a value is in the Set
21     *
22     * @param v the value to find in the Set
23     *
24     * @returns true if the value is in the Set
25     */
26
27    has(value: T): boolean;
28
29    /**
30     * Returns number of unique elements in the Set
31     *
32     * @returns number of unique elements in the Set
33     */
34    get size(): number;
35
36    /**
37     * Executes a provided function once per each value in the Set object, in insertion order
38     *
39     * @param callbackfn to apply
40     */
41    forEach(callbackfn: () => void): void;
42
43    /**
44     * Executes a provided function once per each value in the Set object, in insertion order
45     *
46     * @param callbackfn to apply
47     */
48    forEach(callbackfn: (value: T) => void): void;
49
50    /**
51     * Executes a provided function once per each value in the Set object, in insertion order
52     *
53     * @param callbackfn to apply; value2 is always same as value1
54     */
55    forEach(callbackfn: (value: T, value2: T) => void): void;
56
57    /**
58     * Executes a provided function once per each value in the Set object, in insertion order
59     *
60     * @param callbackfn to apply; value2 is always same as value1
61     */
62    forEach(callbackfn: (value: T, value2: T, set: ReadonlySet<T>) => void): void;
63
64    /**
65     * Despite name, returns elements from the Set
66     * @returns an iterable of the values in the set
67     */
68    keys(): IterableIterator<T>;
69
70    /**
71     * Returns elements from the Set
72     *
73     * @returns an iterable of the values in the set
74     */
75    values(): IterableIterator<T>;
76
77    /**
78     * @returns an iterable of [v,v] pairs for every value `v` in the set.
79     */
80    entries(): IterableIterator<[T, T]>;
81}
82
83/**
84 * Set implementation
85 */
86export final class Set<K> implements ReadonlySet<K> {
87    private readonly elements: Map<K, K>
88
89    /**
90     * Constructs a Set from collection
91     * @param elements initial collection
92     */
93    constructor(elements?: ArrayLike<K> | Iterable<K> | null) {
94        if (elements != null) {
95            const entriesIter = new MappingIterator<K, [K, K]>(elements.$_iterator(), (element: K): [K, K] => [element, element])
96            this.elements = new Map<K, K>(entriesIter)
97        } else {
98            this.elements = new Map<K, K>()
99        }
100    }
101
102    /**
103     * Constructs a Set from another Set
104     * @param set another Set
105     */
106    constructor(set: Set<K>) {
107        this.elements = new Map<K, K>(set.elements)
108    }
109
110    private toStringVals(): String {
111        const strBuf = new StringBuilder()
112
113        const valsIter = this.values()
114        let valsIterRes = valsIter.next()
115        while (!valsIterRes.done) {
116            strBuf.append(`${valsIterRes.value}`)
117
118            valsIterRes = valsIter.next()
119            if (!valsIterRes.done) {
120                strBuf.append(",")
121            }
122        }
123
124        return strBuf.toString()
125    }
126
127    override toString(): String {
128        return "Set[" + this.toStringVals() + "]"
129    }
130
131    /**
132     * Puts a value into the Set
133     *
134     * @param val the value to put into the Set
135     * @returns this
136     */
137    add(val: K): this {
138        this.elements.set(val, val)
139        return this
140    }
141
142    /**
143     * Checks if a value is in the Set
144     *
145     * @param val the value to find in the Set
146     *
147     * @returns true if the value is in the Set
148     */
149    override has(val: K): boolean {
150        return this.elements.has(val)
151    }
152
153    /**
154     * Returns number of unique elements in the Set
155     *
156     * @returns number of unique elements in the Set
157     */
158    override get size(): number {
159        return this.elements.size;
160    }
161
162    /**
163     * Removes a value from the Set
164     *
165     * @param val the value to remove
166     */
167    delete(val: K): boolean {
168        return this.elements.delete(val)
169    }
170
171    /**
172     * Deletes all elements from the Set
173     */
174    clear(): void {
175        this.elements.clear()
176    }
177
178    /**
179     * Despite name, returns elements from the Set
180     * @returns an iterable of the values in the set
181     */
182    override keys(): IterableIterator<K> {
183        return this.elements.keys()
184    }
185
186    /**
187     * Returns elements from the Set
188     *
189     * @returns an iterable of the values in the set
190     */
191    override values(): IterableIterator<K> {
192        return this.elements.keys()
193    }
194
195    override $_iterator(): IterableIterator<K> {
196        return this.values();
197    }
198
199    /**
200     * @returns an iterable of [v,v] pairs for every value `v` in the set.
201     */
202    override entries(): IterableIterator<[K, K]> {
203        return this.elements.entries()
204    }
205
206    /**
207     * Executes a provided function once per each value in the Set object, in insertion order
208     *
209     * @param callbackfn to apply
210     */
211    override forEach(callbackfn: () => void): void {
212        iteratorForEach<K>(this.keys(), (elem: K) => callbackfn())
213    }
214
215    /**
216     * Executes a provided function once per each value in the Set object, in insertion order
217     *
218     * @param callbackfn to apply
219     */
220    override forEach(callbackfn: (k: K) => void): void {
221        iteratorForEach<K>(this.keys(), callbackfn)
222    }
223
224    /**
225     * Executes a provided function once per each value in the Set object, in insertion order
226     *
227     * @param callbackfn to apply
228     */
229    override forEach(callbackfn: (k: K, v: K) => void): void {
230        iteratorForEach<K>(this.keys(), (x: K): void => callbackfn(x, x))
231    }
232
233    /**
234     * Executes a provided function once per each value in the Set object, in insertion order
235     *
236     * @param callbackfn to apply
237     */
238    override forEach(callbackfn: (k: K, v: K, set: Set<K>) => void): void {
239        iteratorForEach<K>(this.keys(), (x: K): void => callbackfn(x, x, this))
240    }
241}
242
243class MappingIterator<I, O> implements IterableIterator<O> {
244    private readonly inputIter: Iterator<I>
245    private readonly mappingFn: (input: I) => O
246
247    constructor(inputIter: Iterator<I>, mappingFn: (input: I) => O) {
248        this.inputIter = inputIter
249        this.mappingFn = mappingFn
250    }
251
252    override next(): IteratorResult<O> {
253        const inputIterRes = this.inputIter.next()
254
255        if (inputIterRes.done) {
256            return new IteratorResult<O>()
257        } else {
258            const output = this.mappingFn(inputIterRes.value as I)
259            return new IteratorResult<O>(output)
260        }
261    }
262}
263