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}