use std::sync::Arc;
use once_cell::sync::Lazy;
use re_log_types::{ArrowMsg, DataRow, LogMsg};
pub trait DataLoader: Send + Sync {
fn name(&self) -> String;
#[cfg(not(target_arch = "wasm32"))]
fn load_from_path(
&self,
store_id: re_log_types::StoreId,
path: std::path::PathBuf,
tx: std::sync::mpsc::Sender<LoadedData>,
) -> Result<(), DataLoaderError>;
fn load_from_file_contents(
&self,
store_id: re_log_types::StoreId,
filepath: std::path::PathBuf,
contents: std::borrow::Cow<'_, [u8]>,
tx: std::sync::mpsc::Sender<LoadedData>,
) -> Result<(), DataLoaderError>;
}
#[derive(thiserror::Error, Debug)]
pub enum DataLoaderError {
#[cfg(not(target_arch = "wasm32"))]
#[error(transparent)]
IO(#[from] std::io::Error),
#[error(transparent)]
Arrow(#[from] re_log_types::DataCellError),
#[error(transparent)]
Decode(#[from] re_log_encoding::decoder::DecodeError),
#[error("No data-loader support for {0:?}")]
Incompatible(std::path::PathBuf),
#[error(transparent)]
Other(#[from] anyhow::Error),
}
impl DataLoaderError {
#[inline]
pub fn is_path_not_found(&self) -> bool {
match self {
#[cfg(not(target_arch = "wasm32"))]
DataLoaderError::IO(err) => err.kind() == std::io::ErrorKind::NotFound,
_ => false,
}
}
#[inline]
pub fn is_incompatible(&self) -> bool {
matches!(self, Self::Incompatible { .. })
}
}
pub enum LoadedData {
DataRow(DataRow),
ArrowMsg(ArrowMsg),
LogMsg(LogMsg),
}
impl From<DataRow> for LoadedData {
#[inline]
fn from(value: DataRow) -> Self {
Self::DataRow(value)
}
}
impl From<ArrowMsg> for LoadedData {
#[inline]
fn from(value: ArrowMsg) -> Self {
LoadedData::ArrowMsg(value)
}
}
impl From<LogMsg> for LoadedData {
#[inline]
fn from(value: LogMsg) -> Self {
LoadedData::LogMsg(value)
}
}
impl LoadedData {
pub fn into_log_msg(
self,
store_id: &re_log_types::StoreId,
) -> Result<LogMsg, re_log_types::DataTableError> {
match self {
Self::DataRow(row) => {
let mut table =
re_log_types::DataTable::from_rows(re_log_types::TableId::new(), [row]);
table.compute_all_size_bytes();
Ok(LogMsg::ArrowMsg(store_id.clone(), table.to_arrow_msg()?))
}
Self::ArrowMsg(msg) => Ok(LogMsg::ArrowMsg(store_id.clone(), msg)),
Self::LogMsg(msg) => Ok(msg),
}
}
}
static BUILTIN_LOADERS: Lazy<Vec<Arc<dyn DataLoader>>> = Lazy::new(|| {
vec![
Arc::new(RrdLoader) as Arc<dyn DataLoader>,
Arc::new(ArchetypeLoader),
Arc::new(DirectoryLoader),
#[cfg(not(target_arch = "wasm32"))]
Arc::new(ExternalLoader),
]
});
#[inline]
pub fn iter_loaders() -> impl Iterator<Item = Arc<dyn DataLoader>> {
BUILTIN_LOADERS
.clone()
.into_iter()
.chain(CUSTOM_LOADERS.read().clone())
}
static CUSTOM_LOADERS: Lazy<parking_lot::RwLock<Vec<Arc<dyn DataLoader>>>> =
Lazy::new(parking_lot::RwLock::default);
#[inline]
pub fn register_custom_data_loader(loader: impl DataLoader + 'static) {
CUSTOM_LOADERS.write().push(Arc::new(loader));
}
mod loader_archetype;
mod loader_directory;
mod loader_rrd;
#[cfg(not(target_arch = "wasm32"))]
mod loader_external;
pub use self::loader_archetype::ArchetypeLoader;
pub use self::loader_directory::DirectoryLoader;
pub use self::loader_rrd::RrdLoader;
#[cfg(not(target_arch = "wasm32"))]
pub use self::loader_external::{
iter_external_loaders, ExternalLoader, EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE,
EXTERNAL_DATA_LOADER_PREFIX,
};