Skip to main content

wnaf/
limb_buffer.rs

1/// This struct represents a view of a sequence of bytes as a sequence of
2/// `u64` limbs in little-endian byte order. It maintains a current index, and
3/// allows access to the limb at that index and the one following it. Bytes
4/// beyond the end of the original buffer are treated as zero.
5pub(crate) struct LimbBuffer<'a> {
6    buf: &'a [u8],
7    cur_idx: usize,
8    cur_limb: u64,
9    next_limb: u64,
10}
11
12impl<'a> LimbBuffer<'a> {
13    pub(crate) fn new(buf: &'a [u8]) -> Self {
14        let mut ret = Self {
15            buf,
16            cur_idx: 0,
17            cur_limb: 0,
18            next_limb: 0,
19        };
20
21        // Initialise the limb buffers.
22        ret.increment_limb();
23        ret.increment_limb();
24        ret.cur_idx = 0usize;
25
26        ret
27    }
28
29    pub(crate) fn increment_limb(&mut self) {
30        self.cur_idx += 1;
31        self.cur_limb = self.next_limb;
32        match self.buf.len() {
33            // There are no more bytes in the buffer; zero-extend.
34            0 => self.next_limb = 0,
35
36            // There are fewer bytes in the buffer than a u64 limb; zero-extend.
37            x @ 1..=7 => {
38                let mut next_limb = [0; 8];
39                next_limb[..x].copy_from_slice(self.buf);
40                self.next_limb = u64::from_le_bytes(next_limb);
41                self.buf = &[];
42            }
43
44            // There are at least eight bytes in the buffer; read the next u64 limb.
45            _ => {
46                let (next_limb, rest) = self.buf.split_at(8);
47                self.next_limb = u64::from_le_bytes([
48                    next_limb[0],
49                    next_limb[1],
50                    next_limb[2],
51                    next_limb[3],
52                    next_limb[4],
53                    next_limb[5],
54                    next_limb[6],
55                    next_limb[7],
56                ]);
57                self.buf = rest;
58            }
59        }
60    }
61
62    pub(crate) fn get(&mut self, idx: usize) -> (u64, u64) {
63        assert!([self.cur_idx, self.cur_idx + 1].contains(&idx));
64        if idx > self.cur_idx {
65            self.increment_limb();
66        }
67        (self.cur_limb, self.next_limb)
68    }
69}