t_rust_less_lib/memguard/
weak.rs1use super::memory;
12use capnp::message::{AllocationStrategy, Allocator, SUGGESTED_ALLOCATION_STRATEGY, SUGGESTED_FIRST_SEGMENT_WORDS};
13use capnp::Word;
14use log::warn;
15use std::ops::{Deref, DerefMut};
16
17#[derive(Clone, Debug, PartialEq, Eq)]
18pub struct ZeroingWords(Vec<Word>);
19
20impl ZeroingWords {
21 pub fn allocate_zeroed_vec(size: usize) -> ZeroingWords {
22 ZeroingWords(Word::allocate_zeroed_vec(size))
23 }
24
25 pub fn is_empty(&self) -> bool {
26 self.0.is_empty()
27 }
28
29 pub fn len(&self) -> usize {
30 self.0.len()
31 }
32}
33
34impl Drop for ZeroingWords {
35 fn drop(&mut self) {
36 unsafe {
37 memory::memzero(self.0.as_mut_ptr() as *mut u8, self.0.capacity() * 8);
38 }
39 }
40}
41
42impl Deref for ZeroingWords {
43 type Target = [u8];
44
45 fn deref(&self) -> &Self::Target {
46 unsafe { std::slice::from_raw_parts(self.0.as_ptr() as *const u8, self.0.len() * 8) }
47 }
48}
49
50impl DerefMut for ZeroingWords {
51 fn deref_mut(&mut self) -> &mut Self::Target {
52 unsafe { std::slice::from_raw_parts_mut(self.0.as_mut_ptr() as *mut u8, self.0.len() * 8) }
53 }
54}
55
56impl From<&[u8]> for ZeroingWords {
57 fn from(bytes: &[u8]) -> Self {
58 if bytes.len() % 8 != 0 {
59 warn!("Bytes not aligned to 8 bytes. Probably these are not the bytes you are looking for.");
60 }
61 let len = bytes.len() / 8;
62 let mut target = ZeroingWords::allocate_zeroed_vec(len);
63 unsafe {
64 std::ptr::copy_nonoverlapping(bytes.as_ptr(), target.as_mut_ptr(), len * 8);
65 }
66
67 target
68 }
69}
70
71#[derive(Debug)]
72pub struct ZeroingHeapAllocator {
73 owned_memory: Vec<ZeroingWords>,
74 next_size: u32,
75 allocation_strategy: AllocationStrategy,
76}
77
78impl ZeroingHeapAllocator {
79 pub fn first_segment_words(mut self, value: u32) -> ZeroingHeapAllocator {
80 self.next_size = value;
81 self
82 }
83
84 pub fn allocation_strategy(mut self, value: AllocationStrategy) -> ZeroingHeapAllocator {
85 self.allocation_strategy = value;
86 self
87 }
88}
89
90impl Default for ZeroingHeapAllocator {
91 fn default() -> Self {
92 ZeroingHeapAllocator {
93 owned_memory: Vec::new(),
94 next_size: SUGGESTED_FIRST_SEGMENT_WORDS,
95 allocation_strategy: SUGGESTED_ALLOCATION_STRATEGY,
96 }
97 }
98}
99
100unsafe impl Allocator for ZeroingHeapAllocator {
101 fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32) {
102 let size = ::std::cmp::max(minimum_size, self.next_size);
103 let mut new_words = ZeroingWords::allocate_zeroed_vec(size as usize);
104 let ptr = new_words.as_mut_ptr();
105 self.owned_memory.push(new_words);
106
107 if let AllocationStrategy::GrowHeuristically = self.allocation_strategy {
108 self.next_size += size;
109 }
110 (ptr, size)
111 }
112
113 fn deallocate_segment(&mut self, _ptr: *mut u8, _word_size: u32, _words_used: u32) {
114 self.next_size = SUGGESTED_FIRST_SEGMENT_WORDS;
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 pub fn test_zeroing_drop() {
124 {
125 let zeroing = ZeroingWords::allocate_zeroed_vec(200);
126
127 assert_eq!(zeroing.len(), 200);
128
129 for w in zeroing.iter() {
130 assert_eq!(*w, 0);
131 }
132 }
133 }
134}