@@ -47,6 +47,15 @@ impl CommonMmap {
47
47
CommonMmap :: Mmap ( _) => Ok ( ( ) ) ,
48
48
}
49
49
}
50
+
51
+ /// Gets the slice
52
+ #[ inline]
53
+ pub fn as_slice ( & self ) -> & [ u8 ] {
54
+ match self {
55
+ CommonMmap :: MmapMut ( x) => x. as_ref ( ) ,
56
+ CommonMmap :: Mmap ( x) => x. as_ref ( ) ,
57
+ }
58
+ }
50
59
}
51
60
52
61
/// Bit vector backed by a mmap-ed file
@@ -69,6 +78,32 @@ pub struct MmapBitVec {
69
78
is_anon : bool ,
70
79
}
71
80
81
+ fn create_bitvec_file (
82
+ filename : & Path ,
83
+ size : usize ,
84
+ magic : [ u8 ; 2 ] ,
85
+ header : & [ u8 ] ,
86
+ ) -> Result < ( std:: fs:: File , u64 ) , io:: Error > {
87
+ let byte_size = ( ( size - 1 ) >> 3 ) as u64 + 1 ;
88
+ let mut file = OpenOptions :: new ( )
89
+ . read ( true )
90
+ . write ( true )
91
+ . create ( true )
92
+ . open ( filename) ?;
93
+ // two magic bytes, u16 header length, header, u64 bitvec length, bitvec
94
+ let total_header_size = ( 2 + 2 + header. len ( ) + 8 ) as u64 ;
95
+ file. set_len ( total_header_size + byte_size) ?;
96
+
97
+ file. write_all ( & magic) ?;
98
+ let serialized_header_size: [ u8 ; 2 ] = ( header. len ( ) as u16 ) . to_be_bytes ( ) ;
99
+ file. write_all ( & serialized_header_size) ?;
100
+ file. write_all ( header) ?;
101
+ let serialized_size: [ u8 ; 8 ] = ( size as u64 ) . to_be_bytes ( ) ;
102
+ file. write_all ( & serialized_size) ?;
103
+
104
+ Ok ( ( file, total_header_size) )
105
+ }
106
+
72
107
impl MmapBitVec {
73
108
/// Creates a new `MmapBitVec` file
74
109
///
@@ -85,26 +120,7 @@ impl MmapBitVec {
85
120
"Headers longer than 65636 bytes not supported"
86
121
) ;
87
122
88
- let byte_size = ( ( size - 1 ) >> 3 ) as u64 + 1 ;
89
- // if we're creating the file, we need to make sure it's bug enough for our
90
- // purposes (memmap doesn't automatically size the file)
91
- let mut file = OpenOptions :: new ( )
92
- . read ( true )
93
- . write ( true )
94
- . create ( true )
95
- . open ( filename) ?;
96
- // two magic bytes, u16 header length, header, u64 bitvec length, bitvec
97
- let total_header_size = ( 2 + 2 + header. len ( ) + 8 ) as u64 ;
98
- file. set_len ( total_header_size + byte_size) ?;
99
- // file.seek(io::SeekFrom::Start(0))?;
100
-
101
- file. write_all ( & magic) ?;
102
- let serialized_header_size: [ u8 ; 2 ] = ( header. len ( ) as u16 ) . to_be_bytes ( ) ;
103
- file. write_all ( & serialized_header_size) ?;
104
- file. write_all ( header) ?;
105
- let serialized_size: [ u8 ; 8 ] = ( size as u64 ) . to_be_bytes ( ) ;
106
- file. write_all ( & serialized_size) ?;
107
-
123
+ let ( file, total_header_size) = create_bitvec_file ( filename. as_ref ( ) , size, magic, header) ?;
108
124
let mmap = unsafe { MmapOptions :: new ( ) . offset ( total_header_size) . map_mut ( & file) } ?;
109
125
Ok ( MmapBitVec {
110
126
mmap : CommonMmap :: MmapMut ( mmap) ,
@@ -227,27 +243,21 @@ impl MmapBitVec {
227
243
} )
228
244
}
229
245
230
- /// Converts an in-memory mmap bitvector to a file-backed one .
246
+ /// Save in-memory mmap bitvector to disk .
231
247
/// This is a no-op if the mmap is already file-backed.
232
- /// Returns the new mmap after flushing.
233
- pub fn into_mmap_file < P : AsRef < Path > > (
234
- self ,
248
+ pub fn save_to_disk < P : AsRef < Path > > (
249
+ & self ,
235
250
filename : P ,
236
251
magic : [ u8 ; 2 ] ,
237
252
header : & [ u8 ] ,
238
- ) -> Result < Self , io:: Error > {
253
+ ) -> Result < ( ) , io:: Error > {
239
254
if !self . is_anon {
240
- return Ok ( self ) ;
241
- }
242
- let mut file_mmap = MmapBitVec :: create ( filename, self . size , magic, header) ?;
243
-
244
- // Not super efficient
245
- for i in 0 ..self . size {
246
- file_mmap. set ( i, self . get ( i) ) ;
255
+ return Ok ( ( ) ) ;
247
256
}
248
- file_mmap. mmap . flush ( ) ?;
249
-
250
- Ok ( file_mmap)
257
+ let ( mut file, _) = create_bitvec_file ( filename. as_ref ( ) , self . size , magic, header) ?;
258
+ // We should already be at the right byte to write the content
259
+ file. write_all ( self . mmap . as_slice ( ) ) ?;
260
+ Ok ( ( ) )
251
261
}
252
262
253
263
/// Returns the header
@@ -814,15 +824,17 @@ mod test {
814
824
}
815
825
816
826
#[ test]
817
- fn can_convert_memory_to_file ( ) {
827
+ fn can_write_anon_mmap_to_disk ( ) {
818
828
let mut b = MmapBitVec :: from_memory ( 128 ) . unwrap ( ) ;
829
+ b. set ( 0 , true ) ;
819
830
b. set ( 7 , true ) ;
820
831
b. set ( 56 , true ) ;
821
832
b. set ( 127 , true ) ;
822
833
let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
823
- let f = b
824
- . into_mmap_file ( dir. path ( ) . join ( "test" ) , * b"!!" , & [ ] )
834
+ b. save_to_disk ( dir. path ( ) . join ( "test" ) , * b"!!" , & [ ] )
825
835
. unwrap ( ) ;
836
+ let f = MmapBitVec :: open ( dir. path ( ) . join ( "test" ) , Some ( b"!!" ) , false ) . unwrap ( ) ;
837
+ assert_eq ! ( f. get( 0 ) , true ) ;
826
838
assert_eq ! ( f. get( 7 ) , true ) ;
827
839
assert_eq ! ( f. get( 56 ) , true ) ;
828
840
assert_eq ! ( f. get( 127 ) , true ) ;
0 commit comments