df_derive/lib.rs
1//! User-facing facade for deriving Polars `DataFrame` conversions.
2//!
3//! Most users should depend on this crate, import the prelude, and derive
4//! `ToDataFrame` without any runtime-path attributes:
5//!
6//! ```toml
7//! [dependencies]
8//! df-derive = "0.3"
9//! polars = "0.53"
10//! ```
11//!
12//! The default facade hides the macro's `polars-arrow` implementation
13//! dependency behind `df_derive::dataframe`; custom runtimes still need to
14//! provide their own compatible direct dependencies.
15//!
16//! ```ignore
17//! use df_derive::prelude::*;
18//!
19//! #[derive(ToDataFrame)]
20//! struct Trade {
21//! symbol: String,
22//! price: f64,
23//! size: u64,
24//! }
25//! ```
26//!
27//! The derive macro targets [`dataframe`] by default, which is re-exported
28//! from `df-derive-core`. Power users can depend on `df-derive-macros`
29//! directly or use `#[df_derive(trait = "...")]`,
30//! `#[df_derive(columnar = "...")]`, and
31//! `#[df_derive(decimal128_encode = "...")]` to target a custom runtime.
32//! Explicit paths back to `df_derive::dataframe::ToDataFrame` or
33//! `df_derive_core::dataframe::ToDataFrame` still use the default runtime's
34//! hidden dependency re-exports.
35
36// `polars` pulls a wide transitive dependency tree where multiple resolved
37// versions are unavoidable. `clippy::multiple_crate_versions` is part of the
38// `clippy::cargo` group `just lint` enables; allow it here so linting stays
39// focused on this crate's own code.
40#![allow(clippy::multiple_crate_versions)]
41
42pub use df_derive_core::dataframe;
43pub use df_derive_macros::ToDataFrame;
44
45/// Common imports for normal users.
46///
47/// This includes the derive macro and the runtime traits. The trait
48/// `ToDataFrame` is also exported as `ToDataFrameTrait` for code that wants
49/// an unambiguous type-namespace name.
50pub mod prelude {
51 pub use crate::ToDataFrame;
52 pub use crate::dataframe::{
53 Columnar, Decimal128Encode, ToDataFrame, ToDataFrame as ToDataFrameTrait, ToDataFrameVec,
54 };
55}
56
57#[cfg(test)]
58mod tests {
59 use crate::ToDataFrame;
60
61 #[derive(ToDataFrame)]
62 struct SelfCrateRow {
63 id: u32,
64 label: String,
65 }
66
67 #[test]
68 fn derive_uses_facade_runtime_inside_facade_crate() -> polars::prelude::PolarsResult<()> {
69 use crate::dataframe::{ToDataFrame as _, ToDataFrameVec as _};
70
71 let row = SelfCrateRow {
72 id: 1,
73 label: "facade".to_owned(),
74 };
75 let single = row.to_dataframe()?;
76 assert_eq!(single.shape(), (1, 2));
77
78 let rows = [
79 row,
80 SelfCrateRow {
81 id: 2,
82 label: "self".to_owned(),
83 },
84 ];
85 let batch = rows.as_slice().to_dataframe()?;
86 assert_eq!(batch.shape(), (2, 2));
87
88 Ok(())
89 }
90}