@@ -158,6 +158,147 @@ impl<R> Volatile<R> {
158
158
}
159
159
}
160
160
161
+ /// Method for extracting the wrapped value.
162
+ impl < R , A > Volatile < R , A > {
163
+ /// Extracts the inner value stored in the wrapper type.
164
+ ///
165
+ /// This method gives direct access to the wrapped reference and thus allows
166
+ /// non-volatile access again. This is seldom what you want since there is usually
167
+ /// a reason that a reference is wrapped in `Volatile`. However, in some cases it might
168
+ /// be required or useful to use the `read_volatile`/`write_volatile` pointer methods of
169
+ /// the standard library directly, which this method makes possible.
170
+ ///
171
+ /// Since no memory safety violation can occur when accessing the referenced value using
172
+ /// non-volatile operations, this method is safe. However, it _can_ lead to bugs at the
173
+ /// application level, so this method should be used with care.
174
+ ///
175
+ /// ## Example
176
+ ///
177
+ /// ```
178
+ /// use volatile::Volatile;
179
+ ///
180
+ /// let mut value = 42;
181
+ /// let mut volatile = Volatile::new(&mut value);
182
+ /// volatile.write(50);
183
+ /// let unwrapped: &mut i32 = volatile.extract_inner();
184
+ ///
185
+ /// assert_eq!(*unwrapped, 50); // non volatile access, be careful!
186
+ /// ```
187
+ pub fn extract_inner ( self ) -> R {
188
+ self . reference
189
+ }
190
+ }
191
+
192
+ /// Transformation methods for accessing struct fields
193
+ impl < R , T , A > Volatile < R , A >
194
+ where
195
+ R : Deref < Target = T > ,
196
+ T : ?Sized ,
197
+ {
198
+ /// Constructs a new `Volatile` reference by mapping the wrapped value.
199
+ ///
200
+ /// This method is useful for accessing individual fields of volatile structs.
201
+ ///
202
+ /// Note that this method gives temporary access to the wrapped reference, which allows
203
+ /// accessing the value in a non-volatile way. This is normally not what you want, so
204
+ /// **this method should only be used for reference-to-reference transformations**.
205
+ ///
206
+ /// ## Examples
207
+ ///
208
+ /// Accessing a struct field:
209
+ ///
210
+ /// ```
211
+ /// use volatile::Volatile;
212
+ ///
213
+ /// struct Example { field_1: u32, field_2: u8, }
214
+ /// let mut value = Example { field_1: 15, field_2: 255 };
215
+ /// let mut volatile = Volatile::new(&mut value);
216
+ ///
217
+ /// // construct a volatile reference to a field
218
+ /// let field_2 = volatile.map(|example| &example.field_2);
219
+ /// assert_eq!(field_2.read(), 255);
220
+ /// ```
221
+ ///
222
+ /// Don't misuse this method to do a non-volatile read of the referenced value:
223
+ ///
224
+ /// ```
225
+ /// use volatile::Volatile;
226
+ ///
227
+ /// let mut value = 5;
228
+ /// let mut volatile = Volatile::new(&mut value);
229
+ ///
230
+ /// // DON'T DO THIS:
231
+ /// let mut readout = 0;
232
+ /// volatile.map(|value| {
233
+ /// readout = *value; // non-volatile read, might lead to bugs
234
+ /// value
235
+ /// });
236
+ /// ```
237
+ pub fn map < ' a , F , U > ( & ' a self , f : F ) -> Volatile < & ' a U , A >
238
+ where
239
+ F : FnOnce ( & ' a T ) -> & ' a U ,
240
+ U : ?Sized ,
241
+ T : ' a ,
242
+ {
243
+ Volatile {
244
+ reference : f ( self . reference . deref ( ) ) ,
245
+ access : self . access ,
246
+ }
247
+ }
248
+
249
+ /// Constructs a new mutable `Volatile` reference by mapping the wrapped value.
250
+ ///
251
+ /// This method is useful for accessing individual fields of volatile structs.
252
+ ///
253
+ /// Note that this method gives temporary access to the wrapped reference, which allows
254
+ /// accessing the value in a non-volatile way. This is normally not what you want, so
255
+ /// **this method should only be used for reference-to-reference transformations**.
256
+ ///
257
+ /// ## Examples
258
+ ///
259
+ /// Accessing a struct field:
260
+ ///
261
+ /// ```
262
+ /// use volatile::Volatile;
263
+ ///
264
+ /// struct Example { field_1: u32, field_2: u8, }
265
+ /// let mut value = Example { field_1: 15, field_2: 255 };
266
+ /// let mut volatile = Volatile::new(&mut value);
267
+ ///
268
+ /// // construct a volatile reference to a field
269
+ /// let mut field_2 = volatile.map_mut(|example| &mut example.field_2);
270
+ /// field_2.write(128);
271
+ /// assert_eq!(field_2.read(), 128);
272
+ /// ```
273
+ ///
274
+ /// Don't misuse this method to do a non-volatile read or write of the referenced value:
275
+ ///
276
+ /// ```
277
+ /// use volatile::Volatile;
278
+ ///
279
+ /// let mut value = 5;
280
+ /// let mut volatile = Volatile::new(&mut value);
281
+ ///
282
+ /// // DON'T DO THIS:
283
+ /// volatile.map_mut(|value| {
284
+ /// *value = 10; // non-volatile write, might lead to bugs
285
+ /// value
286
+ /// });
287
+ /// ```
288
+ pub fn map_mut < ' a , F , U > ( & ' a mut self , f : F ) -> Volatile < & ' a mut U , A >
289
+ where
290
+ F : FnOnce ( & mut T ) -> & mut U ,
291
+ R : DerefMut ,
292
+ U : ?Sized ,
293
+ T : ' a ,
294
+ {
295
+ Volatile {
296
+ reference : f ( & mut self . reference ) ,
297
+ access : self . access ,
298
+ }
299
+ }
300
+ }
301
+
161
302
/// Methods for references to `Copy` types
162
303
impl < R , T , A > Volatile < R , A >
163
304
where
@@ -501,4 +642,24 @@ mod tests {
501
642
volatile. index_mut ( 0 ) . update ( |v| * v += 1 ) ;
502
643
assert_eq ! ( val, [ 2 , 2 , 3 ] ) ;
503
644
}
645
+
646
+ #[ test]
647
+ fn test_struct ( ) {
648
+ struct S {
649
+ field_1 : u32 ,
650
+ field_2 : bool ,
651
+ }
652
+
653
+ let mut val = S {
654
+ field_1 : 60 ,
655
+ field_2 : true ,
656
+ } ;
657
+ let mut volatile = Volatile :: new ( & mut val) ;
658
+ volatile. map_mut ( |s| & mut s. field_1 ) . update ( |v| * v += 1 ) ;
659
+ let mut field_2 = volatile. map_mut ( |s| & mut s. field_2 ) ;
660
+ assert ! ( field_2. read( ) ) ;
661
+ field_2. write ( false ) ;
662
+ assert_eq ! ( volatile. map( |s| & s. field_1) . read( ) , 61 ) ;
663
+ assert_eq ! ( volatile. map( |s| & s. field_2) . read( ) , false ) ;
664
+ }
504
665
}
0 commit comments