<commit_before>#[doc ="Process spawning"];
import option::{some, none};
import libc::{pid_t, c_void, c_int};

export program;
export run_program;
export start_program;
export program_output;
export spawn_process;
export waitpid;

#[abi = "cdecl"]
native mod rustrt {
    fn rust_run_program(argv: **libc::c_char, envp: *c_void,
                        dir: *libc::c_char,
                        in_fd: c_int, out_fd: c_int, err_fd: c_int)
        -> pid_t;
}

#[doc ="A value representing a child process"]
iface program {
    #[doc ="Returns the process id of the program"]
    fn get_id() -> pid_t;

    #[doc ="Returns an io::writer that can be used to write to stdin"]
    fn input() -> io::writer;

    #[doc ="Returns an io::reader that can be used to read from stdout"]
    fn output() -> io::reader;

    #[doc ="Returns an io::reader that can be used to read from stderr"]
    fn err() -> io::reader;

    #[doc = "Closes the handle to the child processes standard input"]
    fn close_input();

    #[doc = "
    Waits for the child process to terminate. Closes the handle
    to stdin if necessary.
    "]
    fn finish() -> int;

    #[doc ="Closes open handles"]
    fn destroy();
}

#[doc = "
Run a program, providing stdin, stdout and stderr handles

# Arguments

* prog - The path to an executable
* args - Vector of arguments to pass to the child process
* env - optional env-modification for child
* dir - optional dir to run child in (default current dir)
* in_fd - A file descriptor for the child to use as std input
* out_fd - A file descriptor for the child to use as std output
* err_fd - A file descriptor for the child to use as std error

# Return value

The process id of the spawned process
"]
fn spawn_process(prog: str, args: [str],
                 env: option<[(str,str)]>,
                 dir: option<str>,
                 in_fd: c_int, out_fd: c_int, err_fd: c_int)
   -> pid_t unsafe {
    with_argv(prog, args) {|argv|
        with_envp(env) { |envp|
            with_dirp(dir) { |dirp|
                rustrt::rust_run_program(argv, envp, dirp,
                                         in_fd, out_fd, err_fd)
            }
        }
    }
}

fn with_argv<T>(prog: str, args: [str],
                cb: fn(**libc::c_char) -> T) -> T unsafe {
    let mut argptrs = str::as_c_str(prog) {|b| [b] };
    let mut tmps = [];
    for vec::each(args) {|arg|
        let t = @arg;
        tmps += [t];
        argptrs += str::as_c_str(*t) {|b| [b] };
    }
    argptrs += [ptr::null()];
    vec::as_buf(argptrs, cb)
}

#[cfg(unix)]
fn with_envp<T>(env: option<[(str,str)]>,
                cb: fn(*c_void) -> T) -> T unsafe {
    // On posixy systems we can pass a char** for envp, which is
    // a null-terminated array of "k=v\n" strings.
    alt env {
      some(es) if !vec::is_empty(es) {
        let mut tmps = [];
        let mut ptrs = [];

        for vec::each(es) {|e|
            let (k,v) = e;
            let t = @(#fmt("%s=%s", k, v));
            vec::push(tmps, t);
            ptrs += str::as_c_str(*t) {|b| [b]};
        }
        ptrs += [ptr::null()];
        vec::as_buf(ptrs) { |p| cb(::unsafe::reinterpret_cast(p)) }
      }
      _ {
        cb(ptr::null())
      }
    }
}

#[cfg(windows)]
fn with_envp<T>(env: option<[(str,str)]>,
                cb: fn(*c_void) -> T) -> T unsafe {
    // On win32 we pass an "environment block" which is not a char**, but
    // rather a concatenation of null-terminated k=v\0 sequences, with a final
    // \0 to terminate.
    alt env {
      some(es) if !vec::is_empty(es) {
        let mut blk : [u8] = [];
        for vec::each(es) {|e|
            let (k,v) = e;
            let t = #fmt("%s=%s", k, v);
            let mut v : [u8] = ::unsafe::reinterpret_cast(t);
            blk += v;
            ::unsafe::forget(v);
        }
        blk += [0_u8];
        vec::as_buf(blk) {|p| cb(::unsafe::reinterpret_cast(p)) }
      }
      _ {
        cb(ptr::null())
      }
    }
}

fn with_dirp<T>(d: option<str>,
                cb: fn(*libc::c_char) -> T) -> T unsafe {
    alt d {
      some(dir) { str::as_c_str(dir, cb) }
      none { cb(ptr::null()) }
    }
}

#[doc ="
Spawns a process and waits for it to terminate

# Arguments

* prog - The path to an executable
* args - Vector of arguments to pass to the child process

# Return value

The process id
"]
fn run_program(prog: str, args: [str]) -> int {
    let pid = spawn_process(prog, args, none, none,
                            0i32, 0i32, 0i32);
    if pid == -1 as pid_t { fail; }
    ret waitpid(pid);
}

#[doc ="
Spawns a process and returns a program

The returned value is a boxed resource containing a <program> object that can
be used for sending and recieving data over the standard file descriptors.
The resource will ensure that file descriptors are closed properly.

# Arguments

* prog - The path to an executable
* args - Vector of arguments to pass to the child process

# Return value

A boxed resource of <program>
"]
fn start_program(prog: str, args: [str]) -> program {
    let pipe_input = os::pipe();
    let pipe_output = os::pipe();
    let pipe_err = os::pipe();
    let pid =
        spawn_process(prog, args, none, none,
                      pipe_input.in, pipe_output.out,
                      pipe_err.out);

    if pid == -1 as pid_t { fail; }
    libc::close(pipe_input.in);
    libc::close(pipe_output.out);
    libc::close(pipe_err.out);

    type prog_repr = {pid: pid_t,
                      mut in_fd: c_int,
                      out_file: *libc::FILE,
                      err_file: *libc::FILE,
                      mut finished: bool};

    fn close_repr_input(r: prog_repr) {
        let invalid_fd = -1i32;
        if r.in_fd != invalid_fd {
            libc::close(r.in_fd);
            r.in_fd = invalid_fd;
        }
    }
    fn finish_repr(r: prog_repr) -> int {
        if r.finished { ret 0; }
        r.finished = true;
        close_repr_input(r);
        ret waitpid(r.pid);
    }
    fn destroy_repr(r: prog_repr) {
        finish_repr(r);
       libc::fclose(r.out_file);
       libc::fclose(r.err_file);
    }
    resource prog_res(r: prog_repr) { destroy_repr(r); }

    impl of program for prog_res {
        fn get_id() -> pid_t { ret self.pid; }
        fn input() -> io::writer { io::fd_writer(self.in_fd, false) }
        fn output() -> io::reader { io::FILE_reader(self.out_file, false) }
        fn err() -> io::reader { io::FILE_reader(self.err_file, false) }
        fn close_input() { close_repr_input(*self); }
        fn finish() -> int { finish_repr(*self) }
        fn destroy() { destroy_repr(*self); }
    }
    let repr = {pid: pid,
                mut in_fd: pipe_input.out,
                out_file: os::fdopen(pipe_output.in),
                err_file: os::fdopen(pipe_err.in),
                mut finished: false};
    ret prog_res(repr) as program;
}

fn read_all(rd: io::reader) -> str {
    let mut buf = "";
    while !rd.eof() {
        let bytes = rd.read_bytes(4096u);
        buf += str::from_bytes(bytes);
    }
    ret buf;
}

#[doc ="
Spawns a process, waits for it to exit, and returns the exit code, and
contents of stdout and stderr.

# Arguments

* prog - The path to an executable
* args - Vector of arguments to pass to the child process

# Return value

A record, {status: int, out: str, err: str} containing the exit code,
the contents of stdout and the contents of stderr.
"]
fn program_output(prog: str, args: [str]) ->
   {status: int, out: str, err: str} {

    let pipe_in = os::pipe();
    let pipe_out = os::pipe();
    let pipe_err = os::pipe();
    let pid = spawn_process(prog, args, none, none,
                            pipe_in.in, pipe_out.out, pipe_err.out);

    os::close(pipe_in.in);
    os::close(pipe_out.out);
    os::close(pipe_err.out);
    if pid == -1i32 {
        os::close(pipe_in.out);
        os::close(pipe_out.in);
        os::close(pipe_err.in);
        fail;
    }

    os::close(pipe_in.out);

    // Spawn two entire schedulers to read both stdout and sterr
    // in parallel so we don't deadlock while blocking on one
    // or the other. FIXME: Surely there's a much more clever way
    // to do this.
    let p = comm::port();
    let ch = comm::chan(p);
    task::spawn_sched(task::single_threaded) {||
        let errput = readclose(pipe_err.in);
        comm::send(ch, (2, errput));
    };
    task::spawn_sched(task::single_threaded) {||
        let output = readclose(pipe_out.in);
        comm::send(ch, (1, output));
    };
    let status = run::waitpid(pid);
    let mut errs = "";
    let mut outs = "";
    let mut count = 2;
    while count > 0 {
        let stream = comm::recv(p);
        alt check stream {
            (1, s) {
                outs = s;
            }
            (2, s) {
                errs = s;
            }
        };
        count -= 1;
    };
    ret {status: status, out: outs, err: errs};
}

fn writeclose(fd: c_int, s: str) {
    import io::writer_util;

    #error("writeclose %d, %s", fd as int, s);
    let writer = io::fd_writer(fd, false);
    writer.write_str(s);

    os::close(fd);
}

fn readclose(fd: c_int) -> str {
    let file = os::fdopen(fd);
    let reader = io::FILE_reader(file, false);
    let mut buf = "";
    while !reader.eof() {
        let bytes = reader.read_bytes(4096u);
        buf += str::from_bytes(bytes);
    }
    os::fclose(file);
    ret buf;
}

#[doc ="Waits for a process to exit and returns the exit code"]
fn waitpid(pid: pid_t) -> int {
    ret waitpid_os(pid);

    #[cfg(windows)]
    fn waitpid_os(pid: pid_t) -> int {
        os::waitpid(pid) as int
    }

    #[cfg(unix)]
    fn waitpid_os(pid: pid_t) -> int {
        #[cfg(target_os = "linux")]
        fn WIFEXITED(status: i32) -> bool {
            (status & 0xffi32) == 0i32
        }

        #[cfg(target_os = "macos")]
        #[cfg(target_os = "freebsd")]
        fn WIFEXITED(status: i32) -> bool {
            (status & 0x7fi32) == 0i32
        }

        #[cfg(target_os = "linux")]
        fn WEXITSTATUS(status: i32) -> i32 {
            (status >> 8i32) & 0xffi32
        }

        #[cfg(target_os = "macos")]
        #[cfg(target_os = "freebsd")]
        fn WEXITSTATUS(status: i32) -> i32 {
            status >> 8i32
        }

        let status = os::waitpid(pid);
        ret if WIFEXITED(status) {
            WEXITSTATUS(status) as int
        } else {
            1
        };
    }
}

#[cfg(test)]
mod tests {

    import io::writer_util;

    // Regression test for memory leaks
    #[ignore(cfg(windows))] // FIXME
    fn test_leaks() {
        run::run_program("echo", []);
        run::start_program("echo", []);
        run::program_output("echo", []);
    }

    #[test]
    fn test_pipes() {
        let pipe_in = os::pipe();
        let pipe_out = os::pipe();
        let pipe_err = os::pipe();

        let pid =
            run::spawn_process(
                "cat", [], none, none,
                pipe_in.in, pipe_out.out, pipe_err.out);
        os::close(pipe_in.in);
        os::close(pipe_out.out);
        os::close(pipe_err.out);

        if pid == -1i32 { fail; }
        let expected = "test";
        writeclose(pipe_in.out, expected);
        let actual = readclose(pipe_out.in);
        readclose(pipe_err.in);
        os::waitpid(pid);

        log(debug, expected);
        log(debug, actual);
        assert (expected == actual);
    }

    #[test]
    fn waitpid() {
        let pid = run::spawn_process("false", [],
                                     none, none,
                                     0i32, 0i32, 0i32);
        let status = run::waitpid(pid);
        assert status == 1;
    }

}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Comments only: annotate FIXMEs in core::run<commit_after>#[doc ="Process spawning"];
import option::{some, none};
import libc::{pid_t, c_void, c_int};

export program;
export run_program;
export start_program;
export program_output;
export spawn_process;
export waitpid;

#[abi = "cdecl"]
native mod rustrt {
    fn rust_run_program(argv: **libc::c_char, envp: *c_void,
                        dir: *libc::c_char,
                        in_fd: c_int, out_fd: c_int, err_fd: c_int)
        -> pid_t;
}

#[doc ="A value representing a child process"]
iface program {
    #[doc ="Returns the process id of the program"]
    fn get_id() -> pid_t;

    #[doc ="Returns an io::writer that can be used to write to stdin"]
    fn input() -> io::writer;

    #[doc ="Returns an io::reader that can be used to read from stdout"]
    fn output() -> io::reader;

    #[doc ="Returns an io::reader that can be used to read from stderr"]
    fn err() -> io::reader;

    #[doc = "Closes the handle to the child processes standard input"]
    fn close_input();

    #[doc = "
    Waits for the child process to terminate. Closes the handle
    to stdin if necessary.
    "]
    fn finish() -> int;

    #[doc ="Closes open handles"]
    fn destroy();
}

#[doc = "
Run a program, providing stdin, stdout and stderr handles

# Arguments

* prog - The path to an executable
* args - Vector of arguments to pass to the child process
* env - optional env-modification for child
* dir - optional dir to run child in (default current dir)
* in_fd - A file descriptor for the child to use as std input
* out_fd - A file descriptor for the child to use as std output
* err_fd - A file descriptor for the child to use as std error

# Return value

The process id of the spawned process
"]
fn spawn_process(prog: str, args: [str],
                 env: option<[(str,str)]>,
                 dir: option<str>,
                 in_fd: c_int, out_fd: c_int, err_fd: c_int)
   -> pid_t unsafe {
    with_argv(prog, args) {|argv|
        with_envp(env) { |envp|
            with_dirp(dir) { |dirp|
                rustrt::rust_run_program(argv, envp, dirp,
                                         in_fd, out_fd, err_fd)
            }
        }
    }
}

fn with_argv<T>(prog: str, args: [str],
                cb: fn(**libc::c_char) -> T) -> T unsafe {
    let mut argptrs = str::as_c_str(prog) {|b| [b] };
    let mut tmps = [];
    for vec::each(args) {|arg|
        let t = @arg;
        tmps += [t];
        argptrs += str::as_c_str(*t) {|b| [b] };
    }
    argptrs += [ptr::null()];
    vec::as_buf(argptrs, cb)
}

#[cfg(unix)]
fn with_envp<T>(env: option<[(str,str)]>,
                cb: fn(*c_void) -> T) -> T unsafe {
    // On posixy systems we can pass a char** for envp, which is
    // a null-terminated array of "k=v\n" strings.
    alt env {
      some(es) if !vec::is_empty(es) {
        let mut tmps = [];
        let mut ptrs = [];

        for vec::each(es) {|e|
            let (k,v) = e;
            let t = @(#fmt("%s=%s", k, v));
            vec::push(tmps, t);
            ptrs += str::as_c_str(*t) {|b| [b]};
        }
        ptrs += [ptr::null()];
        vec::as_buf(ptrs) { |p| cb(::unsafe::reinterpret_cast(p)) }
      }
      _ {
        cb(ptr::null())
      }
    }
}

#[cfg(windows)]
fn with_envp<T>(env: option<[(str,str)]>,
                cb: fn(*c_void) -> T) -> T unsafe {
    // On win32 we pass an "environment block" which is not a char**, but
    // rather a concatenation of null-terminated k=v\0 sequences, with a final
    // \0 to terminate.
    alt env {
      some(es) if !vec::is_empty(es) {
        let mut blk : [u8] = [];
        for vec::each(es) {|e|
            let (k,v) = e;
            let t = #fmt("%s=%s", k, v);
            let mut v : [u8] = ::unsafe::reinterpret_cast(t);
            blk += v;
            ::unsafe::forget(v);
        }
        blk += [0_u8];
        vec::as_buf(blk) {|p| cb(::unsafe::reinterpret_cast(p)) }
      }
      _ {
        cb(ptr::null())
      }
    }
}

fn with_dirp<T>(d: option<str>,
                cb: fn(*libc::c_char) -> T) -> T unsafe {
    alt d {
      some(dir) { str::as_c_str(dir, cb) }
      none { cb(ptr::null()) }
    }
}

#[doc ="
Spawns a process and waits for it to terminate

# Arguments

* prog - The path to an executable
* args - Vector of arguments to pass to the child process

# Return value

The process id
"]
fn run_program(prog: str, args: [str]) -> int {
    let pid = spawn_process(prog, args, none, none,
                            0i32, 0i32, 0i32);
    if pid == -1 as pid_t { fail; }
    ret waitpid(pid);
}

#[doc ="
Spawns a process and returns a program

The returned value is a boxed resource containing a <program> object that can
be used for sending and recieving data over the standard file descriptors.
The resource will ensure that file descriptors are closed properly.

# Arguments

* prog - The path to an executable
* args - Vector of arguments to pass to the child process

# Return value

A boxed resource of <program>
"]
fn start_program(prog: str, args: [str]) -> program {
    let pipe_input = os::pipe();
    let pipe_output = os::pipe();
    let pipe_err = os::pipe();
    let pid =
        spawn_process(prog, args, none, none,
                      pipe_input.in, pipe_output.out,
                      pipe_err.out);

    if pid == -1 as pid_t { fail; }
    libc::close(pipe_input.in);
    libc::close(pipe_output.out);
    libc::close(pipe_err.out);

    type prog_repr = {pid: pid_t,
                      mut in_fd: c_int,
                      out_file: *libc::FILE,
                      err_file: *libc::FILE,
                      mut finished: bool};

    fn close_repr_input(r: prog_repr) {
        let invalid_fd = -1i32;
        if r.in_fd != invalid_fd {
            libc::close(r.in_fd);
            r.in_fd = invalid_fd;
        }
    }
    fn finish_repr(r: prog_repr) -> int {
        if r.finished { ret 0; }
        r.finished = true;
        close_repr_input(r);
        ret waitpid(r.pid);
    }
    fn destroy_repr(r: prog_repr) {
        finish_repr(r);
       libc::fclose(r.out_file);
       libc::fclose(r.err_file);
    }
    resource prog_res(r: prog_repr) { destroy_repr(r); }

    impl of program for prog_res {
        fn get_id() -> pid_t { ret self.pid; }
        fn input() -> io::writer { io::fd_writer(self.in_fd, false) }
        fn output() -> io::reader { io::FILE_reader(self.out_file, false) }
        fn err() -> io::reader { io::FILE_reader(self.err_file, false) }
        fn close_input() { close_repr_input(*self); }
        fn finish() -> int { finish_repr(*self) }
        fn destroy() { destroy_repr(*self); }
    }
    let repr = {pid: pid,
                mut in_fd: pipe_input.out,
                out_file: os::fdopen(pipe_output.in),
                err_file: os::fdopen(pipe_err.in),
                mut finished: false};
    ret prog_res(repr) as program;
}

fn read_all(rd: io::reader) -> str {
    let mut buf = "";
    while !rd.eof() {
        let bytes = rd.read_bytes(4096u);
        buf += str::from_bytes(bytes);
    }
    ret buf;
}

#[doc ="
Spawns a process, waits for it to exit, and returns the exit code, and
contents of stdout and stderr.

# Arguments

* prog - The path to an executable
* args - Vector of arguments to pass to the child process

# Return value

A record, {status: int, out: str, err: str} containing the exit code,
the contents of stdout and the contents of stderr.
"]
fn program_output(prog: str, args: [str]) ->
   {status: int, out: str, err: str} {

    let pipe_in = os::pipe();
    let pipe_out = os::pipe();
    let pipe_err = os::pipe();
    let pid = spawn_process(prog, args, none, none,
                            pipe_in.in, pipe_out.out, pipe_err.out);

    os::close(pipe_in.in);
    os::close(pipe_out.out);
    os::close(pipe_err.out);
    if pid == -1i32 {
        os::close(pipe_in.out);
        os::close(pipe_out.in);
        os::close(pipe_err.in);
        fail;
    }

    os::close(pipe_in.out);

    // Spawn two entire schedulers to read both stdout and sterr
    // in parallel so we don't deadlock while blocking on one
    // or the other. FIXME: Surely there's a much more clever way
    // to do this. (#2625)
    let p = comm::port();
    let ch = comm::chan(p);
    task::spawn_sched(task::single_threaded) {||
        let errput = readclose(pipe_err.in);
        comm::send(ch, (2, errput));
    };
    task::spawn_sched(task::single_threaded) {||
        let output = readclose(pipe_out.in);
        comm::send(ch, (1, output));
    };
    let status = run::waitpid(pid);
    let mut errs = "";
    let mut outs = "";
    let mut count = 2;
    while count > 0 {
        let stream = comm::recv(p);
        alt check stream {
            (1, s) {
                outs = s;
            }
            (2, s) {
                errs = s;
            }
        };
        count -= 1;
    };
    ret {status: status, out: outs, err: errs};
}

fn writeclose(fd: c_int, s: str) {
    import io::writer_util;

    #error("writeclose %d, %s", fd as int, s);
    let writer = io::fd_writer(fd, false);
    writer.write_str(s);

    os::close(fd);
}

fn readclose(fd: c_int) -> str {
    let file = os::fdopen(fd);
    let reader = io::FILE_reader(file, false);
    let mut buf = "";
    while !reader.eof() {
        let bytes = reader.read_bytes(4096u);
        buf += str::from_bytes(bytes);
    }
    os::fclose(file);
    ret buf;
}

#[doc ="Waits for a process to exit and returns the exit code"]
fn waitpid(pid: pid_t) -> int {
    ret waitpid_os(pid);

    #[cfg(windows)]
    fn waitpid_os(pid: pid_t) -> int {
        os::waitpid(pid) as int
    }

    #[cfg(unix)]
    fn waitpid_os(pid: pid_t) -> int {
        #[cfg(target_os = "linux")]
        fn WIFEXITED(status: i32) -> bool {
            (status & 0xffi32) == 0i32
        }

        #[cfg(target_os = "macos")]
        #[cfg(target_os = "freebsd")]
        fn WIFEXITED(status: i32) -> bool {
            (status & 0x7fi32) == 0i32
        }

        #[cfg(target_os = "linux")]
        fn WEXITSTATUS(status: i32) -> i32 {
            (status >> 8i32) & 0xffi32
        }

        #[cfg(target_os = "macos")]
        #[cfg(target_os = "freebsd")]
        fn WEXITSTATUS(status: i32) -> i32 {
            status >> 8i32
        }

        let status = os::waitpid(pid);
        ret if WIFEXITED(status) {
            WEXITSTATUS(status) as int
        } else {
            1
        };
    }
}

#[cfg(test)]
mod tests {

    import io::writer_util;

    // Regression test for memory leaks
    #[ignore(cfg(windows))] // FIXME (#2626)
    fn test_leaks() {
        run::run_program("echo", []);
        run::start_program("echo", []);
        run::program_output("echo", []);
    }

    #[test]
    fn test_pipes() {
        let pipe_in = os::pipe();
        let pipe_out = os::pipe();
        let pipe_err = os::pipe();

        let pid =
            run::spawn_process(
                "cat", [], none, none,
                pipe_in.in, pipe_out.out, pipe_err.out);
        os::close(pipe_in.in);
        os::close(pipe_out.out);
        os::close(pipe_err.out);

        if pid == -1i32 { fail; }
        let expected = "test";
        writeclose(pipe_in.out, expected);
        let actual = readclose(pipe_out.in);
        readclose(pipe_err.in);
        os::waitpid(pid);

        log(debug, expected);
        log(debug, actual);
        assert (expected == actual);
    }

    #[test]
    fn waitpid() {
        let pid = run::spawn_process("false", [],
                                     none, none,
                                     0i32, 0i32, 0i32);
        let status = run::waitpid(pid);
        assert status == 1;
    }

}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>/*!

Higher level communication abstractions.

*/

// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];

use pipes::{Channel, Recv, Chan, Port, Selectable};

/// An extension of `pipes::stream` that allows both sending and receiving.
pub struct DuplexStream<T: Send, U: Send> {
    priv chan: Chan<T>,
    priv port: Port <U>,
}

impl<T: Send, U: Send> DuplexStream<T, U> : Channel<T> {
    fn send(+x: T) {
        self.chan.send(move x)
    }

    fn try_send(+x: T) -> bool {
        self.chan.try_send(move x)
    }
}

impl<T: Send, U: Send> DuplexStream<T, U> : Recv<U> {
    fn recv() -> U {
        self.port.recv()
    }

    fn try_recv() -> Option<U> {
        self.port.try_recv()
    }

    pure fn peek() -> bool {
        self.port.peek()
    }
}

impl<T: Send, U: Send> DuplexStream<T, U> : Selectable {
    pure fn header() -> *pipes::PacketHeader {
        self.port.header()
    }
}

/// Creates a bidirectional stream.
fn DuplexStream<T: Send, U: Send>()
    -> (DuplexStream<T, U>, DuplexStream<U, T>)
{
    let (c2, p1) = pipes::stream();
    let (c1, p2) = pipes::stream();
    (DuplexStream {
        chan: c1,
        port: p1
    },
     DuplexStream {
         chan: c2,
         port: p2
     })
}

#[cfg(test)]
mod test {
    #[legacy_exports];
    #[test]
    fn DuplexStream1() {
        let (left, right) = DuplexStream();

        left.send(~"abc");
        right.send(123);

        assert left.recv() == 123;
        assert right.recv() == ~"abc";
    }
}
<commit_msg>std: Make the DuplexStream constructor public<commit_after>/*!

Higher level communication abstractions.

*/

// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];

use pipes::{Channel, Recv, Chan, Port, Selectable};

/// An extension of `pipes::stream` that allows both sending and receiving.
pub struct DuplexStream<T: Send, U: Send> {
    priv chan: Chan<T>,
    priv port: Port <U>,
}

impl<T: Send, U: Send> DuplexStream<T, U> : Channel<T> {
    fn send(+x: T) {
        self.chan.send(move x)
    }

    fn try_send(+x: T) -> bool {
        self.chan.try_send(move x)
    }
}

impl<T: Send, U: Send> DuplexStream<T, U> : Recv<U> {
    fn recv() -> U {
        self.port.recv()
    }

    fn try_recv() -> Option<U> {
        self.port.try_recv()
    }

    pure fn peek() -> bool {
        self.port.peek()
    }
}

impl<T: Send, U: Send> DuplexStream<T, U> : Selectable {
    pure fn header() -> *pipes::PacketHeader {
        self.port.header()
    }
}

/// Creates a bidirectional stream.
pub fn DuplexStream<T: Send, U: Send>()
    -> (DuplexStream<T, U>, DuplexStream<U, T>)
{
    let (c2, p1) = pipes::stream();
    let (c1, p2) = pipes::stream();
    (DuplexStream {
        chan: c1,
        port: p1
    },
     DuplexStream {
         chan: c2,
         port: p2
     })
}

#[cfg(test)]
mod test {
    #[legacy_exports];
    #[test]
    fn DuplexStream1() {
        let (left, right) = DuplexStream();

        left.send(~"abc");
        right.send(123);

        assert left.recv() == 123;
        assert right.recv() == ~"abc";
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc::hir;
use syntax::codemap;
use utils::{snippet, span_lint_and_then};

/// **What it does:** This lint checks for variable declarations immediately followed by a
/// conditional affectation.
///
/// **Why is this bad?** This is not idiomatic Rust.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust,ignore
/// let foo;
///
/// if bar() {
///     foo = 42;
/// } else {
///     foo = 0;
/// }
///
/// let mut baz = None;
///
/// if bar() {
///     baz = Some(42);
/// }
/// ```
///
/// should be written
///
/// ```rust,ignore
/// let foo = if bar() {
///     42;
/// } else {
///     0;
/// };
///
/// let baz = if bar() {
///     Some(42);
/// } else {
///     None
/// };
/// ```
declare_lint! {
    pub USELESS_LET_IF_SEQ,
    Warn,
    "Checks for unidiomatic `let mut` declaration followed by initialization in `if`"
}

#[derive(Copy,Clone)]
pub struct LetIfSeq;

impl LintPass for LetIfSeq {
    fn get_lints(&self) -> LintArray {
        lint_array!(USELESS_LET_IF_SEQ)
    }
}

impl LateLintPass for LetIfSeq {
    fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
        let mut it = block.stmts.iter().peekable();
        while let Some(ref stmt) = it.next() {
            if_let_chain! {[
                let Some(expr) = it.peek(),
                let hir::StmtDecl(ref decl, _) = stmt.node,
                let hir::DeclLocal(ref decl) = decl.node,
                let hir::PatKind::Ident(mode, ref name, None) = decl.pat.node,
                let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id),
                let hir::StmtExpr(ref if_, _) = expr.node,
                let hir::ExprIf(ref cond, ref then, ref else_) = if_.node,
                let Some(value) = check_assign(cx, def.def_id(), then),
            ], {
                let span = codemap::mk_sp(stmt.span.lo, if_.span.hi);

                let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
                    if let hir::ExprBlock(ref else_) = else_.node {
                        if let Some(default) = check_assign(cx, def.def_id(), else_) {
                            (else_.stmts.len() > 1, default)
                        } else if let Some(ref default) = decl.init {
                            (true, &**default)
                        } else {
                            continue;
                        }
                    } else {
                        continue;
                    }
                } else if let Some(ref default) = decl.init {
                    (false, &**default)
                } else {
                    continue;
                };

                let mutability = match mode {
                    hir::BindByRef(hir::MutMutable) | hir::BindByValue(hir::MutMutable) => "<mut> ",
                    _ => "",
                };

                // FIXME: this should not suggest `mut` if we can detect that the variable is not
                // use mutably after the `if`

                let sug = format!(
                    "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};",
                    mut=mutability,
                    name=name.node,
                    cond=snippet(cx, cond.span, "_"),
                    then=if then.stmts.len() > 1 { " ..;" } else { "" },
                    else=if default_multi_stmts { " ..;" } else { "" },
                    value=snippet(cx, value.span, "<value>"),
                    default=snippet(cx, default.span, "<default>"),
                );
                span_lint_and_then(cx,
                                   USELESS_LET_IF_SEQ,
                                   span,
                                   "`if _ { .. } else { .. }` is an expression",
                                   |db| {
                                       db.span_suggestion(span,
                                                          "it is more idiomatic to write",
                                                          sug);
                                       if !mutability.is_empty() {
                                           db.note("you might not need `mut` at all");
                                       }
                                   });
            }}
        }
    }
}

struct UsedVisitor<'a, 'tcx: 'a> {
    cx: &'a LateContext<'a, 'tcx>,
    id: hir::def_id::DefId,
    used: bool,
}

impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, expr: &'v hir::Expr) {
        if_let_chain! {[
            let hir::ExprPath(None, _) = expr.node,
            let Some(def) = self.cx.tcx.def_map.borrow().get(&expr.id),
            self.id == def.def_id(),
        ], {
            self.used = true;
            return;
        }}
        hir::intravisit::walk_expr(self, expr);
    }
}

fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::Block) -> Option<&'e hir::Expr> {
    if_let_chain! {[
        let Some(expr) = block.stmts.iter().last(),
        let hir::StmtSemi(ref expr, _) = expr.node,
        let hir::ExprAssign(ref var, ref value) = expr.node,
        let hir::ExprPath(None, _) = var.node,
        let Some(def) = cx.tcx.def_map.borrow().get(&var.id),
        decl == def.def_id(),
    ], {
        let mut v = UsedVisitor {
            cx: cx,
            id: decl,
            used: false,
        };

        for s in block.stmts.iter().take(block.stmts.len()-1) {
            hir::intravisit::walk_stmt(&mut v, s);
        }

        return if v.used {
            None
        } else {
            Some(value)
        };
    }}

    None
}
<commit_msg>another one. Somehow I failed to correctly commit<commit_after>use rustc::lint::*;
use rustc::hir;
use syntax::codemap;
use utils::{snippet, span_lint_and_then};

/// **What it does:** This lint checks for variable declarations immediately followed by a
/// conditional affectation.
///
/// **Why is this bad?** This is not idiomatic Rust.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust,ignore
/// let foo;
///
/// if bar() {
///     foo = 42;
/// } else {
///     foo = 0;
/// }
///
/// let mut baz = None;
///
/// if bar() {
///     baz = Some(42);
/// }
/// ```
///
/// should be written
///
/// ```rust,ignore
/// let foo = if bar() {
///     42;
/// } else {
///     0;
/// };
///
/// let baz = if bar() {
///     Some(42);
/// } else {
///     None
/// };
/// ```
declare_lint! {
    pub USELESS_LET_IF_SEQ,
    Warn,
    "Checks for unidiomatic `let mut` declaration followed by initialization in `if`"
}

#[derive(Copy,Clone)]
pub struct LetIfSeq;

impl LintPass for LetIfSeq {
    fn get_lints(&self) -> LintArray {
        lint_array!(USELESS_LET_IF_SEQ)
    }
}

impl LateLintPass for LetIfSeq {
    fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
        let mut it = block.stmts.iter().peekable();
        while let Some(ref stmt) = it.next() {
            if_let_chain! {[
                let Some(expr) = it.peek(),
                let hir::StmtDecl(ref decl, _) = stmt.node,
                let hir::DeclLocal(ref decl) = decl.node,
                let hir::PatKind::Binding(mode, ref name, None) = decl.pat.node,
                let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id),
                let hir::StmtExpr(ref if_, _) = expr.node,
                let hir::ExprIf(ref cond, ref then, ref else_) = if_.node,
                let Some(value) = check_assign(cx, def.def_id(), then),
            ], {
                let span = codemap::mk_sp(stmt.span.lo, if_.span.hi);

                let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
                    if let hir::ExprBlock(ref else_) = else_.node {
                        if let Some(default) = check_assign(cx, def.def_id(), else_) {
                            (else_.stmts.len() > 1, default)
                        } else if let Some(ref default) = decl.init {
                            (true, &**default)
                        } else {
                            continue;
                        }
                    } else {
                        continue;
                    }
                } else if let Some(ref default) = decl.init {
                    (false, &**default)
                } else {
                    continue;
                };

                let mutability = match mode {
                    hir::BindByRef(hir::MutMutable) | hir::BindByValue(hir::MutMutable) => "<mut> ",
                    _ => "",
                };

                // FIXME: this should not suggest `mut` if we can detect that the variable is not
                // use mutably after the `if`

                let sug = format!(
                    "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};",
                    mut=mutability,
                    name=name.node,
                    cond=snippet(cx, cond.span, "_"),
                    then=if then.stmts.len() > 1 { " ..;" } else { "" },
                    else=if default_multi_stmts { " ..;" } else { "" },
                    value=snippet(cx, value.span, "<value>"),
                    default=snippet(cx, default.span, "<default>"),
                );
                span_lint_and_then(cx,
                                   USELESS_LET_IF_SEQ,
                                   span,
                                   "`if _ { .. } else { .. }` is an expression",
                                   |db| {
                                       db.span_suggestion(span,
                                                          "it is more idiomatic to write",
                                                          sug);
                                       if !mutability.is_empty() {
                                           db.note("you might not need `mut` at all");
                                       }
                                   });
            }}
        }
    }
}

struct UsedVisitor<'a, 'tcx: 'a> {
    cx: &'a LateContext<'a, 'tcx>,
    id: hir::def_id::DefId,
    used: bool,
}

impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, expr: &'v hir::Expr) {
        if_let_chain! {[
            let hir::ExprPath(None, _) = expr.node,
            let Some(def) = self.cx.tcx.def_map.borrow().get(&expr.id),
            self.id == def.def_id(),
        ], {
            self.used = true;
            return;
        }}
        hir::intravisit::walk_expr(self, expr);
    }
}

fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::Block) -> Option<&'e hir::Expr> {
    if_let_chain! {[
        let Some(expr) = block.stmts.iter().last(),
        let hir::StmtSemi(ref expr, _) = expr.node,
        let hir::ExprAssign(ref var, ref value) = expr.node,
        let hir::ExprPath(None, _) = var.node,
        let Some(def) = cx.tcx.def_map.borrow().get(&var.id),
        decl == def.def_id(),
    ], {
        let mut v = UsedVisitor {
            cx: cx,
            id: decl,
            used: false,
        };

        for s in block.stmts.iter().take(block.stmts.len()-1) {
            hir::intravisit::walk_stmt(&mut v, s);
        }

        return if v.used {
            None
        } else {
            Some(value)
        };
    }}

    None
}
<|endoftext|>


<commit_before>use crate::{
    SyntaxKind, SyntaxKind::EOF, TextRange, TextUnit,
    parsing::{
        TokenPos,
        parser_impl::TokenSource,
        lexer::Token,
    },
};

impl<'t> TokenSource for ParserInput<'t> {
    fn token_kind(&self, pos: TokenPos) -> SyntaxKind {
        let idx = pos.0 as usize;
        if !(idx < self.tokens.len()) {
            return EOF;
        }
        self.tokens[idx].kind
    }
    fn is_token_joint_to_next(&self, pos: TokenPos) -> bool {
        let idx_curr = pos.0 as usize;
        let idx_next = pos.0 as usize;
        if !(idx_next < self.tokens.len()) {
            return true;
        }
        self.start_offsets[idx_curr] + self.tokens[idx_curr].len == self.start_offsets[idx_next]
    }
    fn is_keyword(&self, pos: TokenPos, kw: &str) -> bool {
        let idx = pos.0 as usize;
        if !(idx < self.tokens.len()) {
            return false;
        }
        let range = TextRange::offset_len(self.start_offsets[idx], self.tokens[idx].len);

        self.text[range] == *kw
    }
}

pub(crate) struct ParserInput<'t> {
    text: &'t str,
    /// start position of each token(expect whitespace and comment)
    /// ```non-rust
    ///  struct Foo;
    /// ^------^---
    /// |      |  ^-
    /// 0      7  10
    /// ```
    /// (token, start_offset): `[(struct, 0), (Foo, 7), (;, 10)]`
    start_offsets: Vec<TextUnit>,
    /// non-whitespace/comment tokens
    /// ```non-rust
    /// struct Foo {}
    /// ^^^^^^ ^^^ ^^
    /// ```
    /// tokens: `[struct, Foo, {, }]`
    tokens: Vec<Token>,
}

impl<'t> ParserInput<'t> {
    /// Generate input from tokens(expect comment and whitespace).
    pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> ParserInput<'t> {
        let mut tokens = Vec::new();
        let mut start_offsets = Vec::new();
        let mut len = 0.into();
        for &token in raw_tokens.iter() {
            if !token.kind.is_trivia() {
                tokens.push(token);
                start_offsets.push(len);
            }
            len += token.len;
        }

        ParserInput { text, start_offsets, tokens }
    }
}
<commit_msg>fix off by one error<commit_after>use crate::{
    SyntaxKind, SyntaxKind::EOF, TextRange, TextUnit,
    parsing::{
        TokenPos,
        parser_impl::TokenSource,
        lexer::Token,
    },
};

impl<'t> TokenSource for ParserInput<'t> {
    fn token_kind(&self, pos: TokenPos) -> SyntaxKind {
        let idx = pos.0 as usize;
        if !(idx < self.tokens.len()) {
            return EOF;
        }
        self.tokens[idx].kind
    }
    fn is_token_joint_to_next(&self, pos: TokenPos) -> bool {
        let idx_curr = pos.0 as usize;
        let idx_next = pos.0 as usize + 1;
        if !(idx_next < self.tokens.len()) {
            return true;
        }
        self.start_offsets[idx_curr] + self.tokens[idx_curr].len == self.start_offsets[idx_next]
    }
    fn is_keyword(&self, pos: TokenPos, kw: &str) -> bool {
        let idx = pos.0 as usize;
        if !(idx < self.tokens.len()) {
            return false;
        }
        let range = TextRange::offset_len(self.start_offsets[idx], self.tokens[idx].len);

        self.text[range] == *kw
    }
}

pub(crate) struct ParserInput<'t> {
    text: &'t str,
    /// start position of each token(expect whitespace and comment)
    /// ```non-rust
    ///  struct Foo;
    /// ^------^---
    /// |      |  ^-
    /// 0      7  10
    /// ```
    /// (token, start_offset): `[(struct, 0), (Foo, 7), (;, 10)]`
    start_offsets: Vec<TextUnit>,
    /// non-whitespace/comment tokens
    /// ```non-rust
    /// struct Foo {}
    /// ^^^^^^ ^^^ ^^
    /// ```
    /// tokens: `[struct, Foo, {, }]`
    tokens: Vec<Token>,
}

impl<'t> ParserInput<'t> {
    /// Generate input from tokens(expect comment and whitespace).
    pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> ParserInput<'t> {
        let mut tokens = Vec::new();
        let mut start_offsets = Vec::new();
        let mut len = 0.into();
        for &token in raw_tokens.iter() {
            if !token.kind.is_trivia() {
                tokens.push(token);
                start_offsets.push(len);
            }
            len += token.len;
        }

        ParserInput { text, start_offsets, tokens }
    }
}
<|endoftext|>


<commit_before>use std::{
    cell::{Cell, RefCell},
    fs,
    path::{Path, PathBuf},
    sync::Once,
    time::Duration,
};

use crossbeam_channel::{after, select, Receiver};
use lsp_server::{Connection, Message, Notification, Request};
use lsp_types::{
    notification::Exit, request::Shutdown, TextDocumentIdentifier, Url, WorkDoneProgress,
};
use lsp_types::{ProgressParams, ProgressParamsValue};
use serde::Serialize;
use serde_json::{to_string_pretty, Value};
use tempfile::TempDir;
use test_utils::{find_mismatch, Fixture};

use ra_project_model::ProjectManifest;
use rust_analyzer::{
    config::{ClientCapsConfig, Config, LinkedProject},
    main_loop,
};

pub struct Project<'a> {
    fixture: &'a str,
    with_sysroot: bool,
    tmp_dir: Option<TempDir>,
    roots: Vec<PathBuf>,
    config: Option<Box<dyn Fn(&mut Config)>>,
}

impl<'a> Project<'a> {
    pub fn with_fixture(fixture: &str) -> Project {
        Project { fixture, tmp_dir: None, roots: vec![], with_sysroot: false, config: None }
    }

    pub fn tmp_dir(mut self, tmp_dir: TempDir) -> Project<'a> {
        self.tmp_dir = Some(tmp_dir);
        self
    }

    pub(crate) fn root(mut self, path: &str) -> Project<'a> {
        self.roots.push(path.into());
        self
    }

    pub fn with_sysroot(mut self, sysroot: bool) -> Project<'a> {
        self.with_sysroot = sysroot;
        self
    }

    pub fn with_config(mut self, config: impl Fn(&mut Config) + 'static) -> Project<'a> {
        self.config = Some(Box::new(config));
        self
    }

    pub fn server(self) -> Server {
        let tmp_dir = self.tmp_dir.unwrap_or_else(|| TempDir::new().unwrap());
        static INIT: Once = Once::new();
        INIT.call_once(|| {
            env_logger::builder().is_test(true).try_init().unwrap();
            ra_prof::init_from(crate::PROFILE);
        });

        for entry in Fixture::parse(self.fixture) {
            let path = tmp_dir.path().join(&entry.path['/'.len_utf8()..]);
            fs::create_dir_all(path.parent().unwrap()).unwrap();
            fs::write(path.as_path(), entry.text.as_bytes()).unwrap();
        }

        let mut roots =
            self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect::<Vec<_>>();
        if roots.is_empty() {
            roots.push(tmp_dir.path().to_path_buf());
        }
        let linked_projects = roots
            .into_iter()
            .map(|it| ProjectManifest::discover_single(&it).unwrap())
            .map(LinkedProject::from)
            .collect::<Vec<_>>();

        let mut config = Config {
            client_caps: ClientCapsConfig {
                location_link: true,
                code_action_literals: true,
                work_done_progress: true,
                ..Default::default()
            },
            with_sysroot: self.with_sysroot,
            linked_projects,
            ..Config::default()
        };

        if let Some(f) = &self.config {
            f(&mut config)
        }

        Server::new(tmp_dir, config)
    }
}

pub fn project(fixture: &str) -> Server {
    Project::with_fixture(fixture).server()
}

pub struct Server {
    req_id: Cell<u64>,
    messages: RefCell<Vec<Message>>,
    _thread: jod_thread::JoinHandle<()>,
    client: Connection,
    /// XXX: remove the tempdir last
    dir: TempDir,
}

impl Server {
    fn new(dir: TempDir, config: Config) -> Server {
        let (connection, client) = Connection::memory();

        let _thread = jod_thread::Builder::new()
            .name("test server".to_string())
            .spawn(move || main_loop(config, connection).unwrap())
            .expect("failed to spawn a thread");

        Server { req_id: Cell::new(1), dir, messages: Default::default(), client, _thread }
    }

    pub fn doc_id(&self, rel_path: &str) -> TextDocumentIdentifier {
        let path = self.dir.path().join(rel_path);
        TextDocumentIdentifier { uri: Url::from_file_path(path).unwrap() }
    }

    pub fn notification<N>(&self, params: N::Params)
    where
        N: lsp_types::notification::Notification,
        N::Params: Serialize,
    {
        let r = Notification::new(N::METHOD.to_string(), params);
        self.send_notification(r)
    }

    pub fn request<R>(&self, params: R::Params, expected_resp: Value)
    where
        R: lsp_types::request::Request,
        R::Params: Serialize,
    {
        let actual = self.send_request::<R>(params);
        if let Some((expected_part, actual_part)) = find_mismatch(&expected_resp, &actual) {
            panic!(
                "JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
                to_string_pretty(&expected_resp).unwrap(),
                to_string_pretty(&actual).unwrap(),
                to_string_pretty(expected_part).unwrap(),
                to_string_pretty(actual_part).unwrap(),
            );
        }
    }

    pub fn send_request<R>(&self, params: R::Params) -> Value
    where
        R: lsp_types::request::Request,
        R::Params: Serialize,
    {
        let id = self.req_id.get();
        self.req_id.set(id + 1);

        let r = Request::new(id.into(), R::METHOD.to_string(), params);
        self.send_request_(r)
    }
    fn send_request_(&self, r: Request) -> Value {
        let id = r.id.clone();
        self.client.sender.send(r.into()).unwrap();
        while let Some(msg) = self.recv() {
            match msg {
                Message::Request(req) if req.method == "window/workDoneProgress/create" => (),
                Message::Request(req) => panic!("unexpected request: {:?}", req),
                Message::Notification(_) => (),
                Message::Response(res) => {
                    assert_eq!(res.id, id);
                    if let Some(err) = res.error {
                        panic!("error response: {:#?}", err);
                    }
                    return res.result.unwrap();
                }
            }
        }
        panic!("no response");
    }
    pub fn wait_until_workspace_is_loaded(&self) {
        self.wait_for_message_cond(1, &|msg: &Message| match msg {
            Message::Notification(n) if n.method == "$/progress" => {
                match n.clone().extract::<ProgressParams>("$/progress").unwrap() {
                    ProgressParams {
                        token: lsp_types::ProgressToken::String(ref token),
                        value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(_)),
                    } if token == "rustAnalyzer/roots scanned" => true,
                    _ => false,
                }
            }
            _ => false,
        })
    }
    fn wait_for_message_cond(&self, n: usize, cond: &dyn Fn(&Message) -> bool) {
        let mut total = 0;
        for msg in self.messages.borrow().iter() {
            if cond(msg) {
                total += 1
            }
        }
        while total < n {
            let msg = self.recv().expect("no response");
            if cond(&msg) {
                total += 1;
            }
        }
    }
    fn recv(&self) -> Option<Message> {
        recv_timeout(&self.client.receiver).map(|msg| {
            self.messages.borrow_mut().push(msg.clone());
            msg
        })
    }
    fn send_notification(&self, not: Notification) {
        self.client.sender.send(Message::Notification(not)).unwrap();
    }

    pub fn path(&self) -> &Path {
        self.dir.path()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.request::<Shutdown>((), Value::Null);
        self.notification::<Exit>(());
    }
}

fn recv_timeout(receiver: &Receiver<Message>) -> Option<Message> {
    let timeout = Duration::from_secs(120);
    select! {
        recv(receiver) -> msg => msg.ok(),
        recv(after(timeout)) -> _ => panic!("timed out"),
    }
}
<commit_msg>Disable file watching when running slow tests<commit_after>use std::{
    cell::{Cell, RefCell},
    fs,
    path::{Path, PathBuf},
    sync::Once,
    time::Duration,
};

use crossbeam_channel::{after, select, Receiver};
use lsp_server::{Connection, Message, Notification, Request};
use lsp_types::{
    notification::Exit, request::Shutdown, TextDocumentIdentifier, Url, WorkDoneProgress,
};
use lsp_types::{ProgressParams, ProgressParamsValue};
use serde::Serialize;
use serde_json::{to_string_pretty, Value};
use tempfile::TempDir;
use test_utils::{find_mismatch, Fixture};

use ra_project_model::ProjectManifest;
use rust_analyzer::{
    config::{ClientCapsConfig, Config, FilesConfig, FilesWatcher, LinkedProject},
    main_loop,
};

pub struct Project<'a> {
    fixture: &'a str,
    with_sysroot: bool,
    tmp_dir: Option<TempDir>,
    roots: Vec<PathBuf>,
    config: Option<Box<dyn Fn(&mut Config)>>,
}

impl<'a> Project<'a> {
    pub fn with_fixture(fixture: &str) -> Project {
        Project { fixture, tmp_dir: None, roots: vec![], with_sysroot: false, config: None }
    }

    pub fn tmp_dir(mut self, tmp_dir: TempDir) -> Project<'a> {
        self.tmp_dir = Some(tmp_dir);
        self
    }

    pub(crate) fn root(mut self, path: &str) -> Project<'a> {
        self.roots.push(path.into());
        self
    }

    pub fn with_sysroot(mut self, sysroot: bool) -> Project<'a> {
        self.with_sysroot = sysroot;
        self
    }

    pub fn with_config(mut self, config: impl Fn(&mut Config) + 'static) -> Project<'a> {
        self.config = Some(Box::new(config));
        self
    }

    pub fn server(self) -> Server {
        let tmp_dir = self.tmp_dir.unwrap_or_else(|| TempDir::new().unwrap());
        static INIT: Once = Once::new();
        INIT.call_once(|| {
            env_logger::builder().is_test(true).try_init().unwrap();
            ra_prof::init_from(crate::PROFILE);
        });

        for entry in Fixture::parse(self.fixture) {
            let path = tmp_dir.path().join(&entry.path['/'.len_utf8()..]);
            fs::create_dir_all(path.parent().unwrap()).unwrap();
            fs::write(path.as_path(), entry.text.as_bytes()).unwrap();
        }

        let mut roots =
            self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect::<Vec<_>>();
        if roots.is_empty() {
            roots.push(tmp_dir.path().to_path_buf());
        }
        let linked_projects = roots
            .into_iter()
            .map(|it| ProjectManifest::discover_single(&it).unwrap())
            .map(LinkedProject::from)
            .collect::<Vec<_>>();

        let mut config = Config {
            client_caps: ClientCapsConfig {
                location_link: true,
                code_action_literals: true,
                work_done_progress: true,
                ..Default::default()
            },
            with_sysroot: self.with_sysroot,
            linked_projects,
            files: FilesConfig { watcher: FilesWatcher::Client, exclude: Vec::new() },
            ..Config::default()
        };
        if let Some(f) = &self.config {
            f(&mut config)
        }

        Server::new(tmp_dir, config)
    }
}

pub fn project(fixture: &str) -> Server {
    Project::with_fixture(fixture).server()
}

pub struct Server {
    req_id: Cell<u64>,
    messages: RefCell<Vec<Message>>,
    _thread: jod_thread::JoinHandle<()>,
    client: Connection,
    /// XXX: remove the tempdir last
    dir: TempDir,
}

impl Server {
    fn new(dir: TempDir, config: Config) -> Server {
        let (connection, client) = Connection::memory();

        let _thread = jod_thread::Builder::new()
            .name("test server".to_string())
            .spawn(move || main_loop(config, connection).unwrap())
            .expect("failed to spawn a thread");

        Server { req_id: Cell::new(1), dir, messages: Default::default(), client, _thread }
    }

    pub fn doc_id(&self, rel_path: &str) -> TextDocumentIdentifier {
        let path = self.dir.path().join(rel_path);
        TextDocumentIdentifier { uri: Url::from_file_path(path).unwrap() }
    }

    pub fn notification<N>(&self, params: N::Params)
    where
        N: lsp_types::notification::Notification,
        N::Params: Serialize,
    {
        let r = Notification::new(N::METHOD.to_string(), params);
        self.send_notification(r)
    }

    pub fn request<R>(&self, params: R::Params, expected_resp: Value)
    where
        R: lsp_types::request::Request,
        R::Params: Serialize,
    {
        let actual = self.send_request::<R>(params);
        if let Some((expected_part, actual_part)) = find_mismatch(&expected_resp, &actual) {
            panic!(
                "JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
                to_string_pretty(&expected_resp).unwrap(),
                to_string_pretty(&actual).unwrap(),
                to_string_pretty(expected_part).unwrap(),
                to_string_pretty(actual_part).unwrap(),
            );
        }
    }

    pub fn send_request<R>(&self, params: R::Params) -> Value
    where
        R: lsp_types::request::Request,
        R::Params: Serialize,
    {
        let id = self.req_id.get();
        self.req_id.set(id + 1);

        let r = Request::new(id.into(), R::METHOD.to_string(), params);
        self.send_request_(r)
    }
    fn send_request_(&self, r: Request) -> Value {
        let id = r.id.clone();
        self.client.sender.send(r.into()).unwrap();
        while let Some(msg) = self.recv() {
            match msg {
                Message::Request(req) => {
                    if req.method != "window/workDoneProgress/create"
                        && !(req.method == "client/registerCapability"
                            && req.params.to_string().contains("workspace/didChangeWatchedFiles"))
                    {
                        panic!("unexpected request: {:?}", req)
                    }
                }
                Message::Notification(_) => (),
                Message::Response(res) => {
                    assert_eq!(res.id, id);
                    if let Some(err) = res.error {
                        panic!("error response: {:#?}", err);
                    }
                    return res.result.unwrap();
                }
            }
        }
        panic!("no response");
    }
    pub fn wait_until_workspace_is_loaded(&self) {
        self.wait_for_message_cond(1, &|msg: &Message| match msg {
            Message::Notification(n) if n.method == "$/progress" => {
                match n.clone().extract::<ProgressParams>("$/progress").unwrap() {
                    ProgressParams {
                        token: lsp_types::ProgressToken::String(ref token),
                        value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(_)),
                    } if token == "rustAnalyzer/roots scanned" => true,
                    _ => false,
                }
            }
            _ => false,
        })
    }
    fn wait_for_message_cond(&self, n: usize, cond: &dyn Fn(&Message) -> bool) {
        let mut total = 0;
        for msg in self.messages.borrow().iter() {
            if cond(msg) {
                total += 1
            }
        }
        while total < n {
            let msg = self.recv().expect("no response");
            if cond(&msg) {
                total += 1;
            }
        }
    }
    fn recv(&self) -> Option<Message> {
        recv_timeout(&self.client.receiver).map(|msg| {
            self.messages.borrow_mut().push(msg.clone());
            msg
        })
    }
    fn send_notification(&self, not: Notification) {
        self.client.sender.send(Message::Notification(not)).unwrap();
    }

    pub fn path(&self) -> &Path {
        self.dir.path()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.request::<Shutdown>((), Value::Null);
        self.notification::<Exit>(());
    }
}

fn recv_timeout(receiver: &Receiver<Message>) -> Option<Message> {
    let timeout = Duration::from_secs(120);
    select! {
        recv(receiver) -> msg => msg.ok(),
        recv(after(timeout)) -> _ => panic!("timed out"),
    }
}
<|endoftext|>


<commit_before>extern crate rustc_version;
extern crate rusoto_codegen;

use std::env;
use std::path::Path;
use std::io::Write;
use std::fs::File;
use std::thread;

use rusoto_codegen::{Service, generate};

/// Parses and generates variables used to construct a User-Agent.
///
/// This is used to create a User-Agent header string resembling
/// `rusoto/x.y.z rust/x.y.z <os>`.
fn generate_user_agent_vars(output_path: &Path) {
    let rust_version = rustc_version::version();
    let mut f = File::create(&output_path.join("user_agent_vars.rs"))
            .expect("Could not create user agent file");
    f.write_all(format!("static RUST_VERSION: &'static str = \"{}\";", rust_version).as_bytes())
            .expect("Unable to write user agent");
}

/*
gamelift/2015-10-01/service-2.json:    "protocol":"json"
support/2013-04-15/service-2.json:    "protocol":"json"
*/

// expand to use cfg!() so codegen only gets run for services
// in the features list
macro_rules! services {
    ( $( [$name:expr, $date:expr] ),* ) => {
        {
            let mut services = Vec::new();
            $(
                if cfg!(feature = $name) {
                    services.push(Service::new($name, $date));
                }
            )*
            services
        }
    }
}

fn main() {
    let out_dir = env::var_os("OUT_DIR").expect("OUT_DIR not specified");
    let out_path = Path::new(&out_dir).to_owned();

    let services = services! {
        ["acm", "2015-12-08"],
        ["cloudformation", "2010-05-15"],
        ["cloudfront", "2016-09-07"],
        ["cloudhsm", "2014-05-30"],
        ["cloudtrail", "2013-11-01"],
        ["cloudwatch", "2010-08-01"],
        ["codecommit", "2015-04-13"],
        ["codedeploy", "2014-10-06"],
        ["codepipeline", "2015-07-09"],
        ["cognito-identity", "2014-06-30"],
        ["config", "2014-11-12"],
        ["datapipeline", "2012-10-29"],
        ["devicefarm", "2015-06-23"],
        ["directconnect", "2012-10-25"],
        ["ds", "2015-04-16"],
        ["dynamodb", "2012-08-10"],
        ["dynamodbstreams", "2012-08-10"],
        ["ec2", "2015-10-01"],
        ["ecr", "2015-09-21"],
        ["ecs", "2014-11-13"],
        ["elastictranscoder", "2012-09-25"],
        ["emr", "2009-03-31"],
        ["events", "2014-02-03"],
        ["firehose", "2015-08-04"],
        ["iam", "2010-05-08"],
        ["inspector", "2016-02-16"],
        ["iot", "2015-05-28"],
        ["kinesis", "2013-12-02"],
        ["kms", "2014-11-01"],
        ["logs", "2014-03-28"],
        ["machinelearning", "2014-12-12"],
        ["marketplacecommerceanalytics", "2015-07-01"],
        ["opsworks", "2013-02-18"],
        ["route53", "2013-04-01"],
        ["route53domains", "2014-05-15"],
        ["s3", "2006-03-01"],
        ["sqs", "2012-11-05"],
        ["ssm", "2014-11-06"],
        ["storagegateway", "2013-06-30"],
        ["swf", "2012-01-25"],
        ["waf", "2015-08-24"],
        ["workspaces", "2015-04-08"]
    };

    let mut generate_threads = vec![];
    for service in services {
        let thread_outpath = out_path.clone();
        generate_threads.push(thread::spawn(move || {
            generate(service, &thread_outpath);
        }));
    }

    for child_thread in generate_threads {
        match child_thread.join() {
            Ok(_) => {},
            Err(err) => panic!(err)
        }
    }

    generate_user_agent_vars(&out_path);

    let codegen_dir = Path::new("codegen");

    // avoid unnecessary recompiles when used as a crates.io dependency
    if codegen_dir.exists() {
        println!("cargo:rerun-if-changed=codegen");
    }
}
<commit_msg>Updates cloudfront to latest service definition.<commit_after>extern crate rustc_version;
extern crate rusoto_codegen;

use std::env;
use std::path::Path;
use std::io::Write;
use std::fs::File;
use std::thread;

use rusoto_codegen::{Service, generate};

/// Parses and generates variables used to construct a User-Agent.
///
/// This is used to create a User-Agent header string resembling
/// `rusoto/x.y.z rust/x.y.z <os>`.
fn generate_user_agent_vars(output_path: &Path) {
    let rust_version = rustc_version::version();
    let mut f = File::create(&output_path.join("user_agent_vars.rs"))
            .expect("Could not create user agent file");
    f.write_all(format!("static RUST_VERSION: &'static str = \"{}\";", rust_version).as_bytes())
            .expect("Unable to write user agent");
}

/*
gamelift/2015-10-01/service-2.json:    "protocol":"json"
support/2013-04-15/service-2.json:    "protocol":"json"
*/

// expand to use cfg!() so codegen only gets run for services
// in the features list
macro_rules! services {
    ( $( [$name:expr, $date:expr] ),* ) => {
        {
            let mut services = Vec::new();
            $(
                if cfg!(feature = $name) {
                    services.push(Service::new($name, $date));
                }
            )*
            services
        }
    }
}

fn main() {
    let out_dir = env::var_os("OUT_DIR").expect("OUT_DIR not specified");
    let out_path = Path::new(&out_dir).to_owned();

    let services = services! {
        ["acm", "2015-12-08"],
        ["cloudformation", "2010-05-15"],
        ["cloudfront", "2016-11-25"],
        ["cloudhsm", "2014-05-30"],
        ["cloudtrail", "2013-11-01"],
        ["cloudwatch", "2010-08-01"],
        ["codecommit", "2015-04-13"],
        ["codedeploy", "2014-10-06"],
        ["codepipeline", "2015-07-09"],
        ["cognito-identity", "2014-06-30"],
        ["config", "2014-11-12"],
        ["datapipeline", "2012-10-29"],
        ["devicefarm", "2015-06-23"],
        ["directconnect", "2012-10-25"],
        ["ds", "2015-04-16"],
        ["dynamodb", "2012-08-10"],
        ["dynamodbstreams", "2012-08-10"],
        ["ec2", "2015-10-01"],
        ["ecr", "2015-09-21"],
        ["ecs", "2014-11-13"],
        ["elastictranscoder", "2012-09-25"],
        ["emr", "2009-03-31"],
        ["events", "2014-02-03"],
        ["firehose", "2015-08-04"],
        ["iam", "2010-05-08"],
        ["inspector", "2016-02-16"],
        ["iot", "2015-05-28"],
        ["kinesis", "2013-12-02"],
        ["kms", "2014-11-01"],
        ["logs", "2014-03-28"],
        ["machinelearning", "2014-12-12"],
        ["marketplacecommerceanalytics", "2015-07-01"],
        ["opsworks", "2013-02-18"],
        ["route53", "2013-04-01"],
        ["route53domains", "2014-05-15"],
        ["s3", "2006-03-01"],
        ["sqs", "2012-11-05"],
        ["ssm", "2014-11-06"],
        ["storagegateway", "2013-06-30"],
        ["swf", "2012-01-25"],
        ["waf", "2015-08-24"],
        ["workspaces", "2015-04-08"]
    };

    let mut generate_threads = vec![];
    for service in services {
        let thread_outpath = out_path.clone();
        generate_threads.push(thread::spawn(move || {
            generate(service, &thread_outpath);
        }));
    }

    for child_thread in generate_threads {
        match child_thread.join() {
            Ok(_) => {},
            Err(err) => panic!(err)
        }
    }

    generate_user_agent_vars(&out_path);

    let codegen_dir = Path::new("codegen");

    // avoid unnecessary recompiles when used as a crates.io dependency
    if codegen_dir.exists() {
        println!("cargo:rerun-if-changed=codegen");
    }
}
<|endoftext|>


<commit_before>extern crate gcc;

fn main()
{
    gcc::Config::new().cpp(true)
        .file("wrapper/wrapper.cpp")
        .file("pugixml/src/pugixml.cpp")
        .include("pugixml/src")
        .compile("libpugixml.a")
}
<commit_msg>Revert "Removing std c++11 to fix travis CI"<commit_after>extern crate gcc;

fn main()
{
    gcc::Config::new().cpp(true)
        .file("wrapper/wrapper.cpp")
        .file("pugixml/src/pugixml.cpp")
        .include("pugixml/src")
        .flag("-std=c++11")
        .compile("libpugixml.a")
}
<|endoftext|>


<commit_before>use ::square_matrix::SquareMatrix;

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum Mark {
   None,
   Star,
   Prime
}

#[derive(Debug)]
pub struct MarkMatrix {
    marks: SquareMatrix<Mark>
}

impl MarkMatrix {
    pub fn new(n: usize) -> MarkMatrix {
        MarkMatrix {marks: SquareMatrix::from_row_vec(n, (0..n*n).map(|_| Mark::None).collect())}
    }

    pub fn n(&self) -> usize { self.marks.n() }

    pub fn toggle_star(&mut self, pos: (usize, usize)) {
        if self.is_star(pos) {
            self.unmark(pos);
        } else {
            self.star(pos);
        }
    }

    pub fn unmark(&mut self, pos: (usize, usize)) {
       self.marks[pos] = Mark::None;
    }

    pub fn star(&mut self, pos: (usize, usize)) {
       self.marks[pos] = Mark::Star;
    }

    pub fn prime(&mut self, pos: (usize, usize)) {
       self.marks[pos] = Mark::Prime;
    }

    pub fn is_star(&self, pos: (usize, usize)) -> bool {
        match self.marks[pos] {
            Mark::Star => true,
            _          => false
        }
    }

    pub fn is_prime(&self, pos: (usize, usize)) -> bool {
        match self.marks[pos] {
            Mark::Prime => true,
            _          => false
        }
    }

    #[cfg(test)]
    pub fn is_none(&self, pos: (usize, usize)) -> bool {
        match self.marks[pos] {
            Mark::None => true,
            _          => false
        }
    }

    pub fn find_first_star_in_row(&self, row: usize) -> Option<usize> {
        for col in 0..self.n() {
            if self.is_star((row, col)) {
                return Some(col);
            }
        }
        return None;
    }

    pub fn find_first_prime_in_row(&self, row: usize) -> Option<usize> {
        for col in 0..self.n() {
            if self.is_prime((row, col)) {
                return Some(col);
            }
        }
        return None;
    }

    pub fn find_first_star_in_col(&self, col: usize) -> Option<usize> {
        for row in 0..self.n() {
            if self.is_star((row, col)) {
                return Some(row);
            }
        }
        return None;
    }

    pub fn clear_primes(&mut self) {
        for row in 0..self.n() {
            for col in 0..self.n() {
                if self.is_prime((row, col)) {
                    self.unmark((row, col));
                }
            }
        }
    }
}
<commit_msg>Add TODO<commit_after>use ::square_matrix::SquareMatrix;

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum Mark {
   None,
   Star,
   Prime
}

#[derive(Debug)]
pub struct MarkMatrix {
    marks: SquareMatrix<Mark>
}

// XXX: Use two bitmatrices. Each row has a fixed number of u64 integers. Use bit-search

impl MarkMatrix {
    pub fn new(n: usize) -> MarkMatrix {
        MarkMatrix {marks: SquareMatrix::from_row_vec(n, (0..n*n).map(|_| Mark::None).collect())}
    }

    pub fn n(&self) -> usize { self.marks.n() }

    pub fn toggle_star(&mut self, pos: (usize, usize)) {
        if self.is_star(pos) {
            self.unmark(pos);
        } else {
            self.star(pos);
        }
    }

    pub fn unmark(&mut self, pos: (usize, usize)) {
       self.marks[pos] = Mark::None;
    }

    pub fn star(&mut self, pos: (usize, usize)) {
       self.marks[pos] = Mark::Star;
    }

    pub fn prime(&mut self, pos: (usize, usize)) {
       self.marks[pos] = Mark::Prime;
    }

    pub fn is_star(&self, pos: (usize, usize)) -> bool {
        match self.marks[pos] {
            Mark::Star => true,
            _          => false
        }
    }

    pub fn is_prime(&self, pos: (usize, usize)) -> bool {
        match self.marks[pos] {
            Mark::Prime => true,
            _          => false
        }
    }

    #[cfg(test)]
    pub fn is_none(&self, pos: (usize, usize)) -> bool {
        match self.marks[pos] {
            Mark::None => true,
            _          => false
        }
    }

    pub fn find_first_star_in_row(&self, row: usize) -> Option<usize> {
        for col in 0..self.n() {
            if self.is_star((row, col)) {
                return Some(col);
            }
        }
        return None;
    }

    pub fn find_first_prime_in_row(&self, row: usize) -> Option<usize> {
        for col in 0..self.n() {
            if self.is_prime((row, col)) {
                return Some(col);
            }
        }
        return None;
    }

    pub fn find_first_star_in_col(&self, col: usize) -> Option<usize> {
        for row in 0..self.n() {
            if self.is_star((row, col)) {
                return Some(row);
            }
        }
        return None;
    }

    pub fn clear_primes(&mut self) {
        for row in 0..self.n() {
            for col in 0..self.n() {
                if self.is_prime((row, col)) {
                    self.unmark((row, col));
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use std::ops::{
    Add,
    BitXor,
    Mul,
};
use num::complex::{Complex32, Complex64};
use default::Default;
use vector::ops::*;
use vector::Vector;
use math::{
    Marker,
    Trans,
};

impl<'a, T> BitXor<Marker> for &'a Vector<T>
{
    type Output = Trans<&'a Vector<T>>;

    fn bitxor(self, m: Marker) -> Trans<&'a Vector<T>> {
        match m {
            Marker::T => Trans::T(self),
            Marker::H => Trans::H(self),
        }
    }
}

impl<'a, T> Add<&'a Vector<T>> for &'a Vector<T>
    where T: Axpy + Copy + Default
{
    type Output = Vec<T>;

    fn add(self, rhs: &Vector<T>) -> Vec<T> {
        let mut v: Vec<T> = self.into();
        let scale = Default::one();

        Axpy::axpy(&scale, rhs, &mut v);
        Vec::from(v)
    }
}

impl<'a, T, V> Mul<&'a V> for Trans<&'a Vector<T>>
    where T: Sized + Copy + Dot + Dotc,
          V: Vector<T>,
{
    type Output = T;

    fn mul(self, x: &'a V) -> T {
        match self {
            Trans::T(v) => Dot::dot(v, x),
            Trans::H(v) => Dotc::dotc(v, x),
        }
    }
}

impl<'a, T> Mul<T> for &'a Vector<T>
    where T: Sized + Copy + Scal
{
    type Output = Vec<T>;

    fn mul(self, alpha: T) -> Vec<T> {
        let mut result: Vec<_> = self.into();
        Scal::scal(&alpha, &mut result);
        result
    }
}

macro_rules! left_scale(($($t: ident), +) => (
    $(
        impl<'a> Mul<&'a Vector<$t>> for $t
        {
            type Output = Vec<$t>;

            fn mul(self, x: &'a Vector<$t>) -> Vec<$t> {
                let mut result: Vec<_> = x.into();
                Scal::scal(&self, &mut result);
                result
            }
        }
    )+
));

left_scale!(f32, f64, Complex32, Complex64);

#[cfg(test)]
mod tests {
    use Vector;
    use math::Marker::{T, H};
    use num::complex::Complex;

    #[test]
    fn add() {
        let x = vec![1f32, 2f32];
        let y = vec![3f32, 4f32];

        let z = &x as &Vector<_> + &y;

        assert_eq!(&z, &vec![4f32, 6f32]);
    }

    #[test]
    fn dot() {
        let x = vec![1f32, 2f32];
        let y = vec![-1f32, 2f32];

        let dot = {
            let z = &x as &Vector<_>;
            (z ^ T) * &y
        };

        assert_eq!(dot, 3.0);
    }

    #[test]
    fn herm_dot() {
        let x = vec![Complex::new(1f32, -1f32), Complex::new(1f32, -3f32)];
        let y = vec![Complex::new(1f32, 2f32), Complex::new(1f32, 3f32)];

        let dot = {
            let z = &x as &Vector<_>;
            (z ^ H) * &y
        };

        assert_eq!(dot, Complex::new(-9f32, 9f32));
    }

    #[test]
    fn scale() {
        let x = vec![1f32, 2f32];
        let xr = &x as &Vector<_>;

        let y = xr * 3.0;
        let z = 3.0 * xr;
        assert_eq!(y, vec![3f32, 6f32]);
        assert_eq!(z, y);
    }
}
<commit_msg>Clean add impl<commit_after>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use std::ops::{
    Add,
    BitXor,
    Mul,
};
use num::complex::{Complex32, Complex64};
use default::Default;
use vector::ops::*;
use vector::Vector;
use math::{
    Marker,
    Trans,
};

impl<'a, T> BitXor<Marker> for &'a Vector<T>
{
    type Output = Trans<&'a Vector<T>>;

    fn bitxor(self, m: Marker) -> Trans<&'a Vector<T>> {
        match m {
            Marker::T => Trans::T(self),
            Marker::H => Trans::H(self),
        }
    }
}

impl<'a, T> Add for &'a Vector<T>
    where T: Axpy + Copy + Default
{
    type Output = Vec<T>;

    fn add(self, x: &Vector<T>) -> Vec<T> {
        let mut result: Vec<_> = self.into();
        let scale = Default::one();

        Axpy::axpy(&scale, x, &mut result);
        result
    }
}

impl<'a, T, V> Mul<&'a V> for Trans<&'a Vector<T>>
    where T: Sized + Copy + Dot + Dotc,
          V: Vector<T>,
{
    type Output = T;

    fn mul(self, x: &'a V) -> T {
        match self {
            Trans::T(v) => Dot::dot(v, x),
            Trans::H(v) => Dotc::dotc(v, x),
        }
    }
}

impl<'a, T> Mul<T> for &'a Vector<T>
    where T: Sized + Copy + Scal
{
    type Output = Vec<T>;

    fn mul(self, alpha: T) -> Vec<T> {
        let mut result: Vec<_> = self.into();
        Scal::scal(&alpha, &mut result);
        result
    }
}

macro_rules! left_scale(($($t: ident), +) => (
    $(
        impl<'a> Mul<&'a Vector<$t>> for $t
        {
            type Output = Vec<$t>;

            fn mul(self, x: &'a Vector<$t>) -> Vec<$t> {
                let mut result: Vec<_> = x.into();
                Scal::scal(&self, &mut result);
                result
            }
        }
    )+
));

left_scale!(f32, f64, Complex32, Complex64);

#[cfg(test)]
mod tests {
    use Vector;
    use math::Marker::{T, H};
    use num::complex::Complex;

    #[test]
    fn add() {
        let x = vec![1f32, 2f32];
        let y = vec![3f32, 4f32];

        let z = &x as &Vector<_> + &y;

        assert_eq!(&z, &vec![4f32, 6f32]);
    }

    #[test]
    fn dot() {
        let x = vec![1f32, 2f32];
        let y = vec![-1f32, 2f32];

        let dot = {
            let z = &x as &Vector<_>;
            (z ^ T) * &y
        };

        assert_eq!(dot, 3.0);
    }

    #[test]
    fn herm_dot() {
        let x = vec![Complex::new(1f32, -1f32), Complex::new(1f32, -3f32)];
        let y = vec![Complex::new(1f32, 2f32), Complex::new(1f32, 3f32)];

        let dot = {
            let z = &x as &Vector<_>;
            (z ^ H) * &y
        };

        assert_eq!(dot, Complex::new(-9f32, 9f32));
    }

    #[test]
    fn scale() {
        let x = vec![1f32, 2f32];
        let xr = &x as &Vector<_>;

        let y = xr * 3.0;
        let z = 3.0 * xr;
        assert_eq!(y, vec![3f32, 6f32]);
        assert_eq!(z, y);
    }
}
<|endoftext|>


<commit_before>use nix::sys::select::{FdSet, FD_SETSIZE, select};
use nix::sys::time::TimeVal;
use nix::unistd::{write, pipe};

#[test]
fn test_fdset() {
    let mut fd_set = FdSet::new();

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }

    fd_set.insert(7);

    assert!(fd_set.contains(7));

    fd_set.remove(7);

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }

    fd_set.insert(1);
    fd_set.insert(FD_SETSIZE / 2);
    fd_set.insert(FD_SETSIZE - 1);

    fd_set.clear();

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }
}

#[test]
fn test_select() {
    let (r1, w1) = pipe().unwrap();
    write(w1, b"hi!").unwrap();
    let (r2, _w2) = pipe().unwrap();

    let mut fd_set = FdSet::new();
    fd_set.insert(r1);
    fd_set.insert(r2);

    let mut timeout = TimeVal::seconds(1);
    assert_eq!(1, select(r2 + 1,
                         Some(&mut fd_set),
                         None,
                         None,
                         Some(&mut timeout)).unwrap());
    assert!(fd_set.contains(r1));
    assert!(!fd_set.contains(r2));
}
<commit_msg>Fix intermittency in test_select<commit_after>use nix::sys::select::{FdSet, FD_SETSIZE, select};
use nix::sys::time::TimeVal;
use nix::unistd::{write, pipe};

#[test]
fn test_fdset() {
    let mut fd_set = FdSet::new();

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }

    fd_set.insert(7);

    assert!(fd_set.contains(7));

    fd_set.remove(7);

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }

    fd_set.insert(1);
    fd_set.insert(FD_SETSIZE / 2);
    fd_set.insert(FD_SETSIZE - 1);

    fd_set.clear();

    for i in 0..FD_SETSIZE {
        assert!(!fd_set.contains(i));
    }
}

#[test]
fn test_select() {
    let (r1, w1) = pipe().unwrap();
    write(w1, b"hi!").unwrap();
    let (r2, _w2) = pipe().unwrap();

    let mut fd_set = FdSet::new();
    fd_set.insert(r1);
    fd_set.insert(r2);

    let mut timeout = TimeVal::seconds(10);
    assert_eq!(1, select(r2 + 1,
                         Some(&mut fd_set),
                         None,
                         None,
                         Some(&mut timeout)).unwrap());
    assert!(fd_set.contains(r1));
    assert!(!fd_set.contains(r2));
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;

use crate::{api::prelude::*, proc_macros::*};

/// This state can be used to operate on the `Pager` widget inside of callbacks.
#[derive(Debug, Clone, PartialEq)]
enum PagerAction {
    Next,
    Previous,
    Navigate(usize),
    NavigateToCurrent,
    Remove(usize),
    Push(Entity),
}

#[derive(Default, Clone, Debug, AsAny)]
pub struct PagerState {
    current_index: usize,
    actions: VecDeque<PagerAction>,
}

impl PagerState {
    // used internal to navigate to the current index.
    fn navigate_to_current_index(&mut self) {
        self.actions.push_front(PagerAction::NavigateToCurrent);
    }

    /// Navigates to the next child. If the current child is the last in the list nothing will happen.
    pub fn next(&mut self) {
        self.actions.push_front(PagerAction::Next);
    }

    /// Navigates to the previous child. If the current child is the first in the list nothing will happen.
    pub fn previous(&mut self) {
        self.actions.push_front(PagerAction::Previous);
    }

    /// Navigates to the given index. Is the index out of bounds nothing will happen.
    pub fn navigate(&mut self, index: usize) {
        self.actions.push_front(PagerAction::Navigate(index));
    }

    /// Removes the child on the given index. If the index is out of bounds nothing will happen.
    pub fn remove(&mut self, index: usize) {
        self.actions.push_front(PagerAction::Remove(index));
    }

    /// Pushes the given entity on the end of the pagers children.
    pub fn push(&mut self, entity: Entity) {
        self.actions.push_front(PagerAction::Push(entity));
    }
}

impl State for PagerState {
    fn init(&mut self, _registry: &mut Registry, ctx: &mut Context) {
        let current_index = Pager::correct_current_index(ctx);

        if let Some(count) = ctx.widget().children_count() {
            for i in 0..count {
                // make child on the current index always visible (todo: use current_index)
                if i == current_index {
                    if let Some(child) = &mut ctx.try_child_from_index(i) {
                        child.set("visibility", Visibility::Visible);
                    }

                    continue;
                }

                // collapse all other children
                if let Some(child) = &mut ctx.try_child_from_index(i) {
                    child.set("visibility", Visibility::Collapsed);
                }
            }
        }

        Pager::update_next_previous_enabled(ctx, current_index);
    }

    fn update(&mut self, _registry: &mut Registry, ctx: &mut Context) {
        if let Some(action) = self.actions.pop_front() {
            match action {
                PagerAction::Next => Pager::next(ctx, ctx.entity),
                PagerAction::Previous => Pager::previous(ctx, ctx.entity),
                PagerAction::Navigate(index) => Pager::navigate(ctx, ctx.entity, index),
                PagerAction::Remove(index) => Pager::remove(ctx, ctx.entity, index),
                PagerAction::Push(entity) => Pager::push(ctx, ctx.entity, entity),
                PagerAction::NavigateToCurrent => {
                    let current_index = Pager::correct_current_index(ctx);
                    Pager::navigate(ctx, ctx.entity, current_index);
                }
            }
        }
    }
}

widget!(
    /// `Pager` is a navigation widget that provides a stack based navigation.
    ///
    /// There are two way to interact with the `Pager`. By using the `PagerState` and by using the associated functions of `Pager`.
    /// It is suggested to use the state methods on callbacks and the associated functions inside of states of other widgets.
    ///
    /// # Example
    ///
    /// ```rust
    /// let pager = Pager::new()
    ///     .child(TextBlock::new().text("Page 1").build(ctx))
    ///     .child(TextBlock::new().text("Page 2").build(ctx))
    ///     .build(ctx);
    ///
    /// let next_button = Button::new()
    ///     .enabled(("next_enabled", pager))
    ///     .text("next")
    ///     .on_click(move |states, _| {
    ///         states.get_mut::<PagerState>(pager).next();
    ///         true
    ///     })
    ///     .build(ctx);
    ///
    /// let previous_button = Button::new()
    ///     .enabled(("previous_enabled", pager))
    ///     .text("previous")
    ///     .on_click(move |states, _| {
    ///         states.get_mut::<PagerState>(pager).previous();
    ///         true
    ///     })
    ///     .build(ctx);
    /// ```
    Pager<PagerState> {
        /// Defines the index of the current shown child.
        current_index: usize,

        /// Used to check if  next can be executed. If the current visible child is the last child next can not be executed.
        next_enabled: bool,

        /// Used to check if a previous can be executed. If the current visible child is the first child previous can not be executed.
        previous_enabled: bool
    }
);

impl Pager {
    // checks and updates if next and previous can be executed.
    fn update_next_previous_enabled(ctx: &mut Context, current_index: usize) {
        if current_index == 0 {
            Pager::previous_enabled_set(&mut ctx.widget(), false);
        } else {
            Pager::previous_enabled_set(&mut ctx.widget(), true);
        }

        if let Some(count) = ctx.widget().children_count() {
            if current_index == count - 1 {
                Pager::next_enabled_set(&mut ctx.widget(), false);
            } else {
                Pager::next_enabled_set(&mut ctx.widget(), true);
            }
        }
    }

    // corrects the current_index to bounds and returns the corrected value.
    fn correct_current_index(ctx: &mut Context) -> usize {
        let mut current_index = *Pager::current_index_ref(&ctx.widget());
        if let Some(count) = ctx.widget().children_count() {
            if current_index >= count {
                current_index = count - 1;
            }
        }

        Pager::current_index_set(&mut ctx.widget(), current_index);

        current_index
    }

    /// Navigates to the next child. If the current child is the last in the list nothing will happen.
    pub fn next(ctx: &mut Context, entity: Entity) {
        let current_index = *Pager::current_index_ref(&ctx.get_widget(entity));
        Pager::navigate(ctx, entity, current_index + 1);
    }

    /// Navigates to the previous child. If the current child is the first in the list nothing will happen.
    pub fn previous(ctx: &mut Context, entity: Entity) {
        let current_index = *Pager::current_index_ref(&ctx.get_widget(entity));
        if current_index == 0 {
            return;
        }
        Pager::navigate(ctx, entity, current_index - 1);
    }

    /// Navigates to the given index. Is the index out of bounds nothing will happen.
    pub fn navigate(ctx: &mut Context, entity: Entity, index: usize) {
        // update enabled next / previous
        Pager::panics_on_wrong_type(&ctx.get_widget(entity));

        // if the index is the index of the current visible items it returns
        if let Some(child) = ctx.try_child_from_index(index) {
            if *child.get::<Visibility>("visibility") == Visibility::Visible {
                return;
            }
        }

        if let Some(count) = ctx.get_widget(entity).children_count() {
            if index >= count {
                return;
            }

            // hide the last visible child
            if let Some(count) = ctx.widget().children_count() {
                for i in 0..count {
                    if let Some(child) = &mut ctx.try_child_from_index(i) {
                        if *child.get::<Visibility>("visibility") != Visibility::Visible {
                            continue;
                        }

                        child.set("visibility", Visibility::Collapsed);
                    }
                }
            }

            if let Some(child) = &mut ctx.try_child_from_index(index) {
                child.set("visibility", Visibility::Visible);
            }

            Pager::current_index_set(&mut ctx.get_widget(entity), index);

            Pager::update_next_previous_enabled(ctx, index);
        }
    }

    /// Removes the child on the given index. If the index is out of bounds nothing will happen.
    pub fn remove(ctx: &mut Context, entity: Entity, index: usize) {
        Pager::panics_on_wrong_type(&ctx.get_widget(entity));

        let current_index = *Pager::current_index_ref(&ctx.get_widget(entity));

        let child_entity = {
            if let Some(child) = ctx.try_child_from_index(index) {
                Some(child.entity())
            } else {
                None
            }
        };

        if let Some(child) = child_entity {
            ctx.remove_child_from(child, entity);
        }

        if current_index >= index && current_index > 0 {
            // callback will handle the rest like navigation
            Pager::current_index_set(&mut ctx.get_widget(entity), current_index - 1);
        }
    }

    /// Pushes the given entity on the end of the pagers children.
    pub fn push(ctx: &mut Context, entity: Entity, child: Entity) {
        Pager::panics_on_wrong_type(&ctx.get_widget(entity));

        ctx.append_child_entity_to(child, entity);
        let current_index = *Pager::current_index_ref(&ctx.get_widget(entity));
        Pager::update_next_previous_enabled(ctx, current_index);
    }
}

impl Template for Pager {
    fn template(self, _id: Entity, _context: &mut BuildContext) -> Self {
        self.name("Pager")
            .on_changed("current_index", |states, id| {
                states.get_mut::<PagerState>(id).navigate_to_current_index();
            })
    }
}
<commit_msg>finish pager<commit_after>use std::collections::VecDeque;

use crate::{api::prelude::*, proc_macros::*};

/// This state can be used to operate on the `Pager` widget inside of callbacks.
#[derive(Debug, Clone, PartialEq)]
enum PagerAction {
    Next,
    Previous,
    Navigate(usize),
    NavigateToCurrent,
    Remove(usize),
    Push(Entity),
}

#[derive(Default, Clone, Debug, AsAny)]
pub struct PagerState {
    current_index: usize,
    actions: VecDeque<PagerAction>,
}

impl PagerState {
    // used internal to navigate to the current index.
    fn navigate_to_current_index(&mut self) {
        self.actions.push_front(PagerAction::NavigateToCurrent);
    }

    /// Navigates to the next child. If the current child is the last in the list nothing will happen.
    pub fn next(&mut self) {
        self.actions.push_front(PagerAction::Next);
    }

    /// Navigates to the previous child. If the current child is the first in the list nothing will happen.
    pub fn previous(&mut self) {
        self.actions.push_front(PagerAction::Previous);
    }

    /// Navigates to the given index. Is the index out of bounds nothing will happen.
    pub fn navigate(&mut self, index: usize) {
        self.actions.push_front(PagerAction::Navigate(index));
    }

    /// Removes the child on the given index. If the index is out of bounds nothing will happen.
    pub fn remove(&mut self, index: usize) {
        self.actions.push_front(PagerAction::Remove(index));
    }

    /// Pushes the given entity on the end of the pagers children.
    pub fn push(&mut self, entity: Entity) {
        self.actions.push_front(PagerAction::Push(entity));
    }
}

impl State for PagerState {
    fn init(&mut self, _registry: &mut Registry, ctx: &mut Context) {
        let current_index = Pager::correct_current_index(ctx);

        if let Some(count) = ctx.widget().children_count() {
            for i in 0..count {
                // make child on the current index always visible (todo: use current_index)
                if i == current_index {
                    if let Some(child) = &mut ctx.try_child_from_index(i) {
                        child.set("visibility", Visibility::Visible);
                    }

                    continue;
                }

                // collapse all other children
                if let Some(child) = &mut ctx.try_child_from_index(i) {
                    child.set("visibility", Visibility::Collapsed);
                }
            }
        }

        Pager::update_next_previous_enabled(ctx, current_index);
    }

    fn update(&mut self, _registry: &mut Registry, ctx: &mut Context) {
        if let Some(action) = self.actions.pop_front() {
            match action {
                PagerAction::Next => Pager::next(ctx, ctx.entity),
                PagerAction::Previous => Pager::previous(ctx, ctx.entity),
                PagerAction::Navigate(index) => Pager::navigate(ctx, ctx.entity, index),
                PagerAction::Remove(index) => Pager::remove(ctx, ctx.entity, index),
                PagerAction::Push(entity) => Pager::push(ctx, ctx.entity, entity),
                PagerAction::NavigateToCurrent => {
                    let current_index = Pager::correct_current_index(ctx);
                    Pager::navigate(ctx, ctx.entity, current_index);
                }
            }
        }
    }
}

widget!(
    /// `Pager` is a navigation widget that provides a stack based navigation.
    ///
    /// There are two way to interact with the `Pager`. By using the `PagerState` and by using the associated functions of `Pager`.
    /// It is suggested to use the state methods on callbacks and the associated functions inside of states of other widgets.
    ///
    /// # Example
    ///
    /// ```rust
    /// let pager = Pager::new()
    ///     .child(TextBlock::new().text("Page 1").build(ctx))
    ///     .child(TextBlock::new().text("Page 2").build(ctx))
    ///     .build(ctx);
    ///
    /// let next_button = Button::new()
    ///     .enabled(("next_enabled", pager))
    ///     .text("next")
    ///     .on_click(move |states, _| {
    ///         states.get_mut::<PagerState>(pager).next();
    ///         true
    ///     })
    ///     .build(ctx);
    ///
    /// let previous_button = Button::new()
    ///     .enabled(("previous_enabled", pager))
    ///     .text("previous")
    ///     .on_click(move |states, _| {
    ///         states.get_mut::<PagerState>(pager).previous();
    ///         true
    ///     })
    ///     .build(ctx);
    /// ```
    Pager<PagerState> {
        /// Defines the index of the current shown child.
        current_index: usize,

        /// Used to check if  next can be executed. If the current visible child is the last child next can not be executed.
        next_enabled: bool,

        /// Used to check if a previous can be executed. If the current visible child is the first child previous can not be executed.
        previous_enabled: bool
    }
);

impl Pager {
    // checks and updates if next and previous can be executed.
    fn update_next_previous_enabled(ctx: &mut Context, current_index: usize) {
        if current_index == 0 {
            Pager::previous_enabled_set(&mut ctx.widget(), false);
        } else {
            Pager::previous_enabled_set(&mut ctx.widget(), true);
        }

        if let Some(count) = ctx.widget().children_count() {
            if current_index == count - 1 {
                Pager::next_enabled_set(&mut ctx.widget(), false);
            } else {
                Pager::next_enabled_set(&mut ctx.widget(), true);
            }
        }
    }

    // corrects the current_index to bounds and returns the corrected value.
    fn correct_current_index(ctx: &mut Context) -> usize {
        let mut current_index = *Pager::current_index_ref(&ctx.widget());
        if let Some(count) = ctx.widget().children_count() {
            if current_index >= count {
                current_index = count - 1;
            }
        }

        Pager::current_index_set(&mut ctx.widget(), current_index);

        current_index
    }

    /// Navigates to the next child. If the current child is the last in the list nothing will happen.
    pub fn next(ctx: &mut Context, entity: Entity) {
        let current_index = *Pager::current_index_ref(&ctx.get_widget(entity));
        Pager::navigate(ctx, entity, current_index + 1);
    }

    /// Navigates to the previous child. If the current child is the first in the list nothing will happen.
    pub fn previous(ctx: &mut Context, entity: Entity) {
        let current_index = *Pager::current_index_ref(&ctx.get_widget(entity));
        if current_index == 0 {
            return;
        }
        Pager::navigate(ctx, entity, current_index - 1);
    }

    /// Navigates to the given index. Is the index out of bounds nothing will happen.
    pub fn navigate(ctx: &mut Context, entity: Entity, index: usize) {
        // update enabled next / previous
        Pager::panics_on_wrong_type(&ctx.get_widget(entity));

        // if the index is the index of the current visible items it returns
        if let Some(child) = ctx.try_child_from_index(index) {
            if *child.get::<Visibility>("visibility") == Visibility::Visible {
                return;
            }
        }

        if let Some(count) = ctx.get_widget(entity).children_count() {
            if index >= count {
                return;
            }

            // hide the last visible child
            if let Some(count) = ctx.widget().children_count() {
                for i in 0..count {
                    if let Some(child) = &mut ctx.try_child_from_index(i) {
                        if *child.get::<Visibility>("visibility") != Visibility::Visible {
                            continue;
                        }

                        child.set("visibility", Visibility::Collapsed);
                    }
                }
            }

            if let Some(child) = &mut ctx.try_child_from_index(index) {
                child.set("visibility", Visibility::Visible);
            }

            Pager::current_index_set(&mut ctx.get_widget(entity), index);

            Pager::update_next_previous_enabled(ctx, index);
        }
    }

    /// Removes the child on the given index. If the index is out of bounds nothing will happen.
    pub fn remove(ctx: &mut Context, entity: Entity, index: usize) {
        Pager::panics_on_wrong_type(&ctx.get_widget(entity));

        let current_index = *Pager::current_index_ref(&ctx.get_widget(entity));

        let child_entity = {
            if let Some(child) = ctx.try_child_from_index(index) {
                Some(child.entity())
            } else {
                None
            }
        };

        if let Some(child) = child_entity {
            ctx.remove_child_from(child, entity);
        }

        if let Some(count) = ctx.widget().children_count() {
            if (index == current_index && index == count - 1) || index < current_index {
                Pager::navigate(ctx, entity, current_index - 1);
                return;
            }
        }

        Pager::navigate(ctx, entity, current_index);
    }

    /// Pushes the given entity on the end of the pagers children.
    pub fn push(ctx: &mut Context, entity: Entity, child: Entity) {
        Pager::panics_on_wrong_type(&ctx.get_widget(entity));

        ctx.append_child_entity_to(child, entity);
        let current_index = *Pager::current_index_ref(&ctx.get_widget(entity));
        Pager::update_next_previous_enabled(ctx, current_index);
    }
}

impl Template for Pager {
    fn template(self, _id: Entity, _context: &mut BuildContext) -> Self {
        self.name("Pager")
            .on_changed("current_index", |states, id| {
                states.get_mut::<PagerState>(id).navigate_to_current_index();
            })
    }
}
<|endoftext|>