11import initializeWasm from './helper' ;
2- import { IFileData } from './types' ;
3- import { IWasmModule } from './unpack' ;
2+ import { IFileData , IUnpackJSAPI } from './types' ;
43
54const fetchByteArray = async ( url : string ) : Promise < Uint8Array > => {
65 const response = await fetch ( url ) ;
@@ -11,138 +10,125 @@ const fetchByteArray = async (url: string): Promise<Uint8Array> => {
1110 return new Uint8Array ( arrayBuffer ) ;
1211} ;
1312
14- const init = async ( ) : Promise < IWasmModule | null > => {
15- try {
16- const wasmModule = await initializeWasm ( ) ;
17- return wasmModule as IWasmModule ;
18- } catch ( error ) {
19- console . error ( 'Error initializing WASM module:' , error ) ;
20- return null ;
21- }
22- } ;
23-
24- export const extractData = async ( data : Uint8Array ) : Promise < IFileData [ ] > => {
25- const wasmModule = await init ( ) ;
26- if ( ! wasmModule ) {
27- console . error ( 'WASM module not initialized.' ) ;
28- return [ ] ;
29- }
30-
31- /**Since WebAssembly, memory is accessed using pointers
32- and the first parameter of extract_archive method from unpack.c, which is Uint8Array of file data, should be a pointer
33- so we have to allocate memory for file data
34- **/
35- const inputPtr = wasmModule . _malloc ( data . length ) ;
36- wasmModule . HEAPU8 . set ( data , inputPtr ) ;
37-
38- // fileCountPtr is the pointer to 4 bytes of memory in WebAssembly's heap that holds fileCount value from the ExtractedArchive structure in unpack.c.
39- const fileCountPtr = wasmModule . _malloc ( 4 ) ;
40-
41- try {
42- const resultPtr = wasmModule . _extract_archive (
43- inputPtr ,
44- data . length ,
45- fileCountPtr
46- ) ;
47-
48- /**
49- * Since extract_archive returns a pointer that refers to an instance of the ExtractedArchive in unpack.c
50- typedef struct {
51- FileData* files;
52- size_t fileCount;
53- int status;
54- char* error_message;
55- } ExtractedArchive;
56-
57- its fields are laid out in memory sequentially. Based on this and types each field will take 4 bytes:
58-
59- 4 bytes 4 bytes 4 bytes 4 bytes
60- ---------------|---------------|---------------|---------------
61- files fileCount status error_message
62-
63- `resultPtr` points to the beginning of the ExtractedArchive structure in WebAssembly memory
64- and in order to get pointer of statusPtr we need to calculate it as: 0(offset of file pointer) + 4 (offset of fileCount) + 4 (offset for status)
65- 'status' field and pointer of `error_message` are 32-bit signed integer
66- */
67- const statusPtr = wasmModule . getValue ( resultPtr + 8 , 'i32' ) ;
68- const errorMessagePtr = wasmModule . getValue ( resultPtr + 12 , 'i32' ) ;
69- if ( statusPtr !== 1 ) {
70- const errorMessage = wasmModule . UTF8ToString ( errorMessagePtr ) ;
71- console . error (
72- 'Extraction failed with status:' ,
73- statusPtr ,
74- 'Error:' ,
75- errorMessage
13+ export const initUntarJS = async ( ) : Promise < IUnpackJSAPI > => {
14+ const wasmModule = await initializeWasm ( ) ;
15+
16+ const extractData = async ( data : Uint8Array ) : Promise < IFileData [ ] > => {
17+ /**Since WebAssembly, memory is accessed using pointers
18+ and the first parameter of extract_archive method from unpack.c, which is Uint8Array of file data, should be a pointer
19+ so we have to allocate memory for file data
20+ **/
21+ const inputPtr = wasmModule . _malloc ( data . length ) ;
22+ wasmModule . HEAPU8 . set ( data , inputPtr ) ;
23+
24+ // fileCountPtr is the pointer to 4 bytes of memory in WebAssembly's heap that holds fileCount value from the ExtractedArchive structure in unpack.c.
25+ const fileCountPtr = wasmModule . _malloc ( 4 ) ;
26+
27+ try {
28+ const resultPtr = wasmModule . _extract_archive (
29+ inputPtr ,
30+ data . length ,
31+ fileCountPtr
7632 ) ;
33+
34+ /**
35+ * Since extract_archive returns a pointer that refers to an instance of the ExtractedArchive in unpack.c
36+ typedef struct {
37+ FileData* files;
38+ size_t fileCount;
39+ int status;
40+ char* error_message;
41+ } ExtractedArchive;
42+
43+ its fields are laid out in memory sequentially. Based on this and types each field will take 4 bytes:
44+
45+ 4 bytes 4 bytes 4 bytes 4 bytes
46+ ---------------|---------------|---------------|---------------
47+ files fileCount status error_message
48+
49+ `resultPtr` points to the beginning of the ExtractedArchive structure in WebAssembly memory
50+ and in order to get pointer of statusPtr we need to calculate it as: 0(offset of file pointer) + 4 (offset of fileCount) + 4 (offset for status)
51+ 'status' field and pointer of `error_message` are 32-bit signed integer
52+ */
53+ const statusPtr = wasmModule . getValue ( resultPtr + 8 , 'i32' ) ;
54+ const errorMessagePtr = wasmModule . getValue ( resultPtr + 12 , 'i32' ) ;
55+ if ( statusPtr !== 1 ) {
56+ const errorMessage = wasmModule . UTF8ToString ( errorMessagePtr ) ;
57+ console . error (
58+ 'Extraction failed with status:' ,
59+ statusPtr ,
60+ 'Error:' ,
61+ errorMessage
62+ ) ;
63+ return [ ] ;
64+ }
65+ const filesPtr = wasmModule . getValue ( resultPtr , 'i32' ) ;
66+ const fileCount = wasmModule . getValue ( resultPtr + 4 , 'i32' ) ;
67+
68+ const files : IFileData [ ] = [ ] ;
69+
70+ /**
71+ * FilesPtr is a pointer that refers to an instance of the FileData in unpack.c
72+ typedef struct {
73+ char* filename;
74+ uint8_t* data;
75+ size_t data_size;
76+ } FileData;
77+
78+ and its fields are laid out in memory sequentially too so each field take 4 bytes:
79+
80+ 4 bytes 4 bytes 4 bytes
81+ ---------------|---------------|---------------
82+ filename data data_size
83+
84+ `filesPtr + i * 12` calculates the memory address of the i-th FileData element in the array
85+ where `12` is the size of each FileData structure in memory in bytes: 4 + 4 + 4
86+ */
87+
88+ for ( let i = 0 ; i < fileCount ; i ++ ) {
89+ const fileDataPtr = filesPtr + i * 12 ;
90+ const filenamePtr = wasmModule . getValue ( fileDataPtr , 'i32' ) ;
91+ const dataSize = wasmModule . getValue ( fileDataPtr + 8 , 'i32' ) ;
92+ const dataPtr = wasmModule . getValue ( fileDataPtr + 4 , 'i32' ) ;
93+ const filename = wasmModule . UTF8ToString ( filenamePtr ) ;
94+ const fileData = new Uint8Array (
95+ wasmModule . HEAPU8 . buffer ,
96+ dataPtr ,
97+ dataSize
98+ ) ;
99+
100+ files . push ( {
101+ filename : filename ,
102+ data : fileData
103+ } ) ;
104+ }
105+
106+ wasmModule . _free ( inputPtr ) ;
107+ wasmModule . _free ( fileCountPtr ) ;
108+ wasmModule . _free ( errorMessagePtr ) ;
109+ wasmModule . _free ( resultPtr ) ;
110+
111+ return files ;
112+ } catch ( error ) {
113+ console . error ( 'Error during extraction:' , error ) ;
77114 return [ ] ;
78115 }
79- const filesPtr = wasmModule . getValue ( resultPtr , 'i32' ) ;
80- const fileCount = wasmModule . getValue ( resultPtr + 4 , 'i32' ) ;
81-
82- const files : IFileData [ ] = [ ] ;
83-
84- /**
85- * FilesPtr is a pointer that refers to an instance of the FileData in unpack.c
86- typedef struct {
87- char* filename;
88- uint8_t* data;
89- size_t data_size;
90- } FileData;
91-
92- and its fields are laid out in memory sequentially too so each field take 4 bytes:
93-
94- 4 bytes 4 bytes 4 bytes
95- ---------------|---------------|---------------
96- filename data data_size
97-
98- `filesPtr + i * 12` calculates the memory address of the i-th FileData element in the array
99- where `12` is the size of each FileData structure in memory in bytes: 4 + 4 + 4
100- */
101-
102- for ( let i = 0 ; i < fileCount ; i ++ ) {
103- const fileDataPtr = filesPtr + i * 12 ;
104- const filenamePtr = wasmModule . getValue ( fileDataPtr , 'i32' ) ;
105- const dataSize = wasmModule . getValue ( fileDataPtr + 8 , 'i32' ) ;
106- const dataPtr = wasmModule . getValue ( fileDataPtr + 4 , 'i32' ) ;
107- const filename = wasmModule . UTF8ToString ( filenamePtr ) ;
108- const fileData = new Uint8Array (
109- wasmModule . HEAPU8 . buffer ,
110- dataPtr ,
111- dataSize
112- ) ;
113-
114- files . push ( {
115- filename : filename ,
116- data : fileData
117- } ) ;
116+ } ;
117+
118+ const extract = async ( url : string ) : Promise < IFileData [ ] > => {
119+ try {
120+ const data = await fetchByteArray ( url ) ;
121+ return await extractData ( data ) ;
122+ } catch ( error ) {
123+ console . error ( 'Error during extracting:' , error ) ;
124+ return [ ] ;
118125 }
119-
120- wasmModule . _free ( inputPtr ) ;
121- wasmModule . _free ( fileCountPtr ) ;
122- wasmModule . _free ( errorMessagePtr ) ;
123- wasmModule . _free ( resultPtr ) ;
124-
125- return files ;
126- } catch ( error ) {
127- console . error ( 'Error during extraction:' , error ) ;
128- return [ ] ;
129126 }
130- } ;
131127
132- export const extract = async ( url : string ) : Promise < IFileData [ ] > => {
133- try {
134- const data = await fetchByteArray ( url ) ;
135- return await extractData ( data ) ;
136- } catch ( error ) {
137- console . error ( 'Error during extracting:' , error ) ;
138- return [ ] ;
139- }
128+ return {
129+ extract,
130+ extractData
131+ } ;
140132} ;
141133
142-
143134export * from './types' ;
144-
145- export default {
146- extract,
147- extractData
148- } ;
0 commit comments