polars-df 0.7.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +41 -0
- data/Cargo.lock +353 -237
- data/Cargo.toml +0 -3
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/ext/polars/Cargo.toml +17 -6
- data/ext/polars/src/batched_csv.rs +6 -7
- data/ext/polars/src/conversion/anyvalue.rs +185 -0
- data/ext/polars/src/conversion/chunked_array.rs +140 -0
- data/ext/polars/src/{conversion.rs → conversion/mod.rs} +268 -347
- data/ext/polars/src/dataframe.rs +96 -116
- data/ext/polars/src/expr/array.rs +74 -0
- data/ext/polars/src/expr/categorical.rs +8 -1
- data/ext/polars/src/expr/datetime.rs +22 -56
- data/ext/polars/src/expr/general.rs +124 -37
- data/ext/polars/src/expr/list.rs +52 -4
- data/ext/polars/src/expr/meta.rs +48 -0
- data/ext/polars/src/expr/rolling.rs +16 -10
- data/ext/polars/src/expr/string.rs +68 -17
- data/ext/polars/src/expr/struct.rs +8 -4
- data/ext/polars/src/functions/aggregation.rs +6 -0
- data/ext/polars/src/functions/lazy.rs +103 -48
- data/ext/polars/src/functions/meta.rs +45 -1
- data/ext/polars/src/functions/range.rs +5 -10
- data/ext/polars/src/functions/string_cache.rs +14 -0
- data/ext/polars/src/{lazyframe.rs → lazyframe/mod.rs} +166 -41
- data/ext/polars/src/lib.rs +245 -187
- data/ext/polars/src/map/dataframe.rs +1 -1
- data/ext/polars/src/map/mod.rs +2 -2
- data/ext/polars/src/map/series.rs +6 -6
- data/ext/polars/src/object.rs +0 -30
- data/ext/polars/src/on_startup.rs +32 -0
- data/ext/polars/src/series/aggregation.rs +23 -0
- data/ext/polars/src/series/construction.rs +1 -1
- data/ext/polars/src/series/export.rs +2 -2
- data/ext/polars/src/{series.rs → series/mod.rs} +45 -21
- data/ext/polars/src/series/{set_at_idx.rs → scatter.rs} +18 -18
- data/ext/polars/src/utils.rs +1 -1
- data/lib/polars/array_expr.rb +449 -0
- data/lib/polars/array_name_space.rb +346 -0
- data/lib/polars/cat_expr.rb +24 -0
- data/lib/polars/cat_name_space.rb +75 -0
- data/lib/polars/config.rb +2 -2
- data/lib/polars/data_frame.rb +248 -108
- data/lib/polars/data_types.rb +195 -29
- data/lib/polars/date_time_expr.rb +41 -24
- data/lib/polars/date_time_name_space.rb +12 -12
- data/lib/polars/exceptions.rb +12 -1
- data/lib/polars/expr.rb +1080 -195
- data/lib/polars/functions/aggregation/horizontal.rb +246 -0
- data/lib/polars/functions/aggregation/vertical.rb +282 -0
- data/lib/polars/functions/as_datatype.rb +248 -0
- data/lib/polars/functions/col.rb +47 -0
- data/lib/polars/functions/eager.rb +182 -0
- data/lib/polars/functions/lazy.rb +1280 -0
- data/lib/polars/functions/len.rb +49 -0
- data/lib/polars/functions/lit.rb +35 -0
- data/lib/polars/functions/random.rb +16 -0
- data/lib/polars/functions/range/date_range.rb +103 -0
- data/lib/polars/functions/range/int_range.rb +51 -0
- data/lib/polars/functions/repeat.rb +144 -0
- data/lib/polars/functions/whenthen.rb +27 -0
- data/lib/polars/functions.rb +29 -416
- data/lib/polars/group_by.rb +3 -3
- data/lib/polars/io.rb +21 -28
- data/lib/polars/lazy_frame.rb +390 -76
- data/lib/polars/list_expr.rb +152 -6
- data/lib/polars/list_name_space.rb +102 -0
- data/lib/polars/meta_expr.rb +175 -7
- data/lib/polars/series.rb +557 -59
- data/lib/polars/sql_context.rb +1 -1
- data/lib/polars/string_cache.rb +75 -0
- data/lib/polars/string_expr.rb +412 -96
- data/lib/polars/string_name_space.rb +4 -4
- data/lib/polars/struct_expr.rb +1 -1
- data/lib/polars/struct_name_space.rb +1 -1
- data/lib/polars/testing.rb +507 -0
- data/lib/polars/utils.rb +64 -20
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +15 -2
- metadata +40 -9
- data/lib/polars/lazy_functions.rb +0 -1197
data/Cargo.toml
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
:fire: Blazingly fast DataFrames for Ruby, powered by [Polars](https://github.com/pola-rs/polars)
|
4
4
|
|
5
|
-
[![Build Status](https://github.com/ankane/polars-ruby/workflows/build/badge.svg
|
5
|
+
[![Build Status](https://github.com/ankane/polars-ruby/actions/workflows/build.yml/badge.svg)](https://github.com/ankane/polars-ruby/actions)
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -357,7 +357,7 @@ Supported types are:
|
|
357
357
|
- float - `Float64`, `Float32`
|
358
358
|
- integer - `Int64`, `Int32`, `Int16`, `Int8`
|
359
359
|
- unsigned integer - `UInt64`, `UInt32`, `UInt16`, `UInt8`
|
360
|
-
- string - `
|
360
|
+
- string - `String`, `Binary`, `Categorical`
|
361
361
|
- temporal - `Date`, `Datetime`, `Time`, `Duration`
|
362
362
|
- nested - `List`, `Struct`, `Array`
|
363
363
|
- other - `Object`, `Null`
|
data/ext/polars/Cargo.toml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
[package]
|
2
2
|
name = "polars"
|
3
|
-
version = "0.
|
3
|
+
version = "0.9.0"
|
4
4
|
license = "MIT"
|
5
5
|
authors = ["Andrew Kane <andrew@ankane.org>"]
|
6
6
|
edition = "2021"
|
@@ -15,17 +15,20 @@ ahash = "0.8"
|
|
15
15
|
chrono = "0.4"
|
16
16
|
either = "1.8"
|
17
17
|
magnus = "0.6"
|
18
|
-
polars-core = "=0.
|
19
|
-
polars-parquet = "=0.
|
18
|
+
polars-core = "=0.38.1"
|
19
|
+
polars-parquet = "=0.38.1"
|
20
|
+
polars-utils = "=0.38.1"
|
20
21
|
serde_json = "1"
|
21
22
|
smartstring = "1"
|
22
23
|
|
23
24
|
[dependencies.polars]
|
24
|
-
version = "=0.
|
25
|
+
version = "=0.38.1"
|
25
26
|
features = [
|
26
27
|
"abs",
|
27
28
|
"approx_unique",
|
28
29
|
"arg_where",
|
30
|
+
"array_any_all",
|
31
|
+
"array_count",
|
29
32
|
"asof_join",
|
30
33
|
"avro",
|
31
34
|
"binary_encoding",
|
@@ -35,6 +38,7 @@ features = [
|
|
35
38
|
"csv",
|
36
39
|
"cum_agg",
|
37
40
|
"cumulative_eval",
|
41
|
+
"cutqcut",
|
38
42
|
"dataframe_arithmetic",
|
39
43
|
"date_offset",
|
40
44
|
"diagonal_concat",
|
@@ -43,9 +47,10 @@ features = [
|
|
43
47
|
"dtype-full",
|
44
48
|
"dynamic_group_by",
|
45
49
|
"ewma",
|
50
|
+
"extract_groups",
|
46
51
|
"extract_jsonpath",
|
52
|
+
"find_many",
|
47
53
|
"fmt",
|
48
|
-
"horizontal_concat",
|
49
54
|
"interpolate",
|
50
55
|
"ipc",
|
51
56
|
"is_first_distinct",
|
@@ -54,12 +59,15 @@ features = [
|
|
54
59
|
"is_unique",
|
55
60
|
"json",
|
56
61
|
"lazy",
|
57
|
-
"
|
62
|
+
"list_any_all",
|
58
63
|
"list_count",
|
64
|
+
"list_drop_nulls",
|
59
65
|
"list_eval",
|
60
66
|
"list_gather",
|
67
|
+
"list_sample",
|
61
68
|
"list_to_struct",
|
62
69
|
"log",
|
70
|
+
"merge_sorted",
|
63
71
|
"meta",
|
64
72
|
"mode",
|
65
73
|
"moment",
|
@@ -75,8 +83,11 @@ features = [
|
|
75
83
|
"random",
|
76
84
|
"rank",
|
77
85
|
"range",
|
86
|
+
"regex",
|
78
87
|
"reinterpret",
|
79
88
|
"repeat_by",
|
89
|
+
"replace",
|
90
|
+
"rle",
|
80
91
|
"rolling_window",
|
81
92
|
"round_series",
|
82
93
|
"row_hash",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
use magnus::{prelude::*, RArray, Value};
|
2
2
|
use polars::io::mmap::MmapBytesReader;
|
3
|
-
use polars::io::
|
3
|
+
use polars::io::RowIndex;
|
4
4
|
use polars::prelude::read_impl::OwnedBatchedCsvReader;
|
5
5
|
use polars::prelude::*;
|
6
6
|
use std::cell::RefCell;
|
@@ -41,21 +41,20 @@ impl RbBatchedCsv {
|
|
41
41
|
// TODO fix
|
42
42
|
let overwrite_dtype_slice = Option::<Vec<Wrap<DataType>>>::None; // Option::<Vec<Wrap<DataType>>>::try_convert(arguments[14])?;
|
43
43
|
let low_memory = bool::try_convert(arguments[15])?;
|
44
|
-
let
|
44
|
+
let comment_prefix = Option::<String>::try_convert(arguments[16])?;
|
45
45
|
let quote_char = Option::<String>::try_convert(arguments[17])?;
|
46
46
|
let null_values = Option::<Wrap<NullValues>>::try_convert(arguments[18])?;
|
47
47
|
let try_parse_dates = bool::try_convert(arguments[19])?;
|
48
48
|
let skip_rows_after_header = usize::try_convert(arguments[20])?;
|
49
|
-
let
|
49
|
+
let row_index = Option::<(String, IdxSize)>::try_convert(arguments[21])?;
|
50
50
|
let sample_size = usize::try_convert(arguments[22])?;
|
51
51
|
let eol_char = String::try_convert(arguments[23])?;
|
52
52
|
// end arguments
|
53
53
|
|
54
54
|
let null_values = null_values.map(|w| w.0);
|
55
|
-
let comment_char = comment_char.map(|s| s.as_bytes()[0]);
|
56
55
|
let eol_char = eol_char.as_bytes()[0];
|
57
56
|
|
58
|
-
let
|
57
|
+
let row_index = row_index.map(|(name, offset)| RowIndex { name, offset });
|
59
58
|
|
60
59
|
let quote_char = if let Some(s) = quote_char {
|
61
60
|
if s.is_empty() {
|
@@ -101,13 +100,13 @@ impl RbBatchedCsv {
|
|
101
100
|
.with_n_threads(n_threads)
|
102
101
|
.with_dtypes_slice(overwrite_dtype_slice.as_deref())
|
103
102
|
.low_memory(low_memory)
|
104
|
-
.
|
103
|
+
.with_comment_prefix(comment_prefix.as_deref())
|
105
104
|
.with_null_values(null_values)
|
106
105
|
.with_try_parse_dates(try_parse_dates)
|
107
106
|
.with_quote_char(quote_char)
|
108
107
|
.with_end_of_line_char(eol_char)
|
109
108
|
.with_skip_rows_after_header(skip_rows_after_header)
|
110
|
-
.
|
109
|
+
.with_row_index(row_index)
|
111
110
|
.sample_size(sample_size);
|
112
111
|
|
113
112
|
let reader = if low_memory {
|
@@ -0,0 +1,185 @@
|
|
1
|
+
use magnus::encoding::{EncodingCapable, Index};
|
2
|
+
use magnus::{
|
3
|
+
class, prelude::*, r_hash::ForEach, Float, Integer, IntoValue, RArray, RHash, RString, Ruby,
|
4
|
+
TryConvert, Value,
|
5
|
+
};
|
6
|
+
use polars::frame::row::any_values_to_dtype;
|
7
|
+
use polars::prelude::*;
|
8
|
+
|
9
|
+
use super::{struct_dict, ObjectValue, Wrap};
|
10
|
+
|
11
|
+
use crate::rb_modules::utils;
|
12
|
+
use crate::{RbPolarsErr, RbResult, RbSeries};
|
13
|
+
|
14
|
+
impl IntoValue for Wrap<AnyValue<'_>> {
|
15
|
+
fn into_value_with(self, ruby: &Ruby) -> Value {
|
16
|
+
match self.0 {
|
17
|
+
AnyValue::UInt8(v) => ruby.into_value(v),
|
18
|
+
AnyValue::UInt16(v) => ruby.into_value(v),
|
19
|
+
AnyValue::UInt32(v) => ruby.into_value(v),
|
20
|
+
AnyValue::UInt64(v) => ruby.into_value(v),
|
21
|
+
AnyValue::Int8(v) => ruby.into_value(v),
|
22
|
+
AnyValue::Int16(v) => ruby.into_value(v),
|
23
|
+
AnyValue::Int32(v) => ruby.into_value(v),
|
24
|
+
AnyValue::Int64(v) => ruby.into_value(v),
|
25
|
+
AnyValue::Float32(v) => ruby.into_value(v),
|
26
|
+
AnyValue::Float64(v) => ruby.into_value(v),
|
27
|
+
AnyValue::Null => ruby.qnil().as_value(),
|
28
|
+
AnyValue::Boolean(v) => ruby.into_value(v),
|
29
|
+
AnyValue::String(v) => ruby.into_value(v),
|
30
|
+
AnyValue::StringOwned(v) => ruby.into_value(v.as_str()),
|
31
|
+
AnyValue::Categorical(idx, rev, arr) | AnyValue::Enum(idx, rev, arr) => {
|
32
|
+
let s = if arr.is_null() {
|
33
|
+
rev.get(idx)
|
34
|
+
} else {
|
35
|
+
unsafe { arr.deref_unchecked().value(idx as usize) }
|
36
|
+
};
|
37
|
+
s.into_value()
|
38
|
+
}
|
39
|
+
AnyValue::Date(v) => utils().funcall("_to_ruby_date", (v,)).unwrap(),
|
40
|
+
AnyValue::Datetime(v, time_unit, time_zone) => {
|
41
|
+
let time_unit = time_unit.to_ascii();
|
42
|
+
utils()
|
43
|
+
.funcall("_to_ruby_datetime", (v, time_unit, time_zone.clone()))
|
44
|
+
.unwrap()
|
45
|
+
}
|
46
|
+
AnyValue::Duration(v, time_unit) => {
|
47
|
+
let time_unit = time_unit.to_ascii();
|
48
|
+
utils()
|
49
|
+
.funcall("_to_ruby_duration", (v, time_unit))
|
50
|
+
.unwrap()
|
51
|
+
}
|
52
|
+
AnyValue::Time(v) => utils().funcall("_to_ruby_time", (v,)).unwrap(),
|
53
|
+
AnyValue::Array(v, _) | AnyValue::List(v) => RbSeries::new(v).to_a().into_value(),
|
54
|
+
ref av @ AnyValue::Struct(_, _, flds) => struct_dict(av._iter_struct_av(), flds),
|
55
|
+
AnyValue::StructOwned(payload) => struct_dict(payload.0.into_iter(), &payload.1),
|
56
|
+
AnyValue::Object(v) => {
|
57
|
+
let object = v.as_any().downcast_ref::<ObjectValue>().unwrap();
|
58
|
+
object.to_object()
|
59
|
+
}
|
60
|
+
AnyValue::ObjectOwned(v) => {
|
61
|
+
let object = v.0.as_any().downcast_ref::<ObjectValue>().unwrap();
|
62
|
+
object.to_object()
|
63
|
+
}
|
64
|
+
AnyValue::Binary(v) => RString::from_slice(v).into_value(),
|
65
|
+
AnyValue::BinaryOwned(v) => RString::from_slice(&v).into_value(),
|
66
|
+
AnyValue::Decimal(v, scale) => utils()
|
67
|
+
.funcall("_to_ruby_decimal", (v.to_string(), -(scale as i32)))
|
68
|
+
.unwrap(),
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
impl<'s> TryConvert for Wrap<AnyValue<'s>> {
|
74
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
75
|
+
if ob.is_kind_of(class::true_class()) || ob.is_kind_of(class::false_class()) {
|
76
|
+
Ok(AnyValue::Boolean(bool::try_convert(ob)?).into())
|
77
|
+
} else if let Some(v) = Integer::from_value(ob) {
|
78
|
+
Ok(AnyValue::Int64(v.to_i64()?).into())
|
79
|
+
} else if let Some(v) = Float::from_value(ob) {
|
80
|
+
Ok(AnyValue::Float64(v.to_f64()).into())
|
81
|
+
} else if let Some(v) = RString::from_value(ob) {
|
82
|
+
if v.enc_get() == Index::utf8() {
|
83
|
+
Ok(AnyValue::StringOwned(v.to_string()?.into()).into())
|
84
|
+
} else {
|
85
|
+
Ok(AnyValue::BinaryOwned(unsafe { v.as_slice() }.to_vec()).into())
|
86
|
+
}
|
87
|
+
// call is_a? for ActiveSupport::TimeWithZone
|
88
|
+
} else if ob.funcall::<_, _, bool>("is_a?", (class::time(),))? {
|
89
|
+
let sec = ob.funcall::<_, _, i64>("to_i", ())?;
|
90
|
+
let nsec = ob.funcall::<_, _, i64>("nsec", ())?;
|
91
|
+
let v = sec * 1_000_000_000 + nsec;
|
92
|
+
// TODO support time zone when possible
|
93
|
+
// https://github.com/pola-rs/polars/issues/9103
|
94
|
+
Ok(AnyValue::Datetime(v, TimeUnit::Nanoseconds, &None).into())
|
95
|
+
} else if ob.is_nil() {
|
96
|
+
Ok(AnyValue::Null.into())
|
97
|
+
} else if let Some(dict) = RHash::from_value(ob) {
|
98
|
+
let len = dict.len();
|
99
|
+
let mut keys = Vec::with_capacity(len);
|
100
|
+
let mut vals = Vec::with_capacity(len);
|
101
|
+
dict.foreach(|k: Value, v: Value| {
|
102
|
+
let key = String::try_convert(k)?;
|
103
|
+
let val = Wrap::<AnyValue>::try_convert(v)?.0;
|
104
|
+
let dtype = DataType::from(&val);
|
105
|
+
keys.push(Field::new(&key, dtype));
|
106
|
+
vals.push(val);
|
107
|
+
Ok(ForEach::Continue)
|
108
|
+
})?;
|
109
|
+
Ok(Wrap(AnyValue::StructOwned(Box::new((vals, keys)))))
|
110
|
+
} else if let Some(v) = RArray::from_value(ob) {
|
111
|
+
if v.is_empty() {
|
112
|
+
Ok(Wrap(AnyValue::List(Series::new_empty("", &DataType::Null))))
|
113
|
+
} else {
|
114
|
+
let list = v;
|
115
|
+
|
116
|
+
let mut avs = Vec::with_capacity(25);
|
117
|
+
let mut iter = list.each();
|
118
|
+
|
119
|
+
for item in (&mut iter).take(25) {
|
120
|
+
avs.push(Wrap::<AnyValue>::try_convert(item?)?.0)
|
121
|
+
}
|
122
|
+
|
123
|
+
let (dtype, _n_types) = any_values_to_dtype(&avs).map_err(RbPolarsErr::from)?;
|
124
|
+
|
125
|
+
// push the rest
|
126
|
+
avs.reserve(list.len());
|
127
|
+
for item in iter {
|
128
|
+
avs.push(Wrap::<AnyValue>::try_convert(item?)?.0)
|
129
|
+
}
|
130
|
+
|
131
|
+
let s = Series::from_any_values_and_dtype("", &avs, &dtype, true)
|
132
|
+
.map_err(RbPolarsErr::from)?;
|
133
|
+
Ok(Wrap(AnyValue::List(s)))
|
134
|
+
}
|
135
|
+
} else if ob.is_kind_of(crate::rb_modules::datetime()) {
|
136
|
+
let sec: i64 = ob.funcall("to_i", ())?;
|
137
|
+
let nsec: i64 = ob.funcall("nsec", ())?;
|
138
|
+
Ok(Wrap(AnyValue::Datetime(
|
139
|
+
sec * 1_000_000_000 + nsec,
|
140
|
+
TimeUnit::Nanoseconds,
|
141
|
+
&None,
|
142
|
+
)))
|
143
|
+
} else if ob.is_kind_of(crate::rb_modules::date()) {
|
144
|
+
// convert to DateTime for UTC
|
145
|
+
let v = ob
|
146
|
+
.funcall::<_, _, Value>("to_datetime", ())?
|
147
|
+
.funcall::<_, _, Value>("to_time", ())?
|
148
|
+
.funcall::<_, _, i64>("to_i", ())?;
|
149
|
+
Ok(Wrap(AnyValue::Date((v / 86400) as i32)))
|
150
|
+
} else if ob.is_kind_of(crate::rb_modules::bigdecimal()) {
|
151
|
+
let (sign, digits, _, exp): (i8, String, i32, i32) = ob.funcall("split", ()).unwrap();
|
152
|
+
let (mut v, scale) = abs_decimal_from_digits(digits, exp).ok_or_else(|| {
|
153
|
+
RbPolarsErr::other("BigDecimal is too large to fit in Decimal128".into())
|
154
|
+
})?;
|
155
|
+
if sign < 0 {
|
156
|
+
// TODO better error
|
157
|
+
v = v.checked_neg().unwrap();
|
158
|
+
}
|
159
|
+
Ok(Wrap(AnyValue::Decimal(v, scale)))
|
160
|
+
} else {
|
161
|
+
Err(RbPolarsErr::other(format!(
|
162
|
+
"object type not supported {:?}",
|
163
|
+
ob
|
164
|
+
)))
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
fn abs_decimal_from_digits(digits: String, exp: i32) -> Option<(i128, usize)> {
|
170
|
+
let exp = exp - (digits.len() as i32);
|
171
|
+
match digits.parse::<i128>() {
|
172
|
+
Ok(mut v) => {
|
173
|
+
let scale = if exp > 0 {
|
174
|
+
v = 10_i128
|
175
|
+
.checked_pow(exp as u32)
|
176
|
+
.and_then(|factor| v.checked_mul(factor))?;
|
177
|
+
0
|
178
|
+
} else {
|
179
|
+
(-exp) as usize
|
180
|
+
};
|
181
|
+
Some((v, scale))
|
182
|
+
}
|
183
|
+
Err(_) => None,
|
184
|
+
}
|
185
|
+
}
|
@@ -0,0 +1,140 @@
|
|
1
|
+
use magnus::{prelude::*, IntoValue, RArray, RString, Ruby, TryConvert, Value};
|
2
|
+
use polars::prelude::*;
|
3
|
+
|
4
|
+
use super::{get_rbseq, struct_dict, Wrap};
|
5
|
+
|
6
|
+
use crate::rb_modules::utils;
|
7
|
+
use crate::RbResult;
|
8
|
+
|
9
|
+
impl TryConvert for Wrap<StringChunked> {
|
10
|
+
fn try_convert(obj: Value) -> RbResult<Self> {
|
11
|
+
let (seq, len) = get_rbseq(obj)?;
|
12
|
+
let mut builder = StringChunkedBuilder::new("", len);
|
13
|
+
|
14
|
+
for res in seq.each() {
|
15
|
+
let item = res?;
|
16
|
+
match String::try_convert(item) {
|
17
|
+
Ok(val) => builder.append_value(&val),
|
18
|
+
Err(_) => builder.append_null(),
|
19
|
+
}
|
20
|
+
}
|
21
|
+
Ok(Wrap(builder.finish()))
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
impl TryConvert for Wrap<BinaryChunked> {
|
26
|
+
fn try_convert(obj: Value) -> RbResult<Self> {
|
27
|
+
let (seq, len) = get_rbseq(obj)?;
|
28
|
+
let mut builder = BinaryChunkedBuilder::new("", len);
|
29
|
+
|
30
|
+
for res in seq.each() {
|
31
|
+
let item = res?;
|
32
|
+
match RString::try_convert(item) {
|
33
|
+
Ok(val) => builder.append_value(unsafe { val.as_slice() }),
|
34
|
+
Err(_) => builder.append_null(),
|
35
|
+
}
|
36
|
+
}
|
37
|
+
Ok(Wrap(builder.finish()))
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
impl IntoValue for Wrap<&StringChunked> {
|
42
|
+
fn into_value_with(self, _: &Ruby) -> Value {
|
43
|
+
let iter = self.0.into_iter();
|
44
|
+
RArray::from_iter(iter).into_value()
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
impl IntoValue for Wrap<&BinaryChunked> {
|
49
|
+
fn into_value_with(self, _: &Ruby) -> Value {
|
50
|
+
let iter = self
|
51
|
+
.0
|
52
|
+
.into_iter()
|
53
|
+
.map(|opt_bytes| opt_bytes.map(RString::from_slice));
|
54
|
+
RArray::from_iter(iter).into_value()
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
impl IntoValue for Wrap<&StructChunked> {
|
59
|
+
fn into_value_with(self, _: &Ruby) -> Value {
|
60
|
+
let s = self.0.clone().into_series();
|
61
|
+
// todo! iterate its chunks and flatten.
|
62
|
+
// make series::iter() accept a chunk index.
|
63
|
+
let s = s.rechunk();
|
64
|
+
let iter = s.iter().map(|av| {
|
65
|
+
if let AnyValue::Struct(_, _, flds) = av {
|
66
|
+
struct_dict(av._iter_struct_av(), flds)
|
67
|
+
} else {
|
68
|
+
unreachable!()
|
69
|
+
}
|
70
|
+
});
|
71
|
+
|
72
|
+
RArray::from_iter(iter).into_value()
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
impl IntoValue for Wrap<&DurationChunked> {
|
77
|
+
fn into_value_with(self, _: &Ruby) -> Value {
|
78
|
+
let utils = utils();
|
79
|
+
let time_unit = Wrap(self.0.time_unit()).into_value();
|
80
|
+
let iter = self.0.into_iter().map(|opt_v| {
|
81
|
+
opt_v.map(|v| {
|
82
|
+
utils
|
83
|
+
.funcall::<_, _, Value>("_to_ruby_duration", (v, time_unit))
|
84
|
+
.unwrap()
|
85
|
+
})
|
86
|
+
});
|
87
|
+
RArray::from_iter(iter).into_value()
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
impl IntoValue for Wrap<&DatetimeChunked> {
|
92
|
+
fn into_value_with(self, _: &Ruby) -> Value {
|
93
|
+
let utils = utils();
|
94
|
+
let time_unit = Wrap(self.0.time_unit()).into_value();
|
95
|
+
let time_zone = self.0.time_zone().clone().into_value();
|
96
|
+
let iter = self.0.into_iter().map(|opt_v| {
|
97
|
+
opt_v.map(|v| {
|
98
|
+
utils
|
99
|
+
.funcall::<_, _, Value>("_to_ruby_datetime", (v, time_unit, time_zone))
|
100
|
+
.unwrap()
|
101
|
+
})
|
102
|
+
});
|
103
|
+
RArray::from_iter(iter).into_value()
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
impl IntoValue for Wrap<&TimeChunked> {
|
108
|
+
fn into_value_with(self, _: &Ruby) -> Value {
|
109
|
+
let utils = utils();
|
110
|
+
let iter = self.0.into_iter().map(|opt_v| {
|
111
|
+
opt_v.map(|v| utils.funcall::<_, _, Value>("_to_ruby_time", (v,)).unwrap())
|
112
|
+
});
|
113
|
+
RArray::from_iter(iter).into_value()
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
impl IntoValue for Wrap<&DateChunked> {
|
118
|
+
fn into_value_with(self, _: &Ruby) -> Value {
|
119
|
+
let utils = utils();
|
120
|
+
let iter = self.0.into_iter().map(|opt_v| {
|
121
|
+
opt_v.map(|v| utils.funcall::<_, _, Value>("_to_ruby_date", (v,)).unwrap())
|
122
|
+
});
|
123
|
+
RArray::from_iter(iter).into_value()
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
impl IntoValue for Wrap<&DecimalChunked> {
|
128
|
+
fn into_value_with(self, _: &Ruby) -> Value {
|
129
|
+
let utils = utils();
|
130
|
+
let rb_scale = (-(self.0.scale() as i32)).into_value();
|
131
|
+
let iter = self.0.into_iter().map(|opt_v| {
|
132
|
+
opt_v.map(|v| {
|
133
|
+
utils
|
134
|
+
.funcall::<_, _, Value>("_to_ruby_decimal", (v.to_string(), rb_scale))
|
135
|
+
.unwrap()
|
136
|
+
})
|
137
|
+
});
|
138
|
+
RArray::from_iter(iter).into_value()
|
139
|
+
}
|
140
|
+
}
|