stream_vbyte/decode/
mod.rs

1pub mod cursor;
2
3#[cfg(feature = "x86_ssse3")]
4pub mod ssse3;
5
6#[cfg(test)]
7mod tests;
8
9/// Decode bytes to numbers.
10pub trait Decoder {
11    type DecodedQuad;
12
13    /// Decode encoded numbers in complete quads.
14    ///
15    /// Only control bytes with 4 corresponding encoded numbers will be provided as input (i.e. no
16    /// trailing partial quad).
17    ///
18    /// `control_bytes` are the control bytes that correspond to `encoded_nums`.
19    ///
20    /// `max_control_bytes_to_decode` may be greater than the number of control bytes remaining, in
21    /// which case only the remaining control bytes will be decoded.
22    ///
23    /// Implementations may decode at most `max_control_bytes_to_decode` control bytes, but may
24    /// decode fewer.
25    ///
26    /// `nums_already_decoded` is the number of numbers that have already been decoded in the
27    /// `DecodeCursor.decode` invocation.
28    ///
29    /// Returns a tuple of the number of numbers decoded (always a multiple of 4; at most
30    /// `4 * max_control_bytes_to_decode`) and the number of bytes read from `encoded_nums`.
31    fn decode_quads<S: DecodeQuadSink<Self>>(
32        control_bytes: &[u8],
33        encoded_nums: &[u8],
34        max_control_bytes_to_decode: usize,
35        nums_already_decoded: usize,
36        sink: &mut S,
37    ) -> (usize, usize);
38}
39
40/// For decoders that wish to support slice-based features like the top-level
41/// `decode()` or DecodeCursor's `decode_slice()`.
42pub trait WriteQuadToSlice: Decoder {
43    /// Write a quad into a size-4 slice.
44    fn write_quad_to_slice(quad: Self::DecodedQuad, slice: &mut [u32]);
45}
46
47/// Receives numbers decoded via a Decoder in `DecodeCursor.decode_sink()` that weren't handed to
48/// `DecodeQuadSink.on_quad()`, whether because the `Decoder` implementation doesn't have a natural
49/// quad representation, or because the numbers are part of a trailing partial quad.
50pub trait DecodeSingleSink {
51    /// `nums_decoded` is the number of numbers that have already been decoded before this number
52    /// in the current invocation of `DecodeCursor.decode_sink()`.
53    fn on_number(&mut self, num: u32, nums_decoded: usize);
54}
55
56/// Receives numbers decoded via a Decoder in `DecodeCursor.decode_sink()`.
57///
58/// Since stream-vbyte is oriented around groups of 4 numbers, some decoders will expose decoded
59/// numbers in some decoder-specific datatype. Or, if that is not applicable for a particular
60/// `Decoder` implementation, all decoded numbers will instead be passed to
61/// `DecodeSingleSink.on_number()`.
62pub trait DecodeQuadSink<D: Decoder + ?Sized>: DecodeSingleSink {
63    /// `nums_decoded` is the number of numbers that have already been decoded before this quad
64    /// in the current invocation of `DecodeCursor.decode_sink()`.
65    fn on_quad(&mut self, quad: D::DecodedQuad, nums_decoded: usize);
66}
67
68/// A sink for writing to a slice.
69pub(crate) struct SliceDecodeSink<'a> {
70    output: &'a mut [u32],
71}
72
73impl<'a> SliceDecodeSink<'a> {
74    /// Create a new sink that wraps a slice.
75    ///
76    /// `output` must be at least as big as the
77    fn new(output: &'a mut [u32]) -> SliceDecodeSink<'a> {
78        SliceDecodeSink { output }
79    }
80}
81
82impl<'a> DecodeSingleSink for SliceDecodeSink<'a> {
83    #[inline]
84    fn on_number(&mut self, num: u32, nums_decoded: usize) {
85        self.output[nums_decoded] = num;
86    }
87}
88
89impl<'a, D: Decoder + WriteQuadToSlice> DecodeQuadSink<D> for SliceDecodeSink<'a> {
90    fn on_quad(&mut self, quad: D::DecodedQuad, nums_decoded: usize) {
91        D::write_quad_to_slice(quad, &mut self.output[nums_decoded..(nums_decoded + 4)]);
92    }
93}
94
95/// Decode `count` numbers from `input`, writing them to `output`.
96///
97/// The `count` must be the same as the number of items originally encoded.
98///
99/// `output` must be at least of size 4, and must be large enough for all `count` numbers.
100///
101/// Returns the number of bytes read from `input`.
102pub fn decode<D: Decoder + WriteQuadToSlice>(
103    input: &[u8],
104    count: usize,
105    output: &mut [u32],
106) -> usize {
107    let mut cursor = cursor::DecodeCursor::new(&input, count);
108
109    assert_eq!(
110        count,
111        cursor.decode_slice::<D>(output),
112        "output buffer was not large enough"
113    );
114
115    cursor.input_consumed()
116}
117
118#[inline]
119pub fn decode_num_scalar(len: usize, input: &[u8]) -> u32 {
120    let mut buf = [0_u8; 4];
121    buf[0..len].copy_from_slice(&input[0..len]);
122
123    u32::from_le_bytes(buf)
124}