1use crate::common;
10use std::fmt;
11use std::fmt::Debug;
12use std::ops::{BitXorAssign, Index, IndexMut};
13
14#[repr(align(128))]
21pub struct Block([u64; common::QWORDS_IN_BLOCK]);
22
23impl Block {
24 pub fn as_u8(&self) -> &[u8] {
26 let bytes: &[u8; common::BLOCK_SIZE] = unsafe {
27 &*(&self.0 as *const [u64; common::QWORDS_IN_BLOCK] as *const [u8; common::BLOCK_SIZE])
28 };
29 bytes
30 }
31
32 pub fn as_u8_mut(&mut self) -> &mut [u8] {
34 let bytes: &mut [u8; common::BLOCK_SIZE] = unsafe {
35 &mut *(&mut self.0 as *mut [u64; common::QWORDS_IN_BLOCK]
36 as *mut [u8; common::BLOCK_SIZE])
37 };
38 bytes
39 }
40
41 pub fn copy_to(&self, dst: &mut Block) {
43 for (d, s) in dst.0.iter_mut().zip(self.0.iter()) {
44 *d = *s
45 }
46 }
47
48 pub fn zero() -> Block {
50 Block([0u64; common::QWORDS_IN_BLOCK])
51 }
52}
53
54impl<'a> BitXorAssign<&'a Block> for Block {
55 fn bitxor_assign(&mut self, rhs: &Block) {
56 for (s, r) in self.0.iter_mut().zip(rhs.0.iter()) {
57 *s ^= *r
58 }
59 }
60}
61
62impl Clone for Block {
63 fn clone(&self) -> Block {
64 Block(self.0)
65 }
66}
67
68impl Debug for Block {
69 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
70 fmt.debug_list().entries(self.0.iter()).finish()
71 }
72}
73
74impl Eq for Block {}
75
76impl Index<usize> for Block {
77 type Output = u64;
78 fn index(&self, index: usize) -> &u64 {
79 &self.0[index]
80 }
81}
82
83impl IndexMut<usize> for Block {
84 fn index_mut(&mut self, index: usize) -> &mut u64 {
85 &mut self.0[index]
86 }
87}
88
89impl PartialEq for Block {
90 fn eq(&self, other: &Block) -> bool {
91 let mut equal = true;
92 for (s, o) in self.0.iter().zip(other.0.iter()) {
93 if s != o {
94 equal = false;
95 }
96 }
97 equal
98 }
99}
100
101#[cfg(test)]
102mod tests {
103
104 use crate::block::Block;
105 use crate::common;
106
107 #[test]
108 fn as_u8_returns_correct_slice() {
109 let block = Block::zero();
110 let expected = vec![0u8; 1024];
111 let actual = block.as_u8();
112 assert_eq!(actual, expected.as_slice());
113 }
114
115 #[test]
116 fn as_u8_mut_returns_correct_slice() {
117 let mut block = Block::zero();
118 let mut expected = vec![0u8; 1024];
119 let actual = block.as_u8_mut();
120 assert_eq!(actual, expected.as_mut_slice());
121 }
122
123 #[test]
124 fn bitxor_assign_updates_lhs() {
125 let mut lhs = Block([0u64; common::QWORDS_IN_BLOCK]);
126 let rhs = Block([1u64; common::QWORDS_IN_BLOCK]);
127 lhs ^= &rhs;
128 assert_eq!(lhs, rhs);
129 }
130
131 #[test]
132 fn copy_to_copies_block() {
133 let src = Block([1u64; common::QWORDS_IN_BLOCK]);
134 let mut dst = Block([0u64; common::QWORDS_IN_BLOCK]);
135 src.copy_to(&mut dst);
136 assert_eq!(dst, src);
137 }
138
139 #[test]
140 fn clone_clones_block() {
141 let orig = Block([1u64; common::QWORDS_IN_BLOCK]);
142 let copy = orig.clone();
143 assert_eq!(copy, orig);
144 }
145
146 #[test]
147 fn zero_creates_block_will_all_zeros() {
148 let expected = Block([0u64; common::QWORDS_IN_BLOCK]);
149 let actual = Block::zero();
150 assert_eq!(actual, expected);
151 }
152}