1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#![no_std]
#![feature(maybe_uninit_ref)]
#![feature(maybe_uninit_extra)]
#[cfg(test)]
extern crate typenum;
#[cfg(test)]
extern crate arraystring;

use core::mem::MaybeUninit;
use core::borrow::{Borrow, BorrowMut};
use core::fmt::{self, Debug, Display};
use core::hash::{Hash, Hasher};
use core::cmp::Ordering;
use core::ops::{Deref, DerefMut};

pub struct Inplace<T>(MaybeUninit<T>);

impl<T: Debug> Debug for Inplace<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

impl<T: Display> Display for Inplace<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

impl<T: Default> Default for Inplace<T> {
    fn default() -> Inplace<T> { T::default().into() }
}

impl<T: Clone> Clone for Inplace<T> {
    fn clone(&self) -> Inplace<T> { self.as_ref().clone().into() }
}

impl<T: Copy> Copy for Inplace<T> { }

impl<T: Hash> Hash for Inplace<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.as_ref().hash(state)
    }
}

impl<T: PartialEq> PartialEq for Inplace<T> {
    fn eq(&self, other: &Self) -> bool {
        self.as_ref().eq(other.as_ref())
    }
}

impl<T: Eq> Eq for Inplace<T> { }

impl<T: Ord> Ord for Inplace<T> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl<T: PartialOrd> PartialOrd for Inplace<T> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_ref().partial_cmp(other.as_ref())
    }
}

impl<T> Inplace<T> {
    pub fn new(v: T) -> Inplace<T> { Inplace(MaybeUninit::new(v)) }
    
    pub fn deref_move(self) -> T { unsafe { self.0.assume_init() } }

    pub fn inplace<R>(&mut self, f: impl FnOnce(T) -> (R, T)) -> R {
        let (r, v) = f(unsafe { self.0.read() });
        self.0.write(v);
        r
    }

    pub fn inplace_(&mut self, f: impl FnOnce(T) -> T) {
        self.0.write(f(unsafe { self.0.read() }));
    }
}

impl<T> From<T> for Inplace<T> {
    fn from(v: T) -> Inplace<T> { Inplace::new(v) }
}

impl<T> Borrow<T> for Inplace<T> {
    fn borrow(&self) -> &T { unsafe { self.0.get_ref() } }
}

impl<T> BorrowMut<T> for Inplace<T> {
    fn borrow_mut(&mut self) -> &mut T { unsafe { self.0.get_mut() } }
}

impl<T> AsRef<T> for Inplace<T> {
    fn as_ref(&self) -> &T { unsafe { self.0.get_ref() } }
}

impl<T> AsMut<T> for Inplace<T> {
    fn as_mut(&mut self) -> &mut T { unsafe { self.0.get_mut() } }
}

impl<T> Deref for Inplace<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target { self.as_ref() }
}

impl<T> DerefMut for Inplace<T> {
    fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() }
}

#[cfg(test)]
mod tests {
    use crate::*;
    use arraystring::ArrayString;
    use typenum::{U255, U4, IsGreaterOrEqual};
    use arraystring::prelude::Capacity;

    struct UnclonableValue {
        value: ArrayString<U255>,
    }
    
    struct Container<'a> {
        value: &'a mut Inplace<UnclonableValue>,
    }
    
    fn replace<C: Capacity>(s: ArrayString<C>, f: char, t: char) -> ArrayString<C> where C: IsGreaterOrEqual<U4> {
        let mut res = ArrayString::new();
        for c in s.chars() {
            if s.len() > C::to_u8() - 4 {
                panic!();
            }
            let r = if c == f { t } else { c };
            unsafe { res.push_unchecked(r) };
        }
        res
    }
    
    fn change(v: UnclonableValue) -> UnclonableValue {
        UnclonableValue { value: replace(v.value, '0', '1') }
    }
    
    fn change_inplace(v: &mut Container) {
        v.value.inplace_(change)
    }

    #[test]
    fn it_works() {
        let mut value = UnclonableValue { value: "0123401234".into() }.into();
        let mut container = Container { value: &mut value };
        change_inplace(&mut container);
        assert_eq!(value.deref_move().value, ArrayString::from("1123411234"));
    }
}