1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#[derive(Debug)]
pub enum EncodeError {
    ///The value is too long.  On 64-bit machines, values must be shorter than 18.4 exabytes in length.  On 32-bit machines, values must be less than 4 gigabytes long.
    ValueTooLong,
}

/// Encodes data!
///
/// # Example
///
/// ```rust
/// # use kvds::EncodeError;
/// #
/// # fn main() -> Result<(), Box<EncodeError>> {
/// #
/// let data = vec![
///     (1, "one".as_bytes().to_vec()),
///     (2, "two".as_bytes().to_vec()),
/// ];
///
/// let encoded = kvds::encode(data)?;
///
/// assert_eq!(encoded, vec![1, 0, 3, 111, 110, 101, 2, 0, 3, 116, 119, 111]);
/// #
/// # Ok(())
/// # }
/// ```
///
/// # Errors
///
/// This function returns an error if any of the values supplied are too long.
pub fn encode(slice: Vec<(u8, Vec<u8>)>) -> Result<Vec<u8>, EncodeError> {
    let mut vec = Vec::new();
    for (key, value) in slice {
        let mut value = value;
        let mut length_vec: Vec<u8> = Vec::new();
        let length = value.len() as u128; // Using `as` is ok here as well because usize will always convert to a u128 on a 64-bit or 32-bit platform.
        let mut n: u128 = length;
        loop {
            length_vec.insert(0, (n % 256u128) as u8); // Using `as` is ok here because any remainder of division by 256 will be a u8.
            n /= 256u128;
            if n == 0 {
                break;
            }
        }

        if length < u16::max_value().into() {
            for _ in 1..=(2 - length_vec.len()) {
                length_vec.insert(0, 0);
            }
        } else if length < u32::max_value().into() {
            for _ in 1..=(4 - length_vec.len()) {
                length_vec.insert(0, 0);
            }
            length_vec.insert(0, 255);
            length_vec.insert(0, 255);
        } else if length < u64::max_value().into() {
            for _ in 1..=(8 - length_vec.len()) {
                length_vec.insert(0, 0);
            }
            for _ in 1..=6 {
                length_vec.insert(0, 255);
            }
        } else if length <= u128::max_value() {
            for _ in 1..=(16 - length_vec.len()) {
                length_vec.insert(0, 0);
            }
            for _ in 1..=14 {
                length_vec.insert(0, 255);
            }
        } else {
            return Err(EncodeError::ValueTooLong);
        }

        vec.push(key);
        vec.append(&mut length_vec);
        vec.append(&mut value);
    }
    Ok(vec)
}