Skip to content

Commit 19469d2

Browse files
committed
Faster encoding
1 parent e641c3a commit 19469d2

3 files changed

Lines changed: 37 additions & 32 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.8"
3+
version = "1.6.9"
44
edition = "2024"
55
license = "MIT"
66
authors = ["Raphael Stefanini <raphael@routechoices.com>"]

src/lib.rs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,55 +11,60 @@ mod gps_data_codec {
1111
offset: u32,
1212
}
1313

14-
fn decode_unsigned_value_from_string(encoded: &[u8], offset: u32) -> DecodingResult {
15-
let mut value: i64 = 0;
16-
let mut consumed: u32 = 0;
17-
let mut byte: u8 = 0;
18-
while consumed == 0 || byte >= 0x20 {
19-
byte = encoded[(consumed + offset) as usize] - 63;
20-
value |= ((byte & 0x1f) as i64) << (consumed * 5);
21-
consumed += 1;
22-
}
23-
DecodingResult {
24-
value,
25-
offset: offset + consumed,
14+
fn decode_unsigned_value_from_string(slice: &[u8], offset: u32) -> DecodingResult {
15+
let mut result: i64 = 0;
16+
let mut shift = 0;
17+
let mut position: u32 = offset;
18+
loop {
19+
let byte = slice[position as usize] - 63;
20+
position += 1;
21+
if (byte & 0x20) == 0 {
22+
result |= (byte as i64) << shift;
23+
return DecodingResult {
24+
value: result,
25+
offset: position,
26+
}
27+
} else {
28+
result |= ((byte & 0x1f) as i64) << shift;
29+
}
30+
shift += 5
2631
}
2732
}
2833

2934
fn decode_signed_value_from_string(encoded: &[u8], offset: u32) -> DecodingResult {
3035
let tmp_result: DecodingResult = decode_unsigned_value_from_string(encoded, offset);
31-
let tmp_value: i64 = tmp_result.value;
32-
if tmp_value & 1 == 1 {
36+
if tmp_result.value & 1 == 1 {
3337
DecodingResult {
34-
value: !(tmp_value >> 1),
38+
value: !(tmp_result.value >> 1),
3539
offset: tmp_result.offset,
3640
}
3741
} else {
3842
DecodingResult {
39-
value: tmp_value >> 1,
43+
value: tmp_result.value >> 1,
4044
offset: tmp_result.offset,
4145
}
4246
}
4347
}
4448

45-
fn encode_unsigned_number(num: u64) -> Vec<u8> {
46-
let mut encoded: Vec<u8> = vec![];
47-
let mut tmp: u64 = num;
48-
while tmp >= 0x20 {
49-
encoded.push((0x20 | (tmp as u8 & 0x1f)) + 63);
50-
tmp >>= 5;
49+
fn encode_unsigned_number(out: &mut Vec<u8>, mut num: u64) {
50+
loop {
51+
if num < 0x20 {
52+
out.push(num as u8 + 63);
53+
break
54+
} else {
55+
out.push(((num as u8 & 0x1f) | 0x20) + 63);
56+
num >>= 5;
57+
}
5158
}
52-
encoded.push(tmp as u8 + 63);
53-
encoded
5459
}
5560

56-
fn encode_signed_number(num: i64) -> Vec<u8> {
61+
fn encode_signed_number(out: &mut Vec<u8>, num: i64) {
5762
let mut sgn_num: i64 = num << 1;
5863
if num < 0 {
5964
sgn_num = !sgn_num;
6065
}
6166
let unsigned_num = sgn_num as u64;
62-
encode_unsigned_number(unsigned_num)
67+
encode_unsigned_number(out, unsigned_num);
6368
}
6469

6570
const YEAR2010: i64 = 1262304000;
@@ -108,16 +113,16 @@ mod gps_data_codec {
108113
prev_longitude += longitude_diff;
109114

110115
if is_first {
111-
output.append(&mut encode_signed_number(timestamp_diff));
116+
encode_signed_number(&mut output, timestamp_diff);
112117
is_first = false;
113118
} else {
114119
if *timestamp < prev_timestamp {
115120
return Err(PyValueError::new_err("Input data is not sorted"));
116121
}
117-
output.append(&mut encode_unsigned_number(timestamp_diff as u64));
122+
encode_unsigned_number(&mut output, timestamp_diff as u64);
118123
}
119-
output.append(&mut encode_signed_number(latitude_diff));
120-
output.append(&mut encode_signed_number(longitude_diff));
124+
encode_signed_number(&mut output, latitude_diff);
125+
encode_signed_number(&mut output, longitude_diff);
121126
}
122127
Ok(unsafe { String::from_utf8_unchecked(output) })
123128
}

0 commit comments

Comments
 (0)