Skip to content

Commit 06ac0c2

Browse files
ericktgraydon
authored andcommitted
Switch reader to work with preallocated vecs
This closes #2901.
1 parent 6d042c0 commit 06ac0c2

File tree

3 files changed

+60
-38
lines changed

3 files changed

+60
-38
lines changed

Diff for: src/libcore/io.rs

+31-17
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ enum seek_style { seek_set, seek_end, seek_cur, }
3030
// The raw underlying reader iface. All readers must implement this.
3131
iface reader {
3232
// FIXME (#2004): Seekable really should be orthogonal.
33-
fn read_bytes(uint) -> ~[u8];
33+
34+
// FIXME (#2982): This should probably return an error.
35+
fn read(buf: &[mut u8], len: uint) -> uint;
3436
fn read_byte() -> int;
3537
fn unread_byte(int);
3638
fn eof() -> bool;
@@ -41,6 +43,16 @@ iface reader {
4143
// Generic utility functions defined on readers
4244

4345
impl reader_util for reader {
46+
fn read_bytes(len: uint) -> ~[u8] {
47+
let mut buf = ~[mut];
48+
vec::reserve(buf, len);
49+
unsafe { vec::unsafe::set_len(buf, len); }
50+
51+
let count = self.read(buf, len);
52+
53+
unsafe { vec::unsafe::set_len(buf, count); }
54+
vec::from_mut(buf)
55+
}
4456
fn read_chars(n: uint) -> ~[char] {
4557
// returns the (consumed offset, n_req), appends characters to &chars
4658
fn chars_from_buf(buf: ~[u8], &chars: ~[char]) -> (uint, uint) {
@@ -192,15 +204,15 @@ fn convert_whence(whence: seek_style) -> i32 {
192204
}
193205

194206
impl of reader for *libc::FILE {
195-
fn read_bytes(len: uint) -> ~[u8] {
196-
let mut buf : ~[mut u8] = ~[mut];
197-
vec::reserve(buf, len);
198-
do vec::as_mut_buf(buf) |b| {
199-
let read = libc::fread(b as *mut c_void, 1u as size_t,
200-
len as size_t, self);
201-
unsafe { vec::unsafe::set_len(buf, read as uint) };
207+
fn read(buf: &[mut u8], len: uint) -> uint {
208+
do vec::unpack_slice(buf) |buf_p, buf_len| {
209+
assert buf_len <= len;
210+
211+
let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
212+
len as size_t, self);
213+
214+
count as uint
202215
}
203-
ret vec::from_mut(buf);
204216
}
205217
fn read_byte() -> int { ret libc::fgetc(self) as int; }
206218
fn unread_byte(byte: int) { libc::ungetc(byte as c_int, self); }
@@ -216,7 +228,7 @@ impl of reader for *libc::FILE {
216228
// duration of its lifetime.
217229
// FIXME there really should be a better way to do this // #2004
218230
impl <T: reader, C> of reader for {base: T, cleanup: C} {
219-
fn read_bytes(len: uint) -> ~[u8] { self.base.read_bytes(len) }
231+
fn read(buf: &[mut u8], len: uint) -> uint { self.base.read(buf, len) }
220232
fn read_byte() -> int { self.base.read_byte() }
221233
fn unread_byte(byte: int) { self.base.unread_byte(byte); }
222234
fn eof() -> bool { self.base.eof() }
@@ -262,13 +274,15 @@ fn file_reader(path: ~str) -> result<reader, ~str> {
262274
type byte_buf = {buf: ~[const u8], mut pos: uint, len: uint};
263275
264276
impl of reader for byte_buf {
265-
fn read_bytes(len: uint) -> ~[u8] {
266-
let rest = self.len - self.pos;
267-
let mut to_read = len;
268-
if rest < to_read { to_read = rest; }
269-
let range = vec::slice(self.buf, self.pos, self.pos + to_read);
270-
self.pos += to_read;
271-
ret range;
277+
fn read(buf: &[mut u8], len: uint) -> uint {
278+
let count = uint::min(len, self.len - self.pos);
279+
280+
vec::u8::memcpy(buf, vec::const_view(self.buf, self.pos, self.len),
281+
count);
282+
283+
self.pos += count;
284+
285+
count
272286
}
273287
fn read_byte() -> int {
274288
if self.pos == self.len { ret -1; }

Diff for: src/libcore/run.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Process spawning
22
import option::{some, none};
33
import libc::{pid_t, c_void, c_int};
4+
import io::reader_util;
45

56
export program;
67
export run_program;

Diff for: src/libstd/net_tcp.rs

+28-21
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import future::extensions;
1111
import result::*;
1212
import libc::size_t;
1313
import str::extensions;
14-
import io::{reader, writer};
14+
import io::{reader, reader_util, writer};
1515

1616
// tcp interfaces
1717
export tcp_socket;
@@ -766,34 +766,41 @@ impl tcp_socket for tcp_socket {
766766

767767
/// Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket`
768768
impl tcp_socket_buf of io::reader for @tcp_socket_buf {
769-
fn read_bytes(amt: uint) -> ~[u8] {
770-
let has_amt_available =
771-
vec::len((*(self.data)).buf) >= amt;
772-
if has_amt_available {
773-
// no arbitrary-length shift in vec::?
774-
let mut ret_buf = ~[];
775-
while vec::len(ret_buf) < amt {
776-
ret_buf += ~[vec::shift((*(self.data)).buf)];
777-
}
778-
ret_buf
779-
}
780-
else {
781-
let read_result = read((*(self.data)).sock, 0u);
769+
fn read(buf: &[mut u8], len: uint) -> uint {
770+
// Loop until our buffer has enough data in it for us to read from.
771+
while self.data.buf.len() < len {
772+
let read_result = read(self.data.sock, 0u);
782773
if read_result.is_err() {
783774
let err_data = read_result.get_err();
784-
log(debug, #fmt("ERROR sock_buf as io::reader.read err %? %?",
785-
err_data.err_name, err_data.err_msg));
786-
~[]
775+
776+
if err_data.err_name == ~"EOF" {
777+
break;
778+
} else {
779+
#debug("ERROR sock_buf as io::reader.read err %? %?",
780+
err_data.err_name, err_data.err_msg);
781+
782+
ret 0;
783+
}
787784
}
788785
else {
789-
let new_chunk = result::unwrap(read_result);
790-
(*(self.data)).buf += new_chunk;
791-
self.read_bytes(amt)
786+
vec::push_all(self.data.buf, result::unwrap(read_result));
792787
}
793788
}
789+
790+
let count = uint::min(len, self.data.buf.len());
791+
792+
let mut data = ~[];
793+
self.data.buf <-> data;
794+
795+
vec::u8::memcpy(buf, vec::view(data, 0, data.len()), count);
796+
797+
vec::push_all(self.data.buf, vec::view(data, count, data.len()));
798+
799+
count
794800
}
795801
fn read_byte() -> int {
796-
self.read_bytes(1u)[0] as int
802+
let bytes = ~[0];
803+
if self.read(bytes, 1u) == 0 { fail } else { bytes[0] as int }
797804
}
798805
fn unread_byte(amt: int) {
799806
vec::unshift((*(self.data)).buf, amt as u8);

0 commit comments

Comments
 (0)