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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::{Decode, Encode};
use prelude::*;
use std::num::NonZeroUsize;

#[cfg(all(feature = "simdutf8", not(miri)))]
use simdutf8::basic::from_utf8;
#[cfg(not(all(feature = "simdutf8", not(miri))))]
use std::str::from_utf8;

mod bit_string;
mod expect_normalized_float;
mod expected_range_u64;
mod gamma;
mod prelude;

pub use bit_string::*;
pub use expect_normalized_float::ExpectNormalizedFloat;
pub use expected_range_u64::ExpectedRangeU64;
pub use gamma::Gamma;

pub trait Encoding: Copy {
    fn is_fixed(self) -> bool {
        false
    }

    fn zigzag(self) -> bool {
        false
    }

    #[inline(always)]
    fn write_u64<const BITS: usize>(self, writer: &mut impl Write, v: u64) {
        writer.write_bits(v, BITS);
    }

    #[inline(always)]
    fn read_u64<const BITS: usize>(self, reader: &mut impl Read) -> Result<u64> {
        reader.read_bits(BITS)
    }

    // TODO add implementations to Gamma and ExpectedRange.
    #[inline(always)]
    fn write_u128<const BITS: usize>(self, writer: &mut impl Write, v: u128) {
        debug_assert!((65..=128).contains(&BITS));

        let lo = v as u64;
        let hi = (v >> 64) as u64;
        writer.write_bits(lo, 64);
        writer.write_bits(hi, BITS - 64);
    }

    #[inline(always)]
    fn read_u128<const BITS: usize>(self, reader: &mut impl Read) -> Result<u128> {
        debug_assert!((65..=128).contains(&BITS));

        let lo = reader.read_bits(64)?;
        let hi = reader.read_bits(BITS - 64)?;
        Ok(lo as u128 | ((hi as u128) << 64))
    }

    #[inline(always)]
    fn write_f32(self, writer: &mut impl Write, v: f32) {
        v.to_bits().encode(Fixed, writer).unwrap()
    }

    #[inline(always)]
    fn read_f32(self, reader: &mut impl Read) -> Result<f32> {
        Ok(f32::from_bits(Decode::decode(Fixed, reader)?))
    }

    #[inline(always)]
    fn write_f64(self, writer: &mut impl Write, v: f64) {
        v.to_bits().encode(Fixed, writer).unwrap()
    }

    #[inline(always)]
    fn read_f64(self, reader: &mut impl Read) -> Result<f64> {
        Ok(f64::from_bits(Decode::decode(Fixed, reader)?))
    }

    #[inline(always)]
    fn write_str(self, writer: &mut impl Write, v: &str) {
        self.write_byte_str(writer, v.as_bytes());
    }

    #[inline(always)]
    fn read_str(self, reader: &mut impl Read) -> Result<&str> {
        let len = usize::decode(Gamma, reader)?;
        if let Some(len) = NonZeroUsize::new(len) {
            from_utf8(self.read_bytes(reader, len)?).map_err(|_| E::Invalid("utf8").e())
        } else {
            Ok("")
        }
    }

    #[inline(always)]
    fn write_byte_str(self, writer: &mut impl Write, v: &[u8]) {
        v.len().encode(Gamma, writer).unwrap();
        writer.write_bytes(v);
    }

    #[inline(always)]
    fn read_byte_str(self, reader: &mut impl Read) -> Result<&[u8]> {
        let len = usize::decode(Gamma, reader)?;
        if let Some(len) = NonZeroUsize::new(len) {
            self.read_bytes(reader, len)
        } else {
            Ok(&[])
        }
    }

    #[inline(always)]
    fn read_bytes(self, reader: &mut impl Read, len: NonZeroUsize) -> Result<&[u8]> {
        reader.read_bytes(len)
    }
}

#[derive(Copy, Clone)]
pub struct Fixed;

impl Encoding for Fixed {
    fn is_fixed(self) -> bool {
        true
    }
}