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")); } }