Skip to main content

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                                .into_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
81#[cfg(feature = "polars_0_53")]
82polars_to_ffi!("0_53");
83
84macro_rules! polars_to_ffi {
85    ($from_ver:literal) => {
86        paste! {
87            impl Interchange {
88                #[doc = "Move Polars version `" $from_ver "` to the Arrow data interchange format."]
89                pub fn [<from_polars_ $from_ver>](df: [<polars_crate_ $from_ver>]::frame::DataFrame) -> Result<Self, InterchangeError> {
90                    Ok(Self {
91                        chunks_aligned: !df.should_rechunk(),
92                        ffi: {
93                            // Number of columns
94                            let num_cols = df.width();
95
96                            // Prepare ffi series vec
97                            let mut ffi = Vec::with_capacity(num_cols);
98
99                            // Get the columns from the df, as series
100                            let series: Vec<[<polars_crate_ $from_ver>]::series::Series> = df
101                                .take_columns()
102                                .into_iter()
103                                .map(|s| s.take_materialized_series())
104                                .collect();
105
106                            for s in series {
107                                // Get arrow-type fields
108                                let field = &s
109                                    .field()
110                                    .to_arrow([<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest());
111
112                                // Get name of column
113                                let name = s.name().to_string();
114
115                                // Get number of chunks in each column
116                                let n_chunks = s.n_chunks();
117
118                                // Prepare chunk vec
119                                let mut ffi_chunk = Vec::with_capacity(num_cols);
120
121                                for c in 0..n_chunks {
122
123                                    // Get ffi array
124                                    let ffi_array = [<polars_arrow_ $from_ver>]::ffi::export_array_to_c(
125                                        s.to_arrow(c, [<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest()),
126                                    );
127
128                                    // Get ffi field
129                                    let ffi_field = [<polars_arrow_ $from_ver>]::ffi::export_field_to_c(field);
130
131                                    // Convert ffi array from polars-arrow to this crate's version of ArrowArray
132                                    let ffi_array = unsafe { transmute::<
133                                        [<polars_arrow_ $from_ver>]::ffi::ArrowArray,
134                                        ArrowArray,
135                                    >(ffi_array)};
136
137                                    // Convert ffi field from polars-arrow to this crate's version of ArrowField
138                                    let ffi_field = unsafe{transmute::<
139                                        [<polars_arrow_ $from_ver>]::ffi::ArrowSchema,
140                                        ArrowSchema,
141                                    >(ffi_field)};
142
143                                    // Create series
144                                    ffi_chunk.push((ffi_array, ffi_field));
145                                }
146
147                                ffi.push((name, ffi_chunk));
148                            }
149
150                            ffi
151                        }
152                    })
153                }
154            }
155        }
156    };
157}
158#[cfg(feature = "polars_0_44")]
159polars_to_ffi!("0_44");
160
161#[cfg(feature = "polars_0_45")]
162polars_to_ffi!("0_45");
163
164#[cfg(feature = "polars_0_46")]
165polars_to_ffi!("0_46");
166
167#[cfg(feature = "polars_0_47")]
168polars_to_ffi!("0_47");
169
170#[cfg(feature = "polars_0_48")]
171polars_to_ffi!("0_48");
172
173#[cfg(feature = "polars_0_49")]
174polars_to_ffi!("0_49");
175
176#[cfg(feature = "polars_0_50")]
177polars_to_ffi!("0_50");
178
179#[cfg(feature = "polars_0_51")]
180polars_to_ffi!("0_51");
181
182#[cfg(feature = "polars_0_52")]
183polars_to_ffi!("0_52");
184
185macro_rules! polars_to_ffi {
186    ($from_ver:literal) => {
187        paste! {
188            impl Interchange {
189                #[doc = "Move Polars version `" $from_ver "` to the Arrow data interchange format."]
190                pub fn [<from_polars_ $from_ver>](df: [<polars_crate_ $from_ver>]::frame::DataFrame) -> Result<Self, InterchangeError> {
191                    Ok(Self {
192                        chunks_aligned: !df.should_rechunk(),
193                        ffi: {
194                            // Number of columns
195                            let num_cols = df.width();
196
197                            // Prepare ffi series vec
198                            let mut ffi = Vec::with_capacity(num_cols);
199
200                            // Get the series from the df
201                            let series: Vec<[<polars_crate_ $from_ver>]::series::Series> = df.take_columns();
202
203                            for s in series {
204                                // Get arrow-type fields
205                                let field = &s
206                                    .field()
207                                    .to_arrow([<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest());
208
209                                // Get name of column
210                                let name = s.name().to_string();
211
212                                // Get number of chunks in each column
213                                let n_chunks = s.n_chunks();
214
215                                // Prepare chunk vec
216                                let mut ffi_chunk = Vec::with_capacity(num_cols);
217
218                                for c in 0..n_chunks {
219
220                                    // Get ffi array
221                                    let ffi_array = [<polars_arrow_ $from_ver>]::ffi::export_array_to_c(
222                                        s.to_arrow(c, [<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest()),
223                                    );
224
225                                    // Get ffi field
226                                    let ffi_field = [<polars_arrow_ $from_ver>]::ffi::export_field_to_c(field);
227
228                                    // Convert ffi array from polars-arrow to this crate's version of ArrowArray
229                                    let ffi_array = unsafe { transmute::<
230                                        [<polars_arrow_ $from_ver>]::ffi::ArrowArray,
231                                        ArrowArray,
232                                    >(ffi_array)};
233
234                                    // Convert ffi field from polars-arrow to this crate's version of ArrowField
235                                    let ffi_field = unsafe{transmute::<
236                                        [<polars_arrow_ $from_ver>]::ffi::ArrowSchema,
237                                        ArrowSchema,
238                                    >(ffi_field)};
239
240                                    // Create series
241                                    ffi_chunk.push((ffi_array, ffi_field));
242                                }
243
244                                ffi.push((name, ffi_chunk));
245                            }
246
247                            ffi
248                        }
249                    })
250                }
251            }
252        }
253    };
254}
255
256#[cfg(feature = "polars_0_42")]
257polars_to_ffi!("0_42");
258
259#[cfg(feature = "polars_0_43")]
260polars_to_ffi!("0_43");
261
262macro_rules! polars_to_ffi {
263    ($from_ver:literal) => {
264        paste! {
265            impl Interchange {
266                #[doc = "Move Polars version `" $from_ver "` to the Arrow data interchange format."]
267                pub fn [<from_polars_ $from_ver>](df: [<polars_crate_ $from_ver>]::frame::DataFrame) -> Result<Self, InterchangeError> {
268                    Ok(Self {
269                        chunks_aligned: !df.should_rechunk(),
270                        ffi: {
271                            // Number of columns
272                            let num_cols = df.width();
273
274                            // Prepare ffi series vec
275                            let mut ffi = Vec::with_capacity(num_cols);
276
277                            // Get column names to remove them one by one
278                            let names = df.get_column_names();
279
280                            // Get the series from the df
281                            let series: Vec<[<polars_crate_ $from_ver>]::series::Series> = df.select_series(names)?;
282
283                            for s in series {
284                                // Get arrow-type fields
285                                let field = &s
286                                    .field()
287                                    .to_arrow(false);
288
289                                // Get name of column
290                                let name = s.name().to_string();
291
292                                // Get number of chunks in each column
293                                let n_chunks = s.n_chunks();
294
295                                // Prepare chunk vec
296                                let mut ffi_chunk = Vec::with_capacity(num_cols);
297
298                                for c in 0..n_chunks {
299
300                                    // Get ffi array
301                                    let ffi_array = [<polars_arrow_ $from_ver>]::ffi::export_array_to_c(
302                                        s.to_arrow(c, false),
303                                    );
304
305                                    // Get ffi field
306                                    let ffi_field = [<polars_arrow_ $from_ver>]::ffi::export_field_to_c(field);
307
308                                    // Convert ffi array from polars-arrow to this crate's version of ArrowArray
309                                    let ffi_array = unsafe { transmute::<
310                                        [<polars_arrow_ $from_ver>]::ffi::ArrowArray,
311                                        ArrowArray,
312                                    >(ffi_array)};
313
314                                    // Convert ffi field from polars-arrow to this crate's version of ArrowField
315                                    let ffi_field = unsafe{transmute::<
316                                        [<polars_arrow_ $from_ver>]::ffi::ArrowSchema,
317                                        ArrowSchema,
318                                    >(ffi_field)};
319
320                                    // Create series
321                                    ffi_chunk.push((ffi_array, ffi_field));
322                                }
323
324                                ffi.push((name, ffi_chunk));
325                            }
326
327                            ffi
328                        }
329                    })
330                }
331            }
332        }
333    };
334}
335
336#[cfg(feature = "polars_0_40")]
337polars_to_ffi!("0_40");
338
339#[cfg(feature = "polars_0_41")]
340polars_to_ffi!("0_41");