24
24
* closure is provided. Safety is ensured by bounds-checking accesses, which
25
25
* are marshalled through get and set functions.
26
26
*
27
- * There are three unsafe functions: the two introduction forms , and the
28
- * pointer elimination form. The introduction forms are unsafe for the
27
+ * There are three unsafe functions: the two constructors , and the
28
+ * unwrap method. The constructors are unsafe for the
29
29
* obvious reason (they act on a pointer that cannot be checked inside the
30
- * method), but the elimination form is somewhat more subtle in its unsafety.
31
- * By using a pointer taken from a c_vec::t without keeping a reference to the
32
- * c_vec::t itself around, the CVec could be garbage collected, and the
33
- * memory within could be destroyed. There are legitimate uses for the
34
- * pointer elimination form -- for instance, to pass memory back into C -- but
35
- * great care must be taken to ensure that a reference to the c_vec::t is
36
- * still held if needed.
30
+ * method), but `unwrap()` is somewhat more subtle in its unsafety.
31
+ * It returns the contained pointer, but at the same time destroys the CVec
32
+ * without running its destructor. This can be used to pass memory back to
33
+ * C, but care must be taken that the ownership of underlying resources are
34
+ * handled correctly, i.e. that allocated memory is eventually freed
35
+ * if necessary.
37
36
*/
38
37
39
38
use std:: ptr;
40
- use std:: util;
41
39
42
40
/**
43
41
* The type representing a foreign chunk of memory
44
42
*/
45
43
pub struct CVec < T > {
46
44
priv base : * mut T ,
47
45
priv len: uint ,
48
- priv rsrc : @ DtorRes ,
46
+ priv rsrc : DtorRes ,
49
47
}
50
48
51
49
struct DtorRes {
@@ -55,7 +53,7 @@ struct DtorRes {
55
53
#[ unsafe_destructor]
56
54
impl Drop for DtorRes {
57
55
fn drop ( & mut self ) {
58
- let dtor = util :: replace ( & mut self . dtor , None ) ;
56
+ let dtor = self . dtor . take ( ) ;
59
57
match dtor {
60
58
None => ( ) ,
61
59
Some ( f) => f ( )
@@ -71,138 +69,158 @@ impl DtorRes {
71
69
}
72
70
}
73
71
74
- /*
75
- Section: Introduction forms
76
- */
72
+ impl < T > CVec < T > {
73
+ /**
74
+ * Create a `CVec` from a raw pointer to a buffer with a given length.
75
+ *
76
+ * Fails if the given pointer is null.
77
+ *
78
+ * # Arguments
79
+ *
80
+ * * base - A raw pointer to a buffer
81
+ * * len - The number of elements in the buffer
82
+ */
83
+ pub unsafe fn new ( base : * mut T , len : uint ) -> CVec < T > {
84
+ assert ! ( base != ptr:: mut_null( ) ) ;
85
+ CVec {
86
+ base : base,
87
+ len : len,
88
+ rsrc : DtorRes :: new ( None )
89
+ }
90
+ }
77
91
78
- /**
79
- * Create a `CVec` from a foreign buffer with a given length.
80
- *
81
- * # Arguments
82
- *
83
- * * base - A foreign pointer to a buffer
84
- * * len - The number of elements in the buffer
85
- */
86
- pub unsafe fn CVec < T > ( base : * mut T , len : uint ) -> CVec < T > {
87
- return CVec {
88
- base : base,
89
- len : len,
90
- rsrc : @DtorRes :: new ( None )
91
- } ;
92
- }
92
+ /**
93
+ * Create a `CVec` from a foreign buffer, with a given length,
94
+ * and a function to run upon destruction.
95
+ *
96
+ * Fails if the given pointer is null.
97
+ *
98
+ * # Arguments
99
+ *
100
+ * * base - A foreign pointer to a buffer
101
+ * * len - The number of elements in the buffer
102
+ * * dtor - A proc to run when the value is destructed, useful
103
+ * for freeing the buffer, etc.
104
+ */
105
+ pub unsafe fn new_with_dtor ( base : * mut T , len : uint , dtor : proc ( ) ) -> CVec < T > {
106
+ assert ! ( base != ptr:: mut_null( ) ) ;
107
+ CVec {
108
+ base : base,
109
+ len : len,
110
+ rsrc : DtorRes :: new ( Some ( dtor) )
111
+ }
112
+ }
93
113
94
- /**
95
- * Create a `CVec` from a foreign buffer, with a given length,
96
- * and a function to run upon destruction.
97
- *
98
- * # Arguments
99
- *
100
- * * base - A foreign pointer to a buffer
101
- * * len - The number of elements in the buffer
102
- * * dtor - A function to run when the value is destructed, useful
103
- * for freeing the buffer, etc.
104
- */
105
- pub unsafe fn c_vec_with_dtor < T > ( base : * mut T , len : uint , dtor : proc ( ) )
106
- -> CVec < T > {
107
- return CVec {
108
- base : base,
109
- len : len,
110
- rsrc : @DtorRes :: new ( Some ( dtor) )
111
- } ;
112
- }
114
+ /**
115
+ * Retrieves an element at a given index
116
+ *
117
+ * Fails if `ofs` is greater or equal to the length of the vector
118
+ */
119
+ pub fn get < ' a > ( & ' a self , ofs : uint ) -> & ' a T {
120
+ assert ! ( ofs < self . len) ;
121
+ unsafe {
122
+ & * ptr:: mut_offset ( self . base , ofs as int )
123
+ }
124
+ }
113
125
114
- /*
115
- Section: Operations
116
- */
126
+ /**
127
+ * Retrieves a mutable element at a given index
128
+ *
129
+ * Fails if `ofs` is greater or equal to the length of the vector
130
+ */
131
+ pub fn get_mut < ' a > ( & ' a mut self , ofs : uint ) -> & ' a mut T {
132
+ assert ! ( ofs < self . len) ;
133
+ unsafe {
134
+ & mut * ptr:: mut_offset ( self . base , ofs as int )
135
+ }
136
+ }
117
137
118
- /**
119
- * Retrieves an element at a given index
120
- *
121
- * Fails if `ofs` is greater or equal to the length of the vector
122
- */
123
- pub fn get < T : Clone > ( t : CVec < T > , ofs : uint ) -> T {
124
- assert ! ( ofs < len( t) ) ;
125
- return unsafe {
126
- ( * ptr:: mut_offset ( t. base , ofs as int ) ) . clone ( )
127
- } ;
138
+ /**
139
+ * Unwrap the pointer without running the destructor
140
+ *
141
+ * This method retrieves the underlying pointer, and in the process
142
+ * destroys the CVec but without running the destructor. A use case
143
+ * would be transferring ownership of the buffer to a C function, as
144
+ * in this case you would not want to run the destructor.
145
+ *
146
+ * Note that if you want to access the underlying pointer without
147
+ * cancelling the destructor, you can simply call `transmute` on the return
148
+ * value of `get(0)`.
149
+ */
150
+ pub unsafe fn unwrap ( mut self ) -> * mut T {
151
+ self . rsrc . dtor = None ;
152
+ self . base
153
+ }
128
154
}
129
155
130
- /**
131
- * Sets the value of an element at a given index
132
- *
133
- * Fails if `ofs` is greater or equal to the length of the vector
134
- */
135
- pub fn set < T > ( t : CVec < T > , ofs : uint , v : T ) {
136
- assert ! ( ofs < len( t) ) ;
137
- unsafe { * ptr:: mut_offset ( t. base , ofs as int ) = v } ;
156
+ impl < T > Container for CVec < T > {
157
+ /// Returns the length of the vector
158
+ fn len ( & self ) -> uint { self . len }
138
159
}
139
160
140
- /*
141
- Section: Elimination forms
142
- */
143
-
144
- /// Returns the length of the vector
145
- pub fn len < T > ( t : CVec < T > ) -> uint { t. len }
146
-
147
- /// Returns a pointer to the first element of the vector
148
- pub unsafe fn ptr < T > ( t : CVec < T > ) -> * mut T { t. base }
149
-
150
161
#[ cfg( test) ]
151
162
mod tests {
152
163
153
- use c_vec :: * ;
164
+ use super :: * ;
154
165
155
166
use std:: libc:: * ;
156
167
use std:: libc;
168
+ use std:: ptr;
157
169
158
- fn malloc ( n : size_t ) -> CVec < u8 > {
170
+ fn malloc ( n : uint ) -> CVec < u8 > {
159
171
unsafe {
160
- let mem = libc:: malloc ( n) ;
172
+ let mem = libc:: malloc ( n as size_t ) ;
161
173
162
174
assert ! ( mem as int != 0 ) ;
163
175
164
- return c_vec_with_dtor ( mem as * mut u8 ,
165
- n as uint ,
166
- proc ( ) unsafe { libc:: free ( mem) ; } ) ;
176
+ CVec :: new_with_dtor ( mem as * mut u8 , n,
177
+ proc ( ) { libc:: free ( mem) ; } )
167
178
}
168
179
}
169
180
170
181
#[ test]
171
182
fn test_basic ( ) {
172
- let cv = malloc ( 16 u as size_t ) ;
183
+ let mut cv = malloc ( 16 ) ;
173
184
174
- set ( cv, 3 u, 8u8 ) ;
175
- set ( cv, 4 u, 9u8 ) ;
176
- assert_eq ! ( get( cv, 3 u) , 8u8 ) ;
177
- assert_eq ! ( get( cv, 4 u) , 9u8 ) ;
178
- assert_eq ! ( len( cv) , 16 u) ;
185
+ * cv. get_mut ( 3 ) = 8 ;
186
+ * cv. get_mut ( 4 ) = 9 ;
187
+ assert_eq ! ( * cv. get( 3 ) , 8 ) ;
188
+ assert_eq ! ( * cv. get( 4 ) , 9 ) ;
189
+ assert_eq ! ( cv. len( ) , 16 ) ;
190
+ }
191
+
192
+ #[ test]
193
+ #[ should_fail]
194
+ fn test_fail_at_null ( ) {
195
+ unsafe {
196
+ CVec :: new ( ptr:: mut_null :: < u8 > ( ) , 9 ) ;
197
+ }
179
198
}
180
199
181
200
#[ test]
182
201
#[ should_fail]
183
202
fn test_overrun_get ( ) {
184
- let cv = malloc ( 16 u as size_t ) ;
203
+ let cv = malloc ( 16 ) ;
185
204
186
- get ( cv , 17 u ) ;
205
+ cv . get ( 17 ) ;
187
206
}
188
207
189
208
#[ test]
190
209
#[ should_fail]
191
210
fn test_overrun_set ( ) {
192
- let cv = malloc ( 16 u as size_t ) ;
211
+ let mut cv = malloc ( 16 ) ;
193
212
194
- set ( cv , 17 u , 0u8 ) ;
213
+ * cv . get_mut ( 17 ) = 0 ;
195
214
}
196
215
197
216
#[ test]
198
- fn test_and_I_mean_it ( ) {
199
- let cv = malloc ( 16 u as size_t ) ;
200
- let p = unsafe { ptr ( cv) } ;
201
-
202
- set ( cv, 0 u, 32u8 ) ;
203
- set ( cv, 1 u, 33u8 ) ;
204
- assert_eq ! ( unsafe { * p } , 32u8 ) ;
205
- set ( cv, 2 u, 34u8 ) ; /* safety */
217
+ fn test_unwrap ( ) {
218
+ unsafe {
219
+ let cv = CVec :: new_with_dtor ( 1 as * mut int , 0 ,
220
+ proc ( ) { fail ! ( "Don't run this destructor!" ) } ) ;
221
+ let p = cv. unwrap ( ) ;
222
+ assert_eq ! ( p, 1 as * mut int) ;
223
+ }
206
224
}
207
225
208
226
}
0 commit comments