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
use super::{Deserialize, Error, Result, Serialize};

#[derive(Debug, Default, PartialEq, Eq)]
pub struct VarInt64(pub u64);

const B: u8 = 7;
const M: u8 = (1 << B) - 1;

impl Serialize for VarInt64 {
    fn serialize_to<S: crate::Serializer>(&self, serializer: &mut S) -> Result<()> {
        let mut v = self.0;
        serializer.prepend([(v as u8) & M])?;
        v >>= B;

        while v != 0 {
            serializer.prepend([v as u8 | (1 << B)])?;
            v >>= B;
        }

        Ok(())
    }
}

impl<'a> Deserialize<'a> for VarInt64 {
    fn deserialize_from<D: crate::Deserializer<'a>>(buf: &mut D) -> Result<Self>
    where
        Self: Sized,
    {
        let mut v = 0u64;
        for _ in 0..10 {
            let front = buf.pop(1)?;
            let c = front[0];
            v = (v << B) | (c & M) as u64;
            if c & (1 << B) == 0 {
                return Ok(Self(v));
            }
        }
        Err(Error::VarintIsShort)
    }
}

#[cfg(test)]
mod tests {
    use crate::*;

    #[test]
    fn test_varint64() {
        for v in [u64::MIN, 1, 10, 127, 128, 255, 256, u64::MAX] {
            let ser = VarInt64(v);
            let bytes = ser.serialize::<DownwardBytes>().unwrap();
            let der = VarInt64::deserialize(&bytes[..]).unwrap();
            assert_eq!(ser, der);
        }

        assert!(VarInt64::deserialize(&[][..]).is_err());
        assert!(VarInt64::deserialize(&[128u8; 11][..]).is_err());
    }
}