diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -18,3 +18,4 @@
 
 subinclude:cfastmanifest/.hgignore
 subinclude:linelog/.hgignore
+subinclude:rust/.hgignore
diff --git a/rust/.hgignore b/rust/.hgignore
new file mode 100644
--- /dev/null
+++ b/rust/.hgignore
@@ -0,0 +1,2 @@
+target/
+vlq/Cargo.lock
diff --git a/rust/vlq/Cargo.toml b/rust/vlq/Cargo.toml
new file mode 100644
--- /dev/null
+++ b/rust/vlq/Cargo.toml
@@ -0,0 +1,5 @@
+[package]
+name = "vlq"
+version = "0.1.0"
+
+[dependencies]
diff --git a/rust/vlq/src/lib.rs b/rust/vlq/src/lib.rs
new file mode 100644
--- /dev/null
+++ b/rust/vlq/src/lib.rs
@@ -0,0 +1,103 @@
+use std::vec::Vec;
+
+/// VLQ (Variable-length quantity) encoding.
+
+/// Encode a u64 value to a byte array
+///
+/// # Example
+///
+/// ```
+/// use vlq::encode;
+///
+/// let x = encode(120);
+/// assert_eq!(x, vec![120]);
+///
+/// let x = encode(22742734291);
+/// assert_eq!(x, vec![211, 171, 202, 220, 84]);
+/// ```
+pub fn encode(value: u64) -> Vec<u8> {
+    let mut result = Vec::new();
+    let mut x = value;
+    loop {
+        let next = x >> 7;
+        let byte = match next {
+            0 => x & 127,
+            _ => x & 127 | 128,
+        } as u8;
+        result.push(byte);
+        x = next;
+        if x == 0 {
+            break;
+        }
+    }
+    result
+}
+
+/// Decode a byte array to a u64 value
+///
+/// # Example
+///
+/// ```
+/// use vlq::decode;
+///
+/// let mut pos = 0;
+/// let buf = vec![120, 211, 171, 202, 220, 84];
+///
+/// let x = decode(&buf, &mut pos);
+/// assert_eq!(x, 120);
+/// assert_eq!(pos, 1);
+///
+/// let x = decode(&buf, &mut pos);
+/// assert_eq!(x, 22742734291);
+/// assert_eq!(pos, buf.len());
+/// ```
+pub fn decode(buf: &Vec<u8>, pos: &mut usize) -> u64 {
+    let mut result: u64 = 0;
+    let mut shift: usize = 0;
+    while *pos < buf.len() {
+        let x: u8 = buf[*pos];
+        *pos += 1;
+        result |= ((x & 127) as u64) << shift;
+        if x & 128 == 0 {
+            break;
+        }
+        shift += 7;
+    }
+    result
+}
+
+#[cfg(test)]
+mod tests {
+    use {encode, decode};
+
+    #[test]
+    fn round_trip() {
+        let numbers = vec![
+            0,
+            1,
+            17,
+            63,
+            127,
+            128,
+            129,
+            255,
+            256,
+            65535,
+            65536,
+            65537,
+            12345678901234,
+            12345678901234567890,
+            18446744073709551615u64,
+        ];
+        let mut buf = vec![255, 127]; // buffer with unrelated bytes
+        let mut pos = buf.len();
+        for i in &numbers {
+            let mut encoded = encode(*i);
+            buf.append(&mut encoded);
+        }
+        for i in &numbers {
+            let v = decode(&buf, &mut pos);
+            assert_eq!(v, *i);
+        }
+    }
+}