|
| 1 | +/// Recursively oads entire directories, using the appropriate [`crate::DataLoader`]:s for each |
| 2 | +/// files within. |
| 3 | +// |
| 4 | +// TODO(cmc): There are a lot more things than can be done be done when it comes to the semantics |
| 5 | +// of a folder, e.g.: HIVE-like partitioning, similarly named files with different indices and/or |
| 6 | +// timestamps (e.g. a folder of video frames), etc. |
| 7 | +// We could support some of those at some point, or at least add examples to show users how. |
| 8 | +pub struct DirectoryLoader; |
| 9 | + |
| 10 | +impl crate::DataLoader for DirectoryLoader { |
| 11 | + #[inline] |
| 12 | + fn name(&self) -> String { |
| 13 | + "rerun.data_loaders.Directory".into() |
| 14 | + } |
| 15 | + |
| 16 | + #[cfg(not(target_arch = "wasm32"))] |
| 17 | + fn load_from_path( |
| 18 | + &self, |
| 19 | + store_id: re_log_types::StoreId, |
| 20 | + dirpath: std::path::PathBuf, |
| 21 | + tx: std::sync::mpsc::Sender<crate::LoadedData>, |
| 22 | + ) -> Result<(), crate::DataLoaderError> { |
| 23 | + if dirpath.is_file() { |
| 24 | + return Ok(()); // simply not interested |
| 25 | + } |
| 26 | + |
| 27 | + re_tracing::profile_function!(dirpath.display().to_string()); |
| 28 | + |
| 29 | + re_log::debug!(?dirpath, loader = self.name(), "Loading directory…",); |
| 30 | + |
| 31 | + for entry in walkdir::WalkDir::new(&dirpath) { |
| 32 | + let entry = match entry { |
| 33 | + Ok(entry) => entry, |
| 34 | + Err(err) => { |
| 35 | + re_log::error!(loader = self.name(), ?dirpath, %err, "Failed to open filesystem entry"); |
| 36 | + continue; |
| 37 | + } |
| 38 | + }; |
| 39 | + |
| 40 | + let filepath = entry.path(); |
| 41 | + if filepath.is_file() { |
| 42 | + let store_id = store_id.clone(); |
| 43 | + let filepath = filepath.to_owned(); |
| 44 | + let tx = tx.clone(); |
| 45 | + |
| 46 | + // NOTE: spawn is fine, this whole function is native-only. |
| 47 | + rayon::spawn(move || { |
| 48 | + let data = match crate::load_file::load(&store_id, &filepath, false, None) { |
| 49 | + Ok(data) => data, |
| 50 | + Err(err) => { |
| 51 | + re_log::error!(?filepath, %err, "Failed to load directory entry"); |
| 52 | + return; |
| 53 | + } |
| 54 | + }; |
| 55 | + |
| 56 | + for datum in data { |
| 57 | + if tx.send(datum).is_err() { |
| 58 | + break; |
| 59 | + } |
| 60 | + } |
| 61 | + }); |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | + Ok(()) |
| 66 | + } |
| 67 | + |
| 68 | + #[inline] |
| 69 | + fn load_from_file_contents( |
| 70 | + &self, |
| 71 | + _store_id: re_log_types::StoreId, |
| 72 | + _path: std::path::PathBuf, |
| 73 | + _contents: std::borrow::Cow<'_, [u8]>, |
| 74 | + _tx: std::sync::mpsc::Sender<crate::LoadedData>, |
| 75 | + ) -> Result<(), crate::DataLoaderError> { |
| 76 | + // TODO(cmc): This could make sense to implement for e.g. archive formats (zip, tar, …) |
| 77 | + Ok(()) // simply not interested |
| 78 | + } |
| 79 | +} |
0 commit comments