1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/// Plugin system for custom data sources, sinks, transforms, validators, and aggregators.
///
/// # Overview
///
/// PandRS's plugin system allows users to extend the library with custom data sources
/// (reading from proprietary formats), data sinks (writing to custom destinations),
/// transforms (row/column manipulations), aggregators, and validators.
///
/// # In-process only
///
/// A "plugin" here is a Rust value implementing one of this module's traits
/// (e.g. [`traits::TransformPlugin`]), registered by name into a
/// [`registry::PluginRegistry`]. There is no dynamic loading of external
/// `.so`/`.dll`/`.dylib` files (no `libloading` or equivalent) -- every
/// plugin is compiled into the same binary as the rest of `pandrs`. This is
/// a real, deliberate scope: the registry gives you name-addressable
/// discovery and pipeline composition (see [`pipeline::PluginPipeline`])
/// across plugins written anywhere in your crate (or a crate you depend
/// on), not runtime extensibility across process/binary boundaries.
///
/// # Non-reentrancy of the global registry
///
/// [`global_registry`], [`with_global_registry`], and
/// [`with_global_registry_mut`] each acquire a lock on the process-wide
/// registry; none of them may be called (directly or transitively) from
/// inside a closure passed to `with_global_registry_mut` on the same
/// thread, or the nested lock attempt deadlocks against the lock that
/// thread already holds. See each function's doc for details.
///
/// # Quick Start
///
/// ```rust,no_run
/// use pandrs::plugins;
/// use std::collections::HashMap;
///
/// // Initialize built-in plugins
/// plugins::register_builtin_plugins().expect("failed to register built-ins");
///
/// // Obtain a registry snapshot and build a pipeline
/// let registry = plugins::global_registry().expect("failed to get registry");
///
/// let mut src_opts = HashMap::new();
/// src_opts.insert("path".to_string(), "data.csv".to_string());
///
/// let pipeline = plugins::PluginPipeline::new(registry)
/// .source("csv_source", src_opts);
///
/// // Execute
/// if let Ok(Some(df)) = pipeline.execute() {
/// println!("Loaded {} rows", df.row_count());
/// }
/// ```
// Re-export the most commonly used types
pub use ;
pub use ;
pub use PluginRegistry;
pub use ;
// Re-export built-ins for convenience
pub use ;