16
16
#![ warn( missing_docs) ]
17
17
#![ deny( unsafe_op_in_unsafe_fn) ]
18
18
19
- use access:: { ReadOnly , ReadWrite , Readable , Writable , WriteOnly } ;
19
+ use access:: {
20
+ ReadOnly , ReadWrite , Readable , UnsafelyReadable , UnsafelyWritable , Writable , WriteOnly ,
21
+ } ;
20
22
use core:: { fmt, marker:: PhantomData , ptr} ;
21
23
#[ cfg( feature = "unstable" ) ]
22
24
use core:: {
@@ -178,6 +180,30 @@ where
178
180
f ( & mut value) ;
179
181
self . write ( value) ;
180
182
}
183
+
184
+ pub unsafe fn read_unsafe ( & self ) -> T
185
+ where
186
+ A : UnsafelyReadable ,
187
+ {
188
+ unsafe { ptr:: read_volatile ( self . pointer ) }
189
+ }
190
+
191
+ pub unsafe fn write_unsafe ( & mut self , value : T )
192
+ where
193
+ A : UnsafelyWritable ,
194
+ {
195
+ unsafe { ptr:: write_volatile ( self . pointer , value) } ;
196
+ }
197
+
198
+ pub unsafe fn update_unsafe < F > ( & mut self , f : F )
199
+ where
200
+ A : UnsafelyReadable + UnsafelyWritable ,
201
+ F : FnOnce ( & mut T ) ,
202
+ {
203
+ let mut value = unsafe { self . read_unsafe ( ) } ;
204
+ f ( & mut value) ;
205
+ unsafe { self . write_unsafe ( value) } ;
206
+ }
181
207
}
182
208
183
209
/// Method for extracting the wrapped value.
@@ -765,7 +791,7 @@ macro_rules! map_field_mut {
765
791
766
792
#[ cfg( test) ]
767
793
mod tests {
768
- use super :: Volatile ;
794
+ use super :: { access :: * , Volatile } ;
769
795
use core:: cell:: UnsafeCell ;
770
796
771
797
#[ test]
@@ -790,6 +816,92 @@ mod tests {
790
816
assert_eq ! ( val, 43 ) ;
791
817
}
792
818
819
+ #[ test]
820
+ fn test_access ( ) {
821
+ let mut val: i64 = 42 ;
822
+
823
+ // ReadWrite
824
+ assert_eq ! ( unsafe { Volatile :: new( & mut val, ReadWrite ) } . read( ) , 42 ) ;
825
+ unsafe { Volatile :: new ( & mut val, ReadWrite ) } . write ( 50 ) ;
826
+ assert_eq ! ( val, 50 ) ;
827
+ unsafe { Volatile :: new ( & mut val, ReadWrite ) } . update ( |i| * i += 1 ) ;
828
+ assert_eq ! ( val, 51 ) ;
829
+
830
+ // ReadOnly and WriteOnly
831
+ assert_eq ! ( unsafe { Volatile :: new( & mut val, ReadOnly ) } . read( ) , 51 ) ;
832
+ unsafe { Volatile :: new ( & mut val, WriteOnly ) } . write ( 12 ) ;
833
+ assert_eq ! ( val, 12 ) ;
834
+
835
+ // Custom: safe read + safe write
836
+ {
837
+ let access = Custom {
838
+ read : SafeAccess ,
839
+ write : SafeAccess ,
840
+ } ;
841
+ let mut volatile = unsafe { Volatile :: new ( & mut val, access) } ;
842
+ let random: i32 = rand:: random ( ) ;
843
+ volatile. write ( i64:: from ( random) ) ;
844
+ assert_eq ! ( volatile. read( ) , i64 :: from( random) ) ;
845
+ let random2: i32 = rand:: random ( ) ;
846
+ volatile. update ( |i| * i += i64:: from ( random2) ) ;
847
+ assert_eq ! ( volatile. read( ) , i64 :: from( random) + i64 :: from( random2) ) ;
848
+ }
849
+
850
+ // Custom: safe read + unsafe write
851
+ {
852
+ let access = Custom {
853
+ read : SafeAccess ,
854
+ write : UnsafeAccess ,
855
+ } ;
856
+ let mut volatile = unsafe { Volatile :: new ( & mut val, access) } ;
857
+ let random: i32 = rand:: random ( ) ;
858
+ unsafe { volatile. write_unsafe ( i64:: from ( random) ) } ;
859
+ assert_eq ! ( volatile. read( ) , i64 :: from( random) ) ;
860
+ let random2: i32 = rand:: random ( ) ;
861
+ unsafe { volatile. update_unsafe ( |i| * i += i64:: from ( random2) ) } ;
862
+ assert_eq ! ( volatile. read( ) , i64 :: from( random) + i64 :: from( random2) ) ;
863
+ }
864
+
865
+ // Custom: safe read + no write
866
+ {
867
+ let access = Custom {
868
+ read : SafeAccess ,
869
+ write : NoAccess ,
870
+ } ;
871
+ let random = rand:: random ( ) ;
872
+ val = random;
873
+ let mut volatile = unsafe { Volatile :: new ( & mut val, access) } ;
874
+ assert_eq ! ( volatile. read( ) , i64 :: from( random) ) ;
875
+ }
876
+
877
+ // Custom: unsafe read + safe write
878
+ {
879
+ let access = Custom {
880
+ read : UnsafeAccess ,
881
+ write : SafeAccess ,
882
+ } ;
883
+ let mut volatile = unsafe { Volatile :: new ( & mut val, access) } ;
884
+ let random: i32 = rand:: random ( ) ;
885
+ volatile. write ( i64:: from ( random) ) ;
886
+ assert_eq ! ( unsafe { volatile. read_unsafe( ) } , i64 :: from( random) ) ;
887
+ let random2: i32 = rand:: random ( ) ;
888
+ volatile. update_unsafe ( |i| * i += i64:: from ( random2) ) ;
889
+ assert_eq ! (
890
+ volatile. read_unsafe( ) ,
891
+ i64 :: from( random) + i64 :: from( random2)
892
+ ) ;
893
+ }
894
+
895
+ // Todo: Custom: unsafe read + unsafe write
896
+ // Todo: Custom: unsafe read + no write
897
+ // Todo: Custom: no read + safe write
898
+ // Todo: Custom: no read + unsafe write
899
+ // Todo: Custom: no read + no write
900
+
901
+ // Todo: is there a way to check that a compile error occurs when trying to use
902
+ // unavailable methods (e.g. `write` when write permission is `UnsafeAccess`)?
903
+ }
904
+
793
905
#[ test]
794
906
fn test_struct ( ) {
795
907
#[ derive( Debug , PartialEq ) ]
0 commit comments