Skip to content

Commit fff596e

Browse files
pks-tgitster
authored andcommitted
misc::varint: reimplement as test balloon for Rust
Implement a trivial test balloon for our Rust build infrastructure by reimplementing the "varint.c" subsystem in Rust. This subsystem is chosen because it is trivial to convert and because it doesn't have any dependencies to other components of Git. If support for Rust is enabled, we stop compiling "varint.c" and instead compile and use "src/varint.rs". Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Ezekiel Newren <ezekielnewren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent c78179f commit fff596e

4 files changed

Lines changed: 101 additions & 1 deletion

File tree

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,9 @@ LIB_OBJS += urlmatch.o
12591259
LIB_OBJS += usage.o
12601260
LIB_OBJS += userdiff.o
12611261
LIB_OBJS += utf8.o
1262+
ifeq ($(WITH_RUST),false)
12621263
LIB_OBJS += varint.o
1264+
endif
12631265
LIB_OBJS += version.o
12641266
LIB_OBJS += versioncmp.o
12651267
LIB_OBJS += walker.o

meson.build

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,6 @@ libgit_sources = [
571571
'usage.c',
572572
'userdiff.c',
573573
'utf8.c',
574-
'varint.c',
575574
'version.c',
576575
'versioncmp.c',
577576
'walker.c',
@@ -591,6 +590,12 @@ libgit_sources = [
591590
'xdiff/xutils.c',
592591
]
593592

593+
if not with_rust
594+
libgit_sources += [
595+
'varint.c',
596+
]
597+
endif
598+
594599
libgit_sources += custom_target(
595600
input: 'command-list.txt',
596601
output: 'command-list.h',

rust/misc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod varint;

rust/misc/src/varint.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#[no_mangle]
2+
pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> usize {
3+
let mut buf = *bufp;
4+
let mut c = *buf;
5+
let mut val = usize::from(c & 127);
6+
7+
buf = buf.add(1);
8+
9+
while (c & 128) != 0 {
10+
val = val.wrapping_add(1);
11+
if val == 0 || val.leading_zeros() < 7 {
12+
return 0; // overflow
13+
}
14+
15+
c = *buf;
16+
buf = buf.add(1);
17+
18+
val = (val << 7) + usize::from(c & 127);
19+
}
20+
21+
*bufp = buf;
22+
val
23+
}
24+
25+
#[no_mangle]
26+
pub unsafe extern "C" fn encode_varint(value: usize, buf: *mut u8) -> u8 {
27+
let mut varint: [u8; 16] = [0; 16];
28+
let mut pos = varint.len() - 1;
29+
30+
varint[pos] = (value & 127) as u8;
31+
32+
let mut value = value >> 7;
33+
while value != 0 {
34+
pos -= 1;
35+
value -= 1;
36+
varint[pos] = 128 | (value & 127) as u8;
37+
value >>= 7;
38+
}
39+
40+
if !buf.is_null() {
41+
std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);
42+
}
43+
44+
(varint.len() - pos) as u8
45+
}
46+
47+
#[cfg(test)]
48+
mod tests {
49+
use super::*;
50+
51+
#[test]
52+
fn test_decode_varint() {
53+
unsafe {
54+
assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);
55+
assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);
56+
assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);
57+
assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);
58+
assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);
59+
assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);
60+
61+
// Overflows are expected to return 0.
62+
assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);
63+
}
64+
}
65+
66+
#[test]
67+
fn test_encode_varint() {
68+
unsafe {
69+
let mut varint: [u8; 16] = [0; 16];
70+
71+
assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);
72+
73+
assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);
74+
assert_eq!(varint, [0; 16]);
75+
76+
assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);
77+
assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
78+
79+
assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);
80+
assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
81+
82+
assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);
83+
assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
84+
85+
assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);
86+
assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
87+
88+
assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);
89+
assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)