@@ -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,49 @@ 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+               if (!dir) {
104+                 dir = std::dynamic_pointer_cast<FetchDirectory>(this ->insertDirectory (tmp, 0777 ));
105+               } else  {
106+                 dir = std::dynamic_pointer_cast<FetchDirectory>(dir->insertDirectory (tmp, 0777 ));
107+               }
108+               assert (dir);
109+             }
110+           }
111+           path_so_far += delimiter;
112+         }
113+       }
114+     }
115+   }
62116
63117  std::shared_ptr<DataFile> insertDataFile (const  std::string& name,
64118                                           mode_t  mode) override  {
@@ -81,6 +135,10 @@ class FetchDirectory : public MemoryDirectory {
81135  std::string getChildPath (const  std::string& name) const  {
82136    return  dirPath + ' /'   + name;
83137  }
138+ 
139+   std::shared_ptr<File> getChild (const  std::string& name) override  {
140+     return  MemoryDirectory::getChild (name);
141+   }
84142};
85143
86144std::shared_ptr<DataFile> FetchBackend::createFile (mode_t  mode) {
@@ -92,41 +150,60 @@ std::shared_ptr<Directory> FetchBackend::createDirectory(mode_t mode) {
92150}
93151
94152const  std::string FetchBackend::getFileURL (const  std::string& filePath) {
95-   //  TODO use manifest
153+   if (manifest) {
154+     if  (auto  search = manifest->find (filePath); search != manifest->end ()) {
155+       return  baseUrl + " /"   + search->second ;
156+     }
157+   }
96158  if (filePath == " "  ) {
97159    return  baseUrl;
98160  }
99161  return  baseUrl + " /"   + filePath;
100162}
163+ 
101164uint32_t  FetchBackend::getChunkSize () {
102165  return  chunkSize;
103166}
104167
105168extern  " C"   {
106-   backend_t  wasmfs_create_fetch_backend (const  char * base_url, uint32_t  chunkSize  /*  TODO manifest  */  ) {
169+   backend_t  wasmfs_create_fetch_backend (const  char * base_url, uint32_t  chunkSize, FetchManifest *manifest ) {
107170  //  ProxyWorker cannot safely be synchronously spawned from the main browser
108171  //  thread. See comment in thread_utils.h for more details.
109172  assert (!emscripten_is_main_browser_thread () &&
110173         " Cannot safely create fetch backend on main browser thread"  );
111174  return  wasmFS.addBackend (std::make_unique<FetchBackend>(
112175    base_url ? base_url : " "  ,
113-     chunkSize !=  0   ? chunkSize : DEFAULT_CHUNK_SIZE,
114-     /*  TODO  manifest  */ 
176+     chunkSize ? chunkSize : DEFAULT_CHUNK_SIZE,
177+     manifest, 
115178    [](backend_t  backend) { _wasmfs_create_fetch_backend_js (backend); }));
116179  }
117180
118- const  char * EMSCRIPTEN_KEEPALIVE  _wasmfs_fetch_get_file_path (void * ptr) {
181+ const  char * _wasmfs_fetch_get_file_path (void * ptr) {
119182  auto * file = reinterpret_cast <wasmfs::FetchFile*>(ptr);
120183  return  file ? file->getPath ().data () : nullptr ;
121184}
122- const  char * EMSCRIPTEN_KEEPALIVE _wasmfs_fetch_get_file_url (void * ptr) {
185+ 
186+ const  char * _wasmfs_fetch_get_file_url (void * ptr) {
123187  auto * file = reinterpret_cast <wasmfs::FetchFile*>(ptr);
124188  return  file ? file->getURL ().data () : nullptr ;
125189}
126- uint32_t  EMSCRIPTEN_KEEPALIVE _wasmfs_fetch_get_chunk_size (void * ptr) {
190+ 
191+ uint32_t  _wasmfs_fetch_get_chunk_size (void * ptr) {
127192  auto * file = reinterpret_cast <wasmfs::FetchFile*>(ptr);
128193  return  file ? file->getChunkSize () : DEFAULT_CHUNK_SIZE;
129194}
195+ 
196+ void  *EMSCRIPTEN_KEEPALIVE wasmfs_fetch_create_manifest () {
197+   return  new  FetchManifest ();
198+ }
199+ 
200+ void  EMSCRIPTEN_KEEPALIVE wasmfs_fetch_add_to_manifest (void  *manifest_ptr, const  char  *path, const  char  *url) {
201+   auto * manifest = reinterpret_cast <FetchManifest *>(manifest_ptr);
202+   auto  path_str = std::string (path);
203+   auto  url_str = std::string (url);
204+   manifest->insert (std::pair (path_str, url_str));
205+ }
206+ 
130207}
131208
132209} //  namespace wasmfs
0 commit comments