Change:
Firstly, this always returns . While it is understandable due to the way it has been implemented, this is incorrect behaviour. for the same implementation is able to determine when the end-of-file has been reached, and therefore should be able to as well. Second, of this implementation will if no data is read from the buffer. While somewhat understandable behaviour, this breaks the use of , which calls repeatedly until it finds an end-of-line or end-of-file. Looking through other implementations of in , it appears that the standard behaviour is to return when end-of-file has been reached. I suggest that we should do the same here, and assume that we have reached the end of the file when no more bytes are read.
I have a fix for this, I'll send a pull request as soon as I figure out how to cleanup my commit history and send a clean pull request ...

Discussion:
*/ struct TcpSocketBuf { data: @TcpBufferedSocketData, <ins> mut end_of_stream: bool, </ins> } pub fn TcpSocketBuf(data: @TcpBufferedSocketData) -> TcpSocketBuf { TcpSocketBuf { <del> data: data </del> <ins> data: data, end_of_stream: false </ins> } }

let err_data = read_result.get_err(); if err_data.err_name == ~"EOF" { <ins> self.end_of_stream = true; </ins> break; } else { debug!("ERROR sock_buf as io::reader.read err %? %?",

} fn read_byte() -> int { let mut bytes = ~[0]; <del> if self.read(bytes, 1u) == 0 { fail } else { bytes[0] as int } </del> <ins> if self.read(bytes, 1u) == 0 { if self.end_of_stream { -1 } else { fail } } else { bytes[0] as int } </ins> } fn unread_byte(amt: int) { self.data.buf.unshift(amt as u8); } fn eof() -> bool { <del> false // noop </del> <ins> self.end_of_stream </ins> } fn seek(dist: int, seek: io::SeekStyle) { log(debug, fmt!("tcp_socket_buf seek stub %? %?", dist, seek));

uv::ll::close(stream_handle_ptr, tcp_socket_dtor_close_cb); }; core::comm::recv(closed_po); <del> log(debug, fmt!("about to free socket_data at %?", socket_data)); </del> <ins> //the line below will most likely crash //log(debug, fmt!("about to free socket_data at %?", socket_data)); </ins> rustrt::rust_uv_current_kernel_free(stream_handle_ptr as *libc::c_void); log(debug, ~"exiting dtor for tcp_socket");

fn test_gl_tcp_ipv4_server_client_reader_writer() { impl_gl_tcp_ipv4_server_client_reader_writer(); } <ins> #[test] fn test_tcp_socket_impl_reader_handles_eof() { impl_tcp_socket_impl_reader_handles_eof(); } </ins> } #[cfg(target_arch="x86")] mod impl32 {

*/ } <ins> fn impl_tcp_socket_impl_reader_handles_eof() { use io::{Reader,ReaderUtil}; let hl_loop = uv::global_loop::get(); let server_ip = ~"127.0.0.1"; let server_port = 10041u; let expected_req = ~"GET /"; let expected_resp = ~"A stringnwith multiple linesn"; let server_result_po = core::comm::Port::<~str>(); let server_result_ch = core::comm::Chan(&server_result_po); let cont_po = core::comm::Port::<()>(); let cont_ch = core::comm::Chan(&cont_po); // server do task::spawn_sched(task::ManualThreads(1u)) { let actual_req = do comm::listen |server_ch| { run_tcp_test_server( server_ip, server_port, expected_resp, server_ch, cont_ch, hl_loop) }; server_result_ch.send(actual_req); }; core::comm::recv(cont_po); // client log(debug, ~"server started, firing up client.."); let server_addr = ip::v4::parse_addr(server_ip); let conn_result = connect(server_addr, server_port, hl_loop); if result::is_err(&conn_result) { assert false; } let sock_buf = @socket_buf(result::unwrap(move conn_result)); buf_write(sock_buf, expected_req); let buf_reader = sock_buf as Reader; let actual_response = str::from_bytes(buf_reader.read_whole_stream()); log(debug, fmt!("Actual response: %s", actual_response)); assert expected_resp == actual_response; } </ins> fn buf_write<W:io::Writer>(w: &W, val: &str) { log(debug, fmt!("BUF_WRITE: val len %?", str::len(val))); do str::byte_slice(val) |b_slice| {