Skip to content

Commit cb8380e

Browse files
committed
Cut out some allocation in read_message
1 parent d7c6339 commit cb8380e

1 file changed

Lines changed: 34 additions & 26 deletions

File tree

src/message.rs

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use std::io::{IoResult, IoError, OtherIoError, MemReader};
1+
use std::io::{IoResult, IoError, OtherIoError, ByRefReader};
2+
use std::io::util::LimitReader;
23
use std::mem;
34

45
use io::Timeout;
@@ -273,7 +274,7 @@ pub trait ReadMessage {
273274
fn read_message(&mut self) -> IoResult<BackendMessage>;
274275
}
275276

276-
impl<R: Reader+Timeout> ReadMessage for R {
277+
impl<R: Buffer+Timeout> ReadMessage for R {
277278
fn read_message(&mut self) -> IoResult<BackendMessage> {
278279
// The first byte read is a bit complex to make
279280
// Notifications::next_block_for work.
@@ -286,25 +287,25 @@ impl<R: Reader+Timeout> ReadMessage for R {
286287

287288
// subtract size of length value
288289
let len = try!(self.read_be_u32()) as uint - mem::size_of::<i32>();
289-
let mut buf = MemReader::new(try!(self.read_exact(len)));
290+
let mut rdr = LimitReader::new(self.by_ref(), len);
290291

291292
let ret = match ident {
292293
b'1' => ParseComplete,
293294
b'2' => BindComplete,
294295
b'3' => CloseComplete,
295296
b'A' => NotificationResponse {
296-
pid: try!(buf.read_be_u32()),
297-
channel: try!(buf.read_cstr()),
298-
payload: try!(buf.read_cstr())
297+
pid: try!(rdr.read_be_u32()),
298+
channel: try!(rdr.read_cstr()),
299+
payload: try!(rdr.read_cstr())
299300
},
300-
b'C' => CommandComplete { tag: try!(buf.read_cstr()) },
301-
b'D' => try!(read_data_row(&mut buf)),
302-
b'E' => ErrorResponse { fields: try!(read_fields(&mut buf)) },
301+
b'C' => CommandComplete { tag: try!(rdr.read_cstr()) },
302+
b'D' => try!(read_data_row(&mut rdr)),
303+
b'E' => ErrorResponse { fields: try!(read_fields(&mut rdr)) },
303304
b'G' => {
304-
let format = try!(buf.read_u8());
305+
let format = try!(rdr.read_u8());
305306
let mut column_formats = vec![];
306-
for _ in range(0, try!(buf.read_be_u16())) {
307-
column_formats.push(try!(buf.read_be_u16()));
307+
for _ in range(0, try!(rdr.read_be_u16())) {
308+
column_formats.push(try!(rdr.read_be_u16()));
308309
}
309310
CopyInResponse {
310311
format: format,
@@ -313,31 +314,38 @@ impl<R: Reader+Timeout> ReadMessage for R {
313314
}
314315
b'I' => EmptyQueryResponse,
315316
b'K' => BackendKeyData {
316-
process_id: try!(buf.read_be_u32()),
317-
secret_key: try!(buf.read_be_u32())
317+
process_id: try!(rdr.read_be_u32()),
318+
secret_key: try!(rdr.read_be_u32())
318319
},
319320
b'n' => NoData,
320-
b'N' => NoticeResponse { fields: try!(read_fields(&mut buf)) },
321-
b'R' => try!(read_auth_message(&mut buf)),
321+
b'N' => NoticeResponse { fields: try!(read_fields(&mut rdr)) },
322+
b'R' => try!(read_auth_message(&mut rdr)),
322323
b's' => PortalSuspended,
323324
b'S' => ParameterStatus {
324-
parameter: try!(buf.read_cstr()),
325-
value: try!(buf.read_cstr())
325+
parameter: try!(rdr.read_cstr()),
326+
value: try!(rdr.read_cstr())
326327
},
327-
b't' => try!(read_parameter_description(&mut buf)),
328-
b'T' => try!(read_row_description(&mut buf)),
329-
b'Z' => ReadyForQuery { _state: try!(buf.read_u8()) },
328+
b't' => try!(read_parameter_description(&mut rdr)),
329+
b'T' => try!(read_row_description(&mut rdr)),
330+
b'Z' => ReadyForQuery { _state: try!(rdr.read_u8()) },
330331
ident => return Err(IoError {
331332
kind: OtherIoError,
332333
desc: "Unexpected message tag",
333334
detail: Some(format!("got {}", ident)),
334335
})
335336
};
337+
if rdr.limit() != 0 {
338+
return Err(IoError {
339+
kind: OtherIoError,
340+
desc: "didn't read entire message",
341+
detail: None,
342+
});
343+
}
336344
Ok(ret)
337345
}
338346
}
339347

340-
fn read_fields(buf: &mut MemReader) -> IoResult<Vec<(u8, String)>> {
348+
fn read_fields<R: Buffer>(buf: &mut R) -> IoResult<Vec<(u8, String)>> {
341349
let mut fields = vec![];
342350
loop {
343351
let ty = try!(buf.read_u8());
@@ -351,7 +359,7 @@ fn read_fields(buf: &mut MemReader) -> IoResult<Vec<(u8, String)>> {
351359
Ok(fields)
352360
}
353361

354-
fn read_data_row(buf: &mut MemReader) -> IoResult<BackendMessage> {
362+
fn read_data_row<R: Buffer>(buf: &mut R) -> IoResult<BackendMessage> {
355363
let len = try!(buf.read_be_i16()) as uint;
356364
let mut values = Vec::with_capacity(len);
357365

@@ -366,7 +374,7 @@ fn read_data_row(buf: &mut MemReader) -> IoResult<BackendMessage> {
366374
Ok(DataRow { row: values })
367375
}
368376

369-
fn read_auth_message(buf: &mut MemReader) -> IoResult<BackendMessage> {
377+
fn read_auth_message<R: Buffer>(buf: &mut R) -> IoResult<BackendMessage> {
370378
Ok(match try!(buf.read_be_i32()) {
371379
0 => AuthenticationOk,
372380
2 => AuthenticationKerberosV5,
@@ -387,7 +395,7 @@ fn read_auth_message(buf: &mut MemReader) -> IoResult<BackendMessage> {
387395
})
388396
}
389397

390-
fn read_parameter_description(buf: &mut MemReader) -> IoResult<BackendMessage> {
398+
fn read_parameter_description<R: Buffer>(buf: &mut R) -> IoResult<BackendMessage> {
391399
let len = try!(buf.read_be_i16()) as uint;
392400
let mut types = Vec::with_capacity(len);
393401

@@ -398,7 +406,7 @@ fn read_parameter_description(buf: &mut MemReader) -> IoResult<BackendMessage> {
398406
Ok(ParameterDescription { types: types })
399407
}
400408

401-
fn read_row_description(buf: &mut MemReader) -> IoResult<BackendMessage> {
409+
fn read_row_description<R: Buffer>(buf: &mut R) -> IoResult<BackendMessage> {
402410
let len = try!(buf.read_be_i16()) as uint;
403411
let mut types = Vec::with_capacity(len);
404412

0 commit comments

Comments
 (0)