@@ -14,23 +14,35 @@ namespace wasmfs {
1414
1515const  uint32_t  DEFAULT_CHUNK_SIZE = 16 *1024 *1024 ;
1616
17+ typedef  std::map<std::string,std::string> FetchManifest;
18+ 
1719class  FetchBackend  : public  wasmfs ::ProxiedAsyncJSBackend {
1820  std::string baseUrl;
1921  uint32_t  chunkSize;
22+   FetchManifest *manifest;
2023 public: 
24+   //  Takes ownership of manifest
2125  FetchBackend (const  std::string& baseUrl,
2226               uint32_t  chunkSize,
27+                FetchManifest *manifest,
2328               std::function<void (backend_t )> setupOnThread)
24-     : ProxiedAsyncJSBackend(setupOnThread), baseUrl(baseUrl), chunkSize(chunkSize)
25-       //  TODO manifest
29+     : ProxiedAsyncJSBackend(setupOnThread), baseUrl(baseUrl), chunkSize(chunkSize), manifest(manifest)
2630  {}
31+   ~FetchBackend () {
32+     if (manifest != NULL ) {
33+       delete  manifest;
34+     }
35+   }
2736  std::shared_ptr<DataFile> createFile (mode_t  mode) override ;
2837  std::shared_ptr<Directory> createDirectory (mode_t  mode) override ;
2938  const  std::string getFileURL (const  std::string& filePath);
3039  uint32_t  getChunkSize ();
40+   const  FetchManifest *getManifest () {
41+     return  manifest;
42+   }
3143};
3244
33-    
45+ 
3446class  FetchFile  : public  ProxiedAsyncJSImplFile  {
3547  std::string filePath;
3648  std::string fileUrl;
@@ -58,7 +70,45 @@ class FetchDirectory : public MemoryDirectory {
5870                 mode_t  mode,
5971                 backend_t  backend,
6072                 emscripten::ProxyWorker& proxy)
61-     : MemoryDirectory(mode, backend), dirPath(path), proxy(proxy) {}
73+     : MemoryDirectory(mode, backend), dirPath(path), proxy(proxy) {
74+     auto  manifest = dynamic_cast <FetchBackend*>(getBackend ())->getManifest ();
75+     if  (manifest && path == " "  ) {
76+       for  (const  auto & pair : *manifest) {
77+         auto  path = pair.first ;
78+         assert (path[0 ] == ' /'  );
79+         char  delimiter = ' /'  ;
80+         std::string path_so_far = " "  ;
81+         std::string tmp = " "  ;
82+         std::shared_ptr<FetchDirectory> dir = NULL ;
83+         std::istringstream iss (path);
84+         while (std::getline (iss, tmp, delimiter)) {
85+           path_so_far += tmp;
86+           if  (path_so_far == path) {
87+             if (!dir) {
88+               assert (this ->insertDataFile (tmp, 0777 ));
89+             } else  {
90+               assert (dir->insertDataFile (tmp, 0777 ));
91+             }
92+           } else  if  (path_so_far != " "  ) {
93+             std::shared_ptr<FetchDirectory> next = NULL ;
94+             if (!dir) {
95+               next = std::dynamic_pointer_cast<FetchDirectory>(this ->getChild (tmp));
96+             } else  {
97+               next = std::dynamic_pointer_cast<FetchDirectory>(dir->getChild (tmp));
98+             }
99+             if  (next) {
100+               dir = next;
101+               assert (dir);
102+             } else  {
103+               dir = std::dynamic_pointer_cast<FetchDirectory>(dir->insertDirectory (tmp, 0777 ));
104+               assert (dir);
105+             }
106+           }
107+           path_so_far += delimiter;
108+         }
109+       }
110+     }
111+   }
62112
63113  std::shared_ptr<DataFile> insertDataFile (const  std::string& name,
64114                                           mode_t  mode) override  {
@@ -81,6 +131,10 @@ class FetchDirectory : public MemoryDirectory {
81131  std::string getChildPath (const  std::string& name) const  {
82132    return  dirPath + ' /'   + name;
83133  }
134+ 
135+   std::shared_ptr<File> getChild (const  std::string& name) override  {
136+     return  MemoryDirectory::getChild (name);
137+   }
84138};
85139
86140std::shared_ptr<DataFile> FetchBackend::createFile (mode_t  mode) {
@@ -92,41 +146,60 @@ std::shared_ptr<Directory> FetchBackend::createDirectory(mode_t mode) {
92146}
93147
94148const  std::string FetchBackend::getFileURL (const  std::string& filePath) {
95-   //  TODO use manifest
149+   if (manifest) {
150+     if  (auto  search = manifest->find (filePath); search != manifest->end ()) {
151+       return  baseUrl + " /"   + search->second ;
152+     }
153+   }
96154  if (filePath == " "  ) {
97155    return  baseUrl;
98156  }
99157  return  baseUrl + " /"   + filePath;
100158}
159+ 
101160uint32_t  FetchBackend::getChunkSize () {
102161  return  chunkSize;
103162}
104163
105164extern  " C"   {
106-   backend_t  wasmfs_create_fetch_backend (const  char * base_url, uint32_t  chunkSize  /*  TODO manifest  */  ) {
165+   backend_t  wasmfs_create_fetch_backend (const  char * base_url, uint32_t  chunkSize, FetchManifest *manifest ) {
107166  //  ProxyWorker cannot safely be synchronously spawned from the main browser
108167  //  thread. See comment in thread_utils.h for more details.
109168  assert (!emscripten_is_main_browser_thread () &&
110169         " Cannot safely create fetch backend on main browser thread"  );
111170  return  wasmFS.addBackend (std::make_unique<FetchBackend>(
112171    base_url ? base_url : " "  ,
113-     chunkSize !=  0   ? chunkSize : DEFAULT_CHUNK_SIZE,
114-     /*  TODO  manifest  */ 
172+     chunkSize ? chunkSize : DEFAULT_CHUNK_SIZE,
173+     manifest, 
115174    [](backend_t  backend) { _wasmfs_create_fetch_backend_js (backend); }));
116175  }
117176
118- const  char * EMSCRIPTEN_KEEPALIVE  _wasmfs_fetch_get_file_path (void * ptr) {
177+ const  char * _wasmfs_fetch_get_file_path (void * ptr) {
119178  auto * file = reinterpret_cast <wasmfs::FetchFile*>(ptr);
120179  return  file ? file->getPath ().data () : nullptr ;
121180}
122- const  char * EMSCRIPTEN_KEEPALIVE _wasmfs_fetch_get_file_url (void * ptr) {
181+ 
182+ const  char * _wasmfs_fetch_get_file_url (void * ptr) {
123183  auto * file = reinterpret_cast <wasmfs::FetchFile*>(ptr);
124184  return  file ? file->getURL ().data () : nullptr ;
125185}
126- uint32_t  EMSCRIPTEN_KEEPALIVE _wasmfs_fetch_get_chunk_size (void * ptr) {
186+ 
187+ uint32_t  _wasmfs_fetch_get_chunk_size (void * ptr) {
127188  auto * file = reinterpret_cast <wasmfs::FetchFile*>(ptr);
128189  return  file ? file->getChunkSize () : DEFAULT_CHUNK_SIZE;
129190}
191+ 
192+ void  *EMSCRIPTEN_KEEPALIVE wasmfs_fetch_create_manifest () {
193+   return  new  FetchManifest ();
194+ }
195+ 
196+ void  EMSCRIPTEN_KEEPALIVE wasmfs_fetch_add_to_manifest (void  *manifest_ptr, const  char  *path, const  char  *url) {
197+   auto * manifest = reinterpret_cast <FetchManifest *>(manifest_ptr);
198+   auto  path_str = std::string (path);
199+   auto  url_str = std::string (url);
200+   manifest->insert (std::pair (path_str, url_str));
201+ }
202+ 
130203}
131204
132205} //  namespace wasmfs
0 commit comments