tracklib 0.1.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }