tracklib 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Cargo.lock +8 -8
- data/Cargo.toml +2 -5
- data/lib/tracklib/version.rb +1 -1
- data/src/lib.rs +167 -111
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 544377b466a27f1adc1885db2ae638e9c94e14f3
|
4
|
+
data.tar.gz: f4e80d1783f605692d0045da784e27a011e432ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd7a4ea44fadb9b2a961fef9ae4c0b811dd1328af6f801074c7440ba1318b0c8a184d0f2e4b9e262cd8e80e11e22b3513a2c4685a4dd2f0f012c878e8270ee42
|
7
|
+
data.tar.gz: 4cbaa1f2ee37375cb050acfb4ee38ebd06becc3c37b52e54e4ba3789ee7ef668f205c88e6fdd7d1546f598fdba4bc91066ba5b09aa051c6c2b0b9cfb0d1852ad
|
data/Cargo.lock
CHANGED
@@ -120,8 +120,8 @@ version = "0.1.0"
|
|
120
120
|
dependencies = [
|
121
121
|
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
122
122
|
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
123
|
-
"rutie 0.
|
124
|
-
"rutie-serde 0.1.1 (
|
123
|
+
"rutie 0.7.0 (git+https://github.com/danlarkin/rutie)",
|
124
|
+
"rutie-serde 0.1.1 (git+https://github.com/danlarkin/rutie-serde)",
|
125
125
|
"tracklib 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
126
126
|
]
|
127
127
|
|
@@ -132,8 +132,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
132
132
|
|
133
133
|
[[package]]
|
134
134
|
name = "rutie"
|
135
|
-
version = "0.
|
136
|
-
source = "
|
135
|
+
version = "0.7.0"
|
136
|
+
source = "git+https://github.com/danlarkin/rutie#6db74585735ca82894d6163357ee4defdc2cdc61"
|
137
137
|
dependencies = [
|
138
138
|
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
139
139
|
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
@@ -142,10 +142,10 @@ dependencies = [
|
|
142
142
|
[[package]]
|
143
143
|
name = "rutie-serde"
|
144
144
|
version = "0.1.1"
|
145
|
-
source = "
|
145
|
+
source = "git+https://github.com/danlarkin/rutie-serde#de14caea6c73cc479438c0c2b27b528d498e77fc"
|
146
146
|
dependencies = [
|
147
147
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
148
|
-
"rutie 0.
|
148
|
+
"rutie 0.7.0 (git+https://github.com/danlarkin/rutie)",
|
149
149
|
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
150
150
|
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
151
151
|
]
|
@@ -241,8 +241,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
241
241
|
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
242
242
|
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
243
243
|
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
244
|
-
"checksum rutie 0.
|
245
|
-
"checksum rutie-serde 0.1.1 (
|
244
|
+
"checksum rutie 0.7.0 (git+https://github.com/danlarkin/rutie)" = "<none>"
|
245
|
+
"checksum rutie-serde 0.1.1 (git+https://github.com/danlarkin/rutie-serde)" = "<none>"
|
246
246
|
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
247
247
|
"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113"
|
248
248
|
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
data/Cargo.toml
CHANGED
@@ -5,16 +5,13 @@ authors = ["Dan Larkin <dan@danlarkin.org>"]
|
|
5
5
|
license = "Apache-2.0 OR MIT"
|
6
6
|
edition = "2018"
|
7
7
|
|
8
|
-
[profile.release]
|
9
|
-
lto = false # LTO broke the ruby module in my testing
|
10
|
-
|
11
8
|
[lib]
|
12
9
|
name = "tracklib"
|
13
10
|
crate-type = ["cdylib"]
|
14
11
|
|
15
12
|
[dependencies]
|
16
13
|
tracklib = "*"
|
17
|
-
rutie = "
|
18
|
-
rutie-serde = "
|
14
|
+
rutie = {git="https://github.com/danlarkin/rutie", features=["no-link"]}
|
15
|
+
rutie-serde = {git="https://github.com/danlarkin/rutie-serde"}
|
19
16
|
lazy_static = "1.3"
|
20
17
|
base64 = "0.10"
|
data/lib/tracklib/version.rb
CHANGED
data/src/lib.rs
CHANGED
@@ -22,10 +22,10 @@ fn any_to_float(o: AnyObject) -> f64 {
|
|
22
22
|
|
23
23
|
fn any_to_int(o: AnyObject) -> i64 {
|
24
24
|
match o.try_convert_to::<Integer>() {
|
25
|
-
Ok(
|
26
|
-
Err(
|
25
|
+
Ok(i) => i.to_i64(),
|
26
|
+
Err(int_e) => o
|
27
27
|
.try_convert_to::<Float>()
|
28
|
-
.map_err(|_| VM::raise_ex(
|
28
|
+
.map_err(|_| VM::raise_ex(int_e))
|
29
29
|
.unwrap()
|
30
30
|
.to_f64() as i64,
|
31
31
|
}
|
@@ -59,7 +59,54 @@ fn any_to_ids(o: AnyObject) -> Vec<u64> {
|
|
59
59
|
.collect()
|
60
60
|
}
|
61
61
|
|
62
|
-
|
62
|
+
#[derive(Debug, Copy, Clone)]
|
63
|
+
enum ColumnType {
|
64
|
+
Numbers,
|
65
|
+
LongFloat,
|
66
|
+
ShortFloat,
|
67
|
+
Base64,
|
68
|
+
String,
|
69
|
+
Bool,
|
70
|
+
IDs,
|
71
|
+
}
|
72
|
+
|
73
|
+
impl ColumnType {
|
74
|
+
fn from_str(name: &str) -> Option<Self> {
|
75
|
+
match name {
|
76
|
+
"Number" => Some(ColumnType::Numbers),
|
77
|
+
"LongFloat" => Some(ColumnType::LongFloat),
|
78
|
+
"ShortFloat" => Some(ColumnType::ShortFloat),
|
79
|
+
"Base64" => Some(ColumnType::Base64),
|
80
|
+
"String" => Some(ColumnType::String),
|
81
|
+
"Bool" => Some(ColumnType::Bool),
|
82
|
+
"IDs" => Some(ColumnType::IDs),
|
83
|
+
_ => None
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
fn exponent(&self) -> u8 {
|
88
|
+
match self {
|
89
|
+
ColumnType::Numbers => 48,
|
90
|
+
ColumnType::LongFloat => 24,
|
91
|
+
ColumnType::ShortFloat => 38,
|
92
|
+
_ => {
|
93
|
+
VM::raise(Class::from_existing("Exception"),
|
94
|
+
&format!("can't handle numeric value for non-numeric field"));
|
95
|
+
unreachable!();
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
fn max_integer(&self) -> i64 {
|
101
|
+
2i64.pow(u32::from(self.exponent()))
|
102
|
+
}
|
103
|
+
|
104
|
+
fn max_float(&self) -> f64 {
|
105
|
+
2f64.powi(i32::from(self.exponent()))
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
fn convert_config(config: Hash) -> HashMap<String, ColumnType> {
|
63
110
|
let mut hm = HashMap::new();
|
64
111
|
|
65
112
|
config.each(|rwtf_type_name, array_of_field_names| {
|
@@ -67,18 +114,26 @@ fn convert_config(config: Hash) -> HashMap<String, String> {
|
|
67
114
|
.try_convert_to::<RString>()
|
68
115
|
.map_err(|e| VM::raise_ex(e))
|
69
116
|
.unwrap();
|
70
|
-
let
|
71
|
-
.try_convert_to::<Array>()
|
72
|
-
.map_err(|e| VM::raise_ex(e))
|
73
|
-
.unwrap();
|
117
|
+
let type_name_str = type_name_obj.to_str();
|
74
118
|
|
75
|
-
|
76
|
-
let
|
77
|
-
.try_convert_to::<
|
119
|
+
if let Some(column_type) = ColumnType::from_str(type_name_str) {
|
120
|
+
let array_obj = array_of_field_names
|
121
|
+
.try_convert_to::<Array>()
|
78
122
|
.map_err(|e| VM::raise_ex(e))
|
79
123
|
.unwrap();
|
80
124
|
|
81
|
-
|
125
|
+
for field_name in array_obj.into_iter() {
|
126
|
+
let field_name_obj = field_name
|
127
|
+
.try_convert_to::<RString>()
|
128
|
+
.map_err(|e| VM::raise_ex(e))
|
129
|
+
.unwrap();
|
130
|
+
|
131
|
+
hm.insert(field_name_obj.to_string(), column_type);
|
132
|
+
}
|
133
|
+
} else {
|
134
|
+
VM::raise(Class::from_existing("Exception"),
|
135
|
+
&format!("unknown rwtf_field_config type: {}", type_name_str));
|
136
|
+
unreachable!();
|
82
137
|
}
|
83
138
|
});
|
84
139
|
|
@@ -99,39 +154,98 @@ fn is_empty_array(v: &AnyObject) -> bool {
|
|
99
154
|
}
|
100
155
|
}
|
101
156
|
|
102
|
-
fn
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
157
|
+
fn is_number_and_too_large(v: &AnyObject, field_type: ColumnType) -> bool {
|
158
|
+
// First we have to try to cast `v` to a numeric type (Integer or Float)
|
159
|
+
// and then call to_i64/f64(). This will raise an exception if the number
|
160
|
+
// is too large to turn into a primitive.
|
161
|
+
let is_number_result = VM::protect(|| {
|
162
|
+
match v.try_convert_to::<Integer>() {
|
163
|
+
Ok(i) => {
|
164
|
+
let _ = i.to_i64(); // force a conversion
|
165
|
+
Boolean::new(true)
|
166
|
+
}
|
167
|
+
Err(_) => match v.try_convert_to::<Float>() {
|
168
|
+
Ok(f) => {
|
169
|
+
let _ = f.to_f64(); // force a conversion
|
170
|
+
Boolean::new(true)
|
171
|
+
}
|
172
|
+
Err(_) => Boolean::new(false)
|
173
|
+
}
|
174
|
+
}.to_any_object()
|
175
|
+
});
|
176
|
+
|
177
|
+
match is_number_result {
|
178
|
+
Ok(is_number) => {
|
179
|
+
// Here we know that no exception was raised during the attempted primitive conversion.
|
180
|
+
// We also know that `is_number` is a Boolean, so this unsafe cast is fine.
|
181
|
+
if unsafe { is_number.to::<Boolean>().to_bool() } {
|
182
|
+
match v.try_convert_to::<Integer>() {
|
183
|
+
Ok(i) => i.to_i64().abs() > field_type.max_integer(),
|
184
|
+
Err(_) => match v.try_convert_to::<Float>() {
|
185
|
+
Ok(f) => f.to_f64().abs() > field_type.max_float(),
|
186
|
+
Err(_) => false
|
187
|
+
}
|
188
|
+
}
|
189
|
+
} else {
|
190
|
+
false
|
191
|
+
}
|
192
|
+
}
|
193
|
+
Err(_) => {
|
194
|
+
VM::clear_error_info(); // clear ruby VM error register
|
195
|
+
true // this IS a number and it IS too large
|
108
196
|
}
|
109
197
|
}
|
110
198
|
}
|
111
199
|
|
112
|
-
fn add_points(
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
200
|
+
fn add_points(source: &Hash,
|
201
|
+
section_points_config: &HashMap<String, ColumnType>,
|
202
|
+
section_type: &str,
|
203
|
+
mut callback: impl FnMut(usize, &str, DataField)) {
|
204
|
+
let maybe_section_points = source
|
205
|
+
.at(&RString::new_utf8(section_type))
|
206
|
+
.try_convert_to::<Array>();
|
207
|
+
|
208
|
+
if let Ok(section_points) = maybe_section_points {
|
209
|
+
for (i, maybe_point) in section_points.into_iter().enumerate() {
|
210
|
+
let point = maybe_point
|
211
|
+
.try_convert_to::<Hash>()
|
122
212
|
.map_err(|e| VM::raise_ex(e))
|
123
213
|
.unwrap();
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
214
|
+
|
215
|
+
point.each(|k: AnyObject, v: AnyObject| {
|
216
|
+
let field_name_obj = k
|
217
|
+
.try_convert_to::<RString>()
|
218
|
+
.map_err(|e| VM::raise_ex(e))
|
219
|
+
.unwrap();
|
220
|
+
let name = field_name_obj.to_str();
|
221
|
+
|
222
|
+
if !name.is_empty() {
|
223
|
+
if let Some(field_type) = section_points_config.get(name) {
|
224
|
+
if !v.is_nil()
|
225
|
+
&& !is_empty_string(&v)
|
226
|
+
&& !is_empty_array(&v)
|
227
|
+
&& !is_number_and_too_large(&v, *field_type)
|
228
|
+
{
|
229
|
+
let data = match field_type {
|
230
|
+
ColumnType::LongFloat => DataField::LongFloat(any_to_float(v)),
|
231
|
+
ColumnType::ShortFloat => DataField::ShortFloat(any_to_float(v)),
|
232
|
+
ColumnType::Numbers => DataField::Number(any_to_int(v)),
|
233
|
+
ColumnType::Base64 => DataField::Base64(any_to_str(v).replace("\n", "")),
|
234
|
+
ColumnType::String => DataField::String(any_to_str(v)),
|
235
|
+
ColumnType::Bool => DataField::Bool(any_to_bool(v)),
|
236
|
+
ColumnType::IDs => DataField::IDs(any_to_ids(v)),
|
237
|
+
};
|
238
|
+
|
239
|
+
callback(i, name, data);
|
240
|
+
}
|
241
|
+
} else {
|
242
|
+
VM::raise(Module::from_existing("Tracklib").get_nested_class("UnknownFieldError"),
|
243
|
+
&format!("unknown {} field: {}", section_type, name));
|
244
|
+
unreachable!();
|
245
|
+
}
|
246
|
+
}
|
247
|
+
});
|
248
|
+
}
|
135
249
|
}
|
136
250
|
}
|
137
251
|
|
@@ -223,79 +337,21 @@ methods!(
|
|
223
337
|
RWTFile::new()
|
224
338
|
};
|
225
339
|
|
226
|
-
|
227
|
-
.
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
match field_type.as_str() {
|
234
|
-
"LongFloat" => DataField::LongFloat(any_to_float(v)),
|
235
|
-
"ShortFloat" => DataField::ShortFloat(any_to_float(v)),
|
236
|
-
"Number" => DataField::Number(any_to_int(v)),
|
237
|
-
"Base64" => DataField::Base64(any_to_str(v).replace("\n", "")),
|
238
|
-
"String" => DataField::String(any_to_str(v)),
|
239
|
-
"Bool" => DataField::Bool(any_to_bool(v)),
|
240
|
-
"IDs" => DataField::IDs(any_to_ids(v)),
|
241
|
-
_ => {
|
242
|
-
VM::raise(
|
243
|
-
Class::from_existing("Exception"),
|
244
|
-
&format!("unknown track_points type: {}", field_type),
|
245
|
-
);
|
246
|
-
unreachable!();
|
247
|
-
}
|
248
|
-
}
|
249
|
-
} else {
|
250
|
-
VM::raise(Module::from_existing("Tracklib").get_nested_class("UnknownFieldError"),
|
251
|
-
&format!("unknown track_points field: {}", k));
|
252
|
-
unreachable!();
|
253
|
-
};
|
254
|
-
|
255
|
-
rwtf.add_track_point(i, k, data)
|
256
|
-
.map_err(|e| {
|
257
|
-
VM::raise(Class::from_existing("Exception"), &format!("{}", e))
|
258
|
-
})
|
259
|
-
.unwrap();
|
260
|
-
});
|
261
|
-
}
|
262
|
-
|
263
|
-
let maybe_course_points = source
|
264
|
-
.at(&RString::new_utf8("course_points"))
|
265
|
-
.try_convert_to::<Array>();
|
266
|
-
|
267
|
-
if let Ok(course_points) = maybe_course_points {
|
268
|
-
add_points(course_points, |i, k, v| {
|
269
|
-
let data = if let Some(field_type) = course_points_config.get(k) {
|
270
|
-
match field_type.as_str() {
|
271
|
-
"LongFloat" => DataField::LongFloat(any_to_float(v)),
|
272
|
-
"ShortFloat" => DataField::ShortFloat(any_to_float(v)),
|
273
|
-
"Number" => DataField::Number(any_to_int(v)),
|
274
|
-
"Base64" => DataField::Base64(any_to_str(v).replace("\n", "")),
|
275
|
-
"String" => DataField::String(any_to_str(v)),
|
276
|
-
"Bool" => DataField::Bool(any_to_bool(v)),
|
277
|
-
"IDs" => DataField::IDs(any_to_ids(v)),
|
278
|
-
_ => {
|
279
|
-
VM::raise(
|
280
|
-
Class::from_existing("Exception"),
|
281
|
-
&format!("unknown course_points type: {}", field_type),
|
282
|
-
);
|
283
|
-
unreachable!();
|
284
|
-
}
|
285
|
-
}
|
286
|
-
} else {
|
287
|
-
VM::raise(Module::from_existing("Tracklib").get_nested_class("UnknownFieldError"),
|
288
|
-
&format!("unknown course_points field: {}", k));
|
289
|
-
unreachable!();
|
290
|
-
};
|
340
|
+
add_points(&source, &track_points_config, "track_points", |i, name, data| {
|
341
|
+
rwtf.add_track_point(i, name, data)
|
342
|
+
.map_err(|e| {
|
343
|
+
VM::raise(Class::from_existing("Exception"), &format!("{}", e))
|
344
|
+
})
|
345
|
+
.unwrap();
|
346
|
+
});
|
291
347
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
})
|
296
|
-
|
297
|
-
|
298
|
-
}
|
348
|
+
add_points(&source, &course_points_config, "course_points", |i, name, data| {
|
349
|
+
rwtf.add_course_point(i, name, data)
|
350
|
+
.map_err(|e| {
|
351
|
+
VM::raise(Class::from_existing("Exception"), &format!("{}", e))
|
352
|
+
})
|
353
|
+
.unwrap();
|
354
|
+
});
|
299
355
|
|
300
356
|
let inner = Inner { inner: rwtf };
|
301
357
|
Class::from_existing("RWTFile").wrap_data(inner, &*INNER_WRAPPER)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tracklib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Larkin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|