@isopodlabs/binary_libs 0.1.1 → 0.1.3

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.
@@ -0,0 +1,129 @@
1
+ import * as binary from '@isopodlabs/binary';
2
+ declare class FAT {
3
+ shift: number;
4
+ sectors: Uint8Array;
5
+ fat: Int32Array;
6
+ freed: number[];
7
+ dirty_fat: Set<number>;
8
+ dirty_sec: Set<number>;
9
+ constructor(size: number, shift: number, sectors: Uint8Array);
10
+ private free;
11
+ private alloc;
12
+ get_chain(id: number): number[];
13
+ resize_chain(chain: number[], data_size: number): void;
14
+ clear_dirty(): void;
15
+ read_chain(chain: number[], dest: Uint8Array): void;
16
+ read_chain_alloc(chain: number[]): Uint8Array;
17
+ read(id: number, dest: Uint8Array): void;
18
+ write_chain(chain: number[], source: Uint8Array): void;
19
+ dirty_chain_part(chain: number[], offset: number): Uint8Array;
20
+ }
21
+ declare const Header_base: (new (s: binary._stream) => {
22
+ magic: bigint;
23
+ id: Uint8Array;
24
+ revision: number;
25
+ version: number;
26
+ byteorder: number;
27
+ sector_shift: number;
28
+ mini_shift: number;
29
+ unused1: void;
30
+ num_directory: number;
31
+ num_fat: number;
32
+ first_directory: number;
33
+ transaction: void;
34
+ mini_cutoff: number;
35
+ first_mini: number;
36
+ num_mini: number;
37
+ first_difat: number;
38
+ num_difat: number;
39
+ difat: Uint8Array;
40
+ } & {
41
+ write(w: binary._stream): void;
42
+ }) & {
43
+ get: (s: binary._stream) => {
44
+ magic: bigint;
45
+ id: Uint8Array;
46
+ revision: number;
47
+ version: number;
48
+ byteorder: number;
49
+ sector_shift: number;
50
+ mini_shift: number;
51
+ unused1: void;
52
+ num_directory: number;
53
+ num_fat: number;
54
+ first_directory: number;
55
+ transaction: void;
56
+ mini_cutoff: number;
57
+ first_mini: number;
58
+ num_mini: number;
59
+ first_difat: number;
60
+ num_difat: number;
61
+ difat: Uint8Array;
62
+ };
63
+ put: (s: binary._stream, v: any) => void;
64
+ };
65
+ export declare class Header extends Header_base {
66
+ sector_size(): number;
67
+ use_mini(size: number): boolean;
68
+ valid(): boolean;
69
+ }
70
+ declare const DirEntry_base: (new (s: binary._stream) => {
71
+ name: string;
72
+ name_size: number;
73
+ type: number;
74
+ colour: number;
75
+ left: number;
76
+ right: number;
77
+ root: number;
78
+ guid: Uint8Array;
79
+ flags: number;
80
+ creation: bigint;
81
+ modification: bigint;
82
+ sec_id: number;
83
+ size: number;
84
+ unused: number;
85
+ } & {
86
+ write(w: binary._stream): void;
87
+ }) & {
88
+ get: (s: binary._stream) => {
89
+ name: string;
90
+ name_size: number;
91
+ type: number;
92
+ colour: number;
93
+ left: number;
94
+ right: number;
95
+ root: number;
96
+ guid: Uint8Array;
97
+ flags: number;
98
+ creation: bigint;
99
+ modification: bigint;
100
+ sec_id: number;
101
+ size: number;
102
+ unused: number;
103
+ };
104
+ put: (s: binary._stream, v: any) => void;
105
+ };
106
+ declare class DirEntry extends DirEntry_base {
107
+ index: number;
108
+ constructor(index: number, r: binary.stream);
109
+ load(fat: FAT): Uint8Array;
110
+ }
111
+ declare class Master {
112
+ header: Header;
113
+ difat: Int32Array;
114
+ fat: FAT;
115
+ mini_fat: FAT;
116
+ mini_chain: number[];
117
+ constructor(sectors: Uint8Array, header: Header);
118
+ get_fat(mini: boolean): FAT;
119
+ flush(filename: string): Promise<void>;
120
+ }
121
+ export declare class Reader extends Master {
122
+ entries: DirEntry[];
123
+ private entry_chain;
124
+ constructor(sectors: Uint8Array, header: Header);
125
+ find(name: string, i?: number): DirEntry | undefined;
126
+ read(e: DirEntry): Uint8Array;
127
+ write(e: DirEntry, data: Uint8Array): void;
128
+ }
129
+ export {};
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.Reader = exports.Header = void 0;
27
+ const binary = __importStar(require("@isopodlabs/binary"));
28
+ const fs_1 = require("fs");
29
+ class FAT {
30
+ shift;
31
+ sectors;
32
+ fat;
33
+ freed = [];
34
+ dirty_fat = new Set();
35
+ dirty_sec = new Set();
36
+ constructor(size, shift, sectors) {
37
+ this.shift = shift;
38
+ this.sectors = sectors;
39
+ this.fat = new Int32Array(size);
40
+ }
41
+ free(id) {
42
+ this.freed.push(id);
43
+ this.fat[id] = -1 /* SecID.FREE */;
44
+ this.dirty_fat.add(id >> (this.shift - 2));
45
+ }
46
+ alloc(prev) {
47
+ if (!this.freed.length) {
48
+ this.fat.forEach((v, i) => {
49
+ if (v === -1 /* SecID.FREE */)
50
+ this.freed.push(i);
51
+ });
52
+ }
53
+ const id = this.freed.length ? this.freed.pop() : this.fat.length;
54
+ this.fat[prev] = id;
55
+ this.dirty_fat.add(id >> (this.shift - 2));
56
+ return id;
57
+ }
58
+ get_chain(id) {
59
+ const chain = [];
60
+ while (id != -2 /* SecID.ENDOFCHAIN */) {
61
+ chain.push(id);
62
+ id = this.fat[id];
63
+ }
64
+ return chain;
65
+ }
66
+ resize_chain(chain, data_size) {
67
+ const size = (data_size + (1 << this.shift) - 1) >> this.shift;
68
+ while (chain.length > size)
69
+ this.free(chain.pop());
70
+ if (size) {
71
+ let last = chain[size - 1];
72
+ while (chain.length < size)
73
+ chain.push(last = this.alloc(last));
74
+ if (this.fat[last] !== -2 /* SecID.ENDOFCHAIN */) {
75
+ this.fat[last] = -2 /* SecID.ENDOFCHAIN */;
76
+ this.dirty_fat.add(last >> (this.shift - 2));
77
+ }
78
+ }
79
+ else {
80
+ chain.push(-2 /* SecID.ENDOFCHAIN */);
81
+ }
82
+ }
83
+ clear_dirty() {
84
+ this.dirty_fat.clear();
85
+ this.dirty_sec.clear();
86
+ }
87
+ read_chain(chain, dest) {
88
+ chain.forEach((id, index) => {
89
+ const id2 = id << this.shift;
90
+ const index2 = index << this.shift;
91
+ dest.set(this.sectors.subarray(id2, id2 + Math.min(dest.length - index2)), index2);
92
+ });
93
+ }
94
+ read_chain_alloc(chain) {
95
+ const dest = new Uint8Array(chain.length << this.shift);
96
+ this.read_chain(chain, dest);
97
+ return dest;
98
+ }
99
+ read(id, dest) {
100
+ this.read_chain(this.get_chain(id), dest);
101
+ }
102
+ write_chain(chain, source) {
103
+ chain.forEach((id, index) => {
104
+ this.sectors.set(source.subarray(index << this.shift, (index + 1) << this.shift), id << this.shift);
105
+ this.dirty_sec.add(id);
106
+ });
107
+ }
108
+ dirty_chain_part(chain, offset) {
109
+ const sector = chain[offset >> this.shift];
110
+ this.dirty_sec.add(sector);
111
+ return this.sectors.subarray((sector << this.shift) + (offset & ((1 << this.shift) - 1)));
112
+ }
113
+ }
114
+ class Header extends binary.Class({
115
+ magic: binary.UINT64_BE,
116
+ id: binary.Buffer(16),
117
+ revision: binary.UINT16_LE,
118
+ version: binary.UINT16_LE,
119
+ byteorder: binary.UINT16_LE,
120
+ sector_shift: binary.UINT16_LE,
121
+ mini_shift: binary.UINT16_LE,
122
+ unused1: binary.SkipType(6),
123
+ num_directory: binary.UINT32_LE,
124
+ num_fat: binary.UINT32_LE,
125
+ first_directory: binary.UINT32_LE,
126
+ transaction: binary.SkipType(4), //must be 0
127
+ mini_cutoff: binary.UINT32_LE,
128
+ first_mini: binary.UINT32_LE,
129
+ num_mini: binary.UINT32_LE,
130
+ first_difat: binary.UINT32_LE,
131
+ num_difat: binary.UINT32_LE,
132
+ difat: binary.Buffer(436),
133
+ }) {
134
+ sector_size() { return 1 << this.sector_shift; }
135
+ use_mini(size) { return size < this.mini_cutoff; }
136
+ valid() { return this.magic == 0xd0cf11e0a1b11ae1n; }
137
+ }
138
+ exports.Header = Header;
139
+ const TYPE = {
140
+ Empty: 0,
141
+ UserStorage: 1,
142
+ UserStream: 2,
143
+ LockBytes: 3,
144
+ Property: 4,
145
+ RootStorage: 5,
146
+ };
147
+ const COLOUR = {
148
+ RED: 0, BLACK: 1
149
+ };
150
+ class DirEntry extends binary.Class({
151
+ name: binary.StringType(64, 'utf16le'),
152
+ name_size: binary.UINT16_LE,
153
+ type: binary.UINT8,
154
+ colour: binary.UINT8,
155
+ left: binary.INT32_LE,
156
+ right: binary.INT32_LE,
157
+ root: binary.INT32_LE,
158
+ guid: binary.Buffer(16),
159
+ flags: binary.UINT32_LE,
160
+ creation: binary.UINT64_LE,
161
+ modification: binary.UINT64_LE,
162
+ sec_id: binary.INT32_LE,
163
+ size: binary.UINT32_LE,
164
+ unused: binary.UINT32_LE
165
+ }) {
166
+ index;
167
+ constructor(index, r) {
168
+ super(r);
169
+ this.index = index;
170
+ this.name = this.name.substring(0, this.name_size / 2 - 1);
171
+ }
172
+ load(fat) {
173
+ const data = new Uint8Array(this.size);
174
+ fat.read(this.sec_id, data);
175
+ return data;
176
+ }
177
+ }
178
+ class Master {
179
+ header;
180
+ difat;
181
+ fat;
182
+ mini_fat;
183
+ mini_chain;
184
+ constructor(sectors, header) {
185
+ this.header = header;
186
+ const shift = header.sector_shift;
187
+ let num = header.num_difat;
188
+ let m_size = 109 + (num << (shift - 2));
189
+ this.difat = new Int32Array(m_size);
190
+ binary.utils.to8(this.difat).set(header.difat, 0);
191
+ let sect = header.first_difat;
192
+ let p = 109 * 4;
193
+ while (num--) {
194
+ const data = sectors.subarray(sect << shift, (sect + 1) << shift);
195
+ const end = data.length - 4;
196
+ sect = new DataView(data.buffer).getUint32(end);
197
+ binary.utils.to8(this.difat).set(data.subarray(0, end), p);
198
+ p += end;
199
+ }
200
+ while (this.difat[m_size - 1] == -1 /* SecID.FREE */)
201
+ --m_size;
202
+ this.fat = new FAT(m_size << (shift - 2), shift, sectors);
203
+ Array.from(this.difat.subarray(0, m_size)).forEach((id, index) => {
204
+ const data = sectors.subarray(id << shift, (id + 1) << shift);
205
+ binary.utils.to8(this.fat.fat).set(data, index << shift);
206
+ });
207
+ const root = new DirEntry(0, new binary.stream(sectors.subarray(header.first_directory << shift)));
208
+ this.mini_chain = this.fat.get_chain(root.sec_id);
209
+ this.mini_fat = new FAT(header.num_mini << (shift - 2), header.mini_shift, root.load(this.fat));
210
+ this.fat.read(header.first_mini, binary.utils.to8(this.mini_fat.fat));
211
+ }
212
+ get_fat(mini) {
213
+ return mini ? this.mini_fat : this.fat;
214
+ }
215
+ async flush(filename) {
216
+ const dirty = new Set(this.fat.dirty_sec);
217
+ function mark_dirty_shift(entries, translate, shift) {
218
+ for (const i of entries)
219
+ dirty.add(translate[i >> shift]);
220
+ }
221
+ const mini_extra = this.fat.shift - this.header.mini_shift;
222
+ mark_dirty_shift(this.fat.dirty_fat.keys(), Array.from(this.difat), 0);
223
+ mark_dirty_shift(this.mini_fat.dirty_sec, this.mini_chain, mini_extra);
224
+ mark_dirty_shift(this.mini_fat.dirty_fat.keys(), this.fat.get_chain(this.header.first_mini), mini_extra);
225
+ if (!dirty.size)
226
+ return;
227
+ let fileHandle;
228
+ try {
229
+ fileHandle = await fs_1.promises.open(filename, 'r+');
230
+ const ss = 1 << this.fat.shift;
231
+ for (const i of dirty.keys()) {
232
+ const position = i * ss;
233
+ await fileHandle.write(this.fat.sectors, position, ss, position + ss);
234
+ }
235
+ this.fat.clear_dirty();
236
+ this.mini_fat.clear_dirty();
237
+ }
238
+ catch (error) {
239
+ console.error('An error occurred:', error);
240
+ }
241
+ finally {
242
+ if (fileHandle)
243
+ await fileHandle.close();
244
+ }
245
+ }
246
+ }
247
+ class Reader extends Master {
248
+ entries = [];
249
+ entry_chain;
250
+ constructor(sectors, header) {
251
+ super(sectors, header);
252
+ this.entry_chain = this.fat.get_chain(header.first_directory);
253
+ const dir_buff = this.fat.read_chain_alloc(this.entry_chain);
254
+ const r2 = new binary.stream(dir_buff);
255
+ for (let i = 0; i < dir_buff.length / 128; i++)
256
+ this.entries[i] = new DirEntry(i, r2.seek(i * 128));
257
+ }
258
+ find(name, i = 0) {
259
+ const stack = [];
260
+ let sp = 0;
261
+ for (;;) {
262
+ const e = this.entries[i];
263
+ if (e.name == name)
264
+ return e;
265
+ if (e.type == TYPE.RootStorage)
266
+ stack[sp++] = e.root;
267
+ if (e.right != -1)
268
+ stack[sp++] = e.right;
269
+ i = e.left;
270
+ if (i == -1) {
271
+ if (sp === 0)
272
+ return undefined;
273
+ i = stack[--sp];
274
+ }
275
+ }
276
+ }
277
+ read(e) {
278
+ const mini = this.header.use_mini(e.size);
279
+ const fat = this.get_fat(mini);
280
+ return e.load(fat);
281
+ }
282
+ write(e, data) {
283
+ const mini1 = this.header.use_mini(e.size);
284
+ const fat1 = this.get_fat(mini1);
285
+ const chain = fat1.get_chain(e.sec_id);
286
+ const mini2 = this.header.use_mini(data.length);
287
+ const fat2 = this.get_fat(mini2);
288
+ if (data.length != e.size) {
289
+ if (mini1 != mini2)
290
+ fat1.resize_chain(chain, 0);
291
+ fat2.resize_chain(chain, data.length);
292
+ e.size = data.length;
293
+ e.sec_id = chain[0];
294
+ const dest = this.fat.dirty_chain_part(this.entry_chain, e.index * 128);
295
+ e.write(new binary.stream(dest));
296
+ }
297
+ fat2.write_chain(chain, data);
298
+ }
299
+ }
300
+ exports.Reader = Reader;
package/dist/arch.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import * as binary from '@isopodlabs/binary';
2
+ export type HEADER = {
3
+ name: string;
4
+ date: number;
5
+ uid: number;
6
+ gid: number;
7
+ mode: number;
8
+ size: number;
9
+ fmag: string;
10
+ contents: any;
11
+ };
12
+ export declare class ArchFile {
13
+ members: {
14
+ name: string;
15
+ date: number;
16
+ uid: number;
17
+ gid: number;
18
+ mode: number;
19
+ size: number;
20
+ fmag: string;
21
+ contents: any;
22
+ }[];
23
+ static check(data: Uint8Array): boolean;
24
+ constructor(data: Uint8Array);
25
+ }
26
+ export {};
package/dist/arch.js ADDED
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.ArchFile = void 0;
27
+ const binary = __importStar(require("@isopodlabs/binary"));
28
+ const _HEADER = {
29
+ name: binary.as(binary.StringType(16), x => {
30
+ x = x.trim();
31
+ return x.endsWith('/') ? x.slice(0, -1) : x;
32
+ }),
33
+ date: binary.asInt(binary.StringType(12)),
34
+ uid: binary.asInt(binary.StringType(6)),
35
+ gid: binary.asInt(binary.StringType(6)),
36
+ mode: binary.asInt(binary.StringType(8), 8),
37
+ size: binary.asInt(binary.StringType(10)),
38
+ fmag: binary.as(binary.StringType(2), x => x.trim() == '`' ? '' : x),
39
+ contents: binary.DontRead()
40
+ };
41
+ const SYM64 = {
42
+ name: binary.StringType(12),
43
+ offset: binary.asInt(binary.StringType(4))
44
+ };
45
+ class ArchFile {
46
+ members = [];
47
+ static check(data) {
48
+ return binary.utils.decodeText(data.subarray(0, 8), 'utf8') == '!<arch>\n';
49
+ }
50
+ constructor(data) {
51
+ const s = new binary.stream(data);
52
+ const header = binary.read(s, binary.StringType(8));
53
+ if (header !== '!<arch>\n')
54
+ throw new Error('Invalid archive file format');
55
+ let long_names;
56
+ while (s.remaining() > 0) {
57
+ const member = binary.read(s, _HEADER);
58
+ const data = s.read_buffer(member.size);
59
+ s.align(2);
60
+ if (member.name == '/') {
61
+ long_names = binary.utils.decodeText(data, 'utf8');
62
+ continue;
63
+ }
64
+ if (member.name[0] == '/' && long_names) {
65
+ const offset = +member.name.substring(1);
66
+ member.name = long_names.substring(offset, long_names.indexOf('/', offset));
67
+ }
68
+ if (member.name == '') {
69
+ const s2 = new binary.stream(data);
70
+ const offsets = binary.ArrayType(binary.INT32_BE, binary.INT32_BE).get(s2);
71
+ member.name = 'Symbols';
72
+ member.contents = offsets.map(offset => [
73
+ binary.NullTerminatedStringType.get(s2),
74
+ offset
75
+ ]);
76
+ }
77
+ else if (member.name == '/SYM') {
78
+ const s2 = new binary.stream(data);
79
+ const syms = binary.ArrayType(binary.INT32_BE, binary.NullTerminatedStringType).get(s2);
80
+ member.contents = syms.map(name => ({
81
+ name,
82
+ offset: binary.INT32_BE.get(s2)
83
+ }));
84
+ }
85
+ else if (member.name == '/SYM64') {
86
+ const s2 = new binary.stream(data);
87
+ member.contents = binary.RemainingArrayType(SYM64).get(s2);
88
+ }
89
+ else {
90
+ member.contents = data;
91
+ }
92
+ this.members.push(member);
93
+ }
94
+ }
95
+ }
96
+ exports.ArchFile = ArchFile;