write_only/reference/
non_volatile.rs1use core::marker::PhantomData;
6
7use crate::{Put, Write};
8
9pub struct WriteOnlyRef<'a, T: 'a> {
11 data: *mut T,
12 _phantom: PhantomData<&'a T>,
13}
14
15impl<'a, T: 'a> WriteOnlyRef<'a, T> {
16 #[inline]
40 pub unsafe fn from_ptr(data: *mut T) -> Self {
41 Self {
42 data,
43 _phantom: PhantomData,
44 }
45 }
46}
47
48impl<'a, T: 'a> Put<T> for WriteOnlyRef<'a, T> {
49 #[inline]
50 fn put(&mut self, guard: T) {
51 unsafe {
52 *self.data = guard;
53 }
54 }
55}
56
57impl<'a, T: 'a> Write<T> for WriteOnlyRef<'a, T> {
58 #[inline]
59 fn write(&mut self, guard: T) {
60 unsafe {
61 self.data.write(guard);
62 }
63 }
64}
65
66impl<'a, T: 'a> From<&'a mut T> for WriteOnlyRef<'a, T> {
67 #[inline]
68 fn from(borrow: &'a mut T) -> Self {
69 unsafe { Self::from_ptr(borrow as *mut T) }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 use droptest::prelude::*;
78
79 #[test]
80 fn from_ptr() {
81 let registry = DropRegistry::default();
82 let (id, mut guard) = registry.new_guard_for(1).by_id();
83
84 let reference = unsafe { WriteOnlyRef::from_ptr(&mut guard) };
85
86 std::mem::drop(reference);
87
88 assert_no_drop!(registry, id);
89 }
90
91 #[test]
92 fn from() {
93 let registry = DropRegistry::default();
94 let (id, mut guard) = registry.new_guard_for(1).by_id();
95
96 let reference = WriteOnlyRef::from(&mut guard);
97
98 std::mem::drop(reference);
99
100 assert_no_drop!(registry, id);
101 }
102
103 #[test]
104 fn put() {
105 let registry = DropRegistry::default();
106 let (old_id, mut guard) = registry.new_guard_for(1).by_id();
107 let (new_id, new_guard) = registry.new_guard_for(2).by_id();
108
109 let mut reference = WriteOnlyRef::from(&mut guard);
110 reference.put(new_guard);
111
112 assert_eq!(guard.value(), &2);
113
114 assert_drop!(registry, old_id);
115 assert_no_drop!(registry, new_id);
116
117 std::mem::drop(guard);
118
119 assert_drop!(registry, old_id);
120 assert_drop!(registry, new_id);
121 }
122
123 #[test]
124 fn write() {
125 let registry = DropRegistry::default();
126 let (old_id, mut guard) = registry.new_guard_for(1).by_id();
127 let (new_id, new_guard) = registry.new_guard_for(2).by_id();
128
129 let mut reference = WriteOnlyRef::from(&mut guard);
130 reference.write(new_guard);
131
132 assert_eq!(guard.value(), &2);
133
134 assert_no_drop!(registry, old_id);
135 assert_no_drop!(registry, new_id);
136
137 std::mem::drop(guard);
138
139 assert_no_drop!(registry, old_id);
140 assert_drop!(registry, new_id);
141 }
142}