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
#![no_std]
extern crate byte_tools;
extern crate generic_array;
use generic_array::{GenericArray, ArrayLength};
use byte_tools::{copy_memory, zero};
type Block<N> = GenericArray<u8, N>;
#[derive(Clone, Copy)]
pub struct DigestBuffer<N: ArrayLength<u8>> where N::ArrayType: Copy {
buffer: GenericArray<u8, N>,
buffer_idx: usize,
}
impl <N: ArrayLength<u8>> DigestBuffer<N> where N::ArrayType: Copy {
pub fn new() -> DigestBuffer<N> {
DigestBuffer::<N> {
buffer: Default::default(),
buffer_idx: 0,
}
}
pub fn input<F: FnMut(&Block<N>)>(&mut self, input: &[u8], mut func: F) {
let mut i = 0;
let size = self.size();
if self.buffer_idx != 0 {
let buffer_remaining = size - self.buffer_idx;
if input.len() >= buffer_remaining {
copy_memory(
&input[..buffer_remaining],
&mut self.buffer[self.buffer_idx..size]);
self.buffer_idx = 0;
func(&self.buffer);
i += buffer_remaining;
} else {
copy_memory(
input,
&mut self.buffer[self.buffer_idx..][..input.len()]);
self.buffer_idx += input.len();
return;
}
}
while input.len() - i >= size {
let block = GenericArray::from_slice(&input[i..i + size]);
func(block);
i += size;
}
let input_remaining = input.len() - i;
copy_memory(
&input[i..],
&mut self.buffer[0..input_remaining]);
self.buffer_idx += input_remaining;
}
pub fn reset(&mut self) {
self.buffer_idx = 0;
}
pub fn zero_until(&mut self, idx: usize) {
assert!(idx >= self.buffer_idx);
zero(&mut self.buffer[self.buffer_idx..idx]);
self.buffer_idx = idx;
}
pub fn next(&mut self, len: usize) -> &mut [u8] {
self.buffer_idx += len;
&mut self.buffer[self.buffer_idx - len..self.buffer_idx]
}
pub fn full_buffer(& mut self) -> &Block<N> {
assert!(self.buffer_idx == self.size());
self.buffer_idx = 0;
&self.buffer
}
pub fn current_buffer(&mut self) -> &[u8] {
let tmp = self.buffer_idx;
self.buffer_idx = 0;
&self.buffer[..tmp]
}
pub fn position(&self) -> usize { self.buffer_idx }
pub fn remaining(&self) -> usize { self.size() - self.buffer_idx }
pub fn standard_padding<F: FnMut(&Block<N>)>(&mut self, rem: usize, mut func: F) {
let size = self.size();
self.next(1)[0] = 128;
if self.remaining() < rem {
self.zero_until(size);
func(self.full_buffer());
}
self.zero_until(size - rem);
}
pub fn size(&self) -> usize {
N::to_usize()
}
}
impl <N: ArrayLength<u8>> Default for DigestBuffer<N> where N::ArrayType: Copy {
fn default() -> Self { Self::new() }
}