df_interchange/
from_polars.rs

1use paste::paste;
2use std::mem::transmute;
3
4use crate::{error::InterchangeError, ArrowArray, ArrowSchema, Interchange};
5
6macro_rules! polars_to_ffi {
7    ($from_ver:literal) => {
8        paste! {
9            impl Interchange {
10                #[doc = "Move Polars version `" $from_ver "` to the Arrow data interchange format."]
11                pub fn [<from_polars_ $from_ver>](df: [<polars_crate_ $from_ver>]::frame::DataFrame) -> Result<Self, InterchangeError> {
12                    Ok(Self {
13                        chunks_aligned: !df.should_rechunk(),
14                        ffi: {
15                            // Number of columns
16                            let num_cols = df.width();
17
18                            // Prepare ffi series vec
19                            let mut ffi = Vec::with_capacity(num_cols);
20
21                            // Get the columns from the df, as series
22                            let series: Vec<[<polars_crate_ $from_ver>]::series::Series> = df
23                                .take_columns()
24                                .into_iter()
25                                .map(|s| s.take_materialized_series())
26                                .collect();
27
28                            for s in series {
29                                // Get arrow-type fields
30                                let field = &s
31                                    .field()
32                                    .to_arrow([<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest());
33
34                                // Get name of column
35                                let name = s.name().to_string();
36
37                                // Get number of chunks in each column
38                                let n_chunks = s.n_chunks();
39
40                                // Prepare chunk vec
41                                let mut ffi_chunk = Vec::with_capacity(num_cols);
42
43                                for c in 0..n_chunks {
44
45                                    // Get ffi array
46                                    let ffi_array = [<polars_arrow_ $from_ver>]::ffi::export_array_to_c(
47                                        s.to_arrow(c, [<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest()),
48                                    );
49
50                                    // Get ffi field
51                                    let ffi_field = [<polars_arrow_ $from_ver>]::ffi::export_field_to_c(field);
52
53                                    // Convert ffi array from polars-arrow to this crate's version of ArrowArray
54                                    let ffi_array = unsafe { transmute::<
55                                        [<polars_arrow_ $from_ver>]::ffi::ArrowArray,
56                                        ArrowArray,
57                                    >(ffi_array)};
58
59                                    // Convert ffi field from polars-arrow to this crate's version of ArrowField
60                                    let ffi_field = unsafe{transmute::<
61                                        [<polars_arrow_ $from_ver>]::ffi::ArrowSchema,
62                                        ArrowSchema,
63                                    >(ffi_field)};
64
65                                    // Create series
66                                    ffi_chunk.push((ffi_array, ffi_field));
67                                }
68
69                                ffi.push((name, ffi_chunk));
70                            }
71
72                            ffi
73                        }
74                    })
75                }
76            }
77        }
78    };
79}
80#[cfg(feature = "polars_0_44")]
81polars_to_ffi!("0_44");
82
83#[cfg(feature = "polars_0_45")]
84polars_to_ffi!("0_45");
85
86#[cfg(feature = "polars_0_46")]
87polars_to_ffi!("0_46");
88
89#[cfg(feature = "polars_0_47")]
90polars_to_ffi!("0_47");
91
92#[cfg(feature = "polars_0_48")]
93polars_to_ffi!("0_48");
94
95#[cfg(feature = "polars_0_49")]
96polars_to_ffi!("0_49");
97
98#[cfg(feature = "polars_0_50")]
99polars_to_ffi!("0_50");
100
101#[cfg(feature = "polars_0_51")]
102polars_to_ffi!("0_51");
103
104#[cfg(feature = "polars_0_52")]
105polars_to_ffi!("0_52");
106
107macro_rules! polars_to_ffi {
108    ($from_ver:literal) => {
109        paste! {
110            impl Interchange {
111                #[doc = "Move Polars version `" $from_ver "` to the Arrow data interchange format."]
112                pub fn [<from_polars_ $from_ver>](df: [<polars_crate_ $from_ver>]::frame::DataFrame) -> Result<Self, InterchangeError> {
113                    Ok(Self {
114                        chunks_aligned: !df.should_rechunk(),
115                        ffi: {
116                            // Number of columns
117                            let num_cols = df.width();
118
119                            // Prepare ffi series vec
120                            let mut ffi = Vec::with_capacity(num_cols);
121
122                            // Get the series from the df
123                            let series: Vec<[<polars_crate_ $from_ver>]::series::Series> = df.take_columns();
124
125                            for s in series {
126                                // Get arrow-type fields
127                                let field = &s
128                                    .field()
129                                    .to_arrow([<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest());
130
131                                // Get name of column
132                                let name = s.name().to_string();
133
134                                // Get number of chunks in each column
135                                let n_chunks = s.n_chunks();
136
137                                // Prepare chunk vec
138                                let mut ffi_chunk = Vec::with_capacity(num_cols);
139
140                                for c in 0..n_chunks {
141
142                                    // Get ffi array
143                                    let ffi_array = [<polars_arrow_ $from_ver>]::ffi::export_array_to_c(
144                                        s.to_arrow(c, [<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest()),
145                                    );
146
147                                    // Get ffi field
148                                    let ffi_field = [<polars_arrow_ $from_ver>]::ffi::export_field_to_c(field);
149
150                                    // Convert ffi array from polars-arrow to this crate's version of ArrowArray
151                                    let ffi_array = unsafe { transmute::<
152                                        [<polars_arrow_ $from_ver>]::ffi::ArrowArray,
153                                        ArrowArray,
154                                    >(ffi_array)};
155
156                                    // Convert ffi field from polars-arrow to this crate's version of ArrowField
157                                    let ffi_field = unsafe{transmute::<
158                                        [<polars_arrow_ $from_ver>]::ffi::ArrowSchema,
159                                        ArrowSchema,
160                                    >(ffi_field)};
161
162                                    // Create series
163                                    ffi_chunk.push((ffi_array, ffi_field));
164                                }
165
166                                ffi.push((name, ffi_chunk));
167                            }
168
169                            ffi
170                        }
171                    })
172                }
173            }
174        }
175    };
176}
177
178#[cfg(feature = "polars_0_42")]
179polars_to_ffi!("0_42");
180
181#[cfg(feature = "polars_0_43")]
182polars_to_ffi!("0_43");
183
184macro_rules! polars_to_ffi {
185    ($from_ver:literal) => {
186        paste! {
187            impl Interchange {
188                #[doc = "Move Polars version `" $from_ver "` to the Arrow data interchange format."]
189                pub fn [<from_polars_ $from_ver>](df: [<polars_crate_ $from_ver>]::frame::DataFrame) -> Result<Self, InterchangeError> {
190                    Ok(Self {
191                        chunks_aligned: !df.should_rechunk(),
192                        ffi: {
193                            // Number of columns
194                            let num_cols = df.width();
195
196                            // Prepare ffi series vec
197                            let mut ffi = Vec::with_capacity(num_cols);
198
199                            // Get column names to remove them one by one
200                            let names = df.get_column_names();
201
202                            // Get the series from the df
203                            let series: Vec<[<polars_crate_ $from_ver>]::series::Series> = df.select_series(names)?;
204
205                            for s in series {
206                                // Get arrow-type fields
207                                let field = &s
208                                    .field()
209                                    .to_arrow(false);
210
211                                // Get name of column
212                                let name = s.name().to_string();
213
214                                // Get number of chunks in each column
215                                let n_chunks = s.n_chunks();
216
217                                // Prepare chunk vec
218                                let mut ffi_chunk = Vec::with_capacity(num_cols);
219
220                                for c in 0..n_chunks {
221
222                                    // Get ffi array
223                                    let ffi_array = [<polars_arrow_ $from_ver>]::ffi::export_array_to_c(
224                                        s.to_arrow(c, false),
225                                    );
226
227                                    // Get ffi field
228                                    let ffi_field = [<polars_arrow_ $from_ver>]::ffi::export_field_to_c(field);
229
230                                    // Convert ffi array from polars-arrow to this crate's version of ArrowArray
231                                    let ffi_array = unsafe { transmute::<
232                                        [<polars_arrow_ $from_ver>]::ffi::ArrowArray,
233                                        ArrowArray,
234                                    >(ffi_array)};
235
236                                    // Convert ffi field from polars-arrow to this crate's version of ArrowField
237                                    let ffi_field = unsafe{transmute::<
238                                        [<polars_arrow_ $from_ver>]::ffi::ArrowSchema,
239                                        ArrowSchema,
240                                    >(ffi_field)};
241
242                                    // Create series
243                                    ffi_chunk.push((ffi_array, ffi_field));
244                                }
245
246                                ffi.push((name, ffi_chunk));
247                            }
248
249                            ffi
250                        }
251                    })
252                }
253            }
254        }
255    };
256}
257
258#[cfg(feature = "polars_0_40")]
259polars_to_ffi!("0_40");
260
261#[cfg(feature = "polars_0_41")]
262polars_to_ffi!("0_41");