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 PlainArray: number; 18 Load(key: number): Object; 19} 20let flag: boolean = false; 21let fastPlainArray: Object = undefined; 22let arkPritvate: ArkPrivate = globalThis.ArkPrivate || undefined; 23if (arkPritvate !== undefined) { 24 fastPlainArray = arkPritvate.Load(arkPritvate.PlainArray); 25} else { 26 flag = true; 27} 28if (flag || fastPlainArray === undefined) { 29 const plainAbility = requireNapi('util.struct'); 30 const errorUtil = plainAbility.errorUtil; 31 interface IterableIterator<T> { 32 next: () => { 33 value: T | undefined; 34 done: boolean; 35 }; 36 } 37 class HandlerPlainArray<T> { 38 set(target: PlainArray<T>, p: string, value: string): 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 PlainArray Object`); 47 } 48 deleteProperty(): boolean { 49 throw new Error(`Can't delete Property on PlainArray Object`); 50 } 51 setPrototypeOf(): boolean { 52 throw new Error(`Can't set Prototype on PlainArray Object`); 53 } 54 } 55 class PlainArray<T> extends plainAbility.PlainArrayClass<T> { 56 constructor() { 57 errorUtil.checkNewTargetIsNullError('PlainArray', !new.target); 58 super(); 59 return new Proxy(this, new HandlerPlainArray()); 60 } 61 get length(): number { 62 return this.memberNumber; 63 } 64 add(key: number, value: T): void { 65 errorUtil.checkBindError('add', PlainArray, this); 66 errorUtil.checkTypeError('key', 'number', key); 67 this.addmember(key, value); 68 } 69 clear(): void { 70 errorUtil.checkBindError('clear', PlainArray, this); 71 if (this.memberNumber !== 0) { 72 this.members.keys = []; 73 this.members.values = []; 74 this.memberNumber = 0; 75 } 76 } 77 clone(): PlainArray<T> { 78 errorUtil.checkBindError('clone', PlainArray, this); 79 let clone: PlainArray<T> = new PlainArray<T>(); 80 clone.memberNumber = this.memberNumber; 81 clone.members.keys = this.members.keys.slice(); 82 clone.members.values = this.members.values.slice(); 83 return clone; 84 } 85 has(key: number): boolean { 86 errorUtil.checkBindError('has', PlainArray, this); 87 errorUtil.checkTypeError('key', 'number', key); 88 return this.binarySearchAtPlain(key) > -1; 89 } 90 get(key: number): T { 91 errorUtil.checkBindError('get', PlainArray, this); 92 errorUtil.checkTypeError('key', 'number', key); 93 let index: number = 0; 94 index = this.binarySearchAtPlain(key); 95 return this.members.values[index]; 96 } 97 getIndexOfKey(key: number): number { 98 errorUtil.checkBindError('getIndexOfKey', PlainArray, this); 99 errorUtil.checkTypeError('key', 'number', key); 100 let result: number = 0; 101 result = this.binarySearchAtPlain(key); 102 return result < 0 ? -1 : result; 103 } 104 getIndexOfValue(value: T): number { 105 errorUtil.checkBindError('getIndexOfValue', PlainArray, this); 106 return this.members.values.indexOf(value); 107 } 108 isEmpty(): boolean { 109 errorUtil.checkBindError('isEmpty', PlainArray, this); 110 return this.memberNumber === 0; 111 } 112 getKeyAt(index: number): number { 113 errorUtil.checkBindError('getKeyAt', PlainArray, this); 114 errorUtil.checkTypeError('index', 'Integer', index); 115 return this.members.keys[index]; 116 } 117 remove(key: number): T { 118 errorUtil.checkBindError('remove', PlainArray, this); 119 errorUtil.checkTypeError('key', 'number', key); 120 let result: T = undefined; 121 let index: number = 0; 122 index = this.binarySearchAtPlain(key); 123 if (index < 0) { 124 return result; 125 } 126 return this.deletemember(index); 127 } 128 removeAt(index: number): T { 129 errorUtil.checkBindError('removeAt', PlainArray, this); 130 errorUtil.checkTypeError('index', 'Integer', index); 131 return this.deletemember(index); 132 } 133 removeRangeFrom(index: number, size: number): number { 134 errorUtil.checkBindError('removeRangeFrom', PlainArray, this); 135 errorUtil.checkTypeError('index', 'Integer', index); 136 errorUtil.checkTypeError('size', 'Integer', size); 137 errorUtil.checkRangeError('index', index, 0, this.memberNumber - 1); 138 let safeSize: number = 0; 139 safeSize = (this.memberNumber - (index + size) < 0) ? this.memberNumber - index : size; 140 this.deletemember(index, safeSize); 141 return safeSize; 142 } 143 setValueAt(index: number, value: T): void { 144 errorUtil.checkBindError('setValueAt', PlainArray, this); 145 errorUtil.checkTypeError('index', 'Integer', index); 146 errorUtil.checkRangeError('index', index, 0, this.memberNumber - 1); 147 this.members.values[index] = value; 148 } 149 toString(): string { 150 errorUtil.checkBindError('toString', PlainArray, this); 151 let result: string[] = []; 152 for (let i: number = 0; i < this.memberNumber; i++) { 153 result.push(this.members.keys[i] + ':' + this.members.values[i]); 154 } 155 return result.join(','); 156 } 157 getValueAt(index: number): T { 158 errorUtil.checkBindError('getValueAt', PlainArray, this); 159 errorUtil.checkTypeError('index', 'Integer', index); 160 errorUtil.checkRangeError('index', index, 0, this.memberNumber - 1); 161 return this.members.values[index]; 162 } 163 forEach(callbackfn: (value: T, index?: number, PlainArray?: PlainArray<T>) => void, 164 thisArg?: Object): void { 165 errorUtil.checkBindError('forEach', PlainArray, this); 166 errorUtil.checkTypeError('callbackfn', 'callable', callbackfn); 167 for (let i: number = 0; i < this.memberNumber; i++) { 168 callbackfn.call(thisArg, this.members.values[i], this.members.keys[i]); 169 } 170 } 171 [Symbol.iterator](): IterableIterator<[number, T]> { 172 errorUtil.checkBindError('Symbol.iterator', PlainArray, this); 173 let count: number = 0; 174 return { 175 next: function (): { done: boolean, value: [number, T] } { 176 let done: boolean = false; 177 let value: [number, T] = undefined; 178 done = count >= this.memberNumber; 179 value = done ? undefined : [this.members.keys[count], this.members.values[count]] as [number, T]; 180 count++; 181 return { 182 done: done, 183 value: value, 184 }; 185 }, 186 }; 187 } 188 } 189 Object.freeze(PlainArray); 190 fastPlainArray = PlainArray; 191} 192export default fastPlainArray; 193