mirror of
https://github.com/git/git.git
synced 2025-09-10 22:44:50 +02:00
rust: implement a test balloon via the "varint" subsystem
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>
This commit is contained in:
committed by
Junio C Hamano
parent
3df0d68b5a
commit
7f464d07d6
3
Makefile
3
Makefile
@@ -1307,7 +1307,9 @@ LIB_OBJS += urlmatch.o
|
||||
LIB_OBJS += usage.o
|
||||
LIB_OBJS += userdiff.o
|
||||
LIB_OBJS += utf8.o
|
||||
ifndef WITH_RUST
|
||||
LIB_OBJS += varint.o
|
||||
endif
|
||||
LIB_OBJS += version.o
|
||||
LIB_OBJS += versioncmp.o
|
||||
LIB_OBJS += walker.o
|
||||
@@ -1499,6 +1501,7 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o
|
||||
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
|
||||
|
||||
RUST_SOURCES += src/lib.rs
|
||||
RUST_SOURCES += src/varint.rs
|
||||
|
||||
GIT-VERSION-FILE: FORCE
|
||||
@OLD=$$(cat $@ 2>/dev/null || :) && \
|
||||
|
||||
@@ -522,7 +522,6 @@ libgit_sources = [
|
||||
'usage.c',
|
||||
'userdiff.c',
|
||||
'utf8.c',
|
||||
'varint.c',
|
||||
'version.c',
|
||||
'versioncmp.c',
|
||||
'walker.c',
|
||||
@@ -1716,6 +1715,10 @@ rust_option = get_option('rust').disable_auto_if(not rust_available)
|
||||
if rust_option.allowed()
|
||||
subdir('src')
|
||||
libgit_c_args += '-DWITH_RUST'
|
||||
else
|
||||
libgit_sources += [
|
||||
'varint.c',
|
||||
]
|
||||
endif
|
||||
|
||||
libgit = declare_dependency(
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pub mod varint;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
libgit_rs_sources = [
|
||||
'lib.rs',
|
||||
'varint.rs',
|
||||
]
|
||||
|
||||
if meson.version().version_compare('>=1.5.0')
|
||||
|
||||
95
src/varint.rs
Normal file
95
src/varint.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
use std::os::raw::c_int;
|
||||
use std::os::raw::c_uchar;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn decode_varint(bufp: *mut *const c_uchar) -> usize {
|
||||
let mut buf = *bufp;
|
||||
let mut c = *buf;
|
||||
let mut val = usize::from(c & 127);
|
||||
|
||||
buf = buf.add(1);
|
||||
|
||||
while (c & 128) != 0 {
|
||||
val = val.wrapping_add(1);
|
||||
if val == 0 || val.leading_zeros() < 7 {
|
||||
return 0; // overflow
|
||||
}
|
||||
|
||||
c = *buf;
|
||||
buf = buf.add(1);
|
||||
|
||||
val = (val << 7) + usize::from(c & 127);
|
||||
}
|
||||
|
||||
*bufp = buf;
|
||||
val
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn encode_varint(value: usize, buf: *mut c_uchar) -> c_int {
|
||||
let mut varint: [u8; 16] = [0; 16];
|
||||
let mut pos = varint.len() - 1;
|
||||
|
||||
varint[pos] = (value & 127) as u8;
|
||||
|
||||
let mut value = value >> 7;
|
||||
while value != 0 {
|
||||
pos -= 1;
|
||||
value -= 1;
|
||||
varint[pos] = 128 | (value & 127) as u8;
|
||||
value >>= 7;
|
||||
}
|
||||
|
||||
if !buf.is_null() {
|
||||
std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);
|
||||
}
|
||||
|
||||
(varint.len() - pos) as c_int
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_decode_varint() {
|
||||
unsafe {
|
||||
assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);
|
||||
assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);
|
||||
assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);
|
||||
assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);
|
||||
assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);
|
||||
assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);
|
||||
|
||||
// Overflows are expected to return 0.
|
||||
assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_varint() {
|
||||
unsafe {
|
||||
let mut varint: [u8; 16] = [0; 16];
|
||||
|
||||
assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);
|
||||
|
||||
assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);
|
||||
assert_eq!(varint, [0; 16]);
|
||||
|
||||
assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);
|
||||
assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);
|
||||
assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);
|
||||
assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);
|
||||
assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);
|
||||
assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user