@@ -20,31 +20,49 @@ pub struct SerializationSink {
20
20
}
21
21
22
22
/// The `BackingStorage` is what the data gets written to.
23
- trait BackingStorage : Write + Send + Debug {
23
+ #[ derive( Debug ) ]
24
+ enum BackingStorage {
25
+ File ( fs:: File ) ,
26
+ Memory ( Vec < u8 > ) ,
27
+ }
28
+
29
+ impl BackingStorage {
24
30
/// Moves all data written so far out into a `Vec<u8>`. This method only
25
31
/// exists so we can write unit tests that don't need to touch the
26
- /// file system. The method is allowed to unconditionally panic for
27
- /// non-test implementations.
28
- fn drain_bytes ( & mut self ) -> Vec < u8 > ;
32
+ /// file system. The method will panic if `self` is `BackingStorage::Memory`.
33
+ fn into_bytes ( self ) -> Vec < u8 > {
34
+ match self {
35
+ BackingStorage :: File ( _) => {
36
+ panic ! ( "into_bytes() is not supported for BackingStorage::File" )
37
+ }
38
+ BackingStorage :: Memory ( data) => data,
39
+ }
40
+ }
29
41
}
30
42
31
- impl BackingStorage for fs:: File {
32
- fn drain_bytes ( & mut self ) -> Vec < u8 > {
33
- unimplemented ! ( )
43
+ impl Write for BackingStorage {
44
+ #[ inline]
45
+ fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
46
+ match * self {
47
+ BackingStorage :: File ( ref mut file) => file. write ( buf) ,
48
+ BackingStorage :: Memory ( ref mut vec) => vec. write ( buf) ,
49
+ }
34
50
}
35
- }
36
51
37
- impl BackingStorage for Vec < u8 > {
38
- fn drain_bytes ( & mut self ) -> Vec < u8 > {
39
- let mut bytes = Vec :: new ( ) ;
40
- std:: mem:: swap ( & mut bytes, self ) ;
41
- bytes
52
+ fn flush ( & mut self ) -> std:: io:: Result < ( ) > {
53
+ match * self {
54
+ BackingStorage :: File ( ref mut file) => file. flush ( ) ,
55
+ BackingStorage :: Memory ( _) => {
56
+ // Nothing to do
57
+ Ok ( ( ) )
58
+ }
59
+ }
42
60
}
43
61
}
44
62
45
63
#[ derive( Debug ) ]
46
64
struct Inner {
47
- file : Box < dyn BackingStorage > ,
65
+ file : BackingStorage ,
48
66
buffer : Vec < u8 > ,
49
67
buf_pos : usize ,
50
68
addr : u32 ,
@@ -54,7 +72,7 @@ impl SerializationSink {
54
72
pub fn new_in_memory ( ) -> SerializationSink {
55
73
SerializationSink {
56
74
data : Mutex :: new ( Inner {
57
- file : Box :: new ( Vec :: new ( ) ) ,
75
+ file : BackingStorage :: Memory ( Vec :: new ( ) ) ,
58
76
buffer : vec ! [ 0 ; 1024 * 512 ] ,
59
77
buf_pos : 0 ,
60
78
addr : 0 ,
@@ -65,21 +83,30 @@ impl SerializationSink {
65
83
/// Create a copy of all data written so far. This method meant to be used
66
84
/// for writing unit tests. It will panic if the underlying `BackingStorage`
67
85
/// does not implement `extract_bytes`.
68
- pub fn into_bytes ( self ) -> Vec < u8 > {
69
- let mut data = self . data . lock ( ) ;
86
+ pub fn into_bytes ( mut self ) -> Vec < u8 > {
87
+ // Swap out the contains of `self` with something that can safely be
88
+ // dropped without side effects.
89
+ let mut data = Mutex :: new ( Inner {
90
+ file : BackingStorage :: Memory ( Vec :: new ( ) ) ,
91
+ buffer : Vec :: new ( ) ,
92
+ buf_pos : 0 ,
93
+ addr : 0 ,
94
+ } ) ;
95
+ std:: mem:: swap ( & mut self . data , & mut data) ;
96
+
97
+ // Extract the data from the mutex.
70
98
let Inner {
71
- ref mut file,
72
- ref mut buffer,
73
- ref mut buf_pos,
99
+ mut file,
100
+ buffer,
101
+ buf_pos,
74
102
addr : _,
75
- } = * data;
103
+ } = data. into_inner ( ) ;
76
104
77
- // We need to flush the buffer first.
78
- file. write_all ( & buffer[ ..* buf_pos] ) . unwrap ( ) ;
79
- * buf_pos = 0 ;
105
+ // Flush the buffer, so all data written so far is in `file`.
106
+ file. write_all ( & buffer[ ..buf_pos] ) . unwrap ( ) ;
80
107
81
- // Then we can create a copy of the data written so far .
82
- file. drain_bytes ( )
108
+ // Then extract the actual bytes .
109
+ file. into_bytes ( )
83
110
}
84
111
85
112
pub fn from_path ( path : & Path ) -> Result < Self , Box < dyn Error + Send + Sync > > {
@@ -89,7 +116,7 @@ impl SerializationSink {
89
116
90
117
Ok ( SerializationSink {
91
118
data : Mutex :: new ( Inner {
92
- file : Box :: new ( file) ,
119
+ file : BackingStorage :: File ( file) ,
93
120
buffer : vec ! [ 0 ; 1024 * 512 ] ,
94
121
buf_pos : 0 ,
95
122
addr : 0 ,
0 commit comments