<commit_before>extern crate pkg_config;
extern crate gcc;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::io::ErrorKind;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let windows = target.contains("windows");

    // OSX ships libcurl by default, so we just use that version
    // unconditionally.
    if target.contains("apple") {
        return println!("cargo:rustc-flags=-l curl");
    }

    // Illumos/Solaris requires explicit linking with libnsl
    if target.contains("solaris") {
        println!("cargo:rustc-flags=-l nsl");
    }

    // Next, fall back and try to use pkg-config if its available.
    if !target.contains("windows") {
        match pkg_config::find_library("libcurl") {
            Ok(lib) => {
                for path in lib.include_paths.iter() {
                    println!("cargo:include={}", path.display());
                }
                return
            }
            Err(e) => println!("Couldn't find libcurl from \
                               pkgconfig ({:?}), compiling it from source...", e),
        }
    }

    if !Path::new("curl/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    println!("cargo:rustc-link-search={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=curl");
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}/include", dst.display());
    if windows {
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=crypt32");
    }

    // MSVC builds are just totally different
    if target.contains("msvc") {
        return build_msvc(&target);
    }

    let cfg = gcc::Config::new();
    let compiler = cfg.get_compiler();

    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("sh");
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // Can't run ./configure directly on msys2 b/c we're handing in
    // Windows-style paths (those starting with C:\), but it chokes on those.
    // For that reason we build up a shell script with paths converted to
    // posix versions hopefully...
    //
    // Also apparently the buildbots choke unless we manually set LD, who knows
    // why?!
    cmd.env("CC", compiler.path())
       .env("CFLAGS", cflags)
       .env("LD", &which("ld").unwrap())
       .env("VERBOSE", "1")
       .current_dir(&dst.join("build"))
       .arg(msys_compatible(&src.join("curl/configure")));

    // For now this build script doesn't support paths with spaces in them. This
    // is arguably a but in curl's configure script, but we could also try to
    // paper over it by using a tmp directory which *doesn't* have spaces in it.
    // As of now though that's not implemented so just give a nicer error for
    // the time being.
    let wants_space_error = windows &&
        (dst.to_str().map(|s| s.contains(" ")).unwrap_or(false) ||
         src.to_str().map(|s| s.contains(" ")).unwrap_or(false));
    if wants_space_error {
        panic!("\n\nunfortunately ./configure of libcurl is known to \
                fail if there's a space in the path to the current \
                directory\n\n\
                there's a space in either\n  {}\n  {}\nand this will cause the \
                build to fail\n\n\
                the MSVC build should work with a directory that has \
                spaces in it, and it would also work to move this to a \
                different directory without spaces\n\n",
               src.display(), dst.display())
    }

    if windows {
        cmd.arg("--with-winssl");
    } else {
        cmd.arg("--without-ca-bundle");
        cmd.arg("--without-ca-path");

        // DEP_OPENSSL_ROOT was what cargo used to use via overrides, and
        // OPENSSL_ROOT_DIR is also used by libssh2 which cargo uses and can be
        // set by various build scripts.
        let openssl_root = env::var_os("DEP_OPENSSL_ROOT").or_else(|| {
            env::var_os("OPENSSL_ROOT_DIR")
        }).or_else(|| {
            env::var_os("DEP_OPENSSL_INCLUDE").and_then(|include| {
                let root = Path::new(&include).parent().unwrap();
                if root.exists() {
                    Some(root.as_os_str().to_owned())
                } else {
                    None
                }
            })
        });
        if let Some(s) = openssl_root {
            cmd.arg(format!("--with-ssl={}", s.to_str().unwrap()));
        }
    }
    if let Ok(root) = env::var("DEP_Z_ROOT") {
        cmd.arg(format!("--with-zlib={}", root));
    }
    cmd.arg("--enable-static=yes");
    cmd.arg("--enable-shared=no");
    match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => {
            cmd.arg("--enable-optimize");
        }
        _ => {
            cmd.arg("--enable-debug");
            cmd.arg("--disable-optimize");
        }
    }
    cmd.arg(format!("--prefix={}", msys_compatible(&dst)));

    if target != host &&
       (!target.contains("windows") || !host.contains("windows")) {
        cmd.arg(format!("--host={}", host));
        cmd.arg(format!("--target={}", target));
    }

    cmd.arg("--without-librtmp");
    cmd.arg("--without-libidn");
    cmd.arg("--without-libssh2");
    cmd.arg("--without-nghttp2");
    cmd.arg("--disable-ldap");
    cmd.arg("--disable-ldaps");
    cmd.arg("--disable-ftp");
    cmd.arg("--disable-rtsp");
    cmd.arg("--disable-dict");
    cmd.arg("--disable-telnet");
    cmd.arg("--disable-tftp");
    cmd.arg("--disable-pop3");
    cmd.arg("--disable-imap");
    cmd.arg("--disable-smtp");
    cmd.arg("--disable-gopher");
    cmd.arg("--disable-manual");
    cmd.arg("--disable-smb");
    cmd.arg("--disable-sspi");

    run(&mut cmd, "sh");
    run(Command::new(make())
                .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap()))
                .current_dir(&dst.join("build")), "make");
    run(Command::new(make())
                .arg("install")
                .current_dir(&dst.join("build")), "make");
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn which(cmd: &str) -> Option<PathBuf> {
    let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX);
    let paths = env::var_os("PATH").unwrap();
    env::split_paths(&paths).map(|p| p.join(&cmd)).find(|p| {
        fs::metadata(p).is_ok()
    })
}

fn msys_compatible(path: &Path) -> String {
    let path = path.to_str().unwrap();
    if !cfg!(windows) {
        return path.to_string()
    }
    path.replace("C:\\", "/c/")
        .replace("\\", "/")
}

fn build_msvc(target: &str) {
    let cmd = gcc::windows_registry::find(target, "nmake.exe");
    let mut cmd = cmd.unwrap_or(Command::new("nmake.exe"));
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let machine = if target.starts_with("x86_64") {
        "x64"
    } else if target.starts_with("i686") {
        "x86"
    } else {
        panic!("unknown msvc target: {}", target);
    };

    t!(fs::create_dir_all(dst.join("include/curl")));
    t!(fs::create_dir_all(dst.join("lib")));

    cmd.current_dir(src.join("curl/winbuild"));
    cmd.arg("/f").arg("Makefile.vc")
       .arg("MODE=static")
       .arg("ENABLE_IDN=yes")
       .arg("DEBUG=no")
       .arg("GEN_PDB=no")
       .arg("ENABLE_WINSSL=yes")
       .arg("ENABLE_SSPI=yes")
       .arg(format!("MACHINE={}", machine));

    if let Some(inc) = env::var_os("DEP_Z_ROOT") {
        let inc = PathBuf::from(inc);
        let mut s = OsString::from("WITH_DEVEL=");
        s.push(&inc);
        cmd.arg("WITH_ZLIB=static").arg(s);

        // the build system for curl expects this library to be called
        // zlib_a.lib, so make sure it's named correctly (where libz-sys just
        // produces zlib.lib)
        let _ = fs::remove_file(&inc.join("lib/zlib_a.lib"));
        t!(fs::hard_link(inc.join("lib/zlib.lib"), inc.join("lib/zlib_a.lib")));
    }
    run(&mut cmd, "nmake");

    let name = format!("libcurl-vc-{}-release-static-zlib-static-\
                        ipv6-sspi-winssl", machine);
    let libs = src.join("curl/builds").join(name);

    t!(fs::copy(libs.join("lib/libcurl_a.lib"), dst.join("lib/curl.lib")));
    for f in t!(fs::read_dir(libs.join("include/curl"))) {
        let path = t!(f).path();
        let dst = dst.join("include/curl").join(path.file_name().unwrap());
        t!(fs::copy(path, dst));
    }
    t!(fs::remove_dir_all(src.join("curl/builds")));
    println!("cargo:rustc-link-lib=wldap32");
    println!("cargo:rustc-link-lib=advapi32");
    println!("cargo:rustc-link-lib=normaliz");
}
<commit_msg>Try again at libz registration<commit_after>extern crate pkg_config;
extern crate gcc;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::io::ErrorKind;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let windows = target.contains("windows");

    // OSX ships libcurl by default, so we just use that version
    // unconditionally.
    if target.contains("apple") {
        return println!("cargo:rustc-flags=-l curl");
    }

    // Illumos/Solaris requires explicit linking with libnsl
    if target.contains("solaris") {
        println!("cargo:rustc-flags=-l nsl");
    }

    // Next, fall back and try to use pkg-config if its available.
    if !target.contains("windows") {
        match pkg_config::find_library("libcurl") {
            Ok(lib) => {
                for path in lib.include_paths.iter() {
                    println!("cargo:include={}", path.display());
                }
                return
            }
            Err(e) => println!("Couldn't find libcurl from \
                               pkgconfig ({:?}), compiling it from source...", e),
        }
    }

    if !Path::new("curl/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    println!("cargo:rustc-link-search={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=curl");
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}/include", dst.display());
    if windows {
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=crypt32");
    }

    // MSVC builds are just totally different
    if target.contains("msvc") {
        return build_msvc(&target);
    }

    let cfg = gcc::Config::new();
    let compiler = cfg.get_compiler();

    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("sh");
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // Can't run ./configure directly on msys2 b/c we're handing in
    // Windows-style paths (those starting with C:\), but it chokes on those.
    // For that reason we build up a shell script with paths converted to
    // posix versions hopefully...
    //
    // Also apparently the buildbots choke unless we manually set LD, who knows
    // why?!
    cmd.env("CC", compiler.path())
       .env("CFLAGS", cflags)
       .env("LD", &which("ld").unwrap())
       .env("VERBOSE", "1")
       .current_dir(&dst.join("build"))
       .arg(msys_compatible(&src.join("curl/configure")));

    // For now this build script doesn't support paths with spaces in them. This
    // is arguably a but in curl's configure script, but we could also try to
    // paper over it by using a tmp directory which *doesn't* have spaces in it.
    // As of now though that's not implemented so just give a nicer error for
    // the time being.
    let wants_space_error = windows &&
        (dst.to_str().map(|s| s.contains(" ")).unwrap_or(false) ||
         src.to_str().map(|s| s.contains(" ")).unwrap_or(false));
    if wants_space_error {
        panic!("\n\nunfortunately ./configure of libcurl is known to \
                fail if there's a space in the path to the current \
                directory\n\n\
                there's a space in either\n  {}\n  {}\nand this will cause the \
                build to fail\n\n\
                the MSVC build should work with a directory that has \
                spaces in it, and it would also work to move this to a \
                different directory without spaces\n\n",
               src.display(), dst.display())
    }

    if windows {
        cmd.arg("--with-winssl");
    } else {
        cmd.arg("--without-ca-bundle");
        cmd.arg("--without-ca-path");
        register_dep("OPENSSL");
    }
    register_dep("Z");
    cmd.arg("--enable-static=yes");
    cmd.arg("--enable-shared=no");
    match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => {
            cmd.arg("--enable-optimize");
        }
        _ => {
            cmd.arg("--enable-debug");
            cmd.arg("--disable-optimize");
        }
    }
    cmd.arg(format!("--prefix={}", msys_compatible(&dst)));

    if target != host &&
       (!target.contains("windows") || !host.contains("windows")) {
        cmd.arg(format!("--host={}", host));
        cmd.arg(format!("--target={}", target));
    }

    cmd.arg("--without-librtmp");
    cmd.arg("--without-libidn");
    cmd.arg("--without-libssh2");
    cmd.arg("--without-nghttp2");
    cmd.arg("--disable-ldap");
    cmd.arg("--disable-ldaps");
    cmd.arg("--disable-ftp");
    cmd.arg("--disable-rtsp");
    cmd.arg("--disable-dict");
    cmd.arg("--disable-telnet");
    cmd.arg("--disable-tftp");
    cmd.arg("--disable-pop3");
    cmd.arg("--disable-imap");
    cmd.arg("--disable-smtp");
    cmd.arg("--disable-gopher");
    cmd.arg("--disable-manual");
    cmd.arg("--disable-smb");
    cmd.arg("--disable-sspi");

    run(&mut cmd, "sh");
    run(Command::new(make())
                .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap()))
                .current_dir(&dst.join("build")), "make");
    run(Command::new(make())
                .arg("install")
                .current_dir(&dst.join("build")), "make");
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn which(cmd: &str) -> Option<PathBuf> {
    let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX);
    let paths = env::var_os("PATH").unwrap();
    env::split_paths(&paths).map(|p| p.join(&cmd)).find(|p| {
        fs::metadata(p).is_ok()
    })
}

fn msys_compatible(path: &Path) -> String {
    let path = path.to_str().unwrap();
    if !cfg!(windows) {
        return path.to_string()
    }
    path.replace("C:\\", "/c/")
        .replace("\\", "/")
}

fn register_dep(dep: &str) {
    if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) {
        prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        return
    }
    if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) {
        let root = Path::new(&s).parent().unwrap();
        env::set_var(&format!("DEP_{}_ROOT", dep), root);
        let path = root.join("lib/pkgconfig");
        if path.exists() {
            prepend("PKG_CONFIG_PATH", path);
            return
        }
    }

    fn prepend(var: &str, val: PathBuf) {
        let prefix = env::var(var).unwrap_or(String::new());
        let mut v = vec![val];
        v.extend(env::split_paths(&prefix));
        env::set_var(var, &env::join_paths(v).unwrap());
    }
}

fn build_msvc(target: &str) {
    let cmd = gcc::windows_registry::find(target, "nmake.exe");
    let mut cmd = cmd.unwrap_or(Command::new("nmake.exe"));
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let machine = if target.starts_with("x86_64") {
        "x64"
    } else if target.starts_with("i686") {
        "x86"
    } else {
        panic!("unknown msvc target: {}", target);
    };

    t!(fs::create_dir_all(dst.join("include/curl")));
    t!(fs::create_dir_all(dst.join("lib")));

    cmd.current_dir(src.join("curl/winbuild"));
    cmd.arg("/f").arg("Makefile.vc")
       .arg("MODE=static")
       .arg("ENABLE_IDN=yes")
       .arg("DEBUG=no")
       .arg("GEN_PDB=no")
       .arg("ENABLE_WINSSL=yes")
       .arg("ENABLE_SSPI=yes")
       .arg(format!("MACHINE={}", machine));

    if let Some(inc) = env::var_os("DEP_Z_ROOT") {
        let inc = PathBuf::from(inc);
        let mut s = OsString::from("WITH_DEVEL=");
        s.push(&inc);
        cmd.arg("WITH_ZLIB=static").arg(s);

        // the build system for curl expects this library to be called
        // zlib_a.lib, so make sure it's named correctly (where libz-sys just
        // produces zlib.lib)
        let _ = fs::remove_file(&inc.join("lib/zlib_a.lib"));
        t!(fs::hard_link(inc.join("lib/zlib.lib"), inc.join("lib/zlib_a.lib")));
    }
    run(&mut cmd, "nmake");

    let name = format!("libcurl-vc-{}-release-static-zlib-static-\
                        ipv6-sspi-winssl", machine);
    let libs = src.join("curl/builds").join(name);

    t!(fs::copy(libs.join("lib/libcurl_a.lib"), dst.join("lib/curl.lib")));
    for f in t!(fs::read_dir(libs.join("include/curl"))) {
        let path = t!(f).path();
        let dst = dst.join("include/curl").join(path.file_name().unwrap());
        t!(fs::copy(path, dst));
    }
    t!(fs::remove_dir_all(src.join("curl/builds")));
    println!("cargo:rustc-link-lib=wldap32");
    println!("cargo:rustc-link-lib=advapi32");
    println!("cargo:rustc-link-lib=normaliz");
}
<|endoftext|>


<commit_before>use core::pipes::Port;
use std::net::tcp::{TcpErrData, TcpConnectErrData, TcpSocket};
use std::net::ip::IpAddr;

pub type ReadPort = Port<Result<~[u8], TcpErrData>>;

/**
An abstract client socket connection. This mirrors the bits
of the net::tcp::TcpSocket interface that we care about
while letting us have additional implementations for
mocking
*/
pub trait Connection {
    fn write_(data: ~[u8]) -> Result<(), TcpErrData>;
    fn read_start_() -> Result<@ReadPort, TcpErrData>;
    fn read_stop_(read_port: @ReadPort) -> Result<(), TcpErrData>;
}

pub trait ConnectionFactory<C: Connection> {
    fn connect(ip: IpAddr, port: uint) -> Result<C, TcpConnectErrData>;
}

impl Connection for TcpSocket {
    fn write_(data: ~[u8]) -> Result<(), TcpErrData> {
        use std::net::tcp::TcpSocket;
        self.write(data)
    }

    fn read_start_() -> Result<@ReadPort, TcpErrData> {
        use std::net::tcp::TcpSocket;
        self.read_start()
    }

    fn read_stop_(read_port: @ReadPort) -> Result<(), TcpErrData> {
        use std::net::tcp::TcpSocket;
        self.read_stop()
    }
}

pub enum UvConnectionFactory {
    UvConnectionFactory
}

impl ConnectionFactory<TcpSocket> for UvConnectionFactory {
    fn connect(ip: IpAddr, port: uint) -> Result<TcpSocket, TcpConnectErrData> {
        use std::uv_global_loop;
        use std::net::tcp::connect;
        let iotask = uv_global_loop::get();
        return connect(copy ip, port, &iotask);
    }
}

pub struct MockConnection {
    write_fn: fn@(~[u8]) -> Result<(), TcpErrData>,
    read_start_fn: fn@() -> Result<@ReadPort, TcpErrData>,
    read_stop_fn: fn@(-port: @ReadPort) -> Result<(), TcpErrData>
}

impl Connection for MockConnection {
    fn write_(data: ~[u8]) -> Result<(), TcpErrData> {
        (self.write_fn)(data)
    }

    fn read_start_() -> Result<@ReadPort, TcpErrData> {
        (self.read_start_fn)()
    }

    fn read_stop_(read_port: @ReadPort) -> Result<(), TcpErrData> {
        (self.read_stop_fn)(read_port)
    }
}

pub struct MockConnectionFactory {
    connect_fn: fn@(IpAddr, uint) -> Result<MockConnection, TcpConnectErrData>
}

impl ConnectionFactory<MockConnection> for MockConnectionFactory {
    fn connect(ip: IpAddr, port: uint) -> Result<MockConnection, TcpConnectErrData> {
        (self.connect_fn)(ip, port)
    }
}
<commit_msg>Language changes.<commit_after>use core::comm::Port;
use std::net::tcp::{TcpErrData, TcpConnectErrData, TcpSocket};
use std::net::ip::IpAddr;

pub type ReadPort = Port<Result<~[u8], TcpErrData>>;

/**
An abstract client socket connection. This mirrors the bits
of the net::tcp::TcpSocket interface that we care about
while letting us have additional implementations for
mocking
*/
pub trait Connection {
    fn write_(data: ~[u8]) -> Result<(), TcpErrData>;
    fn read_start_() -> Result<@ReadPort, TcpErrData>;
    fn read_stop_(read_port: @ReadPort) -> Result<(), TcpErrData>;
}

pub trait ConnectionFactory<C: Connection> {
    fn connect(ip: IpAddr, port: uint) -> Result<C, TcpConnectErrData>;
}

impl Connection for TcpSocket {
    fn write_(data: ~[u8]) -> Result<(), TcpErrData> {
        use std::net::tcp::TcpSocket;
        self.write(data)
    }

    fn read_start_() -> Result<@ReadPort, TcpErrData> {
        use std::net::tcp::TcpSocket;
        self.read_start()
    }

    fn read_stop_(read_port: @ReadPort) -> Result<(), TcpErrData> {
        use std::net::tcp::TcpSocket;
        self.read_stop()
    }
}

pub enum UvConnectionFactory {
    UvConnectionFactory
}

impl ConnectionFactory<TcpSocket> for UvConnectionFactory {
    fn connect(ip: IpAddr, port: uint) -> Result<TcpSocket, TcpConnectErrData> {
        use std::uv_global_loop;
        use std::net::tcp::connect;
        let iotask = uv_global_loop::get();
        return connect(copy ip, port, &iotask);
    }
}

pub struct MockConnection {
    write_fn: fn@(~[u8]) -> Result<(), TcpErrData>,
    read_start_fn: fn@() -> Result<@ReadPort, TcpErrData>,
    read_stop_fn: fn@(-port: @ReadPort) -> Result<(), TcpErrData>
}

impl Connection for MockConnection {
    fn write_(data: ~[u8]) -> Result<(), TcpErrData> {
        (self.write_fn)(data)
    }

    fn read_start_() -> Result<@ReadPort, TcpErrData> {
        (self.read_start_fn)()
    }

    fn read_stop_(read_port: @ReadPort) -> Result<(), TcpErrData> {
        (self.read_stop_fn)(read_port)
    }
}

pub struct MockConnectionFactory {
    connect_fn: fn@(IpAddr, uint) -> Result<MockConnection, TcpConnectErrData>
}

impl ConnectionFactory<MockConnection> for MockConnectionFactory {
    fn connect(ip: IpAddr, port: uint) -> Result<MockConnection, TcpConnectErrData> {
        (self.connect_fn)(ip, port)
    }
}
<|endoftext|>


<commit_before>#[test]
fn test_nan() {
  use core::f64;
  let x = "NaN".to_string();
  assert_eq!(format!("{}", f64::NAN), x);
  assert_eq!(format!("{:e}", f64::NAN), x);
  assert_eq!(format!("{:E}", f64::NAN), x);
}
<commit_msg>Fix format<commit_after>#[test]
fn test_nan() {
    use core::f64;
    let x = "NaN".to_string();
    assert_eq!(format!("{}", f64::NAN), x);
    assert_eq!(format!("{:e}", f64::NAN), x);
    assert_eq!(format!("{:E}", f64::NAN), x);
}
<|endoftext|>


<commit_before>enum List<T> {
    Cons(T, ~List<T>),
    Nil
}

fn lastbutone<'a, T>(list: &'a List<T>) -> Option<(&'a T, &'a T)> {
    match *list {
        Nil => None,
        Cons(_, ~Nil) => None,
        Cons(ref butone, ~Cons(ref last, ~Nil)) => Some((butone, last)),
        Cons(_, ~ref rest) => lastbutone(rest)
    }
}

fn main() {
    let list: List<char> = Cons('a', ~Cons('b', ~Cons('c', ~Nil)));
    println!("{:?}", lastbutone(&list));

    let list: List<uint> = Cons(6, ~Cons(7, ~Cons(42, ~Nil)));
    println!("{:?}", lastbutone(&list));

    let list: List<~str> = Cons(~"six", ~Cons(~"seven", ~Cons(~"forty-two", ~Nil)));
    println!("{:?}", lastbutone(&list));
}
<commit_msg>Redo Problem 02 with vectors<commit_after>fn lastbutone<'a, T>(list: &'a ~[T]) -> Option<(&'a T, &'a T)> {
    if list.len() > 2 {
        Some((&list[list.len()-2], &list[list.len()-1]))
    } else {
        None
    }
}

fn main() {
    let list = ~['a', 'b', 'c', 'd', 'e'];
    println!("{:?}", lastbutone(&list));

    let list = ~['a'];
    println!("{:?}", lastbutone(&list));
}
<|endoftext|>


<commit_before>use azure_sdk_auth_aad::*;
use futures::stream::StreamExt;
use oauth2::ClientId;
use std::env;
use std::error::Error;
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let client_id =
        ClientId::new(env::var("CLIENT_ID").expect("Missing CLIENT_ID environment variable."));
    let tenant_id = env::var("TENANT_ID").expect("Missing TENANT_ID environment variable.");

    let storage_account_name = std::env::args()
        .nth(1)
        .expect("please specify the storage account name as first command line parameter");

    let client = Arc::new(reqwest::Client::new());
    let device_code_flow = begin_authorize_device_code_flow(
        client.clone(),
        &tenant_id,
        &client_id,
        &[
            &format!(
                "https://{}.blob.core.windows.net/.default",
                storage_account_name
            ),
            "offline_access",
        ],
    )
    .await?;

    println!("{}", device_code_flow.message());

    let mut stream = Box::pin(device_code_flow.stream());
    let mut authorization = None;
    while let Some(resp) = stream.next().await {
        println!("{:?}", resp);

        // if we have the authorization, let's store it for later use.
        if let DeviceCodeResponse::AuthorizationSucceded(auth) = resp? {
            authorization = Some(auth);
        }
    }

    let authorization = authorization.unwrap();

    println!(
        "\nReceived valid bearer token: {}",
        &authorization.access_token.secret()
    );

    //// Let's enumerate the Azure SQL Databases instances
    //// in the subscription. Note: this way of calling the REST API
    //// will be different (and easier) using other Azure Rust SDK
    //// crates, this is just an example.
    //let url = Url::parse(&format!(
    //        "https://management.azure.com/subscriptions/{}/providers/Microsoft.Sql/servers?api-version=2015-05-01-preview",
    //        subscription_id
    //    ))?;

    //let resp = reqwest::Client::new()
    //    .get(url)
    //    .header(
    //        "Authorization",
    //        format!("Bearer {}", token.access_token().secret()),
    //    )
    //    .send()
    //    .await?
    //    .text()
    //    .await?;

    //println!("\n\nresp {:?}", resp);

    Ok(())
}
<commit_msg>completed example<commit_after>use azure_sdk_auth_aad::*;
use futures::stream::StreamExt;
use oauth2::ClientId;
use std::env;
use std::error::Error;
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let client_id =
        ClientId::new(env::var("CLIENT_ID").expect("Missing CLIENT_ID environment variable."));
    let tenant_id = env::var("TENANT_ID").expect("Missing TENANT_ID environment variable.");

    let storage_account_name = std::env::args()
        .nth(1)
        .expect("please specify the storage account name as first command line parameter");

    let client = Arc::new(reqwest::Client::new());
    let device_code_flow = begin_authorize_device_code_flow(
        client.clone(),
        &tenant_id,
        &client_id,
        &[
            &format!(
                "https://{}.blob.core.windows.net/.default",
                storage_account_name
            ),
            "offline_access",
        ],
    )
    .await?;

    println!("{}", device_code_flow.message());

    let mut stream = Box::pin(device_code_flow.stream());
    let mut authorization = None;
    while let Some(resp) = stream.next().await {
        println!("{:?}", resp);

        // if we have the authorization, let's store it for later use.
        if let DeviceCodeResponse::AuthorizationSucceded(auth) = resp? {
            authorization = Some(auth);
        }
    }

    // remove the option (this is safe since we
    // unwrapped the errors before).
    let authorization = authorization.unwrap();

    println!(
        "\nReceived valid bearer token: {}",
        &authorization.access_token.secret()
    );

    // let's get the containers using the just received bearer
    // token. We should get 200 as result.
    let dt = chrono::Utc::now();
    let time = format!("{}", dt.format("%a, %d %h %Y %T GMT"));

    let resp = reqwest::Client::new()
        .get(&format!(
            "https://{}.blob.core.windows.net/?comp=list",
            storage_account_name,
        ))
        .header(
            "Authorization",
            format!("Bearer {}", authorization.access_token.secret()),
        )
        .header("x-ms-version", "2019-07-07")
        .header("x-ms-date", time)
        .send()
        .await?
        .text()
        .await?;

    println!("\n\nresp {:?}", resp);

    Ok(())
}
<|endoftext|>


<commit_before>extern mod wyre;
use wyre::pipe::*;
fn main(){
  let pipe = do LinearPipe::new()|p|{
                single_wire(|x| fmt!("%?",x) ,
                  single_wire(|x| x as float ,
                    single_wire(|x: int| x * 2 ,
                      p
                    )
                  )
                )
              };

  do 5.times(){
    pipe.send(21);
  }
  do 5.times(){
    printfln!(pipe.recv_wait());
  }

  pipe.shutdown();
}<commit_msg>delete<commit_after><|endoftext|>


<commit_before>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Core types

pub mod block;
pub mod hash;
pub mod transaction;
#[allow(dead_code)]
#[macro_use]

pub use self::block::{Block, BlockHeader};
pub use self::transaction::{Transaction, Input, Output, TxProof};
use self::hash::{Hash, Hashed, ZERO_HASH};
use ser::{Writeable, Writer, Error, ser_vec};

use time;

use std::fmt;
use std::cmp::Ordering;

use secp;
use secp::{Secp256k1, Signature, Message};
use secp::key::SecretKey;
use secp::pedersen::*;

use tiny_keccak::Keccak;

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Block interval, in seconds
pub const BLOCK_TIME_SEC: u8 = 15;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Implemented by types that hold inputs and outputs including Pedersen
/// commitments. Handles the collection of the commitments as well as their
/// summing, taking potential explicit overages of fees into account.
pub trait Committed {
	/// Gathers commitments and sum them.
	fn sum_commitments(&self, secp: &Secp256k1) -> Result<Commitment, secp::Error> {
		// first, verify each range proof
		let ref outputs = self.outputs_committed();
		for output in *outputs {
			try!(output.verify_proof(secp))
		}

		// then gather the commitments
		let mut input_commits = filter_map_vec!(self.inputs_committed(), |inp| inp.commitment());
		let mut output_commits = filter_map_vec!(self.outputs_committed(), |out| out.commitment());

		// add the overage as input commitment if positive, as an output commitment if
		// negative
		let overage = self.overage();
		if overage != 0 {
			let over_commit = secp.commit_value(overage.abs() as u64).unwrap();
			if overage > 0 {
				input_commits.push(over_commit);
			} else {
				output_commits.push(over_commit);
			}
		}

		// sum all that stuff
		secp.commit_sum(input_commits, output_commits)
	}

	/// Vector of committed inputs to verify
	fn inputs_committed(&self) -> &Vec<Input>;

	/// Vector of committed inputs to verify
	fn outputs_committed(&self) -> &Vec<Output>;

	/// The overage amount expected over the commitments. Can be negative (a
	/// fee) or positive (a reward).
	fn overage(&self) -> i64;
}

/// Proof of work
#[derive(Copy)]
pub struct Proof(pub [u32; PROOFSIZE]);

impl fmt::Debug for Proof {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		try!(write!(f, "Cuckoo("));
		for (i, val) in self.0[..].iter().enumerate() {
			try!(write!(f, "{:x}", val));
			if i < PROOFSIZE - 1 {
				write!(f, " ");
			}
		}
		write!(f, ")")
	}
}
impl PartialOrd for Proof {
	fn partial_cmp(&self, other: &Proof) -> Option<Ordering> {
		self.0.partial_cmp(&other.0)
	}
}
impl PartialEq for Proof {
	fn eq(&self, other: &Proof) -> bool {
		self.0[..] == other.0[..]
	}
}
impl Eq for Proof {}
impl Clone for Proof {
	fn clone(&self) -> Proof {
		*self
	}
}

impl Proof {
	/// Builds a proof with all bytes zeroed out
	pub fn zero() -> Proof {
		Proof([0; 42])
	}
	/// Builds a proof from a vector of exactly PROOFSIZE (42) u32.
	pub fn from_vec(v: Vec<u32>) -> Proof {
		assert!(v.len() == PROOFSIZE);
		let mut p = [0; PROOFSIZE];
		for (n, elem) in v.iter().enumerate() {
			p[n] = *elem;
		}
		Proof(p)
	}
	/// Converts the proof to a vector of u64s
	pub fn to_u64s(&self) -> Vec<u64> {
		let mut nonces = Vec::with_capacity(PROOFSIZE);
		for n in self.0.iter() {
			nonces.push(*n as u64);
		}
		nonces
	}
	/// Converts the proof to a vector of u32s
	pub fn to_u32s(&self) -> Vec<u32> {
		self.0.to_vec()
	}
}

/// Two hashes that will get hashed together in a Merkle tree to build the next
/// level up.
struct HPair(Hash, Hash);
impl Hashed for HPair {
	fn bytes(&self) -> Vec<u8> {
		let mut data = Vec::with_capacity(64);
		data.extend_from_slice(self.0.to_slice());
		data.extend_from_slice(self.1.to_slice());
		return data;
	}
}
/// An iterator over hashes in a vector that pairs them to build a row in a
/// Merkle tree. If the vector has an odd number of hashes, duplicates the last.
struct HPairIter(Vec<Hash>);
impl Iterator for HPairIter {
	type Item = HPair;

	fn next(&mut self) -> Option<HPair> {
		self.0.pop().map(|first| HPair(first, self.0.pop().unwrap_or(first)))
	}
}
/// A row in a Merkle tree. Can be built from a vector of hashes. Calculates
/// the next level up, or can recursively go all the way up to its root.
struct MerkleRow(Vec<HPair>);
impl MerkleRow {
	fn new(hs: Vec<Hash>) -> MerkleRow {
		MerkleRow(HPairIter(hs).map(|hp| hp).collect())
	}
	fn up(&self) -> MerkleRow {
		MerkleRow::new(map_vec!(self.0, |hp| hp.hash()))
	}
	fn root(&self) -> Hash {
		if self.0.len() == 0 {
			vec![].hash()
		} else if self.0.len() == 1 {
			self.0[0].hash()
		} else {
			self.up().root()
		}
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use super::hash::{Hash, Hashed, ZERO_HASH};
	use secp;
	use secp::Secp256k1;
	use secp::key::SecretKey;
	use rand::Rng;
	use rand::os::OsRng;

	fn new_secp() -> Secp256k1 {
		secp::Secp256k1::with_caps(secp::ContextFlag::Commit)
	}

	#[test]
	#[should_panic(expected = "InvalidSecretKey")]
	fn zero_commit() {
		// a transaction whose commitment sums to zero shouldn't validate
		let ref secp = new_secp();
		let mut rng = OsRng::new().unwrap();

		let skey = SecretKey::new(secp, &mut rng);
		let outh = ZERO_HASH;
		let tx = Transaction::new(vec![Input::OvertInput {
			                               output: outh,
			                               value: 10,
			                               blindkey: skey,
		                               }],
		                          vec![Output::OvertOutput {
			                               value: 1,
			                               blindkey: skey,
		                               }],
		                          9);
		// blinding should fail as signing with a zero r*G shouldn't work
		tx.blind(&secp).unwrap();
	}

	#[test]
	fn reward_empty_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let b = Block::new(BlockHeader::default(), vec![], skey).unwrap();
		b.compact().verify(&secp).unwrap();
	}

	#[test]
	fn reward_with_tx_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let tx1 = tx2i1o(secp, &mut rng);
		let mut btx1 = tx1.blind(&secp).unwrap();
		btx1.verify_sig(&secp).unwrap();

		let b = Block::new(BlockHeader::default(), vec![&mut btx1], skey).unwrap();
		b.compact().verify(&secp).unwrap();
	}

	#[test]
	fn simple_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let tx1 = tx2i1o(secp, &mut rng);
		let mut btx1 = tx1.blind(&secp).unwrap();
		btx1.verify_sig(&secp).unwrap();

		let tx2 = tx1i1o(secp, &mut rng);
		let mut btx2 = tx2.blind(&secp).unwrap();
		btx2.verify_sig(&secp).unwrap();

		let b = Block::new(BlockHeader::default(), vec![&mut btx1, &mut btx2], skey).unwrap();
		b.verify(&secp).unwrap();
	}

	// utility producing a transaction with 2 inputs and a single outputs
	pub fn tx2i1o<R: Rng>(secp: &Secp256k1, rng: &mut R) -> Transaction {
		let outh = ZERO_HASH;
		Transaction::new(vec![Input::OvertInput {
			                      output: outh,
			                      value: 10,
			                      blindkey: SecretKey::new(secp, rng),
		                      },
		                      Input::OvertInput {
			                      output: outh,
			                      value: 11,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 vec![Output::OvertOutput {
			                      value: 20,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 1)
	}

	// utility producing a transaction with a single input and output
	pub fn tx1i1o<R: Rng>(secp: &Secp256k1, rng: &mut R) -> Transaction {
		let outh = ZERO_HASH;
		Transaction::new(vec![Input::OvertInput {
			                      output: outh,
			                      value: 5,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 vec![Output::OvertOutput {
			                      value: 4,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 1)
	}
}
<commit_msg>fix merkle tree malleability<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Core types

pub mod block;
pub mod hash;
pub mod transaction;
#[allow(dead_code)]
#[macro_use]

pub use self::block::{Block, BlockHeader};
pub use self::transaction::{Transaction, Input, Output, TxProof};
use self::hash::{Hash, Hashed, ZERO_HASH};
use ser::{Writeable, Writer, Error, ser_vec};

use time;

use std::fmt;
use std::cmp::Ordering;

use secp;
use secp::{Secp256k1, Signature, Message};
use secp::key::SecretKey;
use secp::pedersen::*;

use tiny_keccak::Keccak;

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Block interval, in seconds
pub const BLOCK_TIME_SEC: u8 = 15;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Implemented by types that hold inputs and outputs including Pedersen
/// commitments. Handles the collection of the commitments as well as their
/// summing, taking potential explicit overages of fees into account.
pub trait Committed {
	/// Gathers commitments and sum them.
	fn sum_commitments(&self, secp: &Secp256k1) -> Result<Commitment, secp::Error> {
		// first, verify each range proof
		let ref outputs = self.outputs_committed();
		for output in *outputs {
			try!(output.verify_proof(secp))
		}

		// then gather the commitments
		let mut input_commits = filter_map_vec!(self.inputs_committed(), |inp| inp.commitment());
		let mut output_commits = filter_map_vec!(self.outputs_committed(), |out| out.commitment());

		// add the overage as input commitment if positive, as an output commitment if
		// negative
		let overage = self.overage();
		if overage != 0 {
			let over_commit = secp.commit_value(overage.abs() as u64).unwrap();
			if overage > 0 {
				input_commits.push(over_commit);
			} else {
				output_commits.push(over_commit);
			}
		}

		// sum all that stuff
		secp.commit_sum(input_commits, output_commits)
	}

	/// Vector of committed inputs to verify
	fn inputs_committed(&self) -> &Vec<Input>;

	/// Vector of committed inputs to verify
	fn outputs_committed(&self) -> &Vec<Output>;

	/// The overage amount expected over the commitments. Can be negative (a
	/// fee) or positive (a reward).
	fn overage(&self) -> i64;
}

/// Proof of work
#[derive(Copy)]
pub struct Proof(pub [u32; PROOFSIZE]);

impl fmt::Debug for Proof {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		try!(write!(f, "Cuckoo("));
		for (i, val) in self.0[..].iter().enumerate() {
			try!(write!(f, "{:x}", val));
			if i < PROOFSIZE - 1 {
				write!(f, " ");
			}
		}
		write!(f, ")")
	}
}
impl PartialOrd for Proof {
	fn partial_cmp(&self, other: &Proof) -> Option<Ordering> {
		self.0.partial_cmp(&other.0)
	}
}
impl PartialEq for Proof {
	fn eq(&self, other: &Proof) -> bool {
		self.0[..] == other.0[..]
	}
}
impl Eq for Proof {}
impl Clone for Proof {
	fn clone(&self) -> Proof {
		*self
	}
}

impl Proof {
	/// Builds a proof with all bytes zeroed out
	pub fn zero() -> Proof {
		Proof([0; 42])
	}
	/// Builds a proof from a vector of exactly PROOFSIZE (42) u32.
	pub fn from_vec(v: Vec<u32>) -> Proof {
		assert!(v.len() == PROOFSIZE);
		let mut p = [0; PROOFSIZE];
		for (n, elem) in v.iter().enumerate() {
			p[n] = *elem;
		}
		Proof(p)
	}
	/// Converts the proof to a vector of u64s
	pub fn to_u64s(&self) -> Vec<u64> {
		let mut nonces = Vec::with_capacity(PROOFSIZE);
		for n in self.0.iter() {
			nonces.push(*n as u64);
		}
		nonces
	}
	/// Converts the proof to a vector of u32s
	pub fn to_u32s(&self) -> Vec<u32> {
		self.0.to_vec()
	}
}

/// Two hashes that will get hashed together in a Merkle tree to build the next
/// level up.
struct HPair(Hash, Hash);
impl Hashed for HPair {
	fn bytes(&self) -> Vec<u8> {
		let mut data = Vec::with_capacity(64);
		data.extend_from_slice(self.0.to_slice());
		data.extend_from_slice(self.1.to_slice());
		return data;
	}
}
/// An iterator over hashes in a vector that pairs them to build a row in a
/// Merkle tree. If the vector has an odd number of hashes, it appends a zero hash
struct HPairIter(Vec<Hash>);
impl Iterator for HPairIter {
	type Item = HPair;

	fn next(&mut self) -> Option<HPair> {
		self.0.pop().map(|first| HPair(first, self.0.pop().unwrap_or(ZERO_HASH)))
	}
}
/// A row in a Merkle tree. Can be built from a vector of hashes. Calculates
/// the next level up, or can recursively go all the way up to its root.
struct MerkleRow(Vec<HPair>);
impl MerkleRow {
	fn new(hs: Vec<Hash>) -> MerkleRow {
		MerkleRow(HPairIter(hs).map(|hp| hp).collect())
	}
	fn up(&self) -> MerkleRow {
		MerkleRow::new(map_vec!(self.0, |hp| hp.hash()))
	}
	fn root(&self) -> Hash {
		if self.0.len() == 0 {
			vec![].hash()
		} else if self.0.len() == 1 {
			self.0[0].hash()
		} else {
			self.up().root()
		}
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use super::hash::{Hash, Hashed, ZERO_HASH};
	use secp;
	use secp::Secp256k1;
	use secp::key::SecretKey;
	use rand::Rng;
	use rand::os::OsRng;

	fn new_secp() -> Secp256k1 {
		secp::Secp256k1::with_caps(secp::ContextFlag::Commit)
	}

	#[test]
	#[should_panic(expected = "InvalidSecretKey")]
	fn zero_commit() {
		// a transaction whose commitment sums to zero shouldn't validate
		let ref secp = new_secp();
		let mut rng = OsRng::new().unwrap();

		let skey = SecretKey::new(secp, &mut rng);
		let outh = ZERO_HASH;
		let tx = Transaction::new(vec![Input::OvertInput {
			                               output: outh,
			                               value: 10,
			                               blindkey: skey,
		                               }],
		                          vec![Output::OvertOutput {
			                               value: 1,
			                               blindkey: skey,
		                               }],
		                          9);
		// blinding should fail as signing with a zero r*G shouldn't work
		tx.blind(&secp).unwrap();
	}

	#[test]
	fn reward_empty_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let b = Block::new(BlockHeader::default(), vec![], skey).unwrap();
		b.compact().verify(&secp).unwrap();
	}

	#[test]
	fn reward_with_tx_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let tx1 = tx2i1o(secp, &mut rng);
		let mut btx1 = tx1.blind(&secp).unwrap();
		btx1.verify_sig(&secp).unwrap();

		let b = Block::new(BlockHeader::default(), vec![&mut btx1], skey).unwrap();
		b.compact().verify(&secp).unwrap();
	}

	#[test]
	fn simple_block() {
		let mut rng = OsRng::new().unwrap();
		let ref secp = new_secp();
		let skey = SecretKey::new(secp, &mut rng);

		let tx1 = tx2i1o(secp, &mut rng);
		let mut btx1 = tx1.blind(&secp).unwrap();
		btx1.verify_sig(&secp).unwrap();

		let tx2 = tx1i1o(secp, &mut rng);
		let mut btx2 = tx2.blind(&secp).unwrap();
		btx2.verify_sig(&secp).unwrap();

		let b = Block::new(BlockHeader::default(), vec![&mut btx1, &mut btx2], skey).unwrap();
		b.verify(&secp).unwrap();
	}

	// utility producing a transaction with 2 inputs and a single outputs
	pub fn tx2i1o<R: Rng>(secp: &Secp256k1, rng: &mut R) -> Transaction {
		let outh = ZERO_HASH;
		Transaction::new(vec![Input::OvertInput {
			                      output: outh,
			                      value: 10,
			                      blindkey: SecretKey::new(secp, rng),
		                      },
		                      Input::OvertInput {
			                      output: outh,
			                      value: 11,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 vec![Output::OvertOutput {
			                      value: 20,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 1)
	}

	// utility producing a transaction with a single input and output
	pub fn tx1i1o<R: Rng>(secp: &Secp256k1, rng: &mut R) -> Transaction {
		let outh = ZERO_HASH;
		Transaction::new(vec![Input::OvertInput {
			                      output: outh,
			                      value: 5,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 vec![Output::OvertOutput {
			                      value: 4,
			                      blindkey: SecretKey::new(secp, rng),
		                      }],
		                 1)
	}
}
<|endoftext|>


<commit_before>use std::ops::{Deref, DerefMut};
use std::fmt;
use combine::primitives::SourcePosition;

/// Struct representing a position within a source code file
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Position {
    pub col: isize,
    pub row: isize,
    pub raw: isize
}

impl Position {

    fn new(col: isize, row: isize) -> Self {
        Position { col: col
                 , row: row
                 , raw: col + row
                 }
    }

    fn from_combine(pos: SourcePosition) -> Self {
        Position { col: pos.column
                 , row: pos.line
                 , raw: pos.column + pos.line
                 }
    }
}

impl fmt::Display for Position {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "line {}, column {}", self.row, self.col)
    }
}

#[derive(Clone, Debug)]
pub struct Positional<T> {
    pub pos: Position,
    pub value: T
}

impl Positional {
    fn at<T>(col: isize, row: isize, value: T) -> Positional<T> {
        Positional { pos: Position::new(col, row)
                   , value: value }
    }
}

impl<T> fmt::Display for Positional<T>
where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} at {}", self.value, self.pos)
    }
}

impl<T> PartialEq for Positional<T>
where T: PartialEq {
    fn eq(&self, other: &Positional<T>) -> bool {
        self.value == other.value
    }
}

impl<T> Deref for Positional<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T> DerefMut for Positional<T> {
    fn deref(&self) -> &mut T {
        &mut self.value
    }
}
<commit_msg>Fix misnamed DerefMut method<commit_after>use std::ops::{Deref, DerefMut};
use std::fmt;
use combine::primitives::SourcePosition;

/// Struct representing a position within a source code file
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Position {
    pub col: isize,
    pub row: isize,
    pub raw: isize
}

impl Position {

    fn new(col: isize, row: isize) -> Self {
        Position { col: col
                 , row: row
                 , raw: col + row
                 }
    }

    fn from_combine(pos: SourcePosition) -> Self {
        Position { col: pos.column
                 , row: pos.line
                 , raw: pos.column + pos.line
                 }
    }
}

impl fmt::Display for Position {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "line {}, column {}", self.row, self.col)
    }
}

#[derive(Clone, Debug)]
pub struct Positional<T> {
    pub pos: Position,
    pub value: T
}

impl Positional {
    fn at<T>(col: isize, row: isize, value: T) -> Positional<T> {
        Positional { pos: Position::new(col, row)
                   , value: value }
    }
}

impl<T> fmt::Display for Positional<T>
where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} at {}", self.value, self.pos)
    }
}

impl<T> PartialEq for Positional<T>
where T: PartialEq {
    fn eq(&self, other: &Positional<T>) -> bool {
        self.value == other.value
    }
}

impl<T> Deref for Positional<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T> DerefMut for Positional<T> {
    fn deref_mut(&self) -> &mut T {
        &mut self.value
    }
}
<|endoftext|>


<commit_before>
extern crate uom;

use uom::Conversion;
use uom::fmt::DisplayStyle::Abbreviation;
use uom::si ::Unit;
use uom::si ::length      ::{meter , millimeter , micrometer };
use uom::si ::time        ::{second, millisecond, microsecond};
use uom::si ::velocity    ::{self, meter_per_second};
use uom::si ::acceleration::meter_per_second_squared;
use uom::si ::area        ::square_meter;
use uom::si ::frequency   ::hertz;

// use uom::si ::mass        ::gram;
// use uom::si ::momentum    ::gram_meter_per_second;
use uom::si ::angle                    ::radian;
use uom::si ::ratio                    ::ratio;
// use uom::si ::thermodynamic_temperature::degree_celsius;
// use uom::si ::temperature_interval     ::degree_fahrenheit;

use uom::si ::f64::{ Length
                   , Time
                   , Area
                   , Velocity
                   // , Mass
                   , Angle
                   // , Ratio
                   // , ThermodynamicTemperature
                   // , TemperatureInterval
                   };

use typenum::{P2, P3};

macro_rules! check_n_print {
    ($id:literal, $value:expr) => {
        $value;
        println!("{} => {:?}", $id, $value);
    };
}

macro_rules! check_n_print_unit {
    ($id:literal, $value:expr, $unit:expr) => {
        $value;
        println!("{} => {:>10.4?} => {:>10.4?}", $id, $value, $value.into_format_args($unit, Abbreviation));
    };
}

fn sep(tag: &str) {
    let line = "=".repeat(25);
    println!("");
    println!("{} {} {}", line, tag, line);
    println!("");
}

fn main() {
    sep("new values");

    check_n_print_unit!("new length", Length::new::<meter> (1.0), millimeter );
    check_n_print_unit!("new time  ", Time  ::new::<second>(2.0), microsecond);

    sep("Accessing/Transforming values");

    let l1  = Length::new::<micrometer  >(3.0);
    let l2  = Area  ::new::<square_meter>(4.0);
    let t1  = Time  ::new::<millisecond >(5.0);
    let t2  = t1.powi(P2::new());
    let t3  = t1.powi(P3::new());
    let v1  = l1 / t1;
    // let m1  = Mass  ::new::<gram       >(5.0);
    let fmt = Velocity::format_args(meter_per_second, Abbreviation);

    check_n_print!("get       ", l1.get::<millimeter>());
    check_n_print!("conversion", l1.get::<millimeter>().conversion());

    sep("Formatting");

    check_n_print!("with            ", fmt.with(v1));
    check_n_print!("into_format_args", v1.into_format_args(meter_per_second, Abbreviation));

    sep("Values checks");

    // Arithmetic operations already throw a warning
    // check_n_print_unit!("+", t1 + t1, microsecond);
    // check_n_print_unit!("+", t1 - t1, microsecond);
    // check_n_print_unit!("+", m1 * l1 / t1, gram_meter_per_second);
    // check_n_print_unit!("+", l1 / t2, meter_per_second_squared);

    check_n_print!("is_nan          ", t1.is_nan          ());
    check_n_print!("is_finite       ", l1.is_finite       ());
    check_n_print!("is_infinite     ", t1.is_infinite     ());
    check_n_print!("is_normal       ", l1.is_normal       ());
    check_n_print!("classify        ", t1.classify        ());
    check_n_print!("is_sign_negative", l1.is_sign_negative());
    check_n_print!("is_sign_positive", t1.is_sign_positive());

    sep("Operations on any value");

    check_n_print_unit!("signum ", l2.signum              (         ), square_meter);
    check_n_print_unit!("hypot  ", t1.hypot               (t1 + t1  ), microsecond );
    check_n_print_unit!("powi   ", l1.powi                (P2::new()), square_meter);
    check_n_print_unit!("mul_add", l1.mul_add             (l1, l2   ), square_meter);
    check_n_print_unit!("recip  ", t1.recip               (         ), hertz       );
    check_n_print_unit!("max    ", l1.max                 (l1       ), millimeter  );
    check_n_print_unit!("min    ", t1.min                 (t1       ), microsecond );
    check_n_print_unit!("floor  ", t1.floor::<microsecond>(         ), microsecond );
    check_n_print_unit!("ceil   ", l1.ceil ::<millimeter >(         ), millimeter  );
    check_n_print_unit!("round  ", t1.round::<microsecond>(         ), microsecond );
    check_n_print_unit!("trunc  ", l1.trunc::<millimeter >(         ), millimeter  );
    check_n_print_unit!("fract  ", t1.fract::<microsecond>(         ), microsecond );
    check_n_print_unit!("abs    ", l1.abs                 (         ), millimeter  );
    check_n_print_unit!("sqrt   ", t2.sqrt                (         ), microsecond );
    check_n_print_unit!("cbrt   ", t3.cbrt                (         ), microsecond );

    sep("String representations");

    check_n_print!("description ", velocity                ::description ());
    check_n_print!("abbreviation", meter_per_second_squared::abbreviation());
    check_n_print!("singular    ", second                  ::singular    ());
    check_n_print!("plural      ", meter                   ::plural      ());

    sep("Angle-specific functions");

    let a = Angle::new::<radian>(6.0);

    check_n_print_unit!("sin   ", a.sin    ( ), ratio );
    check_n_print_unit!("sinh  ", a.sinh   ( ), ratio );
    check_n_print_unit!("cos   ", a.cos    ( ), ratio );
    check_n_print_unit!("cosh  ", a.cosh   ( ), ratio );
    check_n_print_unit!("tan   ", a.tan    ( ), ratio );
    check_n_print_unit!("tanh  ", a.tanh   ( ), ratio );
    check_n_print_unit!("atan2 ", a.atan2  (a), radian);
    check_n_print!     ("sincos", a.sin_cos( ));

    sep("Ratio-specific functions");

    // Ratio has the must_use attribute already
    // let r = Ratio::new::<ratio>(0.5);
    //
    // check_n_print_unit!("sin   ", r.asin  (  ), radian );
    // check_n_print_unit!("sinh  ", r.asinh (  ), radian );
    // check_n_print_unit!("cos   ", r.acos  (  ), radian );
    // check_n_print_unit!("cosh  ", r.acosh (  ), radian );
    // check_n_print_unit!("tan   ", r.atan  (  ), radian );
    // check_n_print_unit!("tanh  ", r.atanh (  ), radian );
    // check_n_print_unit!("exp   ", r.exp   (  ), ratio  );
    // check_n_print_unit!("exp2  ", r.exp2  (  ), ratio  );
    // check_n_print_unit!("ln    ", r.ln    (  ), ratio  );
    // check_n_print_unit!("log   ", r.log   (2.), ratio  );
    // check_n_print_unit!("log2  ", r.log2  (  ), ratio  );
    // check_n_print_unit!("log10 ", r.log10 (  ), ratio  );
    // check_n_print_unit!("exp_m1", r.exp_m1(  ), ratio  );
    // check_n_print_unit!("ln_1p ", r.ln_1p (  ), ratio  );

}
<commit_msg>Revert "Add example that intentionally generates unused functions' outputs"<commit_after><|endoftext|>


<commit_before>use std::io::Write;
use std::error::Error;
use std::time::SystemTime;

use backend::Debug;
use types::*;

macro_rules! debug_to_sql {
    ($sql_type:ty, $ty:ty) => {
        impl ToSql<$sql_type, Debug> for $ty {
            fn to_sql<W: Write>(&self, _: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
                Ok(IsNull::No)
            }
        }
    };
}

debug_to_sql!(Bool, bool);
debug_to_sql!(Timestamp, SystemTime);

#[cfg(feature = "postgres")]
mod pg_impls {
    use super::*;
    use data_types::*;

    debug_to_sql!(Timestamp, PgTimestamp);
    debug_to_sql!(Timestamptz, PgTimestamp);
    debug_to_sql!(Date, PgDate);
    debug_to_sql!(Time, PgTime);
    debug_to_sql!(Interval, PgInterval);
}

#[cfg(feature = "chrono")]
mod chrono_impls {
    extern crate chrono;
    use super::*;
    use self::chrono::{NaiveDateTime, NaiveTime, NaiveDate};
    #[cfg(feature = "postgres")]
    use self::chrono::{DateTime, TimeZone};

    debug_to_sql!(Timestamp, NaiveDateTime);
    debug_to_sql!(Time, NaiveTime);
    debug_to_sql!(Date, NaiveDate);

    #[cfg(feature = "postgres")]
    impl<TZ: TimeZone> ToSql<Timestamptz, Debug> for DateTime<TZ> {
        fn to_sql<W: Write>(&self, _: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
            Ok(IsNull::No)
        }
    }
}
<commit_msg>Add a `debug_to_sql!` call for Timespec<commit_after>use std::io::Write;
use std::error::Error;
use std::time::SystemTime;

use backend::Debug;
use types::*;

macro_rules! debug_to_sql {
    ($sql_type:ty, $ty:ty) => {
        impl ToSql<$sql_type, Debug> for $ty {
            fn to_sql<W: Write>(&self, _: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
                Ok(IsNull::No)
            }
        }
    };
}

debug_to_sql!(Bool, bool);
debug_to_sql!(Timestamp, SystemTime);

#[cfg(feature = "postgres")]
mod pg_impls {
    use super::*;
    use data_types::*;

    debug_to_sql!(Timestamp, PgTimestamp);
    debug_to_sql!(Timestamptz, PgTimestamp);
    debug_to_sql!(Date, PgDate);
    debug_to_sql!(Time, PgTime);
    debug_to_sql!(Interval, PgInterval);
}

#[cfg(feature = "deprecated-time")]
mod deprecated_time_impls {
    extern crate time;
    use super::*;
    use self::time::Timespec;

    debug_to_sql!(Timestamp, Timespec);
}

#[cfg(feature = "chrono")]
mod chrono_impls {
    extern crate chrono;
    use super::*;
    use self::chrono::{NaiveDateTime, NaiveTime, NaiveDate};
    #[cfg(feature = "postgres")]
    use self::chrono::{DateTime, TimeZone};

    debug_to_sql!(Timestamp, NaiveDateTime);
    debug_to_sql!(Time, NaiveTime);
    debug_to_sql!(Date, NaiveDate);

    #[cfg(feature = "postgres")]
    impl<TZ: TimeZone> ToSql<Timestamptz, Debug> for DateTime<TZ> {
        fn to_sql<W: Write>(&self, _: &mut W) -> Result<IsNull, Box<Error+Send+Sync>> {
            Ok(IsNull::No)
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::attr::{Attr, AttrValue};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::reflector::{Reflectable};
use dom::document::Document;
use dom::element::RawLayoutElementHelpers;
use dom::element::{AttributeMutation, Element};
use dom::event::{Event};
use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
use dom::htmlformelement::{FormControl, HTMLFormElement};
use dom::htmlinputelement::ChangeEventRunnable;
use dom::keyboardevent::KeyboardEvent;
use dom::node::{ChildrenMutation, Node, NodeDamage, UnbindContext};
use dom::node::{document_from_node};
use dom::nodelist::NodeList;
use dom::validation::Validatable;
use dom::virtualmethods::VirtualMethods;
use msg::constellation_msg::ConstellationChan;
use range::Range;
use script_traits::ScriptMsg as ConstellationMsg;
use std::cell::Cell;
use string_cache::Atom;
use style::element_state::*;
use textinput::{KeyReaction, Lines, TextInput};
use util::str::DOMString;

#[dom_struct]
pub struct HTMLTextAreaElement {
    htmlelement: HTMLElement,
    #[ignore_heap_size_of = "#7193"]
    textinput: DOMRefCell<TextInput<ConstellationChan<ConstellationMsg>>>,
    // https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
    value_changed: Cell<bool>,
}

pub trait LayoutHTMLTextAreaElementHelpers {
    #[allow(unsafe_code)]
    unsafe fn get_value_for_layout(self) -> String;
    #[allow(unsafe_code)]
    unsafe fn get_absolute_selection_for_layout(self) -> Option<Range<usize>>;
    #[allow(unsafe_code)]
    fn get_cols(self) -> u32;
    #[allow(unsafe_code)]
    fn get_rows(self) -> u32;
}

impl LayoutHTMLTextAreaElementHelpers for LayoutJS<HTMLTextAreaElement> {
    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    unsafe fn get_value_for_layout(self) -> String {
        String::from((*self.unsafe_get()).textinput.borrow_for_layout().get_content())
    }

    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    unsafe fn get_absolute_selection_for_layout(self) -> Option<Range<usize>> {
        if (*self.unsafe_get()).upcast::<Element>().get_focus_state() {
            Some((*self.unsafe_get()).textinput.borrow_for_layout()
                                      .get_absolute_selection_range())
        } else {
            None
        }
    }

    #[allow(unsafe_code)]
    fn get_cols(self) -> u32 {
        unsafe {
            (*self.upcast::<Element>().unsafe_get())
                .get_attr_for_layout(&ns!(), &atom!("cols"))
                .map_or(DEFAULT_COLS, AttrValue::as_uint)
        }
    }

    #[allow(unsafe_code)]
    fn get_rows(self) -> u32 {
        unsafe {
            (*self.upcast::<Element>().unsafe_get())
                .get_attr_for_layout(&ns!(), &atom!("rows"))
                .map_or(DEFAULT_ROWS, AttrValue::as_uint)
        }
    }
}

static DEFAULT_COLS: u32 = 20;
static DEFAULT_ROWS: u32 = 2;

impl HTMLTextAreaElement {
    fn new_inherited(localName: Atom,
                     prefix: Option<DOMString>,
                     document: &Document) -> HTMLTextAreaElement {
        let chan = document.window().constellation_chan();
        HTMLTextAreaElement {
            htmlelement:
                HTMLElement::new_inherited_with_state(IN_ENABLED_STATE,
                                                      localName, prefix, document),
            textinput: DOMRefCell::new(TextInput::new(Lines::Multiple, DOMString::new(), chan, None)),
            value_changed: Cell::new(false),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: Atom,
               prefix: Option<DOMString>,
               document: &Document) -> Root<HTMLTextAreaElement> {
        let element = HTMLTextAreaElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLTextAreaElementBinding::Wrap)
    }
}

impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
    // TODO A few of these attributes have default values and additional
    // constraints

    // https://html.spec.whatwg.org/multipage/#dom-textarea-cols
    make_uint_getter!(Cols, "cols", DEFAULT_COLS);

    // https://html.spec.whatwg.org/multipage/#dom-textarea-cols
    make_limited_uint_setter!(SetCols, "cols", DEFAULT_COLS);

    // https://html.spec.whatwg.org/multipage/#dom-fe-disabled
    make_bool_getter!(Disabled, "disabled");

    // https://html.spec.whatwg.org/multipage/#dom-fe-disabled
    make_bool_setter!(SetDisabled, "disabled");

    // https://html.spec.whatwg.org/multipage/#dom-fae-form
    fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
        self.form_owner()
    }

    // https://html.spec.whatwg.org/multipage/#attr-fe-name
    make_getter!(Name, "name");

    // https://html.spec.whatwg.org/multipage/#attr-fe-name
    make_setter!(SetName, "name");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-placeholder
    make_getter!(Placeholder, "placeholder");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-placeholder
    make_setter!(SetPlaceholder, "placeholder");

    // https://html.spec.whatwg.org/multipage/#attr-textarea-readonly
    make_bool_getter!(ReadOnly, "readonly");

    // https://html.spec.whatwg.org/multipage/#attr-textarea-readonly
    make_bool_setter!(SetReadOnly, "readonly");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-required
    make_bool_getter!(Required, "required");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-required
    make_bool_setter!(SetRequired, "required");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-rows
    make_uint_getter!(Rows, "rows", DEFAULT_ROWS);

    // https://html.spec.whatwg.org/multipage/#dom-textarea-rows
    make_limited_uint_setter!(SetRows, "rows", DEFAULT_ROWS);

    // https://html.spec.whatwg.org/multipage/#dom-textarea-wrap
    make_getter!(Wrap, "wrap");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-wrap
    make_setter!(SetWrap, "wrap");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-type
    fn Type(&self) -> DOMString {
        DOMString::from("textarea")
    }

    // https://html.spec.whatwg.org/multipage/#dom-textarea-defaultvalue
    fn DefaultValue(&self) -> DOMString {
        self.upcast::<Node>().GetTextContent().unwrap()
    }

    // https://html.spec.whatwg.org/multipage/#dom-textarea-defaultvalue
    fn SetDefaultValue(&self, value: DOMString) {
        self.upcast::<Node>().SetTextContent(Some(value));

        // if the element's dirty value flag is false, then the element's
        // raw value must be set to the value of the element's textContent IDL attribute
        if !self.value_changed.get() {
            self.reset();
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-textarea-value
    fn Value(&self) -> DOMString {
        self.textinput.borrow().get_content()
    }

    // https://html.spec.whatwg.org/multipage/#dom-textarea-value
    fn SetValue(&self, value: DOMString) {
        // TODO move the cursor to the end of the field
        self.textinput.borrow_mut().set_content(value);
        self.value_changed.set(true);

        self.force_relayout();
    }

    // https://html.spec.whatwg.org/multipage/#dom-lfe-labels
    fn Labels(&self) -> Root<NodeList> {
        self.upcast::<HTMLElement>().labels()
    }
}

impl HTMLTextAreaElement {
    // https://html.spec.whatwg.org/multipage/#concept-fe-mutable
    pub fn mutable(&self) -> bool {
        // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-fe-mutable
        !(self.Disabled() || self.ReadOnly())
    }
    pub fn reset(&self) {
        // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control
        self.SetValue(self.DefaultValue());
        self.value_changed.set(false);
    }
}

impl HTMLTextAreaElement {
    fn force_relayout(&self) {
        let doc = document_from_node(self);
        doc.content_changed(self.upcast(), NodeDamage::OtherNodeDamage)
    }
}

impl VirtualMethods for HTMLTextAreaElement {
    fn super_type(&self) -> Option<&VirtualMethods> {
        Some(self.upcast::<HTMLElement>() as &VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
        self.super_type().unwrap().attribute_mutated(attr, mutation);
        match *attr.local_name() {
            atom!("disabled") => {
                let el = self.upcast::<Element>();
                match mutation {
                    AttributeMutation::Set(_) => {
                        el.set_disabled_state(true);
                        el.set_enabled_state(false);
                    },
                    AttributeMutation::Removed => {
                        el.set_disabled_state(false);
                        el.set_enabled_state(true);
                        el.check_ancestors_disabled_state_for_form_control();
                    }
                }
            },
            _ => {},
        }
    }

    fn bind_to_tree(&self, tree_in_doc: bool) {
        if let Some(ref s) = self.super_type() {
            s.bind_to_tree(tree_in_doc);
        }

        self.upcast::<Element>().check_ancestors_disabled_state_for_form_control();
    }

    fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
        match *name {
            atom!("cols") => AttrValue::from_limited_u32(value, DEFAULT_COLS),
            atom!("rows") => AttrValue::from_limited_u32(value, DEFAULT_ROWS),
            _ => self.super_type().unwrap().parse_plain_attribute(name, value),
        }
    }

    fn unbind_from_tree(&self, context: &UnbindContext) {
        self.super_type().unwrap().unbind_from_tree(context);

        let node = self.upcast::<Node>();
        let el = self.upcast::<Element>();
        if node.ancestors().any(|ancestor| ancestor.is::<HTMLFieldSetElement>()) {
            el.check_ancestors_disabled_state_for_form_control();
        } else {
            el.check_disabled_attribute();
        }
    }

    fn children_changed(&self, mutation: &ChildrenMutation) {
        if let Some(ref s) = self.super_type() {
            s.children_changed(mutation);
        }
        if !self.value_changed.get() {
            self.reset();
        }
    }

    // copied and modified from htmlinputelement.rs
    fn handle_event(&self, event: &Event) {
        if let Some(s) = self.super_type() {
            s.handle_event(event);
        }

        if event.type_() == atom!("click") && !event.DefaultPrevented() {
            //TODO: set the editing position for text inputs

            document_from_node(self).request_focus(self.upcast());
        } else if event.type_() == atom!("keydown") && !event.DefaultPrevented() {
            if let Some(kevent) = event.downcast::<KeyboardEvent>() {
                match self.textinput.borrow_mut().handle_keydown(kevent) {
                    KeyReaction::TriggerDefaultAction => (),
                    KeyReaction::DispatchInput => {
                        self.value_changed.set(true);

                        if event.IsTrusted() {
                            ChangeEventRunnable::send(self.upcast::<Node>());
                        }

                        self.force_relayout();
                        event.PreventDefault();
                    }
                    KeyReaction::RedrawSelection => {
                        self.force_relayout();
                        event.PreventDefault();
                    }
                    KeyReaction::Nothing => (),
                }
            }
        }
    }
}

impl FormControl for HTMLTextAreaElement {}

impl Validatable for HTMLTextAreaElement {}
<commit_msg>Add a spec links for <textarea> magic number constants.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::attr::{Attr, AttrValue};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::reflector::{Reflectable};
use dom::document::Document;
use dom::element::RawLayoutElementHelpers;
use dom::element::{AttributeMutation, Element};
use dom::event::{Event};
use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
use dom::htmlformelement::{FormControl, HTMLFormElement};
use dom::htmlinputelement::ChangeEventRunnable;
use dom::keyboardevent::KeyboardEvent;
use dom::node::{ChildrenMutation, Node, NodeDamage, UnbindContext};
use dom::node::{document_from_node};
use dom::nodelist::NodeList;
use dom::validation::Validatable;
use dom::virtualmethods::VirtualMethods;
use msg::constellation_msg::ConstellationChan;
use range::Range;
use script_traits::ScriptMsg as ConstellationMsg;
use std::cell::Cell;
use string_cache::Atom;
use style::element_state::*;
use textinput::{KeyReaction, Lines, TextInput};
use util::str::DOMString;

#[dom_struct]
pub struct HTMLTextAreaElement {
    htmlelement: HTMLElement,
    #[ignore_heap_size_of = "#7193"]
    textinput: DOMRefCell<TextInput<ConstellationChan<ConstellationMsg>>>,
    // https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
    value_changed: Cell<bool>,
}

pub trait LayoutHTMLTextAreaElementHelpers {
    #[allow(unsafe_code)]
    unsafe fn get_value_for_layout(self) -> String;
    #[allow(unsafe_code)]
    unsafe fn get_absolute_selection_for_layout(self) -> Option<Range<usize>>;
    #[allow(unsafe_code)]
    fn get_cols(self) -> u32;
    #[allow(unsafe_code)]
    fn get_rows(self) -> u32;
}

impl LayoutHTMLTextAreaElementHelpers for LayoutJS<HTMLTextAreaElement> {
    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    unsafe fn get_value_for_layout(self) -> String {
        String::from((*self.unsafe_get()).textinput.borrow_for_layout().get_content())
    }

    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    unsafe fn get_absolute_selection_for_layout(self) -> Option<Range<usize>> {
        if (*self.unsafe_get()).upcast::<Element>().get_focus_state() {
            Some((*self.unsafe_get()).textinput.borrow_for_layout()
                                      .get_absolute_selection_range())
        } else {
            None
        }
    }

    #[allow(unsafe_code)]
    fn get_cols(self) -> u32 {
        unsafe {
            (*self.upcast::<Element>().unsafe_get())
                .get_attr_for_layout(&ns!(), &atom!("cols"))
                .map_or(DEFAULT_COLS, AttrValue::as_uint)
        }
    }

    #[allow(unsafe_code)]
    fn get_rows(self) -> u32 {
        unsafe {
            (*self.upcast::<Element>().unsafe_get())
                .get_attr_for_layout(&ns!(), &atom!("rows"))
                .map_or(DEFAULT_ROWS, AttrValue::as_uint)
        }
    }
}

// https://html.spec.whatwg.org/multipage/#attr-textarea-cols-value
static DEFAULT_COLS: u32 = 20;

// https://html.spec.whatwg.org/multipage/#attr-textarea-rows-value
static DEFAULT_ROWS: u32 = 2;

impl HTMLTextAreaElement {
    fn new_inherited(localName: Atom,
                     prefix: Option<DOMString>,
                     document: &Document) -> HTMLTextAreaElement {
        let chan = document.window().constellation_chan();
        HTMLTextAreaElement {
            htmlelement:
                HTMLElement::new_inherited_with_state(IN_ENABLED_STATE,
                                                      localName, prefix, document),
            textinput: DOMRefCell::new(TextInput::new(Lines::Multiple, DOMString::new(), chan, None)),
            value_changed: Cell::new(false),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: Atom,
               prefix: Option<DOMString>,
               document: &Document) -> Root<HTMLTextAreaElement> {
        let element = HTMLTextAreaElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLTextAreaElementBinding::Wrap)
    }
}

impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
    // TODO A few of these attributes have default values and additional
    // constraints

    // https://html.spec.whatwg.org/multipage/#dom-textarea-cols
    make_uint_getter!(Cols, "cols", DEFAULT_COLS);

    // https://html.spec.whatwg.org/multipage/#dom-textarea-cols
    make_limited_uint_setter!(SetCols, "cols", DEFAULT_COLS);

    // https://html.spec.whatwg.org/multipage/#dom-fe-disabled
    make_bool_getter!(Disabled, "disabled");

    // https://html.spec.whatwg.org/multipage/#dom-fe-disabled
    make_bool_setter!(SetDisabled, "disabled");

    // https://html.spec.whatwg.org/multipage/#dom-fae-form
    fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
        self.form_owner()
    }

    // https://html.spec.whatwg.org/multipage/#attr-fe-name
    make_getter!(Name, "name");

    // https://html.spec.whatwg.org/multipage/#attr-fe-name
    make_setter!(SetName, "name");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-placeholder
    make_getter!(Placeholder, "placeholder");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-placeholder
    make_setter!(SetPlaceholder, "placeholder");

    // https://html.spec.whatwg.org/multipage/#attr-textarea-readonly
    make_bool_getter!(ReadOnly, "readonly");

    // https://html.spec.whatwg.org/multipage/#attr-textarea-readonly
    make_bool_setter!(SetReadOnly, "readonly");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-required
    make_bool_getter!(Required, "required");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-required
    make_bool_setter!(SetRequired, "required");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-rows
    make_uint_getter!(Rows, "rows", DEFAULT_ROWS);

    // https://html.spec.whatwg.org/multipage/#dom-textarea-rows
    make_limited_uint_setter!(SetRows, "rows", DEFAULT_ROWS);

    // https://html.spec.whatwg.org/multipage/#dom-textarea-wrap
    make_getter!(Wrap, "wrap");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-wrap
    make_setter!(SetWrap, "wrap");

    // https://html.spec.whatwg.org/multipage/#dom-textarea-type
    fn Type(&self) -> DOMString {
        DOMString::from("textarea")
    }

    // https://html.spec.whatwg.org/multipage/#dom-textarea-defaultvalue
    fn DefaultValue(&self) -> DOMString {
        self.upcast::<Node>().GetTextContent().unwrap()
    }

    // https://html.spec.whatwg.org/multipage/#dom-textarea-defaultvalue
    fn SetDefaultValue(&self, value: DOMString) {
        self.upcast::<Node>().SetTextContent(Some(value));

        // if the element's dirty value flag is false, then the element's
        // raw value must be set to the value of the element's textContent IDL attribute
        if !self.value_changed.get() {
            self.reset();
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-textarea-value
    fn Value(&self) -> DOMString {
        self.textinput.borrow().get_content()
    }

    // https://html.spec.whatwg.org/multipage/#dom-textarea-value
    fn SetValue(&self, value: DOMString) {
        // TODO move the cursor to the end of the field
        self.textinput.borrow_mut().set_content(value);
        self.value_changed.set(true);

        self.force_relayout();
    }

    // https://html.spec.whatwg.org/multipage/#dom-lfe-labels
    fn Labels(&self) -> Root<NodeList> {
        self.upcast::<HTMLElement>().labels()
    }
}

impl HTMLTextAreaElement {
    // https://html.spec.whatwg.org/multipage/#concept-fe-mutable
    pub fn mutable(&self) -> bool {
        // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-fe-mutable
        !(self.Disabled() || self.ReadOnly())
    }
    pub fn reset(&self) {
        // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control
        self.SetValue(self.DefaultValue());
        self.value_changed.set(false);
    }
}

impl HTMLTextAreaElement {
    fn force_relayout(&self) {
        let doc = document_from_node(self);
        doc.content_changed(self.upcast(), NodeDamage::OtherNodeDamage)
    }
}

impl VirtualMethods for HTMLTextAreaElement {
    fn super_type(&self) -> Option<&VirtualMethods> {
        Some(self.upcast::<HTMLElement>() as &VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
        self.super_type().unwrap().attribute_mutated(attr, mutation);
        match *attr.local_name() {
            atom!("disabled") => {
                let el = self.upcast::<Element>();
                match mutation {
                    AttributeMutation::Set(_) => {
                        el.set_disabled_state(true);
                        el.set_enabled_state(false);
                    },
                    AttributeMutation::Removed => {
                        el.set_disabled_state(false);
                        el.set_enabled_state(true);
                        el.check_ancestors_disabled_state_for_form_control();
                    }
                }
            },
            _ => {},
        }
    }

    fn bind_to_tree(&self, tree_in_doc: bool) {
        if let Some(ref s) = self.super_type() {
            s.bind_to_tree(tree_in_doc);
        }

        self.upcast::<Element>().check_ancestors_disabled_state_for_form_control();
    }

    fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
        match *name {
            atom!("cols") => AttrValue::from_limited_u32(value, DEFAULT_COLS),
            atom!("rows") => AttrValue::from_limited_u32(value, DEFAULT_ROWS),
            _ => self.super_type().unwrap().parse_plain_attribute(name, value),
        }
    }

    fn unbind_from_tree(&self, context: &UnbindContext) {
        self.super_type().unwrap().unbind_from_tree(context);

        let node = self.upcast::<Node>();
        let el = self.upcast::<Element>();
        if node.ancestors().any(|ancestor| ancestor.is::<HTMLFieldSetElement>()) {
            el.check_ancestors_disabled_state_for_form_control();
        } else {
            el.check_disabled_attribute();
        }
    }

    fn children_changed(&self, mutation: &ChildrenMutation) {
        if let Some(ref s) = self.super_type() {
            s.children_changed(mutation);
        }
        if !self.value_changed.get() {
            self.reset();
        }
    }

    // copied and modified from htmlinputelement.rs
    fn handle_event(&self, event: &Event) {
        if let Some(s) = self.super_type() {
            s.handle_event(event);
        }

        if event.type_() == atom!("click") && !event.DefaultPrevented() {
            //TODO: set the editing position for text inputs

            document_from_node(self).request_focus(self.upcast());
        } else if event.type_() == atom!("keydown") && !event.DefaultPrevented() {
            if let Some(kevent) = event.downcast::<KeyboardEvent>() {
                match self.textinput.borrow_mut().handle_keydown(kevent) {
                    KeyReaction::TriggerDefaultAction => (),
                    KeyReaction::DispatchInput => {
                        self.value_changed.set(true);

                        if event.IsTrusted() {
                            ChangeEventRunnable::send(self.upcast::<Node>());
                        }

                        self.force_relayout();
                        event.PreventDefault();
                    }
                    KeyReaction::RedrawSelection => {
                        self.force_relayout();
                        event.PreventDefault();
                    }
                    KeyReaction::Nothing => (),
                }
            }
        }
    }
}

impl FormControl for HTMLTextAreaElement {}

impl Validatable for HTMLTextAreaElement {}
<|endoftext|>