@ddunigma/node 1.1.3 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,394 +6,187 @@ const types_1 = require("../types");
6
6
  const charSets_1 = require("../charSets");
7
7
  class Ddu64 extends BaseDdu_1.BaseDdu {
8
8
  constructor(dduChar, paddingChar, dduOptions) {
9
- var _a, _b, _c;
9
+ var _a, _b, _c, _d, _e, _f, _g;
10
10
  super();
11
11
  this.dduBinaryLookup = new Map();
12
+ const shouldThrowError = (_a = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.useBuildErrorReturn) !== null && _a !== void 0 ? _a : false;
13
+ const getCharSetFromSymbol = (symbol) => {
14
+ const cs = (0, charSets_1.getCharSet)(symbol);
15
+ if (!cs)
16
+ throw new Error(`CharSet with symbol ${symbol} not found`);
17
+ return cs;
18
+ };
12
19
  // charset 초기화
13
- let finalCharSet;
14
- let finalPadding;
15
- let requiredLength;
16
- let bitLength;
17
- let isPredefined = false;
20
+ let charSet, padding, requiredLength, bitLength, isPredefined;
18
21
  try {
19
- const result = this.initializeCharSet(dduChar, paddingChar, dduOptions);
20
- finalCharSet = [...result.finalCharSet];
21
- finalPadding = result.finalPadding;
22
- requiredLength = result.requiredLength;
23
- bitLength = result.bitLength;
24
- isPredefined = result.isPredefined;
22
+ const finalDduChar = dduChar !== null && dduChar !== void 0 ? dduChar : dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.dduChar;
23
+ const finalPadding = paddingChar !== null && paddingChar !== void 0 ? paddingChar : dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.paddingChar;
24
+ if (finalDduChar) {
25
+ // 커스텀 charset
26
+ if (!finalPadding)
27
+ throw new Error("paddingChar is required when dduChar or dduOptions.dduChar is provided");
28
+ const arr = typeof finalDduChar === "string" ? [...new Set(finalDduChar.trim())] : finalDduChar;
29
+ const len = (_b = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.requiredLength) !== null && _b !== void 0 ? _b : arr.length;
30
+ if (arr.length < len)
31
+ throw new Error(`dduChar must be at least ${len} characters long. Provided: ${arr.length}`);
32
+ const usePow2 = (dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.usePowerOfTwo) === true || ((dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.usePowerOfTwo) === undefined && len > 0 && (len & (len - 1)) === 0);
33
+ if (usePow2) {
34
+ const exp = this.getLargestPowerOfTwoExponent(len);
35
+ const pow2Len = 1 << exp;
36
+ [charSet, padding, requiredLength, bitLength, isPredefined] = [arr.slice(0, pow2Len), finalPadding, pow2Len, exp, false];
37
+ }
38
+ else {
39
+ [charSet, padding, requiredLength, bitLength, isPredefined] = [arr.slice(0, len), finalPadding, len, this.getBitLength(len), false];
40
+ }
41
+ }
42
+ else if (dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.dduSetSymbol) {
43
+ // 미리 정의된 charset
44
+ const cs = getCharSetFromSymbol(dduOptions.dduSetSymbol);
45
+ const usePow2 = (dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.usePowerOfTwo) === true || ((dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.usePowerOfTwo) === undefined && cs.maxRequiredLength > 0 && (cs.maxRequiredLength & (cs.maxRequiredLength - 1)) === 0);
46
+ if (usePow2) {
47
+ const exp = this.getLargestPowerOfTwoExponent(cs.maxRequiredLength);
48
+ const pow2Len = 1 << exp;
49
+ [charSet, padding, requiredLength, bitLength, isPredefined] = [cs.charSet.slice(0, pow2Len), cs.paddingChar, pow2Len, exp, true];
50
+ }
51
+ else {
52
+ [charSet, padding, requiredLength, bitLength, isPredefined] = [cs.charSet, cs.paddingChar, cs.maxRequiredLength, cs.bitLength, true];
53
+ }
54
+ }
55
+ else {
56
+ // 기본 charset
57
+ const cs = getCharSetFromSymbol((_c = types_1.dduDefaultConstructorOptions.dduSetSymbol) !== null && _c !== void 0 ? _c : types_1.DduSetSymbol.DDU);
58
+ [charSet, padding, requiredLength, bitLength, isPredefined] = [cs.charSet, cs.paddingChar, cs.maxRequiredLength, cs.bitLength, true];
59
+ }
25
60
  }
26
61
  catch (error) {
27
- // useBuildErrorReturn이 true일 경우 에러를 그대로 throw
28
- if ((_a = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.useBuildErrorReturn) !== null && _a !== void 0 ? _a : false) {
62
+ if (shouldThrowError)
29
63
  throw error;
30
- }
31
- // fallback 처리
32
- const fallbackResult = this.getFallbackCharSet(dduOptions);
33
- finalCharSet = [...fallbackResult.finalCharSet];
34
- finalPadding = fallbackResult.finalPadding;
35
- requiredLength = fallbackResult.requiredLength;
36
- bitLength = fallbackResult.bitLength;
37
- isPredefined = true; // fallback도 predefined charset 사용
64
+ // fallback
65
+ const fallbackSymbol = (_e = (_d = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.dduSetSymbol) !== null && _d !== void 0 ? _d : types_1.dduDefaultConstructorOptions.dduSetSymbol) !== null && _e !== void 0 ? _e : types_1.DduSetSymbol.ONECHARSET;
66
+ const cs = (_f = (0, charSets_1.getCharSet)(fallbackSymbol)) !== null && _f !== void 0 ? _f : (0, charSets_1.getCharSet)(types_1.DduSetSymbol.ONECHARSET);
67
+ if (!cs)
68
+ throw new Error(`Critical: No fallback CharSet available`);
69
+ [charSet, padding, requiredLength, bitLength, isPredefined] = [cs.charSet, cs.paddingChar, cs.maxRequiredLength, cs.bitLength, true];
38
70
  }
39
- const shouldThrowError = (_b = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.useBuildErrorReturn) !== null && _b !== void 0 ? _b : false;
40
- const normalized = this.normalizeCharSet({
41
- charSet: finalCharSet,
42
- padding: finalPadding,
43
- requiredLength,
44
- bitLength,
45
- isPredefined,
46
- shouldThrowError,
47
- dduOptions,
48
- });
71
+ // 정규화 검증
72
+ const normalized = this.normalizeCharSet(charSet, padding, requiredLength, bitLength, isPredefined, shouldThrowError, dduOptions);
49
73
  this.dduChar = normalized.charSet;
50
74
  this.paddingChar = normalized.padding;
51
75
  this.charLength = normalized.charLength;
52
76
  this.bitLength = normalized.bitLength;
53
77
  this.isPredefinedCharSet = normalized.isPredefined;
78
+ this.encoding = (_g = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.encoding) !== null && _g !== void 0 ? _g : this.defaultEncoding;
54
79
  const dduLength = this.dduChar.length;
55
80
  this.usePowerOfTwo = dduLength > 0 && (dduLength & (dduLength - 1)) === 0;
56
- this.effectiveBitLength = this.usePowerOfTwo
57
- ? this.bitLength
58
- : this.getBitLength(dduLength);
59
- const canUseBitwise = this.effectiveBitLength <= 26;
60
- if (canUseBitwise) {
61
- this.binaryChunkToIntFn = (chunk) => {
62
- let value = 0;
63
- for (let i = 0; i < chunk.length; i++) {
64
- value = (value << 1) | (chunk.charCodeAt(i) & 1);
65
- }
66
- return value;
67
- };
68
- }
69
- else {
70
- this.binaryChunkToIntFn = (chunk) => {
71
- let value = 0;
72
- for (let i = 0; i < chunk.length; i++) {
73
- value = value * 2 + (chunk.charCodeAt(i) & 1);
74
- }
75
- return value;
76
- };
77
- }
78
- this.encoding = (_c = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.encoding) !== null && _c !== void 0 ? _c : this.defaultEncoding;
79
- this.dduChar.forEach((char, index) => {
80
- this.dduBinaryLookup.set(char, index);
81
- });
81
+ this.effectiveBitLength = this.usePowerOfTwo ? this.bitLength : this.getBitLength(dduLength);
82
+ this.binaryChunkToIntFn = this.effectiveBitLength <= 26
83
+ ? (chunk) => chunk.split('').reduce((v, c) => (v << 1) | (c.charCodeAt(0) & 1), 0)
84
+ : (chunk) => chunk.split('').reduce((v, c) => v * 2 + (c.charCodeAt(0) & 1), 0);
85
+ this.dduChar.forEach((char, index) => this.dduBinaryLookup.set(char, index));
82
86
  if (this.charLength >= 2 && !this.isPredefinedCharSet) {
83
- this.validateCombinationDuplicates(this.dduChar, this.paddingChar, this.dduChar.length);
87
+ this.validateCombinationDuplicates(this.dduChar, this.paddingChar, dduLength);
84
88
  }
85
89
  if (this.effectiveBitLength <= 16) {
86
- const cacheSize = 1 << this.effectiveBitLength;
87
- this.indexToBinaryCache = new Array(cacheSize);
88
- for (let i = 0; i < cacheSize; i++) {
89
- this.indexToBinaryCache[i] = i
90
- .toString(2)
91
- .padStart(this.effectiveBitLength, "0");
92
- }
90
+ const size = 1 << this.effectiveBitLength;
91
+ this.indexToBinaryCache = Array.from({ length: size }, (_, i) => i.toString(2).padStart(this.effectiveBitLength, "0"));
93
92
  }
94
93
  else {
95
94
  this.indexToBinaryCache = null;
96
95
  }
97
96
  }
98
- /**
99
- * charset 초기화 (커스텀 또는 미리 정의된 charset)
100
- */
101
- initializeCharSet(dduChar, paddingChar, dduOptions) {
102
- const finalDduChar = dduChar !== null && dduChar !== void 0 ? dduChar : dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.dduChar;
103
- const finalPaddingChar = paddingChar !== null && paddingChar !== void 0 ? paddingChar : dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.paddingChar;
104
- // 1. 커스텀 charset 사용
105
- if (finalDduChar) {
106
- return this.processCustomCharSet(finalDduChar, finalPaddingChar, dduOptions);
107
- }
108
- // 2. 미리 정의된 charset 사용
109
- if (dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.dduSetSymbol) {
110
- return this.processPredefinedCharSet(dduOptions.dduSetSymbol, dduOptions);
111
- }
112
- // 3. 기본 charset 사용
113
- return this.processDefaultCharSet();
114
- }
115
- /**
116
- * 커스텀 charset 처리
117
- */
118
- processCustomCharSet(dduChar, paddingChar, dduOptions) {
119
- var _a;
120
- if (!paddingChar) {
121
- throw new Error("paddingChar is required when dduChar or dduOptions.dduChar is provided");
122
- }
123
- // string 타입을 배열로 변환
124
- const dduCharArray = this.convertToCharArray(dduChar);
125
- const dduCharLength = (_a = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.requiredLength) !== null && _a !== void 0 ? _a : dduCharArray.length;
126
- if (dduCharArray.length < dduCharLength) {
127
- throw new Error(`dduChar must be at least ${dduCharLength} characters long. Provided: ${dduCharArray.length}`);
128
- }
129
- // usePowerOfTwo 처리
130
- // charArray의 길이가 2의 제곱수이거나 option에 usePowerOfTwo가 명시적으로 true일 때만 적용
131
- const shouldUsePowerOfTwo = (dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.usePowerOfTwo) === true ||
132
- ((dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.usePowerOfTwo) === undefined && this.isPowerOfTwo(dduCharLength));
133
- const result = this.applyPowerOfTwoOption(dduCharArray, paddingChar, dduCharLength, shouldUsePowerOfTwo);
134
- return Object.assign(Object.assign({}, result), { isPredefined: false // 커스텀 charset은 검증 필요
135
- });
136
- }
137
- /**
138
- * 미리 정의된 charset 처리
139
- */
140
- processPredefinedCharSet(symbol, dduOptions) {
141
- const fixedCharSet = (0, charSets_1.getCharSet)(symbol);
142
- if (!fixedCharSet) {
143
- throw new Error(`CharSet with symbol ${symbol} not found`);
144
- }
145
- const { charSet, paddingChar, maxRequiredLength, bitLength } = fixedCharSet;
146
- // usePowerOfTwo 처리
147
- // charArray의 길이가 2의 제곱수이거나 option에 usePowerOfTwo가 명시적으로 true일 때만 적용
148
- const shouldUsePowerOfTwo = (dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.usePowerOfTwo) === true ||
149
- ((dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.usePowerOfTwo) === undefined && this.isPowerOfTwo(maxRequiredLength));
150
- if (shouldUsePowerOfTwo) {
151
- const result = this.applyPowerOfTwoOption(charSet, paddingChar, maxRequiredLength, true);
152
- return Object.assign(Object.assign({}, result), { isPredefined: true // 미리 정의된 charset은 검증 패스
153
- });
154
- }
155
- return {
156
- finalCharSet: charSet,
157
- finalPadding: paddingChar,
158
- requiredLength: maxRequiredLength,
159
- bitLength,
160
- isPredefined: true // 미리 정의된 charset은 검증 패스
161
- };
162
- }
163
- /**
164
- * 기본 charset 처리
165
- */
166
- processDefaultCharSet() {
167
- var _a;
168
- const defaultSymbol = (_a = types_1.dduDefaultConstructorOptions.dduSetSymbol) !== null && _a !== void 0 ? _a : types_1.DduSetSymbol.DDU;
169
- const fixedCharSet = (0, charSets_1.getCharSet)(defaultSymbol);
170
- if (!fixedCharSet) {
171
- throw new Error(`Default CharSet with symbol ${defaultSymbol} not found`);
172
- }
173
- return {
174
- finalCharSet: fixedCharSet.charSet,
175
- finalPadding: fixedCharSet.paddingChar,
176
- requiredLength: fixedCharSet.maxRequiredLength,
177
- bitLength: fixedCharSet.bitLength,
178
- isPredefined: true // 기본 charset도 미리 정의된 것이므로 검증 패스
179
- };
180
- }
181
- /**
182
- * fallback charset 가져오기
183
- * 우선순위: dduOptions.dduSetSymbol > dduDefaultConstructorOptions.dduSetSymbol > DduSetSymbol.ONECHARSET
184
- */
185
- getFallbackCharSet(dduOptions) {
186
- var _a, _b;
187
- // 우선순위에 따라 fallback symbol 결정
188
- const fallbackSymbol = (_b = (_a = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.dduSetSymbol) !== null && _a !== void 0 ? _a : types_1.dduDefaultConstructorOptions.dduSetSymbol) !== null && _b !== void 0 ? _b : types_1.DduSetSymbol.ONECHARSET; // DDU 대신 ONECHARSET 사용
189
- const fixedCharSet = (0, charSets_1.getCharSet)(fallbackSymbol);
190
- if (!fixedCharSet) {
191
- // 최후의 fallback: ONECHARSET
192
- const lastResort = (0, charSets_1.getCharSet)(types_1.DduSetSymbol.ONECHARSET);
193
- if (!lastResort) {
194
- throw new Error(`Critical: No fallback CharSet available`);
195
- }
196
- return {
197
- finalCharSet: lastResort.charSet,
198
- finalPadding: lastResort.paddingChar,
199
- requiredLength: lastResort.maxRequiredLength,
200
- bitLength: lastResort.bitLength,
201
- };
202
- }
203
- return {
204
- finalCharSet: fixedCharSet.charSet,
205
- finalPadding: fixedCharSet.paddingChar,
206
- requiredLength: fixedCharSet.maxRequiredLength,
207
- bitLength: fixedCharSet.bitLength,
208
- };
209
- }
210
- normalizeCharSet(params) {
211
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
212
- let currentCharSet = [...params.charSet];
213
- let currentPadding = params.padding;
214
- let currentRequiredLength = params.requiredLength;
215
- let currentBitLength = params.bitLength;
216
- let currentIsPredefined = params.isPredefined;
217
- const { shouldThrowError, dduOptions } = params;
218
- let fallbackCache = null;
219
- const getFallback = () => {
220
- if (!fallbackCache) {
221
- const fallback = this.getFallbackCharSet(dduOptions);
222
- fallbackCache = {
223
- finalCharSet: [...fallback.finalCharSet],
224
- finalPadding: fallback.finalPadding,
225
- requiredLength: fallback.requiredLength,
226
- bitLength: fallback.bitLength,
227
- };
228
- }
229
- return fallbackCache;
230
- };
97
+ normalizeCharSet(charSet, padding, requiredLength, bitLength, isPredefined, shouldThrowError, dduOptions) {
98
+ var _a, _b, _c, _d, _e, _f;
231
99
  const applyFallback = () => {
232
- const fallback = getFallback();
233
- currentCharSet = [...fallback.finalCharSet];
234
- currentPadding = fallback.finalPadding;
235
- currentRequiredLength = fallback.requiredLength;
236
- currentBitLength = fallback.bitLength;
237
- currentIsPredefined = true;
100
+ var _a, _b, _c;
101
+ const fallbackSymbol = (_b = (_a = dduOptions === null || dduOptions === void 0 ? void 0 : dduOptions.dduSetSymbol) !== null && _a !== void 0 ? _a : types_1.dduDefaultConstructorOptions.dduSetSymbol) !== null && _b !== void 0 ? _b : types_1.DduSetSymbol.ONECHARSET;
102
+ const cs = (_c = (0, charSets_1.getCharSet)(fallbackSymbol)) !== null && _c !== void 0 ? _c : (0, charSets_1.getCharSet)(types_1.DduSetSymbol.ONECHARSET);
103
+ if (!cs)
104
+ throw new Error(`Critical: No fallback CharSet available`);
105
+ return { charSet: cs.charSet, padding: cs.paddingChar, requiredLength: cs.maxRequiredLength, bitLength: cs.bitLength, isPredefined: true };
238
106
  };
239
- const ensureMinLength = () => {
240
- if (currentCharSet.length < currentRequiredLength) {
241
- if (shouldThrowError) {
242
- throw new Error(`${this.constructor.name} requires at least ${currentRequiredLength} characters in the character set. Provided: ${currentCharSet.length}`);
243
- }
244
- applyFallback();
107
+ const validate = (condition, message) => {
108
+ if (condition) {
109
+ if (shouldThrowError)
110
+ throw new Error(message);
111
+ const fb = applyFallback();
112
+ [charSet, padding, requiredLength, bitLength, isPredefined] = [fb.charSet, fb.padding, fb.requiredLength, fb.bitLength, fb.isPredefined];
113
+ return true;
245
114
  }
115
+ return false;
246
116
  };
247
- if (!currentIsPredefined) {
248
- const uniqueChars = new Set(currentCharSet);
249
- if (uniqueChars.size !== currentCharSet.length) {
250
- if (shouldThrowError) {
251
- throw new Error(`Character set contains duplicate characters. Unique: ${uniqueChars.size}, Total: ${currentCharSet.length}`);
252
- }
253
- currentCharSet = Array.from(uniqueChars);
117
+ // 중복 제거 (커스텀 charset만)
118
+ if (!isPredefined) {
119
+ const uniqueChars = new Set(charSet);
120
+ if (uniqueChars.size !== charSet.length) {
121
+ if (shouldThrowError)
122
+ throw new Error(`Character set contains duplicate characters. Unique: ${uniqueChars.size}, Total: ${charSet.length}`);
123
+ charSet = Array.from(uniqueChars);
124
+ requiredLength = charSet.length;
254
125
  }
255
126
  }
256
- ensureMinLength();
257
- let charLength = (_b = (_a = currentCharSet[0]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
258
- if (charLength === 0) {
259
- if (shouldThrowError) {
260
- throw new Error(`${this.constructor.name} requires at least ${currentRequiredLength} characters in the character set. Provided: ${currentCharSet.length}`);
261
- }
262
- applyFallback();
263
- charLength = (_d = (_c = currentCharSet[0]) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0;
127
+ // 검증
128
+ if (validate(charSet.length < requiredLength, `${this.constructor.name} requires at least ${requiredLength} characters. Provided: ${charSet.length}`)) {
129
+ return this.normalizeCharSet(charSet, padding, requiredLength, bitLength, isPredefined, shouldThrowError, dduOptions);
264
130
  }
265
- const invalidIndex = currentCharSet.findIndex((char) => char.length !== charLength);
131
+ let charLength = (_b = (_a = charSet[0]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
132
+ validate(charLength === 0, `${this.constructor.name} requires at least ${requiredLength} characters. Provided: ${charSet.length}`);
133
+ const invalidIndex = charSet.findIndex(char => char.length !== charLength);
266
134
  if (invalidIndex !== -1) {
267
- if (shouldThrowError) {
268
- throw new Error(`All characters must have the same length. Expected: ${charLength}, but character at index ${invalidIndex} ("${currentCharSet[invalidIndex]}") has length ${currentCharSet[invalidIndex].length}`);
269
- }
270
- currentCharSet = currentCharSet.filter((char) => char.length === charLength);
271
- ensureMinLength();
272
- charLength = (_f = (_e = currentCharSet[0]) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : 0;
273
- }
274
- if (!currentCharSet.length) {
275
- if (shouldThrowError) {
276
- throw new Error(`${this.constructor.name} requires at least ${currentRequiredLength} characters in the character set. Provided: 0`);
277
- }
278
- applyFallback();
279
- charLength = (_h = (_g = currentCharSet[0]) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : 0;
280
- }
281
- if (currentPadding.length !== charLength) {
282
- if (shouldThrowError) {
283
- throw new Error(`Padding character must have the same length as the characters. Expected: ${charLength}, but padding character has length ${currentPadding.length}`);
284
- }
285
- applyFallback();
286
- charLength = (_k = (_j = currentCharSet[0]) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : 0;
287
- }
288
- const charSetLookup = new Set(currentCharSet);
289
- if (charSetLookup.has(currentPadding)) {
290
- if (shouldThrowError) {
291
- throw new Error(`Padding character "${currentPadding}" cannot be in the character set`);
292
- }
293
- currentCharSet = currentCharSet.filter((char) => char !== currentPadding);
294
- ensureMinLength();
295
- charLength = (_m = (_l = currentCharSet[0]) === null || _l === void 0 ? void 0 : _l.length) !== null && _m !== void 0 ? _m : 0;
296
- }
297
- currentCharSet = currentCharSet.slice(0, currentRequiredLength);
298
- return {
299
- charSet: currentCharSet,
300
- padding: currentPadding,
301
- requiredLength: currentRequiredLength,
302
- bitLength: currentBitLength,
303
- isPredefined: currentIsPredefined,
304
- charLength,
305
- };
135
+ if (shouldThrowError)
136
+ throw new Error(`All characters must have the same length. Expected: ${charLength}, but index ${invalidIndex} has length ${charSet[invalidIndex].length}`);
137
+ charSet = charSet.filter(char => char.length === charLength);
138
+ validate(charSet.length < requiredLength, `${this.constructor.name} requires at least ${requiredLength} characters. Provided: ${charSet.length}`);
139
+ charLength = (_d = (_c = charSet[0]) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0;
140
+ }
141
+ validate(!charSet.length, `${this.constructor.name} requires at least ${requiredLength} characters. Provided: 0`);
142
+ validate(padding.length !== charLength, `Padding character must have length ${charLength}, got ${padding.length}`);
143
+ if (new Set(charSet).has(padding)) {
144
+ if (shouldThrowError)
145
+ throw new Error(`Padding character "${padding}" cannot be in the character set`);
146
+ charSet = charSet.filter(char => char !== padding);
147
+ validate(charSet.length < requiredLength, `${this.constructor.name} requires at least ${requiredLength} characters. Provided: ${charSet.length}`);
148
+ charLength = (_f = (_e = charSet[0]) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : 0;
149
+ }
150
+ return { charSet: charSet.slice(0, requiredLength), padding, requiredLength, bitLength, isPredefined, charLength };
306
151
  }
307
152
  getBinaryFromIndex(index) {
308
- const cache = this.indexToBinaryCache;
309
- if (cache && index < cache.length) {
310
- return cache[index];
311
- }
312
- return index.toString(2).padStart(this.effectiveBitLength, "0");
313
- }
314
- /**
315
- * string 또는 배열을 문자 배열로 변환
316
- */
317
- convertToCharArray(input) {
318
- if (typeof input === "string") {
319
- return [...new Set(input.trim())].map((c) => c);
320
- }
321
- return input;
322
- }
323
- /**
324
- * 숫자가 2의 제곱수인지 확인
325
- */
326
- isPowerOfTwo(n) {
327
- return n > 0 && (n & (n - 1)) === 0;
328
- }
329
- /**
330
- * usePowerOfTwo 옵션 적용
331
- */
332
- applyPowerOfTwoOption(charArray, padding, length, usePowerOfTwo) {
333
- if (usePowerOfTwo) {
334
- const powerOfTwoExponent = this.getLargestPowerOfTwoExponent(length);
335
- const powerOfTwoLength = Math.pow(2, powerOfTwoExponent);
336
- return {
337
- finalCharSet: charArray.slice(0, powerOfTwoLength),
338
- finalPadding: padding,
339
- requiredLength: powerOfTwoLength,
340
- bitLength: powerOfTwoExponent,
341
- };
342
- }
343
- return {
344
- finalCharSet: charArray.slice(0, length),
345
- finalPadding: padding,
346
- requiredLength: length,
347
- bitLength: this.getBitLength(length),
348
- };
153
+ var _a, _b;
154
+ return (_b = (_a = this.indexToBinaryCache) === null || _a === void 0 ? void 0 : _a[index]) !== null && _b !== void 0 ? _b : index.toString(2).padStart(this.effectiveBitLength, "0");
349
155
  }
350
- /**
351
- * 2글자 이상의 문자셋에서 조합으로 인한 중복을 검증
352
- * 예: ["AB", "CD"] + padding "AB" 또는 "A" + "B" = "AB" 같은 경우 감지
353
- */
354
156
  validateCombinationDuplicates(charSet, paddingChar, requiredLength) {
355
157
  const charLength = charSet[0].length;
356
- const allStrings = new Set();
357
- // 1. 기본 문자셋과 패딩 문자 추가
358
- charSet.slice(0, requiredLength).forEach((char) => allStrings.add(char));
359
- allStrings.add(paddingChar);
360
- // 2. 2개 조합 검사 (charLength * 2 길이)
361
- for (let i = 0; i < Math.min(charSet.length, requiredLength); i++) {
362
- for (let j = 0; j < Math.min(charSet.length, requiredLength); j++) {
363
- const combination = charSet[i] + charSet[j];
364
- // 조합이 기존 문자와 중복되는지 확인
365
- if (allStrings.has(combination)) {
366
- throw new Error(`Combination conflict detected: "${charSet[i]}" + "${charSet[j]}" = "${combination}" already exists in the character set or padding`);
158
+ const allStrings = new Set([...charSet.slice(0, requiredLength), paddingChar]);
159
+ const limit = Math.min(charSet.length, requiredLength);
160
+ // 2개 조합 검사
161
+ for (let i = 0; i < limit; i++) {
162
+ for (let j = 0; j < limit; j++) {
163
+ const combo = charSet[i] + charSet[j];
164
+ if (allStrings.has(combo)) {
165
+ throw new Error(`Combination conflict: "${charSet[i]}" + "${charSet[j]}" = "${combo}" already exists`);
367
166
  }
368
167
  }
369
- // 문자 + 패딩 조합 검사
370
- const charPlusPadding = charSet[i] + paddingChar;
371
- const paddingPlusChar = paddingChar + charSet[i];
372
- if (allStrings.has(charPlusPadding)) {
373
- throw new Error(`Combination conflict detected: "${charSet[i]}" + padding "${paddingChar}" = "${charPlusPadding}" already exists in the character set`);
374
- }
375
- if (allStrings.has(paddingPlusChar)) {
376
- throw new Error(`Combination conflict detected: padding "${paddingChar}" + "${charSet[i]}" = "${paddingPlusChar}" already exists in the character set`);
377
- }
378
- }
379
- // 3. 패딩 + 패딩 조합 검사
380
- const doublePadding = paddingChar + paddingChar;
381
- if (allStrings.has(doublePadding)) {
382
- throw new Error(`Combination conflict detected: padding "${paddingChar}" + padding "${paddingChar}" = "${doublePadding}" already exists in the character set`);
383
- }
384
- // 4. 3개 이상 조합 검사 (선택적, 성능을 위해 샘플링)
385
- // 모든 조합을 검사하면 O(n^3)이므로 일부만 샘플링
168
+ const charPad = charSet[i] + paddingChar;
169
+ const padChar = paddingChar + charSet[i];
170
+ if (allStrings.has(charPad))
171
+ throw new Error(`Combination conflict: "${charSet[i]}" + padding "${paddingChar}" = "${charPad}"`);
172
+ if (allStrings.has(padChar))
173
+ throw new Error(`Combination conflict: padding "${paddingChar}" + "${charSet[i]}" = "${padChar}"`);
174
+ }
175
+ // 패딩 + 패딩 조합 검사
176
+ const doublePad = paddingChar + paddingChar;
177
+ if (allStrings.has(doublePad)) {
178
+ throw new Error(`Combination conflict: double padding "${doublePad}" already exists`);
179
+ }
180
+ // 3개 조합 검사 (100개 이하만)
386
181
  if (charLength >= 2 && requiredLength <= 100) {
387
- // 100개 이하일 때만 전체 검사
388
- for (let i = 0; i < Math.min(charSet.length, requiredLength); i++) {
389
- for (let j = 0; j < Math.min(charSet.length, requiredLength); j++) {
390
- for (let k = 0; k < Math.min(charSet.length, requiredLength); k++) {
391
- const combination = charSet[i] + charSet[j] + charSet[k];
392
- // 조합의 부분 문자열이 기존 문자와 중복되는지 확인
393
- for (let start = 0; start < combination.length - charLength + 1; start++) {
394
- const substring = combination.substring(start, start + charLength);
395
- if (allStrings.has(substring) && substring !== charSet[i] && substring !== charSet[j] && substring !== charSet[k]) {
396
- throw new Error(`Combination conflict detected: substring "${substring}" from "${charSet[i]}" + "${charSet[j]}" + "${charSet[k]}" conflicts with existing character`);
182
+ for (let i = 0; i < limit; i++) {
183
+ for (let j = 0; j < limit; j++) {
184
+ for (let k = 0; k < limit; k++) {
185
+ const combo = charSet[i] + charSet[j] + charSet[k];
186
+ for (let start = 0; start <= combo.length - charLength; start++) {
187
+ const sub = combo.substring(start, start + charLength);
188
+ if (allStrings.has(sub) && sub !== charSet[i] && sub !== charSet[j] && sub !== charSet[k]) {
189
+ throw new Error(`Combination conflict: substring "${sub}" from "${charSet[i]}" + "${charSet[j]}" + "${charSet[k]}"`);
397
190
  }
398
191
  }
399
192
  }
@@ -13,45 +13,8 @@ export declare class Ddu64 extends BaseDdu {
13
13
  private readonly binaryChunkToIntFn;
14
14
  private readonly indexToBinaryCache;
15
15
  constructor(dduChar?: string[] | string, paddingChar?: string, dduOptions?: DduConstructorOptions);
16
- /**
17
- * charset 초기화 (커스텀 또는 미리 정의된 charset)
18
- */
19
- private initializeCharSet;
20
- /**
21
- * 커스텀 charset 처리
22
- */
23
- private processCustomCharSet;
24
- /**
25
- * 미리 정의된 charset 처리
26
- */
27
- private processPredefinedCharSet;
28
- /**
29
- * 기본 charset 처리
30
- */
31
- private processDefaultCharSet;
32
- /**
33
- * fallback charset 가져오기
34
- * 우선순위: dduOptions.dduSetSymbol > dduDefaultConstructorOptions.dduSetSymbol > DduSetSymbol.ONECHARSET
35
- */
36
- private getFallbackCharSet;
37
16
  private normalizeCharSet;
38
17
  private getBinaryFromIndex;
39
- /**
40
- * string 또는 배열을 문자 배열로 변환
41
- */
42
- private convertToCharArray;
43
- /**
44
- * 숫자가 2의 제곱수인지 확인
45
- */
46
- private isPowerOfTwo;
47
- /**
48
- * usePowerOfTwo 옵션 적용
49
- */
50
- private applyPowerOfTwoOption;
51
- /**
52
- * 2글자 이상의 문자셋에서 조합으로 인한 중복을 검증
53
- * 예: ["AB", "CD"] + padding "AB" 또는 "A" + "B" = "AB" 같은 경우 감지
54
- */
55
18
  private validateCombinationDuplicates;
56
19
  encode(input: Buffer | string, _options?: DduOptions): string;
57
20
  decode(input: string, _options?: DduOptions): string;