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