1/* 2 * Copyright (c) 2022 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 */ 15declare function requireNapi(s: string): any; 16interface ArkPrivate { 17 LightWeightMap: number; 18 Load(key: number): Object; 19} 20let flag: boolean = false; 21let fastLightWeightMap: Object = undefined; 22let arkPritvate: ArkPrivate = globalThis['ArkPrivate'] || undefined; 23if (arkPritvate !== undefined) { 24 fastLightWeightMap = arkPritvate.Load(arkPritvate.LightWeightMap); 25} else { 26 flag = true; 27} 28if (flag || fastLightWeightMap === undefined) { 29 const LightWeightAbility = requireNapi('util.struct'); 30 const ErrorUtil = LightWeightAbility.ErrorUtil; 31 interface IterableIterator<T> { 32 next: () => { 33 value: T | undefined; 34 done: boolean; 35 }; 36 } 37 class HandlerLightWeightMap<K, V> { 38 set(target: LightWeightMap<K, V>, p: any, value: any): boolean { 39 if (p in target) { 40 target[p] = value; 41 return true; 42 } 43 return false; 44 } 45 defineProperty(): boolean { 46 throw new Error(`Can't define Property on LightWeightMap Object`); 47 } 48 deleteProperty(): boolean { 49 throw new Error(`Can't delete Property on LightWeightMap Object`); 50 } 51 setPrototypeOf(): boolean { 52 throw new Error(`Can't set Prototype on LightWeightMap Object`); 53 } 54 } 55 class LightWeightMap<K, V> extends LightWeightAbility.LightWeightClass<K, V> { 56 constructor() { 57 ErrorUtil.checkNewTargetIsNullError("LightWeightMap", !new.target); 58 super(); 59 return new Proxy(this, new HandlerLightWeightMap()); 60 } 61 get length(): number { 62 return this.memberNumber; 63 } 64 hasAll(map: LightWeightMap<K, V>): boolean { 65 ErrorUtil.checkBindError("hasAll", LightWeightMap, this); 66 ErrorUtil.checkTypeError("map", "LightWeightMap", map); 67 if (!(map instanceof LightWeightMap)) { 68 throw new TypeError('map is not JSAPILightWeightMap'); 69 } 70 if (map.memberNumber > this.memberNumber) { 71 return false; 72 } 73 if (LightWeightAbility.isIncludeToArray(this.keyValueStringArray(), map.keyValueStringArray())) { 74 return true; 75 } 76 return false; 77 } 78 hasKey(key: K): boolean { 79 ErrorUtil.checkBindError("hasKey", LightWeightMap, this); 80 return this.members.keys.indexOf(key) > -1; 81 } 82 hasValue(value: V): boolean { 83 ErrorUtil.checkBindError("hasValue", LightWeightMap, this); 84 return this.members.values.indexOf(value) > -1; 85 } 86 increaseCapacityTo(minimumCapacity: number): void { 87 ErrorUtil.checkBindError("increaseCapacityTo", LightWeightMap, this); 88 ErrorUtil.checkTypeError("minimumCapacity", "Integer", minimumCapacity); 89 super.ensureCapacity(minimumCapacity); 90 } 91 entries(): IterableIterator<[K, V]> { 92 ErrorUtil.checkBindError("entries", LightWeightMap, this); 93 let data: LightWeightMap<K, V> = this; 94 let count: number = 0; 95 return { 96 next: function () { 97 let done: boolean = false; 98 let value: [K, V] = undefined; 99 done = count >= data.memberNumber; 100 value = done ? undefined : [data.members.keys[count], data.members.values[count]] as [K, V]; 101 count++; 102 return { 103 done: done, 104 value: value, 105 }; 106 }, 107 }; 108 } 109 get(key: K): V { 110 ErrorUtil.checkBindError("get", LightWeightMap, this); 111 let index: number = 0; 112 index = this.getIndexByKey(key); 113 return this.members.values[index]; 114 } 115 getIndexOfKey(key: K): number { 116 ErrorUtil.checkBindError("getIndexOfKey", LightWeightMap, this); 117 return this.getIndexByKey(key); 118 } 119 getIndexOfValue(value: V): number { 120 ErrorUtil.checkBindError("getIndexOfValue", LightWeightMap, this); 121 return this.members.values.indexOf(value); 122 } 123 isEmpty(): boolean { 124 ErrorUtil.checkBindError("isEmpty", LightWeightMap, this); 125 return this.memberNumber === 0; 126 } 127 getKeyAt(index: number): K { 128 ErrorUtil.checkBindError("getKeyAt", LightWeightMap, this); 129 ErrorUtil.checkTypeError("index", "Integer", index); 130 ErrorUtil.checkRangeError("index", index, 0, this.length - 1); 131 return this.members.keys[index]; 132 } 133 keys(): IterableIterator<K> { 134 ErrorUtil.checkBindError("keys", LightWeightMap, this); 135 let data: LightWeightMap<K, V> = this; 136 let count: number = 0; 137 return { 138 next: function () { 139 let done: boolean = false; 140 let value: K = undefined; 141 done = count >= data.memberNumber; 142 value = done ? undefined : data.members.keys[count]; 143 count++; 144 return { 145 done: done, 146 value: value, 147 }; 148 }, 149 }; 150 } 151 setAll(map: LightWeightMap<K, V>): void { 152 ErrorUtil.checkBindError("setAll", LightWeightMap, this); 153 ErrorUtil.checkTypeError("map", "LightWeightMap", map); 154 if (this.memberNumber === 0) { 155 this.members.hashs = map.members.hashs.slice(); 156 this.members.keys = map.members.keys.slice(); 157 this.members.values = map.members.values.slice(); 158 this.memberNumber = map.memberNumber; 159 } else { 160 for (let i: number = 0; i < map.memberNumber; i++) { 161 this.addmember(map.members.keys[i], map.members.values[i]); 162 } 163 } 164 } 165 set(key: K, value: V): Object { 166 ErrorUtil.checkBindError("set", LightWeightMap, this); 167 this.addmember(key, value); 168 return this; 169 } 170 remove(key: K): V { 171 ErrorUtil.checkBindError("remove", LightWeightMap, this); 172 return this.deletemember(key); 173 } 174 removeAt(index: number): boolean { 175 ErrorUtil.checkBindError("removeAt", LightWeightMap, this); 176 ErrorUtil.checkTypeError("index", "Integer", index); 177 if (index > this.memberNumber--) { 178 return false; 179 } 180 this.members.hashs.splice(index, 1); 181 this.members.values.splice(index, 1); 182 this.members.keys.splice(index, 1); 183 this.memberNumber--; 184 return true; 185 } 186 clear(): void { 187 ErrorUtil.checkBindError("clear", LightWeightMap, this); 188 if (this.memberNumber != 0 || this.capacity > 8) { 189 this.members.hashs = []; 190 this.members.keys = []; 191 this.members.values = []; 192 this.memberNumber = 0; 193 this.capacity = 8; 194 } 195 } 196 setValueAt(index: number, newValue: V): boolean { 197 ErrorUtil.checkBindError("setValueAt", LightWeightMap, this); 198 ErrorUtil.checkTypeError("index", "Integer", index); 199 ErrorUtil.checkRangeError("index", index, 0, this.length - 1); 200 if (index > this.memberNumber || this.members.values[index] === undefined) { 201 return false; 202 } 203 this.members.values[index] = newValue; 204 return true; 205 } 206 forEach(callbackfn: (value?: V, key?: K, map?: LightWeightMap<K, V>) => void, 207 thisArg?: Object): void { 208 ErrorUtil.checkBindError("forEach", LightWeightMap, this); 209 ErrorUtil.checkTypeError("callbackfn", "callable", callbackfn); 210 let data: LightWeightMap<K, V> = this; 211 for (let i: number = 0; i < data.memberNumber; i++) { 212 callbackfn.call(thisArg, data.members.values[i], data.members.keys[i], data); 213 } 214 } 215 [Symbol.iterator](): IterableIterator<[K, V]> { 216 ErrorUtil.checkBindError("Symbol.iterator", LightWeightMap, this); 217 return this.entries(); 218 } 219 toString(): string { 220 ErrorUtil.checkBindError("toString", LightWeightMap, this); 221 let result: string[] = []; 222 for (let i: number = 0; i < this.memberNumber; i++) { 223 result.push(this.members.keys[i] + ':' + this.members.values[i]); 224 } 225 return result.join(','); 226 } 227 getValueAt(index: number): V { 228 ErrorUtil.checkBindError("getValueAt", LightWeightMap, this); 229 ErrorUtil.checkTypeError("index", "Integer", index); 230 ErrorUtil.checkRangeError("index", index, 0, this.length - 1); 231 return this.members.values[index]; 232 } 233 values(): IterableIterator<V> { 234 ErrorUtil.checkBindError("values", LightWeightMap, this); 235 let data: LightWeightMap<K, V> = this; 236 let count: number = 0; 237 return { 238 next: function () { 239 let done: boolean = false; 240 let value: V = undefined; 241 done = count >= data.memberNumber; 242 value = done ? undefined : data.members.values[count]; 243 count++; 244 return { 245 done: done, 246 value: value, 247 }; 248 }, 249 }; 250 } 251 } 252 Object.freeze(LightWeightMap); 253 fastLightWeightMap = LightWeightMap; 254} 255export default fastLightWeightMap; 256