UNPKG

3.36 kBJavaScriptView Raw
1import {ByteStream} from './coders/byte-stream';
2
3import {ByteTakeIterator} from './squeak/byte-take-iterator';
4import {FieldIterator} from './squeak/field-iterator';
5import {TypeIterator} from './squeak/type-iterator';
6import {ReferenceFixer} from './squeak/reference-fixer';
7import {ImageMediaData, SoundMediaData} from './squeak/types';
8
9import {toSb2FakeZipApi} from './to-sb2/fake-zip';
10import {toSb2Json} from './to-sb2/json-generator';
11
12import {SB1Header, SB1Signature} from './sb1-file-packets';
13
14class SB1File {
15 constructor (buffer) {
16 this.buffer = buffer;
17 this.stream = new ByteStream(buffer);
18
19 this.signature = this.stream.readStruct(SB1Signature);
20 this.signature.validate();
21
22 this.infoHeader = this.stream.readStruct(SB1Header);
23 this.infoHeader.validate();
24
25 this.stream.position += this.signature.infoByteLength - SB1Header.size;
26
27 this.dataHeader = this.stream.readStruct(SB1Header);
28 this.dataHeader.validate();
29 }
30
31 get json () {
32 return toSb2Json({
33 info: this.info(),
34 stageData: this.data(),
35 images: this.images(),
36 sounds: this.sounds()
37 });
38 }
39
40 get zip () {
41 return toSb2FakeZipApi({
42 // Use of this `zip` getter assumes that `json` will be used to
43 // fetch the json and not have it read from the produced "fake" zip.
44 images: this.images(),
45 sounds: this.sounds()
46 });
47 }
48
49 view () {
50 return {
51 signature: this.signature,
52 infoHeader: this.infoHeader,
53 dataHeader: this.dataHeader,
54 toString () {
55 return 'SB1File';
56 }
57 };
58 }
59
60 infoRaw () {
61 return new ByteTakeIterator(
62 new FieldIterator(this.buffer, this.infoHeader.offset + SB1Header.size),
63 this.signature.infoByteLength + SB1Signature.size
64 );
65 }
66
67 infoTable () {
68 return new TypeIterator(this.infoRaw());
69 }
70
71 info () {
72 if (!this._info) {
73 this._info = new ReferenceFixer(this.infoTable()).table[0];
74 }
75 return this._info;
76 }
77
78 dataRaw () {
79 return new ByteTakeIterator(
80 new FieldIterator(this.buffer, this.dataHeader.offset + SB1Header.size),
81 this.stream.uint8a.length
82 );
83 }
84
85 dataTable () {
86 return new TypeIterator(this.dataRaw());
87 }
88
89 dataFixed () {
90 if (!this._data) {
91 this._data = new ReferenceFixer(this.dataTable()).table;
92 }
93 return this._data;
94 }
95
96 data () {
97 return this.dataFixed()[0];
98 }
99
100 images () {
101 const unique = new Set();
102 return this.dataFixed().filter(obj => {
103 if (obj instanceof ImageMediaData) {
104 if (unique.has(obj.crc)) return false;
105 unique.add(obj.crc);
106 return true;
107 }
108 return false;
109 });
110 }
111
112 sounds () {
113 const unique = new Set();
114 return this.dataFixed().filter(obj => {
115 if (obj instanceof SoundMediaData) {
116 if (unique.has(obj.crc)) return false;
117 unique.add(obj.crc);
118 return true;
119 }
120 return false;
121 });
122 }
123}
124
125export {SB1File};