1 | // Copyright 2018 Brian Smith. |
2 | // |
3 | // Permission to use, copy, modify, and/or distribute this software for any |
4 | // purpose with or without fee is hereby granted, provided that the above |
5 | // copyright notice and this permission notice appear in all copies. |
6 | // |
7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES |
8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | |
15 | use crate::polyfill::ArrayFlatten; |
16 | use core::ops::{BitXor, BitXorAssign}; |
17 | |
18 | #[repr (transparent)] |
19 | #[derive (Copy, Clone)] |
20 | pub struct Block([u8; 16]); |
21 | |
22 | pub const BLOCK_LEN: usize = 16; |
23 | |
24 | impl Block { |
25 | #[inline ] |
26 | pub fn zero() -> Self { |
27 | Self([0; 16]) |
28 | } |
29 | |
30 | #[inline ] |
31 | pub fn overwrite_part_at(&mut self, index: usize, a: &[u8]) { |
32 | let mut tmp: [u8; BLOCK_LEN] = *self.as_ref(); |
33 | tmp[index..][..a.len()].copy_from_slice(src:a); |
34 | *self = Self::from(&tmp) |
35 | } |
36 | |
37 | #[inline ] |
38 | pub fn zero_from(&mut self, index: usize) { |
39 | let mut tmp: [u8; BLOCK_LEN] = *self.as_ref(); |
40 | tmp[index..].fill(0); |
41 | *self = Self::from(&tmp) |
42 | } |
43 | } |
44 | |
45 | impl BitXorAssign for Block { |
46 | #[inline ] |
47 | fn bitxor_assign(&mut self, a: Self) { |
48 | // Relies heavily on optimizer to optimize this into word- or vector- |
49 | // level XOR. |
50 | for (r: &mut u8, a: &u8) in self.0.iter_mut().zip(a.0.iter()) { |
51 | *r ^= *a; |
52 | } |
53 | } |
54 | } |
55 | |
56 | impl BitXor for Block { |
57 | type Output = Self; |
58 | |
59 | #[inline ] |
60 | fn bitxor(self, a: Self) -> Self { |
61 | let mut r: Block = self; |
62 | r.bitxor_assign(a); |
63 | r |
64 | } |
65 | } |
66 | |
67 | impl<T> From<T> for Block |
68 | where |
69 | T: ArrayFlatten<Output = [u8; 16]>, |
70 | { |
71 | #[inline ] |
72 | fn from(bytes: T) -> Self { |
73 | Self(bytes.array_flatten()) |
74 | } |
75 | } |
76 | |
77 | impl From<&'_ [u8; BLOCK_LEN]> for Block { |
78 | #[inline ] |
79 | fn from(bytes: &[u8; BLOCK_LEN]) -> Self { |
80 | Self(*bytes) |
81 | } |
82 | } |
83 | |
84 | impl AsRef<[u8; BLOCK_LEN]> for Block { |
85 | #[inline ] |
86 | fn as_ref(&self) -> &[u8; BLOCK_LEN] { |
87 | &self.0 |
88 | } |
89 | } |
90 | |