cfx_storage/utils/
guarded_value.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5// FIXME: find a better place for this file.
6
7use std::ops::{Deref, DerefMut};
8
9/// To prevent automatic copy from leaking guarded value.
10/// Please always wrap the value with NonCopy if the value is Copy
11/// otherwise it's so easy to accidentally copy without notice,
12/// e.g. in matching arms, if let clauses.
13#[derive(Clone)]
14pub struct NonCopy<T: ?Sized>(pub T);
15
16/// Please read all comments in this file to prevent leaking of guarded value by
17/// accident.
18pub struct GuardedValue<GuardType, ValueType> {
19    guard: GuardType,
20    value: ValueType,
21}
22
23impl<GuardType, ValueType> GuardedValue<GuardType, ValueType> {
24    pub fn new(guard: GuardType, value: ValueType) -> Self {
25        Self { guard, value }
26    }
27
28    /// It's unsafe to drop the returned guard manually, or to clone the
29    /// ValueType. Extra care is needed when using this method.
30    pub fn into(self) -> (GuardType, ValueType) { (self.guard, self.value) }
31}
32
33impl<'a, GuardType: 'a + Deref<Target = TargetType>, TargetType>
34    GuardedValue<GuardType, NonCopy<&'a TargetType>>
35{
36    pub fn new_derefed(guard: GuardType) -> Self {
37        let derefed: *const TargetType = &*guard;
38        Self {
39            guard,
40            value: NonCopy(unsafe { &*derefed } as &'a TargetType),
41        }
42    }
43}
44
45impl<'a, GuardType: 'a + DerefMut<Target = TargetType>, TargetType>
46    GuardedValue<GuardType, &'a mut TargetType>
47{
48    pub fn new_derefed_mut(mut guard: GuardType) -> Self {
49        let derefed_mut: *mut TargetType = &mut *guard;
50        Self {
51            guard,
52            value: unsafe { &mut *derefed_mut } as &'a mut TargetType,
53        }
54    }
55}
56
57impl<GuardType, ValueType> AsRef<ValueType>
58    for GuardedValue<GuardType, ValueType>
59{
60    fn as_ref(&self) -> &ValueType { &self.value }
61}
62
63impl<GuardType, ValueType> AsMut<ValueType>
64    for GuardedValue<GuardType, ValueType>
65{
66    fn as_mut(&mut self) -> &mut ValueType { &mut self.value }
67}
68
69/// It's safer to directly deref to the next level target, because when the
70/// ValueType is &'a Target, when we deref twice, we get &'a Target, when we
71/// deref to the next level we always get the expected &'_ Target.
72impl<GuardType, ValueType: Deref> Deref for GuardedValue<GuardType, ValueType> {
73    type Target = ValueType::Target;
74
75    fn deref(&self) -> &Self::Target { self.value.deref() }
76}
77
78impl<GuardType, ValueType: DerefMut> DerefMut
79    for GuardedValue<GuardType, ValueType>
80{
81    fn deref_mut(&mut self) -> &mut Self::Target { self.value.deref_mut() }
82}
83
84/// Ideally, we should also deref to the next level like above. However, there
85/// can be GuardedValue like Option<&'a Target>, for which we can't really do
86/// anything more, unless we introduce concept like lifetime coercion classes.
87///
88/// The goal for all implementations here is to make it hard enough to do
89/// something wrong by accident, but still keep it simple.
90impl<T: ?Sized> Deref for NonCopy<T> {
91    type Target = T;
92
93    fn deref(&self) -> &Self::Target { &self.0 }
94}
95
96impl<T: ?Sized> DerefMut for NonCopy<T> {
97    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
98}