@@ -62,6 +62,8 @@ pub enum AioCancelStat {
62
62
#[ repr( C ) ]
63
63
pub struct AioCb < ' a > {
64
64
aiocb : libc:: aiocb ,
65
+ /// Tracks whether the buffer pointed to by aiocb.aio_buf is mutable
66
+ mutable : bool ,
65
67
phantom : PhantomData < & ' a mut [ u8 ] >
66
68
}
67
69
@@ -81,7 +83,7 @@ impl<'a> AioCb<'a> {
81
83
a. aio_nbytes = 0 ;
82
84
a. aio_buf = null_mut ( ) ;
83
85
84
- let aiocb = AioCb { aiocb : a, phantom : PhantomData } ;
86
+ let aiocb = AioCb { aiocb : a, mutable : false , phantom : PhantomData } ;
85
87
aiocb
86
88
}
87
89
@@ -102,37 +104,39 @@ impl<'a> AioCb<'a> {
102
104
let mut a = AioCb :: common_init ( fd, prio, sigev_notify) ;
103
105
a. aio_offset = offs;
104
106
a. aio_nbytes = buf. len ( ) as size_t ;
107
+ // casting an immutable buffer to a mutable pointer looks unsafe, but
108
+ // technically its only unsafe to dereference it, not to create it.
105
109
a. aio_buf = buf. as_ptr ( ) as * mut c_void ;
106
110
a. aio_lio_opcode = opcode as :: c_int ;
107
111
108
- let aiocb = AioCb { aiocb : a, phantom : PhantomData } ;
112
+ let aiocb = AioCb { aiocb : a, mutable : true , phantom : PhantomData } ;
109
113
aiocb
110
114
}
111
115
112
116
/// Like `from_mut_slice`, but works on constant slices rather than
113
117
/// mutable slices.
114
118
///
115
- /// This is technically unsafe, but in practice it's fine
116
- /// to use with any aio functions except `aio_read` and `lio_listio` (with
117
- /// `opcode` set to `LIO_READ`). This method is useful when writing a const
118
- /// buffer with `aio_write`, since from_mut_slice can't work with const
119
+ /// An `AioCb` created this way cannot be used with `read`, and its
120
+ /// `LioOpcode` cannot be set to `LIO_READ`. This method is useful when writing a
121
+ /// const buffer with `aio_write`, since from_mut_slice can't work with const
119
122
/// buffers.
120
123
// Note: another solution to the problem of writing const buffers would be
121
124
// to genericize AioCb for both &mut [u8] and &[u8] buffers. aio_read could
122
125
// take the former and aio_write could take the latter. However, then
123
126
// lio_listio wouldn't work, because that function needs a slice of AioCb,
124
127
// and they must all be the same type. We're basically stuck with using an
125
128
// unsafe function, since aio (as designed in C) is an unsafe API.
126
- pub unsafe fn from_slice ( fd : RawFd , offs : off_t , buf : & ' a [ u8 ] ,
127
- prio : :: c_int , sigev_notify : SigevNotify ,
128
- opcode : LioOpcode ) -> AioCb {
129
+ pub fn from_slice ( fd : RawFd , offs : off_t , buf : & ' a [ u8 ] ,
130
+ prio : :: c_int , sigev_notify : SigevNotify ,
131
+ opcode : LioOpcode ) -> AioCb {
129
132
let mut a = AioCb :: common_init ( fd, prio, sigev_notify) ;
130
133
a. aio_offset = offs;
131
134
a. aio_nbytes = buf. len ( ) as size_t ;
132
135
a. aio_buf = buf. as_ptr ( ) as * mut c_void ;
136
+ assert ! ( opcode != LioOpcode :: LIO_READ , "Can't read into an immutable buffer" ) ;
133
137
a. aio_lio_opcode = opcode as :: c_int ;
134
138
135
- let aiocb = AioCb { aiocb : a, phantom : PhantomData } ;
139
+ let aiocb = AioCb { aiocb : a, mutable : false , phantom : PhantomData } ;
136
140
aiocb
137
141
}
138
142
@@ -185,13 +189,15 @@ impl<'a> AioCb<'a> {
185
189
186
190
/// Asynchronously reads from a file descriptor into a buffer
187
191
pub fn read ( & mut self ) -> Result < ( ) > {
192
+ assert ! ( self . mutable, "Can't read into an immutable buffer" ) ;
188
193
let p: * mut libc:: aiocb = & mut self . aiocb ;
189
194
Errno :: result ( unsafe { libc:: aio_read ( p) } ) . map ( drop)
190
195
}
191
196
192
197
/// Retrieve return status of an asynchronous operation. Should only be called
193
198
/// once for each `AioCb`, after `aio_error` indicates that it has completed.
194
199
/// The result the same as for `read`, `write`, of `fsync`.
200
+ // Note: this should be just `return`, but that's a reserved word
195
201
pub fn aio_return ( & mut self ) -> Result < isize > {
196
202
let p: * mut libc:: aiocb = & mut self . aiocb ;
197
203
Errno :: result ( unsafe { libc:: aio_return ( p) } )
0 commit comments