tracklib 0.1.4 → 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.
data/src/lib.rs CHANGED
@@ -1,348 +1,44 @@
1
- use std::collections::{HashMap};
2
- use std::convert::{TryFrom};
3
- use std::io::{BufWriter};
4
- use lazy_static::lazy_static;
5
- use rutie::{
6
- class, methods, wrappable_struct, AnyObject, Array, Boolean, Class, Encoding, Float, Hash, Integer,
7
- Object, RString, VM,
8
- };
9
- use rutie_serde::{ruby_class, rutie_serde_methods};
10
- use tracklib::{parse_rwtf, DataField, RWTFile, RWTFMetadata, TrackType};
1
+ mod polyline;
2
+ mod rwtfile;
3
+ mod surface;
11
4
 
12
- fn any_to_float(o: AnyObject) -> f64 {
13
- match o.try_convert_to::<Float>() {
14
- Ok(f) => f.to_f64(),
15
- Err(float_e) => o
16
- .try_convert_to::<Integer>()
17
- .map_err(|_| VM::raise_ex(float_e))
18
- .unwrap()
19
- .to_i64() as f64,
20
- }
21
- }
22
-
23
- fn any_to_int(o: AnyObject) -> i64 {
24
- match o.try_convert_to::<Integer>() {
25
- Ok(f) => f.to_i64(),
26
- Err(float_e) => o
27
- .try_convert_to::<Float>()
28
- .map_err(|_| VM::raise_ex(float_e))
29
- .unwrap()
30
- .to_f64() as i64,
31
- }
32
- }
33
-
34
- fn any_to_str(o: AnyObject) -> String {
35
- o.try_convert_to::<RString>()
36
- .map_err(|e| VM::raise_ex(e))
37
- .unwrap()
38
- .to_string()
39
- }
40
-
41
- fn any_to_bool(o: AnyObject) -> bool {
42
- o.try_convert_to::<Boolean>()
43
- .map_err(|e| VM::raise_ex(e))
44
- .unwrap()
45
- .to_bool()
46
- }
47
-
48
- fn any_to_ids(o: AnyObject) -> Vec<u64> {
49
- o.try_convert_to::<Array>()
50
- .map_err(|e| VM::raise_ex(e))
51
- .unwrap()
52
- .into_iter()
53
- .map(|ele| {
54
- ele.try_convert_to::<Integer>()
55
- .map_err(|e| VM::raise_ex(e))
56
- .unwrap()
57
- .to_u64()
58
- })
59
- .collect()
60
- }
61
-
62
- fn convert_config(config: Hash) -> HashMap<String, String> {
63
- let mut hm = HashMap::new();
64
-
65
- config.each(|rwtf_type_name, array_of_field_names| {
66
- let type_name_obj = rwtf_type_name
67
- .try_convert_to::<RString>()
68
- .map_err(|e| VM::raise_ex(e))
69
- .unwrap();
70
- let array_obj = array_of_field_names
71
- .try_convert_to::<Array>()
72
- .map_err(|e| VM::raise_ex(e))
73
- .unwrap();
74
-
75
- for field_name in array_obj.into_iter() {
76
- let field_name_obj = field_name
77
- .try_convert_to::<RString>()
78
- .map_err(|e| VM::raise_ex(e))
79
- .unwrap();
80
-
81
- hm.insert(field_name_obj.to_string(), type_name_obj.to_string());
82
- }
83
- });
84
-
85
- hm
86
- }
87
-
88
- fn add_points(points: Array, mut callback: impl FnMut(usize, &str, AnyObject)) {
89
- for (i, maybe_point) in points.into_iter().enumerate() {
90
- let point = maybe_point
91
- .try_convert_to::<Hash>()
92
- .map_err(|e| VM::raise_ex(e))
93
- .unwrap();
94
-
95
- point.each(|k, v| {
96
- let field_name_obj = k
97
- .try_convert_to::<RString>()
98
- .map_err(|e| VM::raise_ex(e))
99
- .unwrap();
100
- let name = field_name_obj.to_str();
101
- let mut store_field = true;
102
-
103
- if v.is_nil() {
104
- store_field = false;
105
- }
106
-
107
- if name.is_empty() {
108
- store_field = false;
109
- }
110
-
111
- match v.try_convert_to::<RString>() {
112
- Ok(s) => if s.to_str().is_empty() {
113
- store_field = false;
114
- }
115
- Err(_) => {}
116
- }
117
-
118
- match v.try_convert_to::<Array>() {
119
- Ok(a) => if a.length() == 0 {
120
- store_field = false;
121
- }
122
- Err(_) => {}
123
- }
124
-
125
- match v.try_convert_to::<Integer>() {
126
- Ok(i) => if i.to_i64().abs() > 2i64.pow(48) {
127
- store_field = false;
128
- }
129
- Err(_) => match v.try_convert_to::<Float>() {
130
- Ok(f) => if f.to_f64().abs() > 2f64.powi(48) {
131
- store_field = false;
132
- }
133
- Err(_) => {}
134
- }
135
- }
136
-
137
- if store_field {
138
- callback(i, name, v);
139
- }
140
- });
141
- }
142
- }
143
-
144
- pub struct Inner {
145
- inner: RWTFile,
146
- }
147
-
148
- wrappable_struct!(Inner, InnerWrapper, INNER_WRAPPER);
149
-
150
- class!(RubyRWTFile);
151
-
152
- methods!(
153
- RubyRWTFile,
154
- itself,
155
-
156
- fn rwtf_from_bytes(bytes: RString) -> AnyObject {
157
- let source = bytes.map_err(|e| VM::raise_ex(e)).unwrap();
158
- let (_, rwtf) = parse_rwtf(source.to_bytes_unchecked())
159
- .map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
160
- .unwrap();
161
- let inner = Inner { inner: rwtf };
162
-
163
- Class::from_existing("RWTFile").wrap_data(inner, &*INNER_WRAPPER)
164
- }
165
-
166
- fn rwtf_to_bytes() -> RString {
167
- let mut writer = BufWriter::new(Vec::new());
168
- itself.get_data(&*INNER_WRAPPER).inner.write(&mut writer)
169
- .map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
170
- .unwrap();
171
-
172
- let encoding = Encoding::find("ASCII-8BIT")
173
- .map_err(|e| VM::raise_ex(e))
174
- .unwrap();
175
-
176
- let buf = writer.into_inner()
177
- .map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
178
- .unwrap();
179
-
180
- RString::from_bytes(&buf, &encoding)
181
- }
182
-
183
- fn rwtf_from_hash(input: Hash, config_input: Hash, metadata: Hash) -> AnyObject {
184
- let source = input.map_err(|e| VM::raise_ex(e)).unwrap();
185
- let config = config_input.map_err(|e| VM::raise_ex(e)).unwrap();
186
- let track_points_config = convert_config(config.at(&RString::new_utf8("track_points"))
187
- .try_convert_to::<Hash>()
188
- .map_err(|e| VM::raise_ex(e))
189
- .unwrap());
190
- let course_points_config = convert_config(config.at(&RString::new_utf8("course_points"))
191
- .try_convert_to::<Hash>()
192
- .map_err(|e| VM::raise_ex(e))
193
- .unwrap());
194
-
195
- let mut rwtf = if let Some(md) = metadata.ok() {
196
- let tt_metadata = md.at(&RString::new_utf8("track_type"))
197
- .try_convert_to::<Hash>()
198
- .map_err(|e| VM::raise_ex(e))
199
- .unwrap();
200
-
201
- let track_type = tt_metadata.at(&RString::new_utf8("type"))
202
- .try_convert_to::<RString>()
203
- .map_err(|e| VM::raise_ex(e))
204
- .unwrap();
205
-
206
- let id = u32::try_from(tt_metadata.at(&RString::new_utf8("id"))
207
- .try_convert_to::<Integer>()
208
- .map_err(|e| VM::raise_ex(e))
209
- .unwrap()
210
- .to_u64())
211
- .map_err(|e| VM::raise(Class::from_existing("Exception"), &format!("{}", e)))
212
- .unwrap();
213
-
214
- let tt = match track_type.to_str() {
215
- "trip" => TrackType::Trip(id),
216
- "route" => TrackType::Route(id),
217
- "segment" => TrackType::Segment(id),
218
- _ => {
219
- VM::raise(
220
- Class::from_existing("Exception"),
221
- &format!("unknown track_type metadata: {}", track_type.to_str()),
222
- );
223
- unreachable!();
224
- }
225
- };
226
-
227
- RWTFile::with_track_type(tt)
228
- } else {
229
- RWTFile::new()
230
- };
231
-
232
- let maybe_track_points = source
233
- .at(&RString::new_utf8("track_points"))
234
- .try_convert_to::<Array>();
235
-
236
- if let Ok(track_points) = maybe_track_points {
237
- add_points(track_points, |i, k, v| {
238
- let data = if let Some(field_type) = track_points_config.get(k) {
239
- match field_type.as_str() {
240
- "LongFloat" => DataField::LongFloat(any_to_float(v)),
241
- "ShortFloat" => DataField::ShortFloat(any_to_float(v)),
242
- "Number" => DataField::Number(any_to_int(v)),
243
- "Base64" => DataField::Base64(any_to_str(v).replace("\n", "")),
244
- "String" => DataField::String(any_to_str(v)),
245
- "Bool" => DataField::Bool(any_to_bool(v)),
246
- "IDs" => DataField::IDs(any_to_ids(v)),
247
- _ => {
248
- VM::raise(
249
- Class::from_existing("Exception"),
250
- &format!("unknown track_points type: {}", field_type),
251
- );
252
- unreachable!();
253
- }
254
- }
255
- } else {
256
- VM::raise(
257
- Class::from_existing("Exception"),
258
- &format!("unknown track_points field: {}", k),
259
- );
260
- unreachable!();
261
- };
262
-
263
- rwtf.add_track_point(i, k, data)
264
- .map_err(|e| {
265
- VM::raise(Class::from_existing("Exception"), &format!("{}", e))
266
- })
267
- .unwrap();
268
- });
269
- }
270
-
271
- let maybe_course_points = source
272
- .at(&RString::new_utf8("course_points"))
273
- .try_convert_to::<Array>();
274
-
275
- if let Ok(course_points) = maybe_course_points {
276
- add_points(course_points, |i, k, v| {
277
- let data = if let Some(field_type) = course_points_config.get(k) {
278
- match field_type.as_str() {
279
- "LongFloat" => DataField::LongFloat(any_to_float(v)),
280
- "ShortFloat" => DataField::ShortFloat(any_to_float(v)),
281
- "Number" => DataField::Number(any_to_int(v)),
282
- "Base64" => DataField::Base64(any_to_str(v).replace("\n", "")),
283
- "String" => DataField::String(any_to_str(v)),
284
- "Bool" => DataField::Bool(any_to_bool(v)),
285
- "IDs" => DataField::IDs(any_to_ids(v)),
286
- _ => {
287
- VM::raise(
288
- Class::from_existing("Exception"),
289
- &format!("unknown course_points type: {}", field_type),
290
- );
291
- unreachable!();
292
- }
293
- }
294
- } else {
295
- VM::raise(
296
- Class::from_existing("Exception"),
297
- &format!("unknown course_points field: {}", k),
298
- );
299
- unreachable!();
300
- };
301
-
302
- rwtf.add_course_point(i, k, data)
303
- .map_err(|e| {
304
- VM::raise(Class::from_existing("Exception"), &format!("{}", e))
305
- })
306
- .unwrap();
307
- });
308
- }
309
-
310
- let inner = Inner { inner: rwtf };
311
- Class::from_existing("RWTFile").wrap_data(inner, &*INNER_WRAPPER)
312
- }
313
-
314
- fn rwtf_inspect() -> RString {
315
- let rwtf = &itself.get_data(&*INNER_WRAPPER).inner;
316
-
317
- RString::new_utf8(&format!("RWTFile<track_points: {}, course_points: {}>",
318
- rwtf.track_points.len(),
319
- rwtf.course_points.len()))
320
- }
321
- );
322
-
323
- rutie_serde_methods!(
324
- RubyRWTFile,
325
- itself,
326
- ruby_class!(Exception),
327
-
328
- fn rwtf_to_hash() -> &RWTFile {
329
- &itself.get_data(&*INNER_WRAPPER).inner
330
- }
331
-
332
- fn rwtf_metadata() -> &RWTFMetadata {
333
- &itself.get_data(&*INNER_WRAPPER).inner.metadata()
334
- }
335
- );
5
+ use rutie::{Class, Object};
336
6
 
337
7
  #[allow(non_snake_case)]
338
8
  #[no_mangle]
339
9
  pub extern "C" fn Init_Tracklib() {
340
10
  Class::new("RWTFile", Some(&Class::from_existing("Object"))).define(|itself| {
341
- itself.def_self("from_bytes", rwtf_from_bytes);
342
- itself.def_self("from_h", rwtf_from_hash);
343
- itself.def("to_bytes", rwtf_to_bytes);
344
- itself.def("to_h", rwtf_to_hash);
345
- itself.def("metadata", rwtf_metadata);
346
- itself.def("inspect", rwtf_inspect);
11
+ itself.def_self("from_bytes", rwtfile::rwtf_from_bytes);
12
+ itself.def_self("from_h", rwtfile::rwtf_from_hash);
13
+ itself.def("to_bytes", rwtfile::rwtf_to_bytes);
14
+ itself.def("to_h", rwtfile::rwtf_to_hash);
15
+ itself.def("metadata", rwtfile::rwtf_metadata);
16
+ itself.def("simplify_track_points", rwtfile::rwtf_simplify_track_points);
17
+ itself.def("inspect", rwtfile::rwtf_inspect);
18
+ itself.def("to_s", rwtfile::rwtf_inspect);
19
+ });
20
+
21
+ Class::new("TracklibRoadClassMapping", Some(&Class::from_existing("Object"))).define(|itself| {
22
+ itself.def_self("new", surface::road_class_mapping_new);
23
+ itself.def("add_road_class", surface::road_class_mapping_add_road_class);
24
+ itself.def("to_s", surface::road_class_mapping_to_s);
25
+ });
26
+
27
+ Class::new("TracklibSurfaceMapping", Some(&Class::from_existing("Object"))).define(|itself| {
28
+ itself.def_self("new", surface::surface_mapping_new);
29
+ itself.def("add_surface", surface::surface_mapping_add_surface);
30
+ itself.def("add_road_class_mapping", surface::surface_mapping_add_road_class_mapping);
31
+ itself.def("to_s", surface::surface_mapping_to_s);
32
+ });
33
+
34
+ Class::new("TracklibFieldEncodeOptionsVec", Some(&Class::from_existing("Object"))).define(|itself| {
35
+ itself.def_self("new", polyline::field_encode_options_vec_new);
36
+ itself.def("add_y", polyline::field_encode_options_vec_add_field_y);
37
+ itself.def("add_x", polyline::field_encode_options_vec_add_field_x);
38
+ itself.def("add_d", polyline::field_encode_options_vec_add_field_d);
39
+ itself.def("add_e", polyline::field_encode_options_vec_add_field_e);
40
+ itself.def("add_s", polyline::field_encode_options_vec_add_field_s);
41
+ itself.def("add_r", polyline::field_encode_options_vec_add_field_r);
42
+ itself.def("to_s", polyline::field_encode_options_vec_to_s);
347
43
  });
348
44
  }
data/src/polyline.rs ADDED
@@ -0,0 +1,95 @@
1
+ use lazy_static::lazy_static;
2
+ use rutie::{AnyException, AnyObject, Class, Integer, NilClass, Object, RString, VM, VerifiedObject, class, methods, wrappable_struct};
3
+ use tracklib::{FieldEncodeOptions, PointField};
4
+ use std::convert::TryFrom;
5
+
6
+ fn add_field_helper(v: &mut Vec<FieldEncodeOptions>, field: PointField, precision: Result<Integer, AnyException>) {
7
+ let prec = u32::try_from(precision.map_err(|e| VM::raise_ex(e)).unwrap().to_i32())
8
+ .map_err(|_| VM::raise(Class::from_existing("Exception"), "Precision must be a u32")).unwrap();
9
+ v.push(FieldEncodeOptions::new(field, prec))
10
+ }
11
+
12
+ pub struct FieldEncodeOptionsVecInner {
13
+ inner: Vec<FieldEncodeOptions>,
14
+ }
15
+
16
+ wrappable_struct!(
17
+ FieldEncodeOptionsVecInner,
18
+ FieldEncodeOptionsVecInnerWrapper,
19
+ FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER
20
+ );
21
+
22
+ class!(RubyFieldEncodeOptionsVec);
23
+
24
+ methods!(
25
+ RubyFieldEncodeOptionsVec,
26
+ itself,
27
+
28
+ fn field_encode_options_vec_new() -> AnyObject {
29
+ let inner = FieldEncodeOptionsVecInner {
30
+ inner: Vec::new()
31
+ };
32
+
33
+ Class::from_existing("TracklibFieldEncodeOptionsVec").wrap_data(inner, &*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER)
34
+ }
35
+
36
+ fn field_encode_options_vec_add_field_y(precision: Integer) -> NilClass {
37
+ let inner = &mut itself.get_data_mut(&*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER).inner;
38
+ add_field_helper(inner, PointField::Y, precision);
39
+ NilClass::new()
40
+ }
41
+
42
+ fn field_encode_options_vec_add_field_x(precision: Integer) -> NilClass {
43
+ let inner = &mut itself.get_data_mut(&*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER).inner;
44
+ add_field_helper(inner, PointField::X, precision);
45
+ NilClass::new()
46
+ }
47
+
48
+ fn field_encode_options_vec_add_field_d(precision: Integer) -> NilClass {
49
+ let inner = &mut itself.get_data_mut(&*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER).inner;
50
+ add_field_helper(inner, PointField::D, precision);
51
+ NilClass::new()
52
+ }
53
+
54
+ fn field_encode_options_vec_add_field_e(precision: Integer) -> NilClass {
55
+ let inner = &mut itself.get_data_mut(&*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER).inner;
56
+ add_field_helper(inner, PointField::E, precision);
57
+ NilClass::new()
58
+ }
59
+
60
+ fn field_encode_options_vec_add_field_s(default_surface: Integer, precision: Integer) -> NilClass {
61
+ let default_surface_id = default_surface.map_err(|e| VM::raise_ex(e)).unwrap().to_i64();
62
+ let inner = &mut itself.get_data_mut(&*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER).inner;
63
+ add_field_helper(inner, PointField::S(default_surface_id), precision);
64
+ NilClass::new()
65
+ }
66
+
67
+ fn field_encode_options_vec_add_field_r(default_road_class: Integer, precision: Integer) -> NilClass {
68
+ let default_road_class_id = default_road_class.map_err(|e| VM::raise_ex(e)).unwrap().to_i64();
69
+ let inner = &mut itself.get_data_mut(&*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER).inner;
70
+ add_field_helper(inner, PointField::R(default_road_class_id), precision);
71
+ NilClass::new()
72
+ }
73
+
74
+ fn field_encode_options_vec_to_s() -> RString {
75
+ let inner = &itself.get_data(&*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER).inner;
76
+
77
+ RString::new_utf8(&format!("{:?}", inner))
78
+ }
79
+ );
80
+
81
+ impl RubyFieldEncodeOptionsVec {
82
+ pub fn inner(&self) -> &[FieldEncodeOptions] {
83
+ &self.get_data(&*FIELD_ENCODE_OPTIONS_VEC_INNER_WRAPPER).inner
84
+ }
85
+ }
86
+
87
+ impl VerifiedObject for RubyFieldEncodeOptionsVec {
88
+ fn is_correct_type<T: Object>(object: &T) -> bool {
89
+ Class::from_existing("TracklibFieldEncodeOptionsVec").case_equals(object)
90
+ }
91
+
92
+ fn error_message() -> &'static str {
93
+ "Error converting to FieldEncodeOptionsVec"
94
+ }
95
+ }