@@ -27,24 +27,82 @@ export const extractData = async (data: Uint8Array): Promise<IFileData[]> => {
2727 console . error ( 'WASM module not initialized.' ) ;
2828 return [ ] ;
2929 }
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+ **/
3035 const inputPtr = wasmModule . _malloc ( data . length ) ;
3136 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.
3239 const fileCountPtr = wasmModule . _malloc ( 4 ) ;
33- const outputSizePtr = wasmModule . _malloc ( 4 ) ;
3440
3541 try {
36- const extractedFilesPtr = wasmModule . _extract_archive (
42+ const resultPtr = wasmModule . _extract_archive (
3743 inputPtr ,
3844 data . length ,
39- outputSizePtr ,
4045 fileCountPtr
4146 ) ;
4247
43- const fileCount = wasmModule . getValue ( fileCountPtr , 'i32' ) ;
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+ console . log ( 'status' , statusPtr ) ;
70+ console . log ( 'errorMessagePtr' , errorMessagePtr ) ;
71+ if ( statusPtr !== 1 ) {
72+ const errorMessage = wasmModule . UTF8ToString ( errorMessagePtr ) ;
73+ console . error (
74+ 'Extraction failed with status:' ,
75+ statusPtr ,
76+ 'Error:' ,
77+ errorMessage
78+ ) ;
79+ return [ ] ;
80+ }
81+ const filesPtr = wasmModule . getValue ( resultPtr , 'i32' ) ;
82+ const fileCount = wasmModule . getValue ( resultPtr + 4 , 'i32' ) ;
83+
4484 const files : IFileData [ ] = [ ] ;
4585
86+ /**
87+ * FilesPtr is a pointer that refers to an instance of the FileData in unpack.c
88+ typedef struct {
89+ char* filename;
90+ uint8_t* data;
91+ size_t data_size;
92+ } FileData;
93+
94+ and its fields are laid out in memory sequentially too so each field take 4 bytes:
95+
96+ 4 bytes 4 bytes 4 bytes
97+ ---------------|---------------|---------------
98+ filename data data_size
99+
100+ `filesPtr + i * 12` calculates the memory address of the i-th FileData element in the array
101+ where `12` is the size of each FileData structure in memory in bytes: 4 + 4 + 4
102+ */
103+
46104 for ( let i = 0 ; i < fileCount ; i ++ ) {
47- const fileDataPtr = extractedFilesPtr + i * ( 3 * 4 ) ;
105+ const fileDataPtr = filesPtr + i * 12 ;
48106 const filenamePtr = wasmModule . getValue ( fileDataPtr , 'i32' ) ;
49107 const dataSize = wasmModule . getValue ( fileDataPtr + 8 , 'i32' ) ;
50108 const dataPtr = wasmModule . getValue ( fileDataPtr + 4 , 'i32' ) ;
@@ -61,14 +119,15 @@ export const extractData = async (data: Uint8Array): Promise<IFileData[]> => {
61119 } ) ;
62120 }
63121
64- wasmModule . _free ( fileCountPtr ) ;
65- wasmModule . _free ( outputSizePtr ) ;
66122 wasmModule . _free ( inputPtr ) ;
67- wasmModule . _free ( extractedFilesPtr ) ;
123+ wasmModule . _free ( fileCountPtr ) ;
124+ wasmModule . _free ( statusPtr ) ;
125+ wasmModule . _free ( errorMessagePtr ) ;
126+ wasmModule . _free ( resultPtr ) ;
68127
69128 return files ;
70129 } catch ( error ) {
71- console . error ( 'Error during extracting :' , error ) ;
130+ console . error ( 'Error during extraction :' , error ) ;
72131 return [ ] ;
73132 }
74133} ;
0 commit comments