2424 * closure is provided. Safety is ensured by bounds-checking accesses, which
2525 * are marshalled through get and set functions.
2626 *
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
2929 * 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.
3736 */
3837
3938use std:: ptr;
40- use std:: util;
4139
4240/**
4341 * The type representing a foreign chunk of memory
4442 */
4543pub struct CVec < T > {
4644 priv base : * mut T ,
4745 priv len: uint ,
48- priv rsrc : @ DtorRes ,
46+ priv rsrc : DtorRes ,
4947}
5048
5149struct DtorRes {
@@ -55,7 +53,7 @@ struct DtorRes {
5553#[ unsafe_destructor]
5654impl Drop for DtorRes {
5755 fn drop ( & mut self ) {
58- let dtor = util :: replace ( & mut self . dtor , None ) ;
56+ let dtor = self . dtor . take ( ) ;
5957 match dtor {
6058 None => ( ) ,
6159 Some ( f) => f ( )
@@ -71,138 +69,158 @@ impl DtorRes {
7169 }
7270}
7371
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+ }
7791
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+ }
93113
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+ }
113125
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+ }
117137
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+ }
128154}
129155
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 }
138159}
139160
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-
150161#[ cfg( test) ]
151162mod tests {
152163
153- use c_vec :: * ;
164+ use super :: * ;
154165
155166 use std:: libc:: * ;
156167 use std:: libc;
168+ use std:: ptr;
157169
158- fn malloc ( n : size_t ) -> CVec < u8 > {
170+ fn malloc ( n : uint ) -> CVec < u8 > {
159171 unsafe {
160- let mem = libc:: malloc ( n) ;
172+ let mem = libc:: malloc ( n as size_t ) ;
161173
162174 assert ! ( mem as int != 0 ) ;
163175
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) ; } )
167178 }
168179 }
169180
170181 #[ test]
171182 fn test_basic ( ) {
172- let cv = malloc ( 16 u as size_t ) ;
183+ let mut cv = malloc ( 16 ) ;
173184
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+ }
179198 }
180199
181200 #[ test]
182201 #[ should_fail]
183202 fn test_overrun_get ( ) {
184- let cv = malloc ( 16 u as size_t ) ;
203+ let cv = malloc ( 16 ) ;
185204
186- get ( cv , 17 u ) ;
205+ cv . get ( 17 ) ;
187206 }
188207
189208 #[ test]
190209 #[ should_fail]
191210 fn test_overrun_set ( ) {
192- let cv = malloc ( 16 u as size_t ) ;
211+ let mut cv = malloc ( 16 ) ;
193212
194- set ( cv , 17 u , 0u8 ) ;
213+ * cv . get_mut ( 17 ) = 0 ;
195214 }
196215
197216 #[ 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+ }
206224 }
207225
208226}
0 commit comments