polars-df 0.15.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +274 -0
  3. data/Cargo.lock +1465 -867
  4. data/Cargo.toml +3 -0
  5. data/LICENSE.txt +2 -2
  6. data/README.md +87 -37
  7. data/ext/polars/Cargo.toml +47 -16
  8. data/ext/polars/src/c_api/allocator.rs +7 -0
  9. data/ext/polars/src/c_api/mod.rs +1 -0
  10. data/ext/polars/src/catalog/mod.rs +1 -0
  11. data/ext/polars/src/catalog/unity.rs +470 -0
  12. data/ext/polars/src/conversion/any_value.rs +99 -84
  13. data/ext/polars/src/conversion/categorical.rs +30 -0
  14. data/ext/polars/src/conversion/chunked_array.rs +71 -62
  15. data/ext/polars/src/conversion/datetime.rs +63 -0
  16. data/ext/polars/src/conversion/mod.rs +796 -312
  17. data/ext/polars/src/dataframe/construction.rs +6 -18
  18. data/ext/polars/src/dataframe/export.rs +30 -39
  19. data/ext/polars/src/dataframe/general.rs +294 -362
  20. data/ext/polars/src/dataframe/io.rs +33 -150
  21. data/ext/polars/src/dataframe/map.rs +175 -0
  22. data/ext/polars/src/dataframe/mod.rs +37 -5
  23. data/ext/polars/src/dataframe/serde.rs +23 -8
  24. data/ext/polars/src/error.rs +44 -7
  25. data/ext/polars/src/exceptions.rs +21 -8
  26. data/ext/polars/src/expr/array.rs +86 -22
  27. data/ext/polars/src/expr/binary.rs +50 -1
  28. data/ext/polars/src/expr/bitwise.rs +39 -0
  29. data/ext/polars/src/expr/categorical.rs +20 -0
  30. data/ext/polars/src/expr/datatype.rs +51 -0
  31. data/ext/polars/src/expr/datetime.rs +99 -41
  32. data/ext/polars/src/expr/extension.rs +12 -0
  33. data/ext/polars/src/expr/general.rs +252 -128
  34. data/ext/polars/src/expr/list.rs +56 -60
  35. data/ext/polars/src/expr/meta.rs +30 -35
  36. data/ext/polars/src/expr/mod.rs +28 -6
  37. data/ext/polars/src/expr/name.rs +29 -14
  38. data/ext/polars/src/expr/rolling.rs +111 -3
  39. data/ext/polars/src/expr/selector.rs +219 -0
  40. data/ext/polars/src/expr/serde.rs +28 -0
  41. data/ext/polars/src/expr/string.rs +118 -20
  42. data/ext/polars/src/expr/struct.rs +14 -1
  43. data/ext/polars/src/file.rs +194 -86
  44. data/ext/polars/src/functions/aggregation.rs +13 -12
  45. data/ext/polars/src/functions/business.rs +2 -3
  46. data/ext/polars/src/functions/eager.rs +3 -2
  47. data/ext/polars/src/functions/io.rs +90 -18
  48. data/ext/polars/src/functions/lazy.rs +267 -118
  49. data/ext/polars/src/functions/meta.rs +8 -7
  50. data/ext/polars/src/functions/misc.rs +1 -1
  51. data/ext/polars/src/functions/mod.rs +2 -1
  52. data/ext/polars/src/functions/range.rs +88 -31
  53. data/ext/polars/src/functions/strings.rs +6 -0
  54. data/ext/polars/src/functions/utils.rs +8 -0
  55. data/ext/polars/src/interop/arrow/mod.rs +52 -1
  56. data/ext/polars/src/interop/arrow/{to_ruby.rs → to_rb.rs} +37 -7
  57. data/ext/polars/src/interop/arrow/to_rust.rs +43 -0
  58. data/ext/polars/src/interop/numo/to_numo_df.rs +1 -1
  59. data/ext/polars/src/interop/numo/to_numo_series.rs +72 -50
  60. data/ext/polars/src/io/cloud_options.rs +107 -0
  61. data/ext/polars/src/io/mod.rs +4 -0
  62. data/ext/polars/src/io/scan_options.rs +113 -0
  63. data/ext/polars/src/io/sink_options.rs +46 -0
  64. data/ext/polars/src/io/sink_output.rs +21 -0
  65. data/ext/polars/src/lazyframe/exitable.rs +39 -0
  66. data/ext/polars/src/lazyframe/general.rs +846 -368
  67. data/ext/polars/src/lazyframe/mod.rs +58 -5
  68. data/ext/polars/src/lazyframe/optflags.rs +59 -0
  69. data/ext/polars/src/lazyframe/serde.rs +36 -4
  70. data/ext/polars/src/lazyframe/sink.rs +46 -0
  71. data/ext/polars/src/lazygroupby.rs +38 -9
  72. data/ext/polars/src/lib.rs +574 -165
  73. data/ext/polars/src/map/lazy.rs +44 -74
  74. data/ext/polars/src/map/mod.rs +18 -254
  75. data/ext/polars/src/map/series.rs +241 -1087
  76. data/ext/polars/src/on_startup.rs +192 -9
  77. data/ext/polars/src/prelude.rs +1 -0
  78. data/ext/polars/src/rb_modules.rs +10 -57
  79. data/ext/polars/src/ruby/exceptions.rs +26 -0
  80. data/ext/polars/src/ruby/gvl.rs +104 -0
  81. data/ext/polars/src/ruby/lazy.rs +46 -0
  82. data/ext/polars/src/ruby/mod.rs +11 -0
  83. data/ext/polars/src/ruby/numo.rs +52 -0
  84. data/ext/polars/src/ruby/plan_callback.rs +198 -0
  85. data/ext/polars/src/ruby/rb_modules.rs +16 -0
  86. data/ext/polars/src/ruby/ruby_convert_registry.rs +51 -0
  87. data/ext/polars/src/ruby/ruby_function.rs +11 -0
  88. data/ext/polars/src/ruby/ruby_udf.rs +164 -0
  89. data/ext/polars/src/ruby/thread.rs +65 -0
  90. data/ext/polars/src/ruby/utils.rs +39 -0
  91. data/ext/polars/src/series/aggregation.rs +116 -91
  92. data/ext/polars/src/series/arithmetic.rs +16 -22
  93. data/ext/polars/src/series/comparison.rs +101 -222
  94. data/ext/polars/src/series/construction.rs +80 -70
  95. data/ext/polars/src/series/export.rs +98 -56
  96. data/ext/polars/src/series/general.rs +323 -440
  97. data/ext/polars/src/series/import.rs +22 -5
  98. data/ext/polars/src/series/map.rs +103 -0
  99. data/ext/polars/src/series/mod.rs +57 -15
  100. data/ext/polars/src/series/scatter.rs +139 -82
  101. data/ext/polars/src/sql.rs +16 -9
  102. data/ext/polars/src/testing/frame.rs +31 -0
  103. data/ext/polars/src/testing/mod.rs +5 -0
  104. data/ext/polars/src/testing/series.rs +31 -0
  105. data/ext/polars/src/timeout.rs +105 -0
  106. data/ext/polars/src/utils.rs +105 -4
  107. data/lib/polars/array_expr.rb +500 -22
  108. data/lib/polars/array_name_space.rb +384 -10
  109. data/lib/polars/batched_csv_reader.rb +48 -66
  110. data/lib/polars/binary_expr.rb +217 -0
  111. data/lib/polars/binary_name_space.rb +155 -1
  112. data/lib/polars/cat_expr.rb +224 -0
  113. data/lib/polars/cat_name_space.rb +132 -32
  114. data/lib/polars/catalog/unity/catalog_info.rb +20 -0
  115. data/lib/polars/catalog/unity/column_info.rb +31 -0
  116. data/lib/polars/catalog/unity/namespace_info.rb +21 -0
  117. data/lib/polars/catalog/unity/table_info.rb +50 -0
  118. data/lib/polars/catalog.rb +448 -0
  119. data/lib/polars/collect_batches.rb +22 -0
  120. data/lib/polars/config.rb +3 -3
  121. data/lib/polars/convert.rb +201 -36
  122. data/lib/polars/data_frame.rb +2851 -1017
  123. data/lib/polars/data_frame_plot.rb +173 -0
  124. data/lib/polars/data_type_expr.rb +52 -0
  125. data/lib/polars/data_type_group.rb +6 -0
  126. data/lib/polars/data_types.rb +118 -18
  127. data/lib/polars/date_time_expr.rb +426 -84
  128. data/lib/polars/date_time_name_space.rb +384 -111
  129. data/lib/polars/dynamic_group_by.rb +102 -10
  130. data/lib/polars/exceptions.rb +50 -5
  131. data/lib/polars/expr.rb +2159 -915
  132. data/lib/polars/extension_expr.rb +39 -0
  133. data/lib/polars/extension_name_space.rb +39 -0
  134. data/lib/polars/functions/aggregation/horizontal.rb +11 -6
  135. data/lib/polars/functions/aggregation/vertical.rb +2 -3
  136. data/lib/polars/functions/as_datatype.rb +290 -8
  137. data/lib/polars/functions/business.rb +95 -0
  138. data/lib/polars/functions/col.rb +6 -5
  139. data/lib/polars/functions/datatype.rb +62 -0
  140. data/lib/polars/functions/eager.rb +426 -24
  141. data/lib/polars/functions/escape_regex.rb +21 -0
  142. data/lib/polars/functions/lazy.rb +813 -195
  143. data/lib/polars/functions/lit.rb +21 -10
  144. data/lib/polars/functions/range/int_range.rb +74 -2
  145. data/lib/polars/functions/range/linear_space.rb +195 -0
  146. data/lib/polars/functions/range/time_range.rb +1 -1
  147. data/lib/polars/functions/repeat.rb +7 -12
  148. data/lib/polars/functions/whenthen.rb +2 -2
  149. data/lib/polars/group_by.rb +188 -58
  150. data/lib/polars/iceberg_dataset.rb +108 -0
  151. data/lib/polars/in_process_query.rb +37 -0
  152. data/lib/polars/io/cloud.rb +18 -0
  153. data/lib/polars/io/csv.rb +336 -128
  154. data/lib/polars/io/database.rb +19 -4
  155. data/lib/polars/io/delta.rb +134 -0
  156. data/lib/polars/io/iceberg.rb +34 -0
  157. data/lib/polars/io/ipc.rb +63 -63
  158. data/lib/polars/io/json.rb +16 -0
  159. data/lib/polars/io/lines.rb +172 -0
  160. data/lib/polars/io/ndjson.rb +176 -20
  161. data/lib/polars/io/parquet.rb +173 -95
  162. data/lib/polars/io/scan_options.rb +55 -0
  163. data/lib/polars/io/sink_options.rb +27 -0
  164. data/lib/polars/io/utils.rb +17 -0
  165. data/lib/polars/lazy_frame.rb +3017 -622
  166. data/lib/polars/lazy_group_by.rb +436 -2
  167. data/lib/polars/list_expr.rb +551 -59
  168. data/lib/polars/list_name_space.rb +465 -51
  169. data/lib/polars/meta_expr.rb +146 -24
  170. data/lib/polars/name_expr.rb +87 -2
  171. data/lib/polars/query_opt_flags.rb +264 -0
  172. data/lib/polars/rolling_group_by.rb +90 -5
  173. data/lib/polars/scan_cast_options.rb +86 -0
  174. data/lib/polars/schema.rb +128 -0
  175. data/lib/polars/selector.rb +245 -0
  176. data/lib/polars/selectors.rb +1048 -201
  177. data/lib/polars/series.rb +2522 -774
  178. data/lib/polars/series_plot.rb +72 -0
  179. data/lib/polars/slice.rb +1 -1
  180. data/lib/polars/sql_context.rb +13 -6
  181. data/lib/polars/string_cache.rb +19 -72
  182. data/lib/polars/string_expr.rb +561 -107
  183. data/lib/polars/string_name_space.rb +781 -109
  184. data/lib/polars/struct_expr.rb +139 -18
  185. data/lib/polars/struct_name_space.rb +19 -1
  186. data/lib/polars/testing.rb +24 -273
  187. data/lib/polars/utils/constants.rb +2 -0
  188. data/lib/polars/utils/construction/data_frame.rb +410 -0
  189. data/lib/polars/utils/construction/series.rb +350 -0
  190. data/lib/polars/utils/construction/utils.rb +9 -0
  191. data/lib/polars/utils/convert.rb +18 -8
  192. data/lib/polars/utils/deprecation.rb +11 -0
  193. data/lib/polars/utils/parse.rb +62 -9
  194. data/lib/polars/utils/reduce_balanced.rb +43 -0
  195. data/lib/polars/utils/serde.rb +22 -0
  196. data/lib/polars/utils/unstable.rb +19 -0
  197. data/lib/polars/utils/various.rb +86 -1
  198. data/lib/polars/utils.rb +63 -48
  199. data/lib/polars/version.rb +1 -1
  200. data/lib/polars.rb +85 -2
  201. metadata +80 -28
  202. data/ext/polars/src/allocator.rs +0 -13
  203. data/ext/polars/src/batched_csv.rs +0 -138
  204. data/ext/polars/src/functions/string_cache.rs +0 -25
  205. data/ext/polars/src/map/dataframe.rs +0 -338
  206. data/lib/polars/plot.rb +0 -109
@@ -0,0 +1,219 @@
1
+ use std::hash::{Hash, Hasher};
2
+ use std::sync::Arc;
3
+
4
+ use polars::prelude::{
5
+ DataType, DataTypeSelector, Selector, TimeUnit, TimeUnitSet, TimeZone, TimeZoneSet,
6
+ };
7
+ use polars_plan::dsl;
8
+
9
+ use crate::prelude::Wrap;
10
+ use crate::{RbResult, RbTypeError};
11
+
12
+ #[magnus::wrap(class = "Polars::RbSelector")]
13
+ #[repr(transparent)]
14
+ #[derive(Clone)]
15
+ pub struct RbSelector {
16
+ pub inner: Selector,
17
+ }
18
+
19
+ impl From<Selector> for RbSelector {
20
+ fn from(inner: Selector) -> Self {
21
+ Self { inner }
22
+ }
23
+ }
24
+
25
+ fn parse_time_unit_set(time_units: Vec<Wrap<TimeUnit>>) -> TimeUnitSet {
26
+ let mut tu = TimeUnitSet::empty();
27
+ for v in time_units {
28
+ match v.0 {
29
+ TimeUnit::Nanoseconds => tu |= TimeUnitSet::NANO_SECONDS,
30
+ TimeUnit::Microseconds => tu |= TimeUnitSet::MICRO_SECONDS,
31
+ TimeUnit::Milliseconds => tu |= TimeUnitSet::MILLI_SECONDS,
32
+ }
33
+ }
34
+ tu
35
+ }
36
+
37
+ pub fn parse_datatype_selector(selector: &RbSelector) -> RbResult<DataTypeSelector> {
38
+ selector.inner.clone().to_dtype_selector().ok_or_else(|| {
39
+ RbTypeError::new_err(format!(
40
+ "expected datatype based expression got '{}'",
41
+ selector.inner
42
+ ))
43
+ })
44
+ }
45
+
46
+ impl RbSelector {
47
+ pub fn union(&self, other: &Self) -> Self {
48
+ Self {
49
+ inner: self.inner.clone() | other.inner.clone(),
50
+ }
51
+ }
52
+
53
+ pub fn difference(&self, other: &Self) -> Self {
54
+ Self {
55
+ inner: self.inner.clone() - other.inner.clone(),
56
+ }
57
+ }
58
+
59
+ pub fn exclusive_or(&self, other: &Self) -> Self {
60
+ Self {
61
+ inner: self.inner.clone() ^ other.inner.clone(),
62
+ }
63
+ }
64
+
65
+ pub fn intersect(&self, other: &Self) -> Self {
66
+ Self {
67
+ inner: self.inner.clone() & other.inner.clone(),
68
+ }
69
+ }
70
+
71
+ pub fn by_dtype(dtypes: Vec<Wrap<DataType>>) -> Self {
72
+ let dtypes = dtypes.into_iter().map(|x| x.0).collect::<Vec<_>>();
73
+ dsl::functions::dtype_cols(dtypes).as_selector().into()
74
+ }
75
+
76
+ pub fn by_name(names: Vec<String>, strict: bool, expand_patterns: bool) -> Self {
77
+ dsl::functions::by_name(names, strict, expand_patterns).into()
78
+ }
79
+
80
+ pub fn by_index(indices: Vec<i64>, strict: bool) -> Self {
81
+ Selector::ByIndex {
82
+ indices: indices.into(),
83
+ strict,
84
+ }
85
+ .into()
86
+ }
87
+
88
+ pub fn first(strict: bool) -> Self {
89
+ Selector::ByIndex {
90
+ indices: [0].into(),
91
+ strict,
92
+ }
93
+ .into()
94
+ }
95
+
96
+ pub fn last(strict: bool) -> Self {
97
+ Selector::ByIndex {
98
+ indices: [-1].into(),
99
+ strict,
100
+ }
101
+ .into()
102
+ }
103
+
104
+ pub fn matches(pattern: String) -> Self {
105
+ Selector::Matches(pattern.into()).into()
106
+ }
107
+
108
+ pub fn enum_() -> Self {
109
+ DataTypeSelector::Enum.as_selector().into()
110
+ }
111
+
112
+ pub fn categorical() -> Self {
113
+ DataTypeSelector::Categorical.as_selector().into()
114
+ }
115
+
116
+ pub fn nested() -> Self {
117
+ DataTypeSelector::Nested.as_selector().into()
118
+ }
119
+
120
+ pub fn list(inner_dst: Option<&Self>) -> RbResult<Self> {
121
+ let inner_dst = match inner_dst {
122
+ None => None,
123
+ Some(inner_dst) => Some(Arc::new(parse_datatype_selector(inner_dst)?)),
124
+ };
125
+ Ok(DataTypeSelector::List(inner_dst).as_selector().into())
126
+ }
127
+
128
+ pub fn array(inner_dst: Option<&Self>, width: Option<usize>) -> RbResult<Self> {
129
+ let inner_dst = match inner_dst {
130
+ None => None,
131
+ Some(inner_dst) => Some(Arc::new(parse_datatype_selector(inner_dst)?)),
132
+ };
133
+ Ok(DataTypeSelector::Array(inner_dst, width)
134
+ .as_selector()
135
+ .into())
136
+ }
137
+
138
+ pub fn struct_() -> Self {
139
+ DataTypeSelector::Struct.as_selector().into()
140
+ }
141
+
142
+ pub fn integer() -> Self {
143
+ DataTypeSelector::Integer.as_selector().into()
144
+ }
145
+
146
+ pub fn signed_integer() -> Self {
147
+ DataTypeSelector::SignedInteger.as_selector().into()
148
+ }
149
+
150
+ pub fn unsigned_integer() -> Self {
151
+ DataTypeSelector::UnsignedInteger.as_selector().into()
152
+ }
153
+
154
+ pub fn float() -> Self {
155
+ DataTypeSelector::Float.as_selector().into()
156
+ }
157
+
158
+ pub fn decimal() -> Self {
159
+ DataTypeSelector::Decimal.as_selector().into()
160
+ }
161
+
162
+ pub fn numeric() -> Self {
163
+ DataTypeSelector::Numeric.as_selector().into()
164
+ }
165
+
166
+ pub fn temporal() -> Self {
167
+ DataTypeSelector::Temporal.as_selector().into()
168
+ }
169
+
170
+ pub fn datetime(tu: Vec<Wrap<TimeUnit>>, tz: Vec<Wrap<Option<TimeZone>>>) -> Self {
171
+ use TimeZoneSet as TZS;
172
+
173
+ let mut allow_unset = false;
174
+ let mut allow_set = false;
175
+ let mut any_of: Vec<TimeZone> = Vec::new();
176
+
177
+ let tu = parse_time_unit_set(tu);
178
+ for t in tz {
179
+ let t = t.0;
180
+ match t {
181
+ None => allow_unset = true,
182
+ Some(s) if s.as_str() == "*" => allow_set = true,
183
+ Some(t) => any_of.push(t),
184
+ }
185
+ }
186
+
187
+ let tzs = match (allow_unset, allow_set) {
188
+ (true, true) => TZS::Any,
189
+ (false, true) => TZS::AnySet,
190
+ (true, false) if any_of.is_empty() => TZS::Unset,
191
+ (true, false) => TZS::UnsetOrAnyOf(any_of.into()),
192
+ (false, false) => TZS::AnyOf(any_of.into()),
193
+ };
194
+ DataTypeSelector::Datetime(tu, tzs).as_selector().into()
195
+ }
196
+
197
+ pub fn duration(tu: Vec<Wrap<TimeUnit>>) -> Self {
198
+ let tu = parse_time_unit_set(tu);
199
+ DataTypeSelector::Duration(tu).as_selector().into()
200
+ }
201
+
202
+ pub fn object() -> Self {
203
+ DataTypeSelector::Object.as_selector().into()
204
+ }
205
+
206
+ pub fn empty() -> Self {
207
+ dsl::functions::empty().into()
208
+ }
209
+
210
+ pub fn all() -> Self {
211
+ dsl::functions::all().into()
212
+ }
213
+
214
+ pub fn hash(&self) -> u64 {
215
+ let mut hasher = std::hash::DefaultHasher::default();
216
+ self.inner.hash(&mut hasher);
217
+ hasher.finish()
218
+ }
219
+ }
@@ -0,0 +1,28 @@
1
+ use std::io::{BufReader, BufWriter};
2
+
3
+ use magnus::Value;
4
+ use polars::lazy::prelude::Expr;
5
+ use polars_utils::pl_serialize;
6
+
7
+ use crate::exceptions::ComputeError;
8
+ use crate::file::get_file_like;
9
+ use crate::{RbExpr, RbResult};
10
+
11
+ impl RbExpr {
12
+ pub fn serialize_binary(&self, rb_f: Value) -> RbResult<()> {
13
+ let file = get_file_like(rb_f, true)?;
14
+ let writer = BufWriter::new(file);
15
+ pl_serialize::SerializeOptions::default()
16
+ .serialize_into_writer::<_, _, true>(writer, &self.inner)
17
+ .map_err(|err| ComputeError::new_err(err.to_string()))
18
+ }
19
+
20
+ pub fn deserialize_binary(rb_f: Value) -> RbResult<RbExpr> {
21
+ let file = get_file_like(rb_f, false)?;
22
+ let reader = BufReader::new(file);
23
+ let expr: Expr = pl_serialize::SerializeOptions::default()
24
+ .deserialize_from_reader::<_, _, true>(reader)
25
+ .map_err(|err| ComputeError::new_err(err.to_string()))?;
26
+ Ok(expr.into())
27
+ }
28
+ }
@@ -1,7 +1,7 @@
1
1
  use polars::prelude::*;
2
2
 
3
3
  use crate::conversion::Wrap;
4
- use crate::{RbExpr, RbPolarsErr, RbResult};
4
+ use crate::{RbDataTypeExpr, RbExpr, RbPolarsErr, RbResult};
5
5
 
6
6
  impl RbExpr {
7
7
  pub fn str_join(&self, delimiter: String, ignore_nulls: bool) -> Self {
@@ -30,19 +30,18 @@ impl RbExpr {
30
30
  self.inner.clone().str().to_date(options).into()
31
31
  }
32
32
 
33
- #[allow(clippy::too_many_arguments)]
34
33
  pub fn str_to_datetime(
35
34
  &self,
36
35
  format: Option<String>,
37
36
  time_unit: Option<Wrap<TimeUnit>>,
38
- time_zone: Option<Wrap<TimeZone>>,
37
+ time_zone: Wrap<Option<TimeZone>>,
39
38
  strict: bool,
40
39
  exact: bool,
41
40
  cache: bool,
42
41
  ambiguous: &Self,
43
42
  ) -> Self {
44
43
  let format = format.map(|x| x.into());
45
- let time_zone = time_zone.map(|x| x.0);
44
+ let time_zone = time_zone.0;
46
45
 
47
46
  let options = StrptimeOptions {
48
47
  format,
@@ -122,6 +121,14 @@ impl RbExpr {
122
121
  .into()
123
122
  }
124
123
 
124
+ pub fn str_head(&self, n: &Self) -> Self {
125
+ self.inner.clone().str().head(n.inner.clone()).into()
126
+ }
127
+
128
+ pub fn str_tail(&self, n: &Self) -> Self {
129
+ self.inner.clone().str().tail(n.inner.clone()).into()
130
+ }
131
+
125
132
  pub fn str_to_uppercase(&self) -> Self {
126
133
  self.inner.clone().str().to_uppercase().into()
127
134
  }
@@ -159,16 +166,28 @@ impl RbExpr {
159
166
  .into()
160
167
  }
161
168
 
169
+ pub fn str_normalize(&self, form: Wrap<UnicodeForm>) -> Self {
170
+ self.inner.clone().str().normalize(form.0).into()
171
+ }
172
+
162
173
  pub fn str_reverse(&self) -> Self {
163
174
  self.inner.clone().str().reverse().into()
164
175
  }
165
176
 
166
- pub fn str_pad_start(&self, length: usize, fillchar: char) -> Self {
167
- self.clone().inner.str().pad_start(length, fillchar).into()
177
+ pub fn str_pad_start(&self, length: &RbExpr, fillchar: char) -> Self {
178
+ self.clone()
179
+ .inner
180
+ .str()
181
+ .pad_start(length.inner.clone(), fillchar)
182
+ .into()
168
183
  }
169
184
 
170
- pub fn str_pad_end(&self, length: usize, fillchar: char) -> Self {
171
- self.clone().inner.str().pad_end(length, fillchar).into()
185
+ pub fn str_pad_end(&self, length: &RbExpr, fillchar: char) -> Self {
186
+ self.clone()
187
+ .inner
188
+ .str()
189
+ .pad_end(length.inner.clone(), fillchar)
190
+ .into()
172
191
  }
173
192
 
174
193
  pub fn str_zfill(&self, length: &Self) -> Self {
@@ -192,6 +211,23 @@ impl RbExpr {
192
211
  }
193
212
  }
194
213
 
214
+ pub fn str_find(&self, pat: &Self, literal: Option<bool>, strict: bool) -> Self {
215
+ match literal {
216
+ Some(true) => self
217
+ .inner
218
+ .clone()
219
+ .str()
220
+ .find_literal(pat.inner.clone())
221
+ .into(),
222
+ _ => self
223
+ .inner
224
+ .clone()
225
+ .str()
226
+ .find(pat.inner.clone(), strict)
227
+ .into(),
228
+ }
229
+ }
230
+
195
231
  pub fn str_ends_with(&self, sub: &RbExpr) -> Self {
196
232
  self.inner.clone().str().ends_with(sub.inner.clone()).into()
197
233
  }
@@ -220,25 +256,19 @@ impl RbExpr {
220
256
  self.inner.clone().str().base64_decode(strict).into()
221
257
  }
222
258
 
223
- pub fn str_to_integer(&self, base: &Self, strict: bool) -> Self {
259
+ pub fn str_to_integer(&self, base: &Self, dtype: Option<Wrap<DataType>>, strict: bool) -> Self {
224
260
  self.inner
225
261
  .clone()
226
262
  .str()
227
- .to_integer(base.inner.clone(), strict)
228
- .with_fmt("str.to_integer")
263
+ .to_integer(base.inner.clone(), dtype.map(|wrap| wrap.0), strict)
229
264
  .into()
230
265
  }
231
266
 
232
- pub fn str_json_decode(
233
- &self,
234
- dtype: Option<Wrap<DataType>>,
235
- infer_schema_len: Option<usize>,
236
- ) -> Self {
237
- let dtype = dtype.map(|wrap| wrap.0);
267
+ pub fn str_json_decode(&self, dtype: &RbDataTypeExpr) -> Self {
238
268
  self.inner
239
269
  .clone()
240
270
  .str()
241
- .json_decode(dtype, infer_schema_len)
271
+ .json_decode(dtype.inner.clone())
242
272
  .into()
243
273
  }
244
274
 
@@ -316,8 +346,32 @@ impl RbExpr {
316
346
  self.inner.clone().str().splitn(by.inner.clone(), n).into()
317
347
  }
318
348
 
319
- pub fn str_to_decimal(&self, infer_len: usize) -> Self {
320
- self.inner.clone().str().to_decimal(infer_len).into()
349
+ pub fn str_split_regex(&self, by: &Self, strict: bool) -> Self {
350
+ self.str_split_regex_with_strict(by, strict)
351
+ }
352
+
353
+ pub fn str_split_regex_inclusive(&self, by: &Self, strict: bool) -> Self {
354
+ self.str_split_regex_inclusive_with_strict(by, strict)
355
+ }
356
+
357
+ fn str_split_regex_with_strict(&self, by: &Self, strict: bool) -> Self {
358
+ self.inner
359
+ .clone()
360
+ .str()
361
+ .split_regex(by.inner.clone(), strict)
362
+ .into()
363
+ }
364
+
365
+ fn str_split_regex_inclusive_with_strict(&self, by: &Self, strict: bool) -> Self {
366
+ self.inner
367
+ .clone()
368
+ .str()
369
+ .split_regex_inclusive(by.inner.clone(), strict)
370
+ .into()
371
+ }
372
+
373
+ pub fn str_to_decimal(&self, scale: usize) -> Self {
374
+ self.inner.clone().str().to_decimal(scale).into()
321
375
  }
322
376
 
323
377
  pub fn str_contains_any(&self, patterns: &RbExpr, ascii_case_insensitive: bool) -> Self {
@@ -333,6 +387,7 @@ impl RbExpr {
333
387
  patterns: &RbExpr,
334
388
  replace_with: &RbExpr,
335
389
  ascii_case_insensitive: bool,
390
+ leftmost: bool,
336
391
  ) -> Self {
337
392
  self.inner
338
393
  .clone()
@@ -341,7 +396,50 @@ impl RbExpr {
341
396
  patterns.inner.clone(),
342
397
  replace_with.inner.clone(),
343
398
  ascii_case_insensitive,
399
+ leftmost,
400
+ )
401
+ .into()
402
+ }
403
+
404
+ pub fn str_extract_many(
405
+ &self,
406
+ patterns: &RbExpr,
407
+ ascii_case_insensitive: bool,
408
+ overlapping: bool,
409
+ leftmost: bool,
410
+ ) -> Self {
411
+ self.inner
412
+ .clone()
413
+ .str()
414
+ .extract_many(
415
+ patterns.inner.clone(),
416
+ ascii_case_insensitive,
417
+ overlapping,
418
+ leftmost,
419
+ )
420
+ .into()
421
+ }
422
+
423
+ pub fn str_find_many(
424
+ &self,
425
+ patterns: &RbExpr,
426
+ ascii_case_insensitive: bool,
427
+ overlapping: bool,
428
+ leftmost: bool,
429
+ ) -> Self {
430
+ self.inner
431
+ .clone()
432
+ .str()
433
+ .find_many(
434
+ patterns.inner.clone(),
435
+ ascii_case_insensitive,
436
+ overlapping,
437
+ leftmost,
344
438
  )
345
439
  .into()
346
440
  }
441
+
442
+ pub fn str_escape_regex(&self) -> Self {
443
+ self.inner.clone().str().escape_regex().into()
444
+ }
347
445
  }
@@ -1,4 +1,7 @@
1
- use crate::RbExpr;
1
+ use magnus::RArray;
2
+
3
+ use crate::expr::ToExprs;
4
+ use crate::{RbExpr, RbResult};
2
5
 
3
6
  impl RbExpr {
4
7
  pub fn struct_field_by_index(&self, index: i64) -> Self {
@@ -9,6 +12,10 @@ impl RbExpr {
9
12
  self.inner.clone().struct_().field_by_name(&name).into()
10
13
  }
11
14
 
15
+ pub fn struct_multiple_fields(&self, names: Vec<String>) -> Self {
16
+ self.inner.clone().struct_().field_by_names(&names).into()
17
+ }
18
+
12
19
  pub fn struct_rename_fields(&self, names: Vec<String>) -> Self {
13
20
  self.inner.clone().struct_().rename_fields(names).into()
14
21
  }
@@ -16,4 +23,10 @@ impl RbExpr {
16
23
  pub fn struct_json_encode(&self) -> Self {
17
24
  self.inner.clone().struct_().json_encode().into()
18
25
  }
26
+
27
+ pub fn struct_with_fields(&self, fields: RArray) -> RbResult<Self> {
28
+ let fields = fields.to_exprs()?;
29
+ let e = self.inner.clone().struct_().with_fields(fields);
30
+ Ok(e.into())
31
+ }
19
32
  }