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");