1/* 2 * Copyright (c) 2023 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 16import {randomBytes} from 'crypto'; 17 18import type {INameGenerator, NameGeneratorOptions} from './INameGenerator'; 19 20/** 21 * @Desc: a name generator which used given length to generate random length-limiting name 22 */ 23export class HexNameGenerator implements INameGenerator { 24 private readonly mHexLength: number; 25 private readonly mReservedNames: Set<string>; 26 private readonly mWithPrefixSuffix: boolean; 27 28 private readonly mHexPrefix: string; 29 private readonly mHexSuffix: string; 30 31 private mHistoryNameList: string[]; 32 33 /** 34 * constructor for hex name generator 35 * @param options: {hexLength: number} 36 */ 37 constructor(options?: NameGeneratorOptions) { 38 this.mHexLength = 4; 39 if (options && options.hexLength) { 40 this.mHexLength = options.hexLength; 41 } 42 43 this.mWithPrefixSuffix = options && options.hexWithPrefixSuffix; 44 this.mReservedNames = options?.reservedNames; 45 46 this.mHexPrefix = '_0x'; 47 this.mHexSuffix = '_'; 48 49 this.mHistoryNameList = []; 50 } 51 52 private generateName(): string { 53 let buffer: Buffer = randomBytes(this.mHexLength); 54 let generatedName: string = buffer.toString('hex'); 55 if (this.mWithPrefixSuffix) { 56 return this.mHexPrefix + generatedName + this.mHexSuffix; 57 } 58 59 return generatedName; 60 } 61 62 /** 63 * @return: null for end 64 */ 65 public getName(): string { 66 while (true) { 67 let generatedName: string = this.generateName(); 68 if (!this.mHistoryNameList.includes(generatedName) && !this.mReservedNames?.has(generatedName)) { 69 this.mHistoryNameList.push(generatedName); 70 return generatedName; 71 } 72 const baseHex: number = 16; 73 if (this.mHistoryNameList.length >= Math.pow(baseHex, this.mHexLength)) { 74 return null; 75 } 76 } 77 } 78 79 public reset(): void { 80 this.mHistoryNameList.length = 0; 81 } 82} 83