summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/cargo-meson.sh32
-rw-r--r--src/lib.rs1
-rw-r--r--src/meson.build41
-rw-r--r--src/varint.rs92
4 files changed, 166 insertions, 0 deletions
diff --git a/src/cargo-meson.sh b/src/cargo-meson.sh
new file mode 100755
index 0000000000..99400986d9
--- /dev/null
+++ b/src/cargo-meson.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+if test "$#" -lt 2
+then
+ exit 1
+fi
+
+SOURCE_DIR="$1"
+BUILD_DIR="$2"
+BUILD_TYPE=debug
+
+shift 2
+
+for arg
+do
+ case "$arg" in
+ --release)
+ BUILD_TYPE=release;;
+ esac
+done
+
+cargo build --lib --quiet --manifest-path="$SOURCE_DIR/Cargo.toml" --target-dir="$BUILD_DIR" "$@"
+RET=$?
+if test $RET -ne 0
+then
+ exit $RET
+fi
+
+if ! cmp "$BUILD_DIR/$BUILD_TYPE/libgitcore.a" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1
+then
+ cp "$BUILD_DIR/$BUILD_TYPE/libgitcore.a" "$BUILD_DIR/libgitcore.a"
+fi
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000000..9da70d8b57
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1 @@
+pub mod varint;
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000000..25b9ad5a14
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,41 @@
+libgit_rs_sources = [
+ 'lib.rs',
+ 'varint.rs',
+]
+
+# Unfortunately we must use a wrapper command to move the output file into the
+# current build directory. This can fixed once `cargo build --artifact-dir`
+# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that
+# effort.
+cargo_command = [
+ shell,
+ meson.current_source_dir() / 'cargo-meson.sh',
+ meson.project_source_root(),
+ meson.current_build_dir(),
+]
+if get_option('buildtype') == 'release'
+ cargo_command += '--release'
+endif
+
+libgit_rs = custom_target('git_rs',
+ input: libgit_rs_sources + [
+ meson.project_source_root() / 'Cargo.toml',
+ ],
+ output: 'libgitcore.a',
+ command: cargo_command,
+)
+libgit_dependencies += declare_dependency(link_with: libgit_rs)
+
+if get_option('tests')
+ test('rust', cargo,
+ args: [
+ 'test',
+ '--manifest-path',
+ meson.project_source_root() / 'Cargo.toml',
+ '--target-dir',
+ meson.current_build_dir() / 'target',
+ ],
+ timeout: 0,
+ protocol: 'rust',
+ )
+endif
diff --git a/src/varint.rs b/src/varint.rs
new file mode 100644
index 0000000000..6e610bdd8e
--- /dev/null
+++ b/src/varint.rs
@@ -0,0 +1,92 @@
+#[no_mangle]
+pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> u64 {
+ let mut buf = *bufp;
+ let mut c = *buf;
+ let mut val = u64::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) + u64::from(c & 127);
+ }
+
+ *bufp = buf;
+ val
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn encode_varint(value: u64, buf: *mut u8) -> u8 {
+ 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 u8
+}
+
+#[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]);
+ }
+ }
+}