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