1#![no_std]
2extern crate byte_tools;
3extern crate generic_array;
4use generic_array::{GenericArray, ArrayLength};
5use byte_tools::zero;
6
7type Block<N> = GenericArray<u8, N>;
8
9#[derive(Clone, Copy)]
10pub struct DigestBuffer<N: ArrayLength<u8>> where N::ArrayType: Copy {
11 buffer: GenericArray<u8, N>,
12 pos: usize,
13}
14
15impl <N: ArrayLength<u8>> DigestBuffer<N> where N::ArrayType: Copy {
16 pub fn new() -> DigestBuffer<N> {
17 DigestBuffer::<N> {
18 buffer: Default::default(),
19 pos: 0,
20 }
21 }
22
23 pub fn input<F: FnMut(&Block<N>)>(&mut self, mut input: &[u8], mut func: F) {
24 if self.pos != 0 {
27 let rem = N::to_usize() - self.pos;
28
29 if input.len() >= rem {
30 let (l, r) = input.split_at(rem);
31 input = r;
32 self.buffer[self.pos..].copy_from_slice(l);
33 self.pos = 0;
34 func(&self.buffer);
35 } else {
36 let end = self.pos + input.len();
37 self.buffer[self.pos..end].copy_from_slice(input);
38 self.pos = end;
39 return;
40 }
41 }
42
43 while input.len() >= N::to_usize() {
46 let (l, r) = input.split_at(N::to_usize());
47 input = r;
48 let block = GenericArray::from_slice(&l);
49 func(block);
50 }
51
52 self.buffer[..input.len()].copy_from_slice(input);
56 self.pos += input.len();
57 }
58
59 pub fn reset(&mut self) {
60 self.pos = 0;
61 }
62
63 pub fn zero_until(&mut self, idx: usize) {
64 assert!(idx >= self.pos);
65 zero(&mut self.buffer[self.pos..idx]);
66 self.pos = idx;
67 }
68
69 pub fn next(&mut self, len: usize) -> &mut [u8] {
70 self.pos += len;
71 &mut self.buffer[self.pos - len..self.pos]
72 }
73
74 pub fn full_buffer(& mut self) -> &Block<N> {
75 assert!(self.pos == self.size());
76 self.pos = 0;
77 &self.buffer
78 }
79
80 pub fn current_buffer(&mut self) -> &[u8] {
81 let tmp = self.pos;
82 self.pos = 0;
83 &self.buffer[..tmp]
84 }
85
86 pub fn position(&self) -> usize { self.pos }
87
88 pub fn remaining(&self) -> usize { self.size() - self.pos }
89
90 pub fn standard_padding<F: FnMut(&Block<N>)>(&mut self, rem: usize, mut func: F) {
91 let size = self.size();
92
93 self.next(1)[0] = 128;
94
95 if self.remaining() < rem {
96 self.zero_until(size);
97 func(self.full_buffer());
98 }
99
100 self.zero_until(size - rem);
101 }
102
103 pub fn size(&self) -> usize {
104 N::to_usize()
105 }
106}
107
108impl <N: ArrayLength<u8>> Default for DigestBuffer<N> where N::ArrayType: Copy {
109 fn default() -> Self { Self::new() }
110}