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