tracklib 0.1.7 → 0.3.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.
- checksums.yaml +5 -5
- data/Cargo.lock +95 -75
- data/Cargo.toml +1 -1
- data/lib/tracklib/version.rb +1 -1
- data/src/lib.rs +35 -385
- data/src/polyline.rs +95 -0
- data/src/rwtfile.rs +429 -0
- data/src/surface.rs +143 -0
- data/tracklib.gemspec +4 -1
- metadata +9 -7
data/src/rwtfile.rs
ADDED
@@ -0,0 +1,429 @@
|
|
1
|
+
use lazy_static::lazy_static;
|
2
|
+
use rutie::{
|
3
|
+
class, methods, wrappable_struct, AnyObject, Array, Boolean, Class, Encoding, Float, Hash,
|
4
|
+
Integer, Module, Object, RString, VM,
|
5
|
+
};
|
6
|
+
use rutie_serde::{ruby_class, rutie_serde_methods};
|
7
|
+
use std::collections::HashMap;
|
8
|
+
use std::convert::TryFrom;
|
9
|
+
use std::io::BufWriter;
|
10
|
+
use tracklib::{parse_rwtf, DataField, RWTFMetadata, RWTFile, TrackType};
|
11
|
+
use super::polyline;
|
12
|
+
use super::surface;
|
13
|
+
|
14
|
+
fn any_to_float(o: AnyObject) -> f64 {
|
15
|
+
match o.try_convert_to::<Float>() {
|
16
|
+
Ok(f) => f.to_f64(),
|
17
|
+
Err(float_e) => o
|
18
|
+
.try_convert_to::<Integer>()
|
19
|
+
.map_err(|_| VM::raise_ex(float_e))
|
20
|
+
.unwrap()
|
21
|
+
.to_i64() as f64,
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
fn any_to_int(o: AnyObject) -> i64 {
|
26
|
+
match o.try_convert_to::<Integer>() {
|
27
|
+
Ok(i) => i.to_i64(),
|
28
|
+
Err(int_e) => o
|
29
|
+
.try_convert_to::<Float>()
|
30
|
+
.map_err(|_| VM::raise_ex(int_e))
|
31
|
+
.unwrap()
|
32
|
+
.to_f64() as i64,
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
fn any_to_str(o: AnyObject) -> String {
|
37
|
+
o.try_convert_to::<RString>()
|
38
|
+
.map_err(|e| VM::raise_ex(e))
|
39
|
+
.unwrap()
|
40
|
+
.to_string()
|
41
|
+
}
|
42
|
+
|
43
|
+
fn any_to_bool(o: AnyObject) -> bool {
|
44
|
+
o.try_convert_to::<Boolean>()
|
45
|
+
.map_err(|e| VM::raise_ex(e))
|
46
|
+
.unwrap()
|
47
|
+
.to_bool()
|
48
|
+
}
|
49
|
+
|
50
|
+
fn any_to_ids(o: AnyObject) -> Vec<u64> {
|
51
|
+
o.try_convert_to::<Array>()
|
52
|
+
.map_err(|e| VM::raise_ex(e))
|
53
|
+
.unwrap()
|
54
|
+
.into_iter()
|
55
|
+
.map(|ele| {
|
56
|
+
ele.try_convert_to::<Integer>()
|
57
|
+
.map_err(|e| VM::raise_ex(e))
|
58
|
+
.unwrap()
|
59
|
+
.to_u64()
|
60
|
+
})
|
61
|
+
.collect()
|
62
|
+
}
|
63
|
+
|
64
|
+
#[derive(Debug, Copy, Clone)]
|
65
|
+
enum ColumnType {
|
66
|
+
Numbers,
|
67
|
+
LongFloat,
|
68
|
+
ShortFloat,
|
69
|
+
Base64,
|
70
|
+
String,
|
71
|
+
Bool,
|
72
|
+
IDs,
|
73
|
+
}
|
74
|
+
|
75
|
+
impl ColumnType {
|
76
|
+
fn from_str(name: &str) -> Option<Self> {
|
77
|
+
match name {
|
78
|
+
"Number" => Some(ColumnType::Numbers),
|
79
|
+
"LongFloat" => Some(ColumnType::LongFloat),
|
80
|
+
"ShortFloat" => Some(ColumnType::ShortFloat),
|
81
|
+
"Base64" => Some(ColumnType::Base64),
|
82
|
+
"String" => Some(ColumnType::String),
|
83
|
+
"Bool" => Some(ColumnType::Bool),
|
84
|
+
"IDs" => Some(ColumnType::IDs),
|
85
|
+
_ => None,
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
fn exponent(&self) -> u8 {
|
90
|
+
match self {
|
91
|
+
ColumnType::Numbers => 48,
|
92
|
+
ColumnType::LongFloat => 24,
|
93
|
+
ColumnType::ShortFloat => 38,
|
94
|
+
_ => {
|
95
|
+
VM::raise(
|
96
|
+
Class::from_existing("Exception"),
|
97
|
+
&format!("can't handle numeric value for non-numeric field"),
|
98
|
+
);
|
99
|
+
unreachable!();
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
fn max_integer(&self) -> i64 {
|
105
|
+
2i64.pow(u32::from(self.exponent()))
|
106
|
+
}
|
107
|
+
|
108
|
+
fn max_float(&self) -> f64 {
|
109
|
+
2f64.powi(i32::from(self.exponent()))
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
fn convert_config(config: Hash) -> HashMap<String, ColumnType> {
|
114
|
+
let mut hm = HashMap::new();
|
115
|
+
|
116
|
+
config.each(|rwtf_type_name, array_of_field_names| {
|
117
|
+
let type_name_obj = rwtf_type_name
|
118
|
+
.try_convert_to::<RString>()
|
119
|
+
.map_err(|e| VM::raise_ex(e))
|
120
|
+
.unwrap();
|
121
|
+
let type_name_str = type_name_obj.to_str();
|
122
|
+
|
123
|
+
if let Some(column_type) = ColumnType::from_str(type_name_str) {
|
124
|
+
let array_obj = array_of_field_names
|
125
|
+
.try_convert_to::<Array>()
|
126
|
+
.map_err(|e| VM::raise_ex(e))
|
127
|
+
.unwrap();
|
128
|
+
|
129
|
+
for field_name in array_obj.into_iter() {
|
130
|
+
let field_name_obj = field_name
|
131
|
+
.try_convert_to::<RString>()
|
132
|
+
.map_err(|e| VM::raise_ex(e))
|
133
|
+
.unwrap();
|
134
|
+
|
135
|
+
hm.insert(field_name_obj.to_string(), column_type);
|
136
|
+
}
|
137
|
+
} else {
|
138
|
+
VM::raise(
|
139
|
+
Class::from_existing("Exception"),
|
140
|
+
&format!("unknown rwtf_field_config type: {}", type_name_str),
|
141
|
+
);
|
142
|
+
unreachable!();
|
143
|
+
}
|
144
|
+
});
|
145
|
+
|
146
|
+
hm
|
147
|
+
}
|
148
|
+
|
149
|
+
fn is_empty_string(v: &AnyObject) -> bool {
|
150
|
+
match v.try_convert_to::<RString>() {
|
151
|
+
Ok(s) => s.to_str().is_empty(),
|
152
|
+
Err(_) => false,
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
fn is_empty_array(v: &AnyObject) -> bool {
|
157
|
+
match v.try_convert_to::<Array>() {
|
158
|
+
Ok(a) => a.length() == 0,
|
159
|
+
Err(_) => false,
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
fn is_number_and_too_large(v: &AnyObject, field_type: ColumnType) -> bool {
|
164
|
+
// First we have to try to cast `v` to a numeric type (Integer or Float)
|
165
|
+
// and then call to_i64/f64(). This will raise an exception if the number
|
166
|
+
// is too large to turn into a primitive.
|
167
|
+
let is_number_result = VM::protect(|| {
|
168
|
+
match v.try_convert_to::<Integer>() {
|
169
|
+
Ok(i) => {
|
170
|
+
let _ = i.to_i64(); // force a conversion
|
171
|
+
Boolean::new(true)
|
172
|
+
}
|
173
|
+
Err(_) => match v.try_convert_to::<Float>() {
|
174
|
+
Ok(f) => {
|
175
|
+
let _ = f.to_f64(); // force a conversion
|
176
|
+
Boolean::new(true)
|
177
|
+
}
|
178
|
+
Err(_) => Boolean::new(false),
|
179
|
+
},
|
180
|
+
}
|
181
|
+
.to_any_object()
|
182
|
+
});
|
183
|
+
|
184
|
+
match is_number_result {
|
185
|
+
Ok(is_number) => {
|
186
|
+
// Here we know that no exception was raised during the attempted primitive conversion.
|
187
|
+
// We also know that `is_number` is a Boolean, so this unsafe cast is fine.
|
188
|
+
if unsafe { is_number.to::<Boolean>().to_bool() } {
|
189
|
+
match v.try_convert_to::<Integer>() {
|
190
|
+
Ok(i) => i.to_i64().abs() > field_type.max_integer(),
|
191
|
+
Err(_) => match v.try_convert_to::<Float>() {
|
192
|
+
Ok(f) => f.to_f64().abs() > field_type.max_float(),
|
193
|
+
Err(_) => false,
|
194
|
+
},
|
195
|
+
}
|
196
|
+
} else {
|
197
|
+
false
|
198
|
+
}
|
199
|
+
}
|
200
|
+
Err(_) => {
|
201
|
+
VM::clear_error_info(); // clear ruby VM error register
|
202
|
+
true // this IS a number and it IS too large
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
fn add_points(
|
208
|
+
source: &Hash,
|
209
|
+
section_points_config: &HashMap<String, ColumnType>,
|
210
|
+
section_type: &str,
|
211
|
+
mut callback: impl FnMut(usize, &str, DataField),
|
212
|
+
) {
|
213
|
+
let maybe_section_points = source
|
214
|
+
.at(&RString::new_utf8(section_type))
|
215
|
+
.try_convert_to::<Array>();
|
216
|
+
|
217
|
+
if let Ok(section_points) = maybe_section_points {
|
218
|
+
for (i, maybe_point) in section_points.into_iter().enumerate() {
|
219
|
+
let point = maybe_point
|
220
|
+
.try_convert_to::<Hash>()
|
221
|
+
.map_err(|e| VM::raise_ex(e))
|
222
|
+
.unwrap();
|
223
|
+
|
224
|
+
point.each(|k: AnyObject, v: AnyObject| {
|
225
|
+
let field_name_obj = k
|
226
|
+
.try_convert_to::<RString>()
|
227
|
+
.map_err(|e| VM::raise_ex(e))
|
228
|
+
.unwrap();
|
229
|
+
let name = field_name_obj.to_str();
|
230
|
+
|
231
|
+
if !name.is_empty() {
|
232
|
+
if let Some(field_type) = section_points_config.get(name) {
|
233
|
+
if !v.is_nil()
|
234
|
+
&& !is_empty_string(&v)
|
235
|
+
&& !is_empty_array(&v)
|
236
|
+
&& !is_number_and_too_large(&v, *field_type)
|
237
|
+
{
|
238
|
+
let data = match field_type {
|
239
|
+
ColumnType::LongFloat => DataField::LongFloat(any_to_float(v)),
|
240
|
+
ColumnType::ShortFloat => DataField::ShortFloat(any_to_float(v)),
|
241
|
+
ColumnType::Numbers => DataField::Number(any_to_int(v)),
|
242
|
+
ColumnType::Base64 => {
|
243
|
+
DataField::Base64(any_to_str(v).replace("\n", ""))
|
244
|
+
}
|
245
|
+
ColumnType::String => DataField::String(any_to_str(v)),
|
246
|
+
ColumnType::Bool => DataField::Bool(any_to_bool(v)),
|
247
|
+
ColumnType::IDs => DataField::IDs(any_to_ids(v)),
|
248
|
+
};
|
249
|
+
|
250
|
+
callback(i, name, data);
|
251
|
+
}
|
252
|
+
} else {
|
253
|
+
VM::raise(
|
254
|
+
Module::from_existing("Tracklib").get_nested_class("UnknownFieldError"),
|
255
|
+
&format!("unknown {} field: {}", section_type, name),
|
256
|
+
);
|
257
|
+
unreachable!();
|
258
|
+
}
|
259
|
+
}
|
260
|
+
});
|
261
|
+
}
|
262
|
+
}
|
263
|
+
}
|
264
|
+
|
265
|
+
pub struct Inner {
|
266
|
+
inner: RWTFile,
|
267
|
+
}
|
268
|
+
|
269
|
+
wrappable_struct!(Inner, InnerWrapper, INNER_WRAPPER);
|
270
|
+
|
271
|
+
class!(RubyRWTFile);
|
272
|
+
|
273
|
+
methods!(
|
274
|
+
RubyRWTFile,
|
275
|
+
itself,
|
276
|
+
fn rwtf_from_bytes(bytes: RString) -> AnyObject {
|
277
|
+
let source = bytes.map_err(|e| VM::raise_ex(e)).unwrap();
|
278
|
+
let (_, rwtf) = parse_rwtf(source.to_bytes_unchecked())
|
279
|
+
.map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
|
280
|
+
.unwrap();
|
281
|
+
let inner = Inner { inner: rwtf };
|
282
|
+
|
283
|
+
Class::from_existing("RWTFile").wrap_data(inner, &*INNER_WRAPPER)
|
284
|
+
}
|
285
|
+
|
286
|
+
fn rwtf_to_bytes() -> RString {
|
287
|
+
let mut writer = BufWriter::new(Vec::new());
|
288
|
+
itself
|
289
|
+
.get_data(&*INNER_WRAPPER)
|
290
|
+
.inner
|
291
|
+
.write(&mut writer)
|
292
|
+
.map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
|
293
|
+
.unwrap();
|
294
|
+
|
295
|
+
let encoding = Encoding::find("ASCII-8BIT")
|
296
|
+
.map_err(|e| VM::raise_ex(e))
|
297
|
+
.unwrap();
|
298
|
+
|
299
|
+
let buf = writer
|
300
|
+
.into_inner()
|
301
|
+
.map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
|
302
|
+
.unwrap();
|
303
|
+
|
304
|
+
RString::from_bytes(&buf, &encoding)
|
305
|
+
}
|
306
|
+
|
307
|
+
fn rwtf_from_hash(input: Hash, config_input: Hash, metadata: Hash) -> AnyObject {
|
308
|
+
let source = input.map_err(|e| VM::raise_ex(e)).unwrap();
|
309
|
+
let config = config_input.map_err(|e| VM::raise_ex(e)).unwrap();
|
310
|
+
let track_points_config = convert_config(
|
311
|
+
config
|
312
|
+
.at(&RString::new_utf8("track_points"))
|
313
|
+
.try_convert_to::<Hash>()
|
314
|
+
.map_err(|e| VM::raise_ex(e))
|
315
|
+
.unwrap(),
|
316
|
+
);
|
317
|
+
let course_points_config = convert_config(
|
318
|
+
config
|
319
|
+
.at(&RString::new_utf8("course_points"))
|
320
|
+
.try_convert_to::<Hash>()
|
321
|
+
.map_err(|e| VM::raise_ex(e))
|
322
|
+
.unwrap(),
|
323
|
+
);
|
324
|
+
|
325
|
+
let mut rwtf = if let Some(md) = metadata.ok() {
|
326
|
+
let tt_metadata = md
|
327
|
+
.at(&RString::new_utf8("track_type"))
|
328
|
+
.try_convert_to::<Hash>()
|
329
|
+
.map_err(|e| VM::raise_ex(e))
|
330
|
+
.unwrap();
|
331
|
+
|
332
|
+
let track_type = tt_metadata
|
333
|
+
.at(&RString::new_utf8("type"))
|
334
|
+
.try_convert_to::<RString>()
|
335
|
+
.map_err(|e| VM::raise_ex(e))
|
336
|
+
.unwrap();
|
337
|
+
|
338
|
+
let id = u32::try_from(
|
339
|
+
tt_metadata
|
340
|
+
.at(&RString::new_utf8("id"))
|
341
|
+
.try_convert_to::<Integer>()
|
342
|
+
.map_err(|e| VM::raise_ex(e))
|
343
|
+
.unwrap()
|
344
|
+
.to_u64(),
|
345
|
+
)
|
346
|
+
.map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
|
347
|
+
.unwrap();
|
348
|
+
|
349
|
+
let tt = match track_type.to_str() {
|
350
|
+
"trip" => TrackType::Trip(id),
|
351
|
+
"route" => TrackType::Route(id),
|
352
|
+
"segment" => TrackType::Segment(id),
|
353
|
+
_ => {
|
354
|
+
VM::raise(
|
355
|
+
Class::from_existing("Exception"),
|
356
|
+
&format!("unknown track_type metadata: {}", track_type.to_str()),
|
357
|
+
);
|
358
|
+
unreachable!();
|
359
|
+
}
|
360
|
+
};
|
361
|
+
|
362
|
+
RWTFile::with_track_type(tt)
|
363
|
+
} else {
|
364
|
+
RWTFile::new()
|
365
|
+
};
|
366
|
+
|
367
|
+
add_points(
|
368
|
+
&source,
|
369
|
+
&track_points_config,
|
370
|
+
"track_points",
|
371
|
+
|i, name, data| {
|
372
|
+
rwtf.add_track_point(i, name, data)
|
373
|
+
.map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
|
374
|
+
.unwrap();
|
375
|
+
},
|
376
|
+
);
|
377
|
+
|
378
|
+
add_points(
|
379
|
+
&source,
|
380
|
+
&course_points_config,
|
381
|
+
"course_points",
|
382
|
+
|i, name, data| {
|
383
|
+
rwtf.add_course_point(i, name, data)
|
384
|
+
.map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
|
385
|
+
.unwrap();
|
386
|
+
},
|
387
|
+
);
|
388
|
+
|
389
|
+
let inner = Inner { inner: rwtf };
|
390
|
+
Class::from_existing("RWTFile").wrap_data(inner, &*INNER_WRAPPER)
|
391
|
+
}
|
392
|
+
|
393
|
+
fn rwtf_simplify_track_points(surface_mapping: surface::RubySurfaceMapping,
|
394
|
+
tolerance: Float,
|
395
|
+
encode_options: polyline::RubyFieldEncodeOptionsVec) -> RString {
|
396
|
+
let track_points = &itself.get_data(&*INNER_WRAPPER).inner.track_points;
|
397
|
+
let surface_mapping_container = surface_mapping.map_err(|e| VM::raise_ex(e)).unwrap();
|
398
|
+
let mapping = surface_mapping_container.inner();
|
399
|
+
let tol = tolerance.map_err(|e| VM::raise_ex(e)).unwrap().to_f64();
|
400
|
+
let encode_options_container = encode_options.map_err(|e| VM::raise_ex(e)).unwrap();
|
401
|
+
let enc_opts = encode_options_container.inner();
|
402
|
+
|
403
|
+
RString::new_utf8(&track_points.simplify_and_encode(mapping, tol, enc_opts))
|
404
|
+
}
|
405
|
+
|
406
|
+
fn rwtf_inspect() -> RString {
|
407
|
+
let rwtf = &itself.get_data(&*INNER_WRAPPER).inner;
|
408
|
+
|
409
|
+
RString::new_utf8(&format!(
|
410
|
+
"RWTFile<track_points: {}, course_points: {}>",
|
411
|
+
rwtf.track_points.len(),
|
412
|
+
rwtf.course_points.len()
|
413
|
+
))
|
414
|
+
}
|
415
|
+
);
|
416
|
+
|
417
|
+
rutie_serde_methods!(
|
418
|
+
RubyRWTFile,
|
419
|
+
itself,
|
420
|
+
ruby_class!(Exception),
|
421
|
+
|
422
|
+
fn rwtf_to_hash() -> &RWTFile {
|
423
|
+
&itself.get_data(&*INNER_WRAPPER).inner
|
424
|
+
}
|
425
|
+
|
426
|
+
fn rwtf_metadata() -> &RWTFMetadata {
|
427
|
+
&itself.get_data(&*INNER_WRAPPER).inner.metadata()
|
428
|
+
}
|
429
|
+
);
|
data/src/surface.rs
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
use lazy_static::lazy_static;
|
2
|
+
use rutie::{
|
3
|
+
class, methods, wrappable_struct, AnyObject, Array, Class, Float, Integer, NilClass, Object,
|
4
|
+
RString, VerifiedObject, VM,
|
5
|
+
};
|
6
|
+
use tracklib::{RoadClassMapping, SurfaceMapping};
|
7
|
+
|
8
|
+
pub struct RoadClassInner {
|
9
|
+
inner: RoadClassMapping,
|
10
|
+
}
|
11
|
+
|
12
|
+
wrappable_struct!(
|
13
|
+
RoadClassInner,
|
14
|
+
RoadClassInnerWrapper,
|
15
|
+
ROAD_CLASS_INNER_WRAPPER
|
16
|
+
);
|
17
|
+
|
18
|
+
class!(RubyRoadClassMapping);
|
19
|
+
|
20
|
+
methods!(
|
21
|
+
RubyRoadClassMapping,
|
22
|
+
itself,
|
23
|
+
|
24
|
+
fn road_class_mapping_new(bbox_array: Array) -> AnyObject {
|
25
|
+
let bbox_vec: Vec<f64> = bbox_array
|
26
|
+
.map_err(|e| VM::raise_ex(e))
|
27
|
+
.unwrap()
|
28
|
+
.into_iter()
|
29
|
+
.map(|ele| match ele.try_convert_to::<Float>() {
|
30
|
+
Ok(f) => f.to_f64(),
|
31
|
+
Err(float_e) => ele
|
32
|
+
.try_convert_to::<Integer>()
|
33
|
+
.map_err(|_| VM::raise_ex(float_e))
|
34
|
+
.unwrap()
|
35
|
+
.to_i32()
|
36
|
+
.into(),
|
37
|
+
})
|
38
|
+
.collect();
|
39
|
+
if bbox_vec.len() != 4 {
|
40
|
+
VM::raise(
|
41
|
+
Class::from_existing("Exception"),
|
42
|
+
"BBOX Array len must be 4",
|
43
|
+
);
|
44
|
+
}
|
45
|
+
let bbox = [bbox_vec[0], bbox_vec[1], bbox_vec[2], bbox_vec[3]];
|
46
|
+
|
47
|
+
let inner = RoadClassInner {
|
48
|
+
inner: tracklib::RoadClassMapping::new(bbox),
|
49
|
+
};
|
50
|
+
|
51
|
+
Class::from_existing("TracklibRoadClassMapping").wrap_data(inner, &*ROAD_CLASS_INNER_WRAPPER)
|
52
|
+
}
|
53
|
+
|
54
|
+
fn road_class_mapping_add_road_class(road_class_id: Integer, surface_id: Integer) -> NilClass {
|
55
|
+
let rc_id = road_class_id.map_err(|e| VM::raise_ex(e)).unwrap().to_i64();
|
56
|
+
let s_id = surface_id.map_err(|e| VM::raise_ex(e)).unwrap().to_i64();
|
57
|
+
let mapping = &mut itself.get_data_mut(&*ROAD_CLASS_INNER_WRAPPER).inner;
|
58
|
+
mapping.add_road_class(rc_id, s_id);
|
59
|
+
|
60
|
+
NilClass::new()
|
61
|
+
}
|
62
|
+
|
63
|
+
fn road_class_mapping_to_s() -> RString {
|
64
|
+
let mapping = &itself.get_data(&*ROAD_CLASS_INNER_WRAPPER).inner;
|
65
|
+
|
66
|
+
RString::new_utf8(&format!("{:?}", mapping))
|
67
|
+
}
|
68
|
+
);
|
69
|
+
|
70
|
+
impl VerifiedObject for RubyRoadClassMapping {
|
71
|
+
fn is_correct_type<T: Object>(object: &T) -> bool {
|
72
|
+
Class::from_existing("TracklibRoadClassMapping").case_equals(object)
|
73
|
+
}
|
74
|
+
|
75
|
+
fn error_message() -> &'static str {
|
76
|
+
"Error converting to RoadClassMapping"
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
pub struct SurfaceInner {
|
81
|
+
inner: SurfaceMapping,
|
82
|
+
}
|
83
|
+
|
84
|
+
wrappable_struct!(SurfaceInner, SurfaceInnerWrapper, SURFACE_INNER_WRAPPER);
|
85
|
+
|
86
|
+
class!(RubySurfaceMapping);
|
87
|
+
|
88
|
+
methods!(
|
89
|
+
RubySurfaceMapping,
|
90
|
+
itself,
|
91
|
+
|
92
|
+
fn surface_mapping_new(unknown_surface_id: Integer) -> AnyObject {
|
93
|
+
let id = unknown_surface_id
|
94
|
+
.map_err(|e| VM::raise_ex(e))
|
95
|
+
.unwrap()
|
96
|
+
.to_i64();
|
97
|
+
let inner = SurfaceInner {
|
98
|
+
inner: tracklib::SurfaceMapping::new(id),
|
99
|
+
};
|
100
|
+
|
101
|
+
Class::from_existing("TracklibSurfaceMapping").wrap_data(inner, &*SURFACE_INNER_WRAPPER)
|
102
|
+
}
|
103
|
+
|
104
|
+
fn surface_mapping_add_surface(surface_id: Integer, group: RString) -> NilClass {
|
105
|
+
let id = surface_id.map_err(|e| VM::raise_ex(e)).unwrap().to_i64();
|
106
|
+
let group_name = group.map_err(|e| VM::raise_ex(e)).unwrap().to_string();
|
107
|
+
let mapping = &mut itself.get_data_mut(&*SURFACE_INNER_WRAPPER).inner;
|
108
|
+
mapping.add_surface(id, group_name);
|
109
|
+
|
110
|
+
NilClass::new()
|
111
|
+
}
|
112
|
+
|
113
|
+
fn surface_mapping_add_road_class_mapping(road_class_mapping: RubyRoadClassMapping) -> NilClass {
|
114
|
+
let rcm = road_class_mapping.map_err(|e| VM::raise_ex(e)).unwrap();
|
115
|
+
let mapping = &mut itself.get_data_mut(&*SURFACE_INNER_WRAPPER).inner;
|
116
|
+
let road_class = &rcm.get_data(&*ROAD_CLASS_INNER_WRAPPER).inner;
|
117
|
+
mapping.add_road_class_mapping(road_class.clone());
|
118
|
+
|
119
|
+
NilClass::new()
|
120
|
+
}
|
121
|
+
|
122
|
+
fn surface_mapping_to_s() -> RString {
|
123
|
+
let mapping = &itself.get_data(&*SURFACE_INNER_WRAPPER).inner;
|
124
|
+
|
125
|
+
RString::new_utf8(&format!("{:?}", mapping))
|
126
|
+
}
|
127
|
+
);
|
128
|
+
|
129
|
+
impl RubySurfaceMapping {
|
130
|
+
pub fn inner(&self) -> &SurfaceMapping {
|
131
|
+
&self.get_data(&*SURFACE_INNER_WRAPPER).inner
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
impl VerifiedObject for RubySurfaceMapping {
|
136
|
+
fn is_correct_type<T: Object>(object: &T) -> bool {
|
137
|
+
Class::from_existing("TracklibSurfaceMapping").case_equals(object)
|
138
|
+
}
|
139
|
+
|
140
|
+
fn error_message() -> &'static str {
|
141
|
+
"Error converting to SurfaceMapping"
|
142
|
+
}
|
143
|
+
}
|
data/tracklib.gemspec
CHANGED
@@ -20,7 +20,10 @@ Gem::Specification.new do |spec|
|
|
20
20
|
"lib/tracklib/version.rb",
|
21
21
|
"Cargo.toml",
|
22
22
|
"Cargo.lock",
|
23
|
-
"src/lib.rs"
|
23
|
+
"src/lib.rs",
|
24
|
+
"src/polyline.rs",
|
25
|
+
"src/rwtfile.rs",
|
26
|
+
"src/surface.rs"]
|
24
27
|
|
25
28
|
spec.require_paths = ["lib"]
|
26
29
|
spec.extensions = ["ext/Rakefile"]
|
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.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Larkin
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -82,13 +82,16 @@ files:
|
|
82
82
|
- lib/tracklib.rb
|
83
83
|
- lib/tracklib/version.rb
|
84
84
|
- src/lib.rs
|
85
|
+
- src/polyline.rs
|
86
|
+
- src/rwtfile.rs
|
87
|
+
- src/surface.rs
|
85
88
|
- tracklib.gemspec
|
86
89
|
homepage: https://ridewithgps.com
|
87
90
|
licenses:
|
88
91
|
- Apache-2.0
|
89
92
|
- MIT
|
90
93
|
metadata: {}
|
91
|
-
post_install_message:
|
94
|
+
post_install_message:
|
92
95
|
rdoc_options: []
|
93
96
|
require_paths:
|
94
97
|
- lib
|
@@ -103,9 +106,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
106
|
- !ruby/object:Gem::Version
|
104
107
|
version: '0'
|
105
108
|
requirements: []
|
106
|
-
|
107
|
-
|
108
|
-
signing_key:
|
109
|
+
rubygems_version: 3.2.16
|
110
|
+
signing_key:
|
109
111
|
specification_version: 4
|
110
112
|
summary: tracklib
|
111
113
|
test_files: []
|