# vu64 Library Design
## 1. Overview
The `vu64` library provides a variable-length integer encoding scheme for `u64` and `i64` values. The goal is to represent integers using a smaller number of bytes than their fixed-size counterparts, which is particularly useful for data serialization and network protocols where space is a concern.
## 2. Core Components
### 2.1. `Vu64` Struct
The central data structure is `Vu64`, which represents a variable-length encoded integer. It contains two fields:
* `length`: A `u8` indicating the number of bytes used for the encoded integer (from 1 to 9).
* `bytes`: A `[u8; 9]` array holding the encoded bytes.
This struct implements `AsRef<[u8]>` for easy access to the encoded byte slice.
### 2.2. Encoding and Decoding Functions
#### 2.2.1. `encode(value: u64) -> Vu64`
This function takes a `u64` value and returns a `Vu64` struct containing the variable-length encoded representation. The encoding scheme is as follows:
| `0xxxxxxx` | 7 bits | 1 byte |
| `10xxxxxx` | 14 bits | 2 bytes |
| `110xxxxx` | 21 bits | 3 bytes |
| `1110xxxx` | 28 bits | 4 bytes |
| `11110xxx` | 35 bits | 5 bytes |
| `111110xx` | 42 bits | 6 bytes |
| `1111110x` | 49 bits | 7 bytes |
| `11111110` | 56 bits | 8 bytes |
| `11111111` | 64 bits | 9 bytes |
To optimize performance, the `encoded_len` function uses a lookup table (`ENCODED_LEN_TBL`) to determine the required number of bytes based on the number of leading zeros in the input value.
#### 2.2.2. `decode(bytes: &[u8]) -> Result<u64, Error>`
This function takes a byte slice containing a `vu64`-encoded value and returns a `Result` with either the decoded `u64` value or an `Error` if the input is invalid. The `decoded_len` function determines the expected length from the first byte of the input.
### 2.3. Signed Integer Handling
Signed integers (`i64`) are supported through the `signed` module, which uses zigzag encoding to map `i64` values to `u64` values. This allows the same variable-length encoding logic to be used for both signed and unsigned integers.
* `signed::zigzag::encode(value: i64) -> u64`
* `signed::zigzag::decode(encoded: u64) -> i64`
### 2.4. I/O Integration
When the `io` feature is enabled, the `io` module provides the `ReadVu64` and `WriteVu64` traits, which extend `std::io::Read` and `std::io::Write` respectively. These traits provide methods for reading and writing `vu64` and `vi64` values directly from/to I/O streams.
* `read_and_decode_vu64(&mut self) -> Result<u64>`
* `encode_and_write_vu64(&mut self, value: u64) -> Result<()>`
* `read_and_decode_vi64(&mut self) -> Result<i64>`
* `encode_and_write_vi64(&mut self, value: i66) -> Result<()>`
### 2.5. Error Handling
The `Error` enum defines the possible errors that can occur during decoding:
* `Truncated`: The input byte slice is shorter than expected.
* `RedundantEncode`: The input value is a redundant encoding.
## 3. Module Structure
* `lib.rs`: The root of the crate, defining the `Vu64` struct, the core `encode` and `decode` functions, and the `Error` enum. It also contains the `io` and `signed` modules.
* `io.rs`: Contains the I/O traits and their implementations. This module is conditionally compiled based on the `io` feature.
* `signed.rs`: Contains the logic for handling signed integers, including the `zigzag` submodule.
## 4. Dependencies
The library has no external dependencies and relies only on the Rust standard library (`std::core` and `std::io`).