Git fork

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: Junio C Hamano <gitster@pobox.com>

authored by

Patrick Steinhardt and committed by
Junio C Hamano
8832e728 f366bfe1

+101 -1
+3
Makefile
··· 1307 1307 LIB_OBJS += usage.o 1308 1308 LIB_OBJS += userdiff.o 1309 1309 LIB_OBJS += utf8.o 1310 + ifndef WITH_RUST 1310 1311 LIB_OBJS += varint.o 1312 + endif 1311 1313 LIB_OBJS += version.o 1312 1314 LIB_OBJS += versioncmp.o 1313 1315 LIB_OBJS += walker.o ··· 1499 1501 UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o 1500 1502 1501 1503 RUST_SOURCES += src/lib.rs 1504 + RUST_SOURCES += src/varint.rs 1502 1505 1503 1506 GIT-VERSION-FILE: FORCE 1504 1507 @OLD=$$(cat $@ 2>/dev/null || :) && \
+4 -1
meson.build
··· 522 522 'usage.c', 523 523 'userdiff.c', 524 524 'utf8.c', 525 - 'varint.c', 526 525 'version.c', 527 526 'versioncmp.c', 528 527 'walker.c', ··· 1707 1706 if rust_option.allowed() 1708 1707 subdir('src') 1709 1708 libgit_c_args += '-DWITH_RUST' 1709 + else 1710 + libgit_sources += [ 1711 + 'varint.c', 1712 + ] 1710 1713 endif 1711 1714 1712 1715 libgit = declare_dependency(
+1
src/lib.rs
··· 1 + pub mod varint;
+1
src/meson.build
··· 1 1 libgit_rs_sources = [ 2 2 'lib.rs', 3 + 'varint.rs', 3 4 ] 4 5 5 6 # Unfortunately we must use a wrapper command to move the output file into the
+92
src/varint.rs
··· 1 + #[no_mangle] 2 + pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> u64 { 3 + let mut buf = *bufp; 4 + let mut c = *buf; 5 + let mut val = u64::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) + u64::from(c & 127); 19 + } 20 + 21 + *bufp = buf; 22 + val 23 + } 24 + 25 + #[no_mangle] 26 + pub unsafe extern "C" fn encode_varint(value: u64, 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 + }