tracklib 0.1.6 → 0.1.7
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.
- 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
|