1pub const fn sha1(data: &ConstBuffer) -> Digest {
2 let state: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
3 let len: u64 = 0;
4 let blocks: Blocks = Blocks {
5 len: 0,
6 data: [0; 64],
7 };
8 let (blocks: Blocks, len: u64, state: [u32; 5]) = process_blocks(blocks, data, len, state);
9 digest(state, len, blocks)
10}
11
12const BUFFER_SIZE: usize = 1024;
13
14pub struct ConstBuffer {
15 data: [u8; BUFFER_SIZE],
16 head: usize,
17}
18
19impl ConstBuffer {
20 pub const fn for_class<C: crate::RuntimeName, I: crate::RuntimeType>() -> Self {
21 Self::new()
22 .push_slice(b"rc(")
23 .push_slice(C::NAME.as_bytes())
24 .push(b';')
25 .push_other(I::SIGNATURE)
26 .push(b')')
27 }
28
29 pub const fn for_interface<T: crate::Interface>() -> Self {
30 Self::new().push_guid(&T::IID)
31 }
32
33 pub const fn from_slice(slice: &[u8]) -> Self {
34 let s = Self::new();
35 s.push_slice(slice)
36 }
37
38 pub const fn new() -> Self {
39 Self {
40 data: [0; BUFFER_SIZE],
41 head: 0,
42 }
43 }
44
45 pub const fn push_slice(self, slice: &[u8]) -> Self {
46 self.push_amount(slice, slice.len())
47 }
48
49 const fn get(&self, index: usize) -> u8 {
50 self.data[index]
51 }
52
53 const fn len(&self) -> usize {
54 self.head
55 }
56
57 pub fn as_slice(&self) -> &[u8] {
58 &self.data[..self.head]
59 }
60
61 pub const fn push_other(self, other: Self) -> Self {
62 self.push_amount(&other.data, other.len())
63 }
64
65 const fn push(mut self, value: u8) -> Self {
66 self.data[self.head] = value;
67 self.head += 1;
68 self
69 }
70
71 const fn push_hex_u8(self, value: u8) -> Self {
72 const fn digit(mut value: u8) -> u8 {
73 value &= 0xF;
74
75 if value < 10 {
76 b'0' + value
77 } else {
78 b'a' + (value - 10)
79 }
80 }
81
82 self.push(digit(value >> 4)).push(digit(value))
83 }
84
85 const fn push_hex_u16(self, value: u16) -> Self {
86 self.push_hex_u8((value >> 8) as u8)
87 .push_hex_u8((value & 0xFF) as u8)
88 }
89
90 const fn push_hex_u32(self, value: u32) -> Self {
91 self.push_hex_u16((value >> 16) as u16)
92 .push_hex_u16((value & 0xFFFF) as u16)
93 }
94
95 const fn push_amount(mut self, slice: &[u8], amount: usize) -> Self {
96 let mut i = 0;
97 while i < amount {
98 self.data[self.head + i] = slice[i];
99 i += 1;
100 }
101 self.head += i;
102 self
103 }
104
105 const fn push_guid(self, guid: &crate::GUID) -> Self {
106 self.push(b'{')
107 .push_hex_u32(guid.data1)
108 .push(b'-')
109 .push_hex_u16(guid.data2)
110 .push(b'-')
111 .push_hex_u16(guid.data3)
112 .push(b'-')
113 .push_hex_u16(((guid.data4[0] as u16) << 8) | guid.data4[1] as u16)
114 .push(b'-')
115 .push_hex_u16(((guid.data4[2] as u16) << 8) | guid.data4[3] as u16)
116 .push_hex_u16(((guid.data4[4] as u16) << 8) | guid.data4[5] as u16)
117 .push_hex_u16(((guid.data4[6] as u16) << 8) | guid.data4[7] as u16)
118 .push(b'}')
119 }
120}
121
122struct Blocks {
123 len: u32,
124 data: [u8; 64],
125}
126
127const fn process_blocks(
128 mut blocks: Blocks,
129 data: &ConstBuffer,
130 mut len: u64,
131 mut state: [u32; 5],
132) -> (Blocks, u64, [u32; 5]) {
133 const fn as_block(input: &ConstBuffer, offset: usize) -> [u32; 16] {
134 let mut result = [0u32; 16];
135
136 let mut i = 0;
137 while i != 16 {
138 let off = offset + (i * 4);
139 result[i] = (input.get(off + 3) as u32)
140 | ((input.get(off + 2) as u32) << 8)
141 | ((input.get(off + 1) as u32) << 16)
142 | ((input.get(off) as u32) << 24);
143 i += 1;
144 }
145 result
146 }
147
148 const fn clone_from_slice_64(
149 mut data: [u8; 64],
150 slice: &[u8],
151 offset: usize,
152 num_elems: usize,
153 ) -> [u8; 64] {
154 let mut i = 0;
155 while i < num_elems {
156 data[i] = slice[offset + i];
157 i += 1;
158 }
159 data
160 }
161
162 let mut i = 0;
163 while i < data.len() {
164 if data.len() - i >= 64 {
165 let chunk_block = as_block(data, i);
166 len += 64;
167 state = process_state(state, chunk_block);
168 i += 64;
169 } else {
170 let num_elems = data.len() - i;
171 blocks.data = clone_from_slice_64(blocks.data, &data.data, i, num_elems);
172 blocks.len = num_elems as u32;
173 break;
174 }
175 }
176 (blocks, len, state)
177}
178
179const fn process_state(mut state: [u32; 5], block: [u32; 16]) -> [u32; 5] {
180 let a = state[0];
181 let b = state[1];
182 let c = state[2];
183 let d = state[3];
184 let e = state[4];
185 let (block, b, e) = r0(block, a, b, c, d, e, 0);
186 let (block, a, d) = r0(block, e, a, b, c, d, 1);
187 let (block, e, c) = r0(block, d, e, a, b, c, 2);
188 let (block, d, b) = r0(block, c, d, e, a, b, 3);
189 let (block, c, a) = r0(block, b, c, d, e, a, 4);
190 let (block, b, e) = r0(block, a, b, c, d, e, 5);
191 let (block, a, d) = r0(block, e, a, b, c, d, 6);
192 let (block, e, c) = r0(block, d, e, a, b, c, 7);
193 let (block, d, b) = r0(block, c, d, e, a, b, 8);
194 let (block, c, a) = r0(block, b, c, d, e, a, 9);
195 let (block, b, e) = r0(block, a, b, c, d, e, 10);
196 let (block, a, d) = r0(block, e, a, b, c, d, 11);
197 let (block, e, c) = r0(block, d, e, a, b, c, 12);
198 let (block, d, b) = r0(block, c, d, e, a, b, 13);
199 let (block, c, a) = r0(block, b, c, d, e, a, 14);
200 let (block, b, e) = r0(block, a, b, c, d, e, 15);
201 let (block, a, d) = r1(block, e, a, b, c, d, 0);
202 let (block, e, c) = r1(block, d, e, a, b, c, 1);
203 let (block, d, b) = r1(block, c, d, e, a, b, 2);
204 let (block, c, a) = r1(block, b, c, d, e, a, 3);
205 let (block, b, e) = r2(block, a, b, c, d, e, 4);
206 let (block, a, d) = r2(block, e, a, b, c, d, 5);
207 let (block, e, c) = r2(block, d, e, a, b, c, 6);
208 let (block, d, b) = r2(block, c, d, e, a, b, 7);
209 let (block, c, a) = r2(block, b, c, d, e, a, 8);
210 let (block, b, e) = r2(block, a, b, c, d, e, 9);
211 let (block, a, d) = r2(block, e, a, b, c, d, 10);
212 let (block, e, c) = r2(block, d, e, a, b, c, 11);
213 let (block, d, b) = r2(block, c, d, e, a, b, 12);
214 let (block, c, a) = r2(block, b, c, d, e, a, 13);
215 let (block, b, e) = r2(block, a, b, c, d, e, 14);
216 let (block, a, d) = r2(block, e, a, b, c, d, 15);
217 let (block, e, c) = r2(block, d, e, a, b, c, 0);
218 let (block, d, b) = r2(block, c, d, e, a, b, 1);
219 let (block, c, a) = r2(block, b, c, d, e, a, 2);
220 let (block, b, e) = r2(block, a, b, c, d, e, 3);
221 let (block, a, d) = r2(block, e, a, b, c, d, 4);
222 let (block, e, c) = r2(block, d, e, a, b, c, 5);
223 let (block, d, b) = r2(block, c, d, e, a, b, 6);
224 let (block, c, a) = r2(block, b, c, d, e, a, 7);
225 let (block, b, e) = r3(block, a, b, c, d, e, 8);
226 let (block, a, d) = r3(block, e, a, b, c, d, 9);
227 let (block, e, c) = r3(block, d, e, a, b, c, 10);
228 let (block, d, b) = r3(block, c, d, e, a, b, 11);
229 let (block, c, a) = r3(block, b, c, d, e, a, 12);
230 let (block, b, e) = r3(block, a, b, c, d, e, 13);
231 let (block, a, d) = r3(block, e, a, b, c, d, 14);
232 let (block, e, c) = r3(block, d, e, a, b, c, 15);
233 let (block, d, b) = r3(block, c, d, e, a, b, 0);
234 let (block, c, a) = r3(block, b, c, d, e, a, 1);
235 let (block, b, e) = r3(block, a, b, c, d, e, 2);
236 let (block, a, d) = r3(block, e, a, b, c, d, 3);
237 let (block, e, c) = r3(block, d, e, a, b, c, 4);
238 let (block, d, b) = r3(block, c, d, e, a, b, 5);
239 let (block, c, a) = r3(block, b, c, d, e, a, 6);
240 let (block, b, e) = r3(block, a, b, c, d, e, 7);
241 let (block, a, d) = r3(block, e, a, b, c, d, 8);
242 let (block, e, c) = r3(block, d, e, a, b, c, 9);
243 let (block, d, b) = r3(block, c, d, e, a, b, 10);
244 let (block, c, a) = r3(block, b, c, d, e, a, 11);
245 let (block, b, e) = r4(block, a, b, c, d, e, 12);
246 let (block, a, d) = r4(block, e, a, b, c, d, 13);
247 let (block, e, c) = r4(block, d, e, a, b, c, 14);
248 let (block, d, b) = r4(block, c, d, e, a, b, 15);
249 let (block, c, a) = r4(block, b, c, d, e, a, 0);
250 let (block, b, e) = r4(block, a, b, c, d, e, 1);
251 let (block, a, d) = r4(block, e, a, b, c, d, 2);
252 let (block, e, c) = r4(block, d, e, a, b, c, 3);
253 let (block, d, b) = r4(block, c, d, e, a, b, 4);
254 let (block, c, a) = r4(block, b, c, d, e, a, 5);
255 let (block, b, e) = r4(block, a, b, c, d, e, 6);
256 let (block, a, d) = r4(block, e, a, b, c, d, 7);
257 let (block, e, c) = r4(block, d, e, a, b, c, 8);
258 let (block, d, b) = r4(block, c, d, e, a, b, 9);
259 let (block, c, a) = r4(block, b, c, d, e, a, 10);
260 let (block, b, e) = r4(block, a, b, c, d, e, 11);
261 let (block, a, d) = r4(block, e, a, b, c, d, 12);
262 let (block, e, c) = r4(block, d, e, a, b, c, 13);
263 let (block, d, b) = r4(block, c, d, e, a, b, 14);
264 let (_, c, a) = r4(block, b, c, d, e, a, 15);
265
266 state[0] = state[0].wrapping_add(a);
267 state[1] = state[1].wrapping_add(b);
268 state[2] = state[2].wrapping_add(c);
269 state[3] = state[3].wrapping_add(d);
270 state[4] = state[4].wrapping_add(e);
271 state
272}
273
274const fn digest(mut state: [u32; 5], len: u64, blocks: Blocks) -> Digest {
275 const fn clone_from_slice_128(
276 mut data: [u8; 128],
277 slice: &[u8],
278 offset: usize,
279 num_elems: usize,
280 ) -> [u8; 128] {
281 let mut i = 0;
282 while i < num_elems {
283 data[i] = slice[offset + i];
284 i += 1;
285 }
286 data
287 }
288
289 const fn clone_slice_128(mut data: [u8; 128], slice: &[u8], _offset: usize) -> [u8; 128] {
290 let mut i = 0;
291 while i < slice.len() {
292 data[_offset + i] = slice[i];
293 i += 1;
294 }
295 data
296 }
297
298 const fn as_block(input: &[u8], offset: usize) -> [u32; 16] {
299 let mut result = [0u32; 16];
300
301 let mut i = 0;
302 while i != 16 {
303 let off = offset + (i * 4);
304 result[i] = (input[off + 3] as u32)
305 | ((input[off + 2] as u32) << 8)
306 | ((input[off + 1] as u32) << 16)
307 | ((input[off] as u32) << 24);
308 i += 1;
309 }
310 result
311 }
312
313 let bits = (len + (blocks.len as u64)) * 8;
314 let extra = [
315 (bits >> 56) as u8,
316 (bits >> 48) as u8,
317 (bits >> 40) as u8,
318 (bits >> 32) as u8,
319 (bits >> 24) as u8,
320 (bits >> 16) as u8,
321 (bits >> 8) as u8,
322 bits as u8,
323 ];
324 let mut last = [0; 128];
325 let blocklen = blocks.len as usize;
326 last = clone_from_slice_128(last, &blocks.data, 0, blocklen);
327 last[blocklen] = 0x80;
328
329 if blocklen < 56 {
330 last = clone_slice_128(last, &extra, 56);
331 state = process_state(state, as_block(&last, 0));
332 } else {
333 last = clone_slice_128(last, &extra, 120);
334 state = process_state(state, as_block(&last, 0));
335 state = process_state(state, as_block(&last, 64));
336 }
337 Digest { data: state }
338}
339
340const fn rol(value: u32, bits: usize) -> u32 {
341 (value << bits) | (value >> (32 - bits))
342}
343
344const fn blk(block: &[u32], i: usize) -> u32 {
345 let value: u32 = block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i];
346 rol(value, bits:1)
347}
348
349const fn r0(
350 block: [u32; 16],
351 v: u32,
352 mut w: u32,
353 x: u32,
354 y: u32,
355 mut z: u32,
356 i: usize,
357) -> ([u32; 16], u32, u32) {
358 let n: u32 = ((w & (x ^ y)) ^ y)
359 .wrapping_add(block[i])
360 .wrapping_add(0x5a82_7999)
361 .wrapping_add(rol(value:v, bits:5));
362 z = z.wrapping_add(n);
363 w = rol(value:w, bits:30);
364 (block, w, z)
365}
366
367const fn r1(
368 mut block: [u32; 16],
369 v: u32,
370 mut w: u32,
371 x: u32,
372 y: u32,
373 mut z: u32,
374 i: usize,
375) -> ([u32; 16], u32, u32) {
376 block[i] = blk(&block, i);
377 let n: u32 = ((w & (x ^ y)) ^ y)
378 .wrapping_add(block[i])
379 .wrapping_add(0x5a82_7999)
380 .wrapping_add(rol(value:v, bits:5));
381 z = z.wrapping_add(n);
382 w = rol(value:w, bits:30);
383 (block, w, z)
384}
385
386const fn r2(
387 mut block: [u32; 16],
388 v: u32,
389 mut w: u32,
390 x: u32,
391 y: u32,
392 mut z: u32,
393 i: usize,
394) -> ([u32; 16], u32, u32) {
395 block[i] = blk(&block, i);
396 let n: u32 = (w ^ x ^ y)
397 .wrapping_add(block[i])
398 .wrapping_add(0x6ed9_eba1)
399 .wrapping_add(rol(value:v, bits:5));
400 z = z.wrapping_add(n);
401 w = rol(value:w, bits:30);
402 (block, w, z)
403}
404
405const fn r3(
406 mut block: [u32; 16],
407 v: u32,
408 mut w: u32,
409 x: u32,
410 y: u32,
411 mut z: u32,
412 i: usize,
413) -> ([u32; 16], u32, u32) {
414 block[i] = blk(&block, i);
415 let n: u32 = (((w | x) & y) | (w & x))
416 .wrapping_add(block[i])
417 .wrapping_add(0x8f1b_bcdc)
418 .wrapping_add(rol(value:v, bits:5));
419 z = z.wrapping_add(n);
420 w = rol(value:w, bits:30);
421 (block, w, z)
422}
423
424const fn r4(
425 mut block: [u32; 16],
426 v: u32,
427 mut w: u32,
428 x: u32,
429 y: u32,
430 mut z: u32,
431 i: usize,
432) -> ([u32; 16], u32, u32) {
433 block[i] = blk(&block, i);
434 let n: u32 = (w ^ x ^ y)
435 .wrapping_add(block[i])
436 .wrapping_add(0xca62_c1d6)
437 .wrapping_add(rol(value:v, bits:5));
438 z = z.wrapping_add(n);
439 w = rol(value:w, bits:30);
440 (block, w, z)
441}
442
443pub struct Digest {
444 data: [u32; 5],
445}
446
447impl Digest {
448 pub const fn bytes(&self) -> [u8; 20] {
449 [
450 (self.data[0] >> 24) as u8,
451 (self.data[0] >> 16) as u8,
452 (self.data[0] >> 8) as u8,
453 self.data[0] as u8,
454 (self.data[1] >> 24) as u8,
455 (self.data[1] >> 16) as u8,
456 (self.data[1] >> 8) as u8,
457 self.data[1] as u8,
458 (self.data[2] >> 24) as u8,
459 (self.data[2] >> 16) as u8,
460 (self.data[2] >> 8) as u8,
461 self.data[2] as u8,
462 (self.data[3] >> 24) as u8,
463 (self.data[3] >> 16) as u8,
464 (self.data[3] >> 8) as u8,
465 self.data[3] as u8,
466 (self.data[4] >> 24) as u8,
467 (self.data[4] >> 16) as u8,
468 (self.data[4] >> 8) as u8,
469 self.data[4] as u8,
470 ]
471 }
472}
473
474impl core::fmt::Display for Digest {
475 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
476 for i: &u32 in self.data.iter() {
477 write!(f, "{:08x}", i)?;
478 }
479 Ok(())
480 }
481}
482