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
89macro_rules! polars_to_ffi {
90    ($from_ver:literal) => {
91        paste! {
92            impl Interchange {
93                #[doc = "Move Polars version `" $from_ver "` to the Arrow data interchange format."]
94                pub fn [<from_polars_ $from_ver>](df: [<polars_crate_ $from_ver>]::frame::DataFrame) -> Result<Self, InterchangeError> {
95                    Ok(Self {
96                        chunks_aligned: !df.should_rechunk(),
97                        ffi: {
98                            // Number of columns
99                            let num_cols = df.width();
100
101                            // Prepare ffi series vec
102                            let mut ffi = Vec::with_capacity(num_cols);
103
104                            // Get the series from the df
105                            let series: Vec<[<polars_crate_ $from_ver>]::series::Series> = df.take_columns();
106
107                            for s in series {
108                                // Get arrow-type fields
109                                let field = &s
110                                    .field()
111                                    .to_arrow([<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest());
112
113                                // Get name of column
114                                let name = s.name().to_string();
115
116                                // Get number of chunks in each column
117                                let n_chunks = s.n_chunks();
118
119                                // Prepare chunk vec
120                                let mut ffi_chunk = Vec::with_capacity(num_cols);
121
122                                for c in 0..n_chunks {
123
124                                    // Get ffi array
125                                    let ffi_array = [<polars_arrow_ $from_ver>]::ffi::export_array_to_c(
126                                        s.to_arrow(c, [<polars_crate_ $from_ver>]::datatypes::CompatLevel::newest()),
127                                    );
128
129                                    // Get ffi field
130                                    let ffi_field = [<polars_arrow_ $from_ver>]::ffi::export_field_to_c(field);
131
132                                    // Convert ffi array from polars-arrow to this crate's version of ArrowArray
133                                    let ffi_array = unsafe { transmute::<
134                                        [<polars_arrow_ $from_ver>]::ffi::ArrowArray,
135                                        ArrowArray,
136                                    >(ffi_array)};
137
138                                    // Convert ffi field from polars-arrow to this crate's version of ArrowField
139                                    let ffi_field = unsafe{transmute::<
140                                        [<polars_arrow_ $from_ver>]::ffi::ArrowSchema,
141                                        ArrowSchema,
142                                    >(ffi_field)};
143
144                                    // Create series
145                                    ffi_chunk.push((ffi_array, ffi_field));
146                                }
147
148                                ffi.push((name, ffi_chunk));
149                            }
150
151                            ffi
152                        }
153                    })
154                }
155            }
156        }
157    };
158}
159
160#[cfg(feature = "polars_0_42")]
161polars_to_ffi!("0_42");
162
163#[cfg(feature = "polars_0_43")]
164polars_to_ffi!("0_43");
165
166macro_rules! polars_to_ffi {
167    ($from_ver:literal) => {
168        paste! {
169            impl Interchange {
170                #[doc = "Move Polars version `" $from_ver "` to the Arrow data interchange format."]
171                pub fn [<from_polars_ $from_ver>](df: [<polars_crate_ $from_ver>]::frame::DataFrame) -> Result<Self, InterchangeError> {
172                    Ok(Self {
173                        chunks_aligned: !df.should_rechunk(),
174                        ffi: {
175                            // Number of columns
176                            let num_cols = df.width();
177
178                            // Prepare ffi series vec
179                            let mut ffi = Vec::with_capacity(num_cols);
180
181                            // Get column names to remove them one by one
182                            let names = df.get_column_names();
183
184                            // Get the series from the df
185                            let series: Vec<[<polars_crate_ $from_ver>]::series::Series> = df.select_series(names)?;
186
187                            for s in series {
188                                // Get arrow-type fields
189                                let field = &s
190                                    .field()
191                                    .to_arrow(false);
192
193                                // Get name of column
194                                let name = s.name().to_string();
195
196                                // Get number of chunks in each column
197                                let n_chunks = s.n_chunks();
198
199                                // Prepare chunk vec
200                                let mut ffi_chunk = Vec::with_capacity(num_cols);
201
202                                for c in 0..n_chunks {
203
204                                    // Get ffi array
205                                    let ffi_array = [<polars_arrow_ $from_ver>]::ffi::export_array_to_c(
206                                        s.to_arrow(c, false),
207                                    );
208
209                                    // Get ffi field
210                                    let ffi_field = [<polars_arrow_ $from_ver>]::ffi::export_field_to_c(field);
211
212                                    // Convert ffi array from polars-arrow to this crate's version of ArrowArray
213                                    let ffi_array = unsafe { transmute::<
214                                        [<polars_arrow_ $from_ver>]::ffi::ArrowArray,
215                                        ArrowArray,
216                                    >(ffi_array)};
217
218                                    // Convert ffi field from polars-arrow to this crate's version of ArrowField
219                                    let ffi_field = unsafe{transmute::<
220                                        [<polars_arrow_ $from_ver>]::ffi::ArrowSchema,
221                                        ArrowSchema,
222                                    >(ffi_field)};
223
224                                    // Create series
225                                    ffi_chunk.push((ffi_array, ffi_field));
226                                }
227
228                                ffi.push((name, ffi_chunk));
229                            }
230
231                            ffi
232                        }
233                    })
234                }
235            }
236        }
237    };
238}
239
240#[cfg(feature = "polars_0_40")]
241polars_to_ffi!("0_40");
242
243#[cfg(feature = "polars_0_41")]
244polars_to_ffi!("0_41");