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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 51bc0c50cee5c08e2a0ab5a48e5a9d4cd00f4db1
4
- data.tar.gz: 496ec85199832aa9cd953d0ef621a5508d03bef0
3
+ metadata.gz: 544377b466a27f1adc1885db2ae638e9c94e14f3
4
+ data.tar.gz: f4e80d1783f605692d0045da784e27a011e432ea
5
5
  SHA512:
6
- metadata.gz: 9ebff64b608756ac55476fc9661249419e746539753e5bcde585f546b08e9a665bb492118b1b2d882670769456b23d80b719952f67b3efcf591b7c49950bcf81
7
- data.tar.gz: e0cdf446ca0fc4f386f186bb4655509a58a4d43e5e41ca9e43f2c8183afdd1d962eeb457bbb5f88dcfa9dcab7165bed896b85e67ed22fb0de7489890bc9da173
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.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
124
- "rutie-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
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.5.6"
136
- source = "registry+https://github.com/rust-lang/crates.io-index"
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 = "registry+https://github.com/rust-lang/crates.io-index"
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.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
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.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5386200cd74705d2f0f6f5076d833ed26070240dea32b778807af38159900284"
245
- "checksum rutie-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d43d8aea0107683e12860daed2e0fa7c36702927c181ecd270552c39dcc94b27"
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 = "0.5"
18
- rutie-serde = "0.1"
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"
@@ -1,3 +1,3 @@
1
1
  module Tracklib
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
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(f) => f.to_i64(),
26
- Err(float_e) => o
25
+ Ok(i) => i.to_i64(),
26
+ Err(int_e) => o
27
27
  .try_convert_to::<Float>()
28
- .map_err(|_| VM::raise_ex(float_e))
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
- fn convert_config(config: Hash) -> HashMap<String, String> {
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 array_obj = array_of_field_names
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
- for field_name in array_obj.into_iter() {
76
- let field_name_obj = field_name
77
- .try_convert_to::<RString>()
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
- hm.insert(field_name_obj.to_string(), type_name_obj.to_string());
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 is_number_too_large(v: &AnyObject) -> bool {
103
- match v.try_convert_to::<Integer>() {
104
- Ok(i) => i.to_i64().abs() > 2i64.pow(48),
105
- Err(_) => match v.try_convert_to::<Float>() {
106
- Ok(f) => f.to_f64().abs() > 2f64.powi(48),
107
- Err(_) => false
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(points: Array, mut callback: impl FnMut(usize, &str, AnyObject)) {
113
- for (i, maybe_point) in points.into_iter().enumerate() {
114
- let point = maybe_point
115
- .try_convert_to::<Hash>()
116
- .map_err(|e| VM::raise_ex(e))
117
- .unwrap();
118
-
119
- point.each(|k, v| {
120
- let field_name_obj = k
121
- .try_convert_to::<RString>()
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
- let name = field_name_obj.to_str();
125
-
126
- if !v.is_nil()
127
- && !name.is_empty()
128
- && !is_empty_string(&v)
129
- && !is_empty_array(&v)
130
- && !is_number_too_large(&v)
131
- {
132
- callback(i, name, v);
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
- let maybe_track_points = source
227
- .at(&RString::new_utf8("track_points"))
228
- .try_convert_to::<Array>();
229
-
230
- if let Ok(track_points) = maybe_track_points {
231
- add_points(track_points, |i, k, v| {
232
- let data = if let Some(field_type) = track_points_config.get(k) {
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
- rwtf.add_course_point(i, k, data)
293
- .map_err(|e| {
294
- VM::raise(Class::from_existing("Exception"), &format!("{}", e))
295
- })
296
- .unwrap();
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.6
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-19 00:00:00.000000000 Z
11
+ date: 2019-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec