bplist-lossless 0.1.0 → 0.1.1
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.
- package/dist/classes/plist-date.d.ts +82 -0
- package/dist/classes/plist-date.js +389 -0
- package/dist/classes/uid.d.ts +6 -0
- package/dist/classes/uid.js +26 -0
- package/dist/classes/utf16-string.d.ts +7 -0
- package/dist/classes/utf16-string.js +38 -0
- package/{src/exports/main.ts → dist/exports/main.d.ts} +1 -1
- package/dist/exports/main.js +5 -0
- package/dist/utils/parse.d.ts +3 -0
- package/dist/utils/parse.js +279 -0
- package/dist/utils/serialize.d.ts +1 -0
- package/dist/utils/serialize.js +494 -0
- package/package.json +4 -1
- package/readme.md +2 -2
- package/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +0 -111
- package/bun.lock +0 -176
- package/src/classes/plist-date.ts +0 -489
- package/src/classes/uid.ts +0 -38
- package/src/classes/utf16-string.ts +0 -54
- package/src/utils/parse.ts +0 -312
- package/src/utils/serialize.ts +0 -536
- package/test/plist.fuzz.test.ts +0 -298
- package/tsconfig.json +0 -30
- package/vitest.config.ts +0 -16
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export type PlistDateBinaryInput = Buffer | Uint8Array | ArrayBuffer;
|
|
2
|
+
export type PlistDateInput = PlistDate | Date | number | PlistDateBinaryInput;
|
|
3
|
+
export declare class PlistDate extends Date {
|
|
4
|
+
#private;
|
|
5
|
+
static readonly APPLE_PLIST_EPOCH_MS: number;
|
|
6
|
+
constructor();
|
|
7
|
+
constructor(value: PlistDateInput);
|
|
8
|
+
static from(input: PlistDateInput): PlistDate;
|
|
9
|
+
static fromBuffer(input: PlistDateBinaryInput): PlistDate;
|
|
10
|
+
static fromPlistSeconds(seconds: number): PlistDate;
|
|
11
|
+
static fromUnixMilliseconds(milliseconds: number): PlistDate;
|
|
12
|
+
static isPlistDate(value: unknown): value is PlistDate;
|
|
13
|
+
/**
|
|
14
|
+
* Exact plist-native value:
|
|
15
|
+
* seconds since 2001-01-01T00:00:00Z stored as IEEE 754
|
|
16
|
+
* (Institute of Electrical and Electronics Engineers 754) double.
|
|
17
|
+
*/
|
|
18
|
+
get plistSeconds(): number;
|
|
19
|
+
getPlistSeconds(): number;
|
|
20
|
+
getPlistSecondsString(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Exact raw 8-byte plist payload.
|
|
23
|
+
* If the object was constructed from raw bytes, those bytes are preserved
|
|
24
|
+
* until the date is mutated.
|
|
25
|
+
*/
|
|
26
|
+
getRawBytes(): Buffer;
|
|
27
|
+
toRawString(encoding?: BufferEncoding): string;
|
|
28
|
+
getRawHex(): string;
|
|
29
|
+
getRawBase64(): string;
|
|
30
|
+
toPlistString(): string;
|
|
31
|
+
toBuffer(): Buffer;
|
|
32
|
+
/**
|
|
33
|
+
* Set the exact plist-native seconds value.
|
|
34
|
+
* Returns the plist-seconds string.
|
|
35
|
+
*/
|
|
36
|
+
setPlistSeconds(seconds: number): string;
|
|
37
|
+
/**
|
|
38
|
+
* Replace the date from exact raw plist bytes.
|
|
39
|
+
* Returns the plist-seconds string.
|
|
40
|
+
*/
|
|
41
|
+
setRawBytes(input: PlistDateBinaryInput): string;
|
|
42
|
+
/**
|
|
43
|
+
* Parse raw hex into the exact 8-byte plist payload.
|
|
44
|
+
*/
|
|
45
|
+
setRawHex(hex: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Exact Unix milliseconds derived from the canonical plist bytes.
|
|
48
|
+
* This may include a fractional millisecond.
|
|
49
|
+
*/
|
|
50
|
+
getTime(): number;
|
|
51
|
+
valueOf(): number;
|
|
52
|
+
[Symbol.toPrimitive](hint: "default"): string;
|
|
53
|
+
[Symbol.toPrimitive](hint: "string"): string;
|
|
54
|
+
[Symbol.toPrimitive](hint: "number"): number;
|
|
55
|
+
toJSON(): string;
|
|
56
|
+
clone(): PlistDate;
|
|
57
|
+
equalsExactly(other: PlistDateInput): boolean;
|
|
58
|
+
equalsValue(other: PlistDateInput): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Direct time-setting path: normalize immediately to the exact
|
|
61
|
+
* plist-representable value.
|
|
62
|
+
*/
|
|
63
|
+
setTime(time: number): number;
|
|
64
|
+
setMilliseconds(ms: number): number;
|
|
65
|
+
setUTCMilliseconds(ms: number): number;
|
|
66
|
+
setSeconds(sec: number, ms?: number): number;
|
|
67
|
+
setUTCSeconds(sec: number, ms?: number): number;
|
|
68
|
+
setMinutes(min: number, sec?: number, ms?: number): number;
|
|
69
|
+
setUTCMinutes(min: number, sec?: number, ms?: number): number;
|
|
70
|
+
setHours(hours: number, min?: number, sec?: number, ms?: number): number;
|
|
71
|
+
setUTCHours(hours: number, min?: number, sec?: number, ms?: number): number;
|
|
72
|
+
setDate(date: number): number;
|
|
73
|
+
setUTCDate(date: number): number;
|
|
74
|
+
setMonth(month: number, date?: number): number;
|
|
75
|
+
setUTCMonth(month: number, date?: number): number;
|
|
76
|
+
setFullYear(year: number, month?: number, date?: number): number;
|
|
77
|
+
setUTCFullYear(year: number, month?: number, date?: number): number;
|
|
78
|
+
/**
|
|
79
|
+
* @deprecated This method is deprecated and should not be used. Use setFullYear() instead.
|
|
80
|
+
*/
|
|
81
|
+
setYear(year: number): number;
|
|
82
|
+
}
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
const APPLE_PLIST_EPOCH_MS = Date.UTC(2001, 0, 1);
|
|
2
|
+
function isBinaryInput(value) {
|
|
3
|
+
return (Buffer.isBuffer(value) ||
|
|
4
|
+
value instanceof Uint8Array ||
|
|
5
|
+
value instanceof ArrayBuffer);
|
|
6
|
+
}
|
|
7
|
+
function normalizeRaw8(input) {
|
|
8
|
+
const raw = Buffer.isBuffer(input)
|
|
9
|
+
? Buffer.from(input)
|
|
10
|
+
: input instanceof Uint8Array
|
|
11
|
+
? Buffer.from(input)
|
|
12
|
+
: Buffer.from(new Uint8Array(input));
|
|
13
|
+
if (raw.length !== 8) {
|
|
14
|
+
throw new RangeError(`PlistDate raw value must be exactly 8 bytes, got ${raw.length}.`);
|
|
15
|
+
}
|
|
16
|
+
return raw;
|
|
17
|
+
}
|
|
18
|
+
function encodePlistSeconds(seconds) {
|
|
19
|
+
const raw = Buffer.allocUnsafe(8);
|
|
20
|
+
raw.writeDoubleBE(seconds, 0);
|
|
21
|
+
return raw;
|
|
22
|
+
}
|
|
23
|
+
function decodePlistSeconds(raw) {
|
|
24
|
+
return raw.readDoubleBE(0);
|
|
25
|
+
}
|
|
26
|
+
function plistSecondsToUnixMilliseconds(seconds) {
|
|
27
|
+
return APPLE_PLIST_EPOCH_MS + seconds * 1000;
|
|
28
|
+
}
|
|
29
|
+
function unixMillisecondsToPlistSeconds(milliseconds) {
|
|
30
|
+
return (milliseconds - APPLE_PLIST_EPOCH_MS) / 1000;
|
|
31
|
+
}
|
|
32
|
+
function numberToStableString(value) {
|
|
33
|
+
if (Object.is(value, -0))
|
|
34
|
+
return "-0";
|
|
35
|
+
if (Number.isNaN(value))
|
|
36
|
+
return "NaN";
|
|
37
|
+
if (value === Infinity)
|
|
38
|
+
return "Infinity";
|
|
39
|
+
if (value === -Infinity)
|
|
40
|
+
return "-Infinity";
|
|
41
|
+
return value.toString();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Exact raw plist path.
|
|
45
|
+
*/
|
|
46
|
+
function canonicalStateFromRaw(input) {
|
|
47
|
+
const raw = normalizeRaw8(input);
|
|
48
|
+
const plistSeconds = decodePlistSeconds(raw);
|
|
49
|
+
const unixMilliseconds = plistSecondsToUnixMilliseconds(plistSeconds);
|
|
50
|
+
return { raw, plistSeconds, unixMilliseconds };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Canonicalize a plist-seconds number by round-tripping it through the
|
|
54
|
+
* actual 8-byte binary representation.
|
|
55
|
+
*/
|
|
56
|
+
function canonicalStateFromPlistSeconds(seconds) {
|
|
57
|
+
const raw = encodePlistSeconds(seconds);
|
|
58
|
+
const plistSeconds = decodePlistSeconds(raw);
|
|
59
|
+
const unixMilliseconds = plistSecondsToUnixMilliseconds(plistSeconds);
|
|
60
|
+
return { raw, plistSeconds, unixMilliseconds };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Canonicalize Unix milliseconds into the exact plist-representable value.
|
|
64
|
+
*
|
|
65
|
+
* This is the key fix for discrepancies like:
|
|
66
|
+
* 4410317596806472
|
|
67
|
+
* becoming
|
|
68
|
+
* 4410317596806471.5
|
|
69
|
+
*
|
|
70
|
+
* We normalize immediately instead of only discovering the change after
|
|
71
|
+
* encode -> decode.
|
|
72
|
+
*/
|
|
73
|
+
function canonicalStateFromUnixMilliseconds(milliseconds) {
|
|
74
|
+
return canonicalStateFromPlistSeconds(unixMillisecondsToPlistSeconds(milliseconds));
|
|
75
|
+
}
|
|
76
|
+
function resolveInitialState(value) {
|
|
77
|
+
if (value instanceof PlistDate) {
|
|
78
|
+
return canonicalStateFromRaw(value.getRawBytes());
|
|
79
|
+
}
|
|
80
|
+
if (isBinaryInput(value)) {
|
|
81
|
+
return canonicalStateFromRaw(value);
|
|
82
|
+
}
|
|
83
|
+
if (value instanceof Date) {
|
|
84
|
+
return canonicalStateFromUnixMilliseconds(value.getTime());
|
|
85
|
+
}
|
|
86
|
+
if (typeof value === "number") {
|
|
87
|
+
return canonicalStateFromUnixMilliseconds(value);
|
|
88
|
+
}
|
|
89
|
+
return canonicalStateFromUnixMilliseconds(Date.now());
|
|
90
|
+
}
|
|
91
|
+
export class PlistDate extends Date {
|
|
92
|
+
static APPLE_PLIST_EPOCH_MS = APPLE_PLIST_EPOCH_MS;
|
|
93
|
+
/**
|
|
94
|
+
* Raw 8-byte plist payload is the canonical source of truth.
|
|
95
|
+
*/
|
|
96
|
+
#raw = encodePlistSeconds(0);
|
|
97
|
+
constructor(value) {
|
|
98
|
+
const state = resolveInitialState(value);
|
|
99
|
+
super(state.unixMilliseconds);
|
|
100
|
+
this.#raw = state.raw;
|
|
101
|
+
}
|
|
102
|
+
static from(input) {
|
|
103
|
+
return new PlistDate(input);
|
|
104
|
+
}
|
|
105
|
+
static fromBuffer(input) {
|
|
106
|
+
return new PlistDate(input);
|
|
107
|
+
}
|
|
108
|
+
static fromPlistSeconds(seconds) {
|
|
109
|
+
return new PlistDate(encodePlistSeconds(seconds));
|
|
110
|
+
}
|
|
111
|
+
static fromUnixMilliseconds(milliseconds) {
|
|
112
|
+
return new PlistDate(milliseconds);
|
|
113
|
+
}
|
|
114
|
+
static isPlistDate(value) {
|
|
115
|
+
return value instanceof PlistDate;
|
|
116
|
+
}
|
|
117
|
+
#applyCanonicalState(state) {
|
|
118
|
+
this.#raw = Buffer.from(state.raw);
|
|
119
|
+
// Native Date only keeps whole-millisecond precision internally.
|
|
120
|
+
// We still keep the exact plist value in #raw and expose it through
|
|
121
|
+
// plistSeconds/getTime().
|
|
122
|
+
super.setTime(state.unixMilliseconds);
|
|
123
|
+
}
|
|
124
|
+
#replaceFromRaw(input) {
|
|
125
|
+
this.#applyCanonicalState(canonicalStateFromRaw(input));
|
|
126
|
+
}
|
|
127
|
+
#replaceFromPlistSeconds(seconds) {
|
|
128
|
+
this.#applyCanonicalState(canonicalStateFromPlistSeconds(seconds));
|
|
129
|
+
}
|
|
130
|
+
#replaceFromUnixMilliseconds(milliseconds) {
|
|
131
|
+
this.#applyCanonicalState(canonicalStateFromUnixMilliseconds(milliseconds));
|
|
132
|
+
return this.getTime();
|
|
133
|
+
}
|
|
134
|
+
#resyncFromDateState() {
|
|
135
|
+
return this.#replaceFromUnixMilliseconds(super.getTime());
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Exact plist-native value:
|
|
139
|
+
* seconds since 2001-01-01T00:00:00Z stored as IEEE 754
|
|
140
|
+
* (Institute of Electrical and Electronics Engineers 754) double.
|
|
141
|
+
*/
|
|
142
|
+
get plistSeconds() {
|
|
143
|
+
return decodePlistSeconds(this.#raw);
|
|
144
|
+
}
|
|
145
|
+
getPlistSeconds() {
|
|
146
|
+
return this.plistSeconds;
|
|
147
|
+
}
|
|
148
|
+
getPlistSecondsString() {
|
|
149
|
+
return numberToStableString(this.plistSeconds);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Exact raw 8-byte plist payload.
|
|
153
|
+
* If the object was constructed from raw bytes, those bytes are preserved
|
|
154
|
+
* until the date is mutated.
|
|
155
|
+
*/
|
|
156
|
+
getRawBytes() {
|
|
157
|
+
return Buffer.from(this.#raw);
|
|
158
|
+
}
|
|
159
|
+
toRawString(encoding = "hex") {
|
|
160
|
+
return this.#raw.toString(encoding);
|
|
161
|
+
}
|
|
162
|
+
getRawHex() {
|
|
163
|
+
return this.toRawString("hex");
|
|
164
|
+
}
|
|
165
|
+
getRawBase64() {
|
|
166
|
+
return this.toRawString("base64");
|
|
167
|
+
}
|
|
168
|
+
toPlistString() {
|
|
169
|
+
return this.getPlistSecondsString();
|
|
170
|
+
}
|
|
171
|
+
toBuffer() {
|
|
172
|
+
return this.getRawBytes();
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Set the exact plist-native seconds value.
|
|
176
|
+
* Returns the plist-seconds string.
|
|
177
|
+
*/
|
|
178
|
+
setPlistSeconds(seconds) {
|
|
179
|
+
if (typeof seconds !== "number") {
|
|
180
|
+
throw new TypeError("PlistDate seconds must be a number.");
|
|
181
|
+
}
|
|
182
|
+
this.#replaceFromPlistSeconds(seconds);
|
|
183
|
+
return this.getPlistSecondsString();
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Replace the date from exact raw plist bytes.
|
|
187
|
+
* Returns the plist-seconds string.
|
|
188
|
+
*/
|
|
189
|
+
setRawBytes(input) {
|
|
190
|
+
this.#replaceFromRaw(input);
|
|
191
|
+
return this.getPlistSecondsString();
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Parse raw hex into the exact 8-byte plist payload.
|
|
195
|
+
*/
|
|
196
|
+
setRawHex(hex) {
|
|
197
|
+
if (typeof hex !== "string" || !/^[0-9a-fA-F]{16}$/.test(hex)) {
|
|
198
|
+
throw new TypeError("PlistDate raw hex must be a 16-character hexadecimal string.");
|
|
199
|
+
}
|
|
200
|
+
return this.setRawBytes(Buffer.from(hex, "hex"));
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Exact Unix milliseconds derived from the canonical plist bytes.
|
|
204
|
+
* This may include a fractional millisecond.
|
|
205
|
+
*/
|
|
206
|
+
getTime() {
|
|
207
|
+
return plistSecondsToUnixMilliseconds(this.plistSeconds);
|
|
208
|
+
}
|
|
209
|
+
valueOf() {
|
|
210
|
+
return this.getTime();
|
|
211
|
+
}
|
|
212
|
+
[Symbol.toPrimitive](hint) {
|
|
213
|
+
if (hint === "number") {
|
|
214
|
+
return this.getTime();
|
|
215
|
+
}
|
|
216
|
+
return this.toString();
|
|
217
|
+
}
|
|
218
|
+
toJSON() {
|
|
219
|
+
return new Date(this.getTime()).toISOString();
|
|
220
|
+
}
|
|
221
|
+
clone() {
|
|
222
|
+
return new PlistDate(this.#raw);
|
|
223
|
+
}
|
|
224
|
+
equalsExactly(other) {
|
|
225
|
+
const rhs = PlistDate.from(other);
|
|
226
|
+
return this.#raw.equals(rhs.#raw);
|
|
227
|
+
}
|
|
228
|
+
equalsValue(other) {
|
|
229
|
+
const rhs = PlistDate.from(other);
|
|
230
|
+
return Object.is(this.plistSeconds, rhs.plistSeconds);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Direct time-setting path: normalize immediately to the exact
|
|
234
|
+
* plist-representable value.
|
|
235
|
+
*/
|
|
236
|
+
setTime(time) {
|
|
237
|
+
return this.#replaceFromUnixMilliseconds(time);
|
|
238
|
+
}
|
|
239
|
+
setMilliseconds(ms) {
|
|
240
|
+
super.setMilliseconds(ms);
|
|
241
|
+
return this.#resyncFromDateState();
|
|
242
|
+
}
|
|
243
|
+
setUTCMilliseconds(ms) {
|
|
244
|
+
super.setUTCMilliseconds(ms);
|
|
245
|
+
return this.#resyncFromDateState();
|
|
246
|
+
}
|
|
247
|
+
setSeconds(sec, ms) {
|
|
248
|
+
if (ms === undefined) {
|
|
249
|
+
super.setSeconds(sec);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
super.setSeconds(sec, ms);
|
|
253
|
+
}
|
|
254
|
+
return this.#resyncFromDateState();
|
|
255
|
+
}
|
|
256
|
+
setUTCSeconds(sec, ms) {
|
|
257
|
+
if (ms === undefined) {
|
|
258
|
+
super.setUTCSeconds(sec);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
super.setUTCSeconds(sec, ms);
|
|
262
|
+
}
|
|
263
|
+
return this.#resyncFromDateState();
|
|
264
|
+
}
|
|
265
|
+
setMinutes(min, sec, ms) {
|
|
266
|
+
if (sec === undefined) {
|
|
267
|
+
super.setMinutes(min);
|
|
268
|
+
}
|
|
269
|
+
else if (ms === undefined) {
|
|
270
|
+
super.setMinutes(min, sec);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
super.setMinutes(min, sec, ms);
|
|
274
|
+
}
|
|
275
|
+
return this.#resyncFromDateState();
|
|
276
|
+
}
|
|
277
|
+
setUTCMinutes(min, sec, ms) {
|
|
278
|
+
if (sec === undefined) {
|
|
279
|
+
super.setUTCMinutes(min);
|
|
280
|
+
}
|
|
281
|
+
else if (ms === undefined) {
|
|
282
|
+
super.setUTCMinutes(min, sec);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
super.setUTCMinutes(min, sec, ms);
|
|
286
|
+
}
|
|
287
|
+
return this.#resyncFromDateState();
|
|
288
|
+
}
|
|
289
|
+
setHours(hours, min, sec, ms) {
|
|
290
|
+
if (min === undefined) {
|
|
291
|
+
super.setHours(hours);
|
|
292
|
+
}
|
|
293
|
+
else if (sec === undefined) {
|
|
294
|
+
super.setHours(hours, min);
|
|
295
|
+
}
|
|
296
|
+
else if (ms === undefined) {
|
|
297
|
+
super.setHours(hours, min, sec);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
super.setHours(hours, min, sec, ms);
|
|
301
|
+
}
|
|
302
|
+
return this.#resyncFromDateState();
|
|
303
|
+
}
|
|
304
|
+
setUTCHours(hours, min, sec, ms) {
|
|
305
|
+
if (min === undefined) {
|
|
306
|
+
super.setUTCHours(hours);
|
|
307
|
+
}
|
|
308
|
+
else if (sec === undefined) {
|
|
309
|
+
super.setUTCHours(hours, min);
|
|
310
|
+
}
|
|
311
|
+
else if (ms === undefined) {
|
|
312
|
+
super.setUTCHours(hours, min, sec);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
super.setUTCHours(hours, min, sec, ms);
|
|
316
|
+
}
|
|
317
|
+
return this.#resyncFromDateState();
|
|
318
|
+
}
|
|
319
|
+
setDate(date) {
|
|
320
|
+
super.setDate(date);
|
|
321
|
+
return this.#resyncFromDateState();
|
|
322
|
+
}
|
|
323
|
+
setUTCDate(date) {
|
|
324
|
+
super.setUTCDate(date);
|
|
325
|
+
return this.#resyncFromDateState();
|
|
326
|
+
}
|
|
327
|
+
setMonth(month, date) {
|
|
328
|
+
if (date === undefined) {
|
|
329
|
+
super.setMonth(month);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
super.setMonth(month, date);
|
|
333
|
+
}
|
|
334
|
+
return this.#resyncFromDateState();
|
|
335
|
+
}
|
|
336
|
+
setUTCMonth(month, date) {
|
|
337
|
+
if (date === undefined) {
|
|
338
|
+
super.setUTCMonth(month);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
super.setUTCMonth(month, date);
|
|
342
|
+
}
|
|
343
|
+
return this.#resyncFromDateState();
|
|
344
|
+
}
|
|
345
|
+
setFullYear(year, month, date) {
|
|
346
|
+
if (month === undefined) {
|
|
347
|
+
super.setFullYear(year);
|
|
348
|
+
}
|
|
349
|
+
else if (date === undefined) {
|
|
350
|
+
super.setFullYear(year, month);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
super.setFullYear(year, month, date);
|
|
354
|
+
}
|
|
355
|
+
return this.#resyncFromDateState();
|
|
356
|
+
}
|
|
357
|
+
setUTCFullYear(year, month, date) {
|
|
358
|
+
if (month === undefined) {
|
|
359
|
+
super.setUTCFullYear(year);
|
|
360
|
+
}
|
|
361
|
+
else if (date === undefined) {
|
|
362
|
+
super.setUTCFullYear(year, month);
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
super.setUTCFullYear(year, month, date);
|
|
366
|
+
}
|
|
367
|
+
return this.#resyncFromDateState();
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* @deprecated This method is deprecated and should not be used. Use setFullYear() instead.
|
|
371
|
+
*/
|
|
372
|
+
// @ts-ignore
|
|
373
|
+
setYear(year) {
|
|
374
|
+
// @ts-ignore
|
|
375
|
+
super.setYear(year);
|
|
376
|
+
return this.#resyncFromDateState();
|
|
377
|
+
}
|
|
378
|
+
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
379
|
+
const iso = (() => {
|
|
380
|
+
try {
|
|
381
|
+
return this.toISOString();
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
return "Invalid Date";
|
|
385
|
+
}
|
|
386
|
+
})();
|
|
387
|
+
return `PlistDate(${iso}, plistSeconds=${this.getPlistSecondsString()}, raw=${this.getRawHex()})`;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const UID_BRAND = Symbol.for('plist.UID');
|
|
2
|
+
export class UID extends Uint8Array {
|
|
3
|
+
static from(bytes) {
|
|
4
|
+
return new UID(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
5
|
+
}
|
|
6
|
+
constructor(buffer, byteOffset, length) {
|
|
7
|
+
super(buffer, byteOffset, length);
|
|
8
|
+
Object.defineProperty(this, UID_BRAND, {
|
|
9
|
+
value: true,
|
|
10
|
+
enumerable: false,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
static isUID(value) {
|
|
14
|
+
return (value instanceof Uint8Array &&
|
|
15
|
+
value != null &&
|
|
16
|
+
value[UID_BRAND] === true);
|
|
17
|
+
}
|
|
18
|
+
toHex() {
|
|
19
|
+
return Array.from(this)
|
|
20
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
21
|
+
.join('');
|
|
22
|
+
}
|
|
23
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
24
|
+
return `UID(${this.toHex()})`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class Utf16String extends Uint8Array {
|
|
2
|
+
static from(bytes: Uint8Array): Utf16String;
|
|
3
|
+
constructor(buffer: ArrayBuffer, byteOffset?: number, length?: number);
|
|
4
|
+
static isUtf16String(value: unknown): value is Utf16String;
|
|
5
|
+
toString(): string;
|
|
6
|
+
toHex(): string;
|
|
7
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const UTF16_STRING_BRAND = Symbol.for('plist.Utf16String');
|
|
2
|
+
export class Utf16String extends Uint8Array {
|
|
3
|
+
static from(bytes) {
|
|
4
|
+
return new Utf16String(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
5
|
+
}
|
|
6
|
+
constructor(buffer, byteOffset, length) {
|
|
7
|
+
super(buffer, byteOffset, length);
|
|
8
|
+
Object.defineProperty(this, UTF16_STRING_BRAND, {
|
|
9
|
+
value: true,
|
|
10
|
+
enumerable: false,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
static isUtf16String(value) {
|
|
14
|
+
return (value instanceof Uint8Array &&
|
|
15
|
+
value != null &&
|
|
16
|
+
value[UTF16_STRING_BRAND] === true);
|
|
17
|
+
}
|
|
18
|
+
toString() {
|
|
19
|
+
const copy = new Uint8Array(this);
|
|
20
|
+
if (this.length % 2 !== 0) {
|
|
21
|
+
throw new Error('Invalid UTF-16 byte length');
|
|
22
|
+
}
|
|
23
|
+
for (let i = 0; i < copy.length; i += 2) {
|
|
24
|
+
const a = copy[i];
|
|
25
|
+
copy[i] = copy[i + 1];
|
|
26
|
+
copy[i + 1] = a;
|
|
27
|
+
}
|
|
28
|
+
return Buffer.from(copy).toString('ucs2');
|
|
29
|
+
}
|
|
30
|
+
toHex() {
|
|
31
|
+
return Array.from(this)
|
|
32
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
33
|
+
.join('');
|
|
34
|
+
}
|
|
35
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
36
|
+
return `Utf16String(${this.toString()})`;
|
|
37
|
+
}
|
|
38
|
+
}
|