Skip to content

Commit 2aa7ba0

Browse files
committed
Bump gps-data-codec
1 parent c72fb08 commit 2aa7ba0

3 files changed

Lines changed: 102 additions & 105 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "gps-data-codec"
3-
version = "1.6.6"
3+
version = "1.6.7"
44
edition = "2024"
55
license = "MIT"
66
authors = ["Raphael Stefanini <raphael@routechoices.com>"]

src/lib.rs

Lines changed: 100 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,126 @@
1-
use pyo3::exceptions::PyValueError;
2-
use pyo3::prelude::*;
1+
use pyo3::pymodule;
32

4-
struct DecodingResult {
5-
value: i64,
6-
offset: u32,
7-
}
3+
#[pymodule]
4+
mod gps_data_codec {
5+
use pyo3::exceptions::PyValueError;
6+
use pyo3::prelude::*;
87

9-
fn decode_unsigned_value_from_string(encoded: &[u8], offset: u32) -> DecodingResult {
10-
let mut value: i64 = 0;
11-
let mut consumed: u32 = 0;
12-
let mut byte: u8 = 0;
13-
while consumed == 0 || byte >= 0x20 {
14-
byte = encoded[(consumed + offset) as usize] - 63;
15-
value |= ((byte & 0x1f) as i64) << (consumed * 5);
16-
consumed += 1;
8+
struct DecodingResult {
9+
value: i64,
10+
offset: u32,
1711
}
18-
DecodingResult {
19-
value,
20-
offset: offset + consumed,
21-
}
22-
}
2312

24-
fn decode_signed_value_from_string(encoded: &[u8], offset: u32) -> DecodingResult {
25-
let tmp_result: DecodingResult = decode_unsigned_value_from_string(encoded, offset);
26-
let tmp_value: i64 = tmp_result.value;
27-
if tmp_value & 1 == 1 {
28-
DecodingResult {
29-
value: !(tmp_value >> 1),
30-
offset: tmp_result.offset,
13+
fn decode_unsigned_value_from_string(encoded: &[u8], offset: u32) -> DecodingResult {
14+
let mut value: i64 = 0;
15+
let mut consumed: u32 = 0;
16+
let mut byte: u8 = 0;
17+
while consumed == 0 || byte >= 0x20 {
18+
byte = encoded[(consumed + offset) as usize] - 63;
19+
value |= ((byte & 0x1f) as i64) << (consumed * 5);
20+
consumed += 1;
3121
}
32-
} else {
3322
DecodingResult {
34-
value: tmp_value >> 1,
35-
offset: tmp_result.offset,
23+
value,
24+
offset: offset + consumed,
3625
}
3726
}
38-
}
3927

40-
fn encode_unsigned_number(num: u64) -> Vec<u8> {
41-
let mut encoded: Vec<u8> = vec![];
42-
let mut tmp: u64 = num;
43-
while tmp >= 0x20 {
44-
encoded.push((0x20 | (tmp as u8 & 0x1f)) + 63);
45-
tmp >>= 5;
28+
fn decode_signed_value_from_string(encoded: &[u8], offset: u32) -> DecodingResult {
29+
let tmp_result: DecodingResult = decode_unsigned_value_from_string(encoded, offset);
30+
let tmp_value: i64 = tmp_result.value;
31+
if tmp_value & 1 == 1 {
32+
DecodingResult {
33+
value: !(tmp_value >> 1),
34+
offset: tmp_result.offset,
35+
}
36+
} else {
37+
DecodingResult {
38+
value: tmp_value >> 1,
39+
offset: tmp_result.offset,
40+
}
41+
}
4642
}
47-
encoded.push(tmp as u8 + 63);
48-
encoded
49-
}
5043

51-
fn encode_signed_number(num: i64) -> Vec<u8> {
52-
let mut sgn_num: i64 = num << 1;
53-
if num < 0 {
54-
sgn_num = !sgn_num;
44+
fn encode_unsigned_number(num: u64) -> Vec<u8> {
45+
let mut encoded: Vec<u8> = vec![];
46+
let mut tmp: u64 = num;
47+
while tmp >= 0x20 {
48+
encoded.push((0x20 | (tmp as u8 & 0x1f)) + 63);
49+
tmp >>= 5;
50+
}
51+
encoded.push(tmp as u8 + 63);
52+
encoded
5553
}
56-
let unsigned_num = sgn_num as u64;
57-
encode_unsigned_number(unsigned_num)
58-
}
5954

60-
const YEAR2010: i64 = 1262304000;
55+
fn encode_signed_number(num: i64) -> Vec<u8> {
56+
let mut sgn_num: i64 = num << 1;
57+
if num < 0 {
58+
sgn_num = !sgn_num;
59+
}
60+
let unsigned_num = sgn_num as u64;
61+
encode_unsigned_number(unsigned_num)
62+
}
6163

62-
#[pyfunction]
63-
fn decode(input: String) -> PyResult<Vec<(i64, f64, f64)>> {
64-
let mut vals: [i64; 3] = [YEAR2010, 0, 0];
65-
let mut bytes_consumed: u32 = 0;
66-
let mut decoding_result: DecodingResult;
67-
let encoded: &[u8] = input.as_bytes();
68-
let encoded_length: u32 = encoded.len() as u32;
69-
let mut output: Vec<(i64, f64, f64)> = Vec::new();
64+
const YEAR2010: i64 = 1262304000;
7065

71-
while bytes_consumed < encoded_length {
72-
for (i, val) in vals.iter_mut().enumerate() {
73-
if i == 0 && bytes_consumed != 0 {
74-
decoding_result = decode_unsigned_value_from_string(encoded, bytes_consumed);
75-
} else {
76-
decoding_result = decode_signed_value_from_string(encoded, bytes_consumed);
66+
#[pyfunction]
67+
fn decode(input: String) -> PyResult<Vec<(i64, f64, f64)>> {
68+
let mut vals: [i64; 3] = [YEAR2010, 0, 0];
69+
let mut bytes_consumed: u32 = 0;
70+
let mut decoding_result: DecodingResult;
71+
let encoded: &[u8] = input.as_bytes();
72+
let encoded_length: u32 = encoded.len() as u32;
73+
let mut output: Vec<(i64, f64, f64)> = Vec::new();
74+
75+
while bytes_consumed < encoded_length {
76+
for (i, val) in vals.iter_mut().enumerate() {
77+
if i == 0 && bytes_consumed != 0 {
78+
decoding_result = decode_unsigned_value_from_string(encoded, bytes_consumed);
79+
} else {
80+
decoding_result = decode_signed_value_from_string(encoded, bytes_consumed);
81+
}
82+
bytes_consumed = decoding_result.offset;
83+
*val += decoding_result.value;
7784
}
78-
bytes_consumed = decoding_result.offset;
79-
*val += decoding_result.value;
85+
output.push((vals[0], (vals[1] as f64) / 1e5, (vals[2] as f64) / 1e5));
8086
}
81-
output.push((vals[0], (vals[1] as f64) / 1e5, (vals[2] as f64) / 1e5));
87+
Ok(output)
8288
}
83-
Ok(output)
84-
}
8589

86-
#[pyfunction]
87-
fn encode(data: Vec<(f64, f64, f64)>) -> PyResult<String> {
88-
let mut prev_timestamp: i64 = YEAR2010;
89-
let mut prev_latitude: f64 = 0.0;
90-
let mut prev_longitude: f64 = 0.0;
90+
#[pyfunction]
91+
fn encode(data: Vec<(f64, f64, f64)>) -> PyResult<String> {
92+
let mut prev_timestamp: i64 = YEAR2010;
93+
let mut prev_latitude: f64 = 0.0;
94+
let mut prev_longitude: f64 = 0.0;
9195

92-
let mut output: Vec<u8> = vec![];
93-
let mut is_first: bool = true;
94-
for point_object in data.iter() {
95-
let point_data = point_object;
96-
let timestamp = point_data.0.round() as i64;
97-
let timestamp_diff = timestamp - prev_timestamp;
98-
if is_first {
99-
output.append(&mut encode_signed_number(timestamp_diff));
100-
is_first = false;
101-
} else {
102-
if timestamp < prev_timestamp {
103-
return Err(PyValueError::new_err("Input data is not sorted"));
96+
let mut output: Vec<u8> = vec![];
97+
let mut is_first: bool = true;
98+
for point_object in data.iter() {
99+
let point_data = point_object;
100+
let timestamp = point_data.0.round() as i64;
101+
let timestamp_diff = timestamp - prev_timestamp;
102+
if is_first {
103+
output.append(&mut encode_signed_number(timestamp_diff));
104+
is_first = false;
105+
} else {
106+
if timestamp < prev_timestamp {
107+
return Err(PyValueError::new_err("Input data is not sorted"));
108+
}
109+
output.append(&mut encode_unsigned_number(timestamp_diff as u64));
104110
}
105-
output.append(&mut encode_unsigned_number(timestamp_diff as u64));
106-
}
107111

108-
let latitude: f64 = point_data.1;
109-
let latitude_diff: i64 = ((latitude - prev_latitude) * 1e5).round() as i64;
110-
output.append(&mut encode_signed_number(latitude_diff));
112+
let latitude: f64 = point_data.1;
113+
let latitude_diff: i64 = ((latitude - prev_latitude) * 1e5).round() as i64;
114+
output.append(&mut encode_signed_number(latitude_diff));
111115

112-
let longitude: f64 = point_data.2;
113-
let longitude_diff: i64 = ((longitude - prev_longitude) * 1e5).round() as i64;
114-
output.append(&mut encode_signed_number(longitude_diff));
116+
let longitude: f64 = point_data.2;
117+
let longitude_diff: i64 = ((longitude - prev_longitude) * 1e5).round() as i64;
118+
output.append(&mut encode_signed_number(longitude_diff));
115119

116-
prev_timestamp += timestamp_diff;
117-
prev_latitude += (latitude_diff as f64) / 1e5;
118-
prev_longitude += (longitude_diff as f64) / 1e5;
120+
prev_timestamp += timestamp_diff;
121+
prev_latitude += (latitude_diff as f64) / 1e5;
122+
prev_longitude += (longitude_diff as f64) / 1e5;
123+
}
124+
Ok(unsafe { String::from_utf8_unchecked(output) })
119125
}
120-
Ok(unsafe { String::from_utf8_unchecked(output) })
121-
}
122-
123-
#[pymodule]
124-
fn gps_data_codec(m: &Bound<'_, PyModule>) -> PyResult<()> {
125-
m.add_function(wrap_pyfunction!(encode, m)?)?;
126-
m.add_function(wrap_pyfunction!(decode, m)?)?;
127-
128-
Ok(())
129126
}

0 commit comments

Comments
 (0)