<commit_before>#[doc="
Types/fns concerning Internet Protocol (IP), versions 4 & 6
"];

import vec;
import uint;
import iotask = uv::iotask::iotask;
import interact = uv::iotask::interact;
import comm::methods;

import sockaddr_in = uv::ll::sockaddr_in;
import sockaddr_in6 = uv::ll::sockaddr_in6;
import addrinfo = uv::ll::addrinfo;
import uv_getaddrinfo_t = uv::ll::uv_getaddrinfo_t;
import uv_ip4_addr = uv::ll::ip4_addr;
import uv_ip4_name = uv::ll::ip4_name;
import uv_ip6_addr = uv::ll::ip6_addr;
import uv_ip6_name = uv::ll::ip6_name;
import uv_getaddrinfo = uv::ll::getaddrinfo;
import uv_freeaddrinfo = uv::ll::freeaddrinfo;
import create_uv_getaddrinfo_t = uv::ll::getaddrinfo_t;
import set_data_for_req = uv::ll::set_data_for_req;
import get_data_for_req = uv::ll::get_data_for_req;
import ll = uv::ll;

export ip_addr, parse_addr_err;
export format_addr;
export v4, v6;
export get_addr;

#[doc = "An IP address"]
enum ip_addr {
    #[doc="An IPv4 address"]
    ipv4(sockaddr_in),
    ipv6(sockaddr_in6)
}

#[doc="
Human-friendly feedback on why a parse_addr attempt failed
"]
type parse_addr_err = {
    err_msg: str
};

#[doc="
Convert a `ip_addr` to a str

# Arguments

* ip - a `std::net::ip::ip_addr`
"]
fn format_addr(ip: ip_addr) -> str {
    alt ip {
      ipv4(addr) {
        unsafe {
            let result = uv_ip4_name(&addr);
            if result == "" {
                fail "failed to convert inner sockaddr_in address to str"
            }
            result
        }
      }
      ipv6(addr) {
        unsafe {
            let result = uv_ip6_name(&addr);
            if result == "" {
                fail "failed to convert inner sockaddr_in address to str"
            }
            result
        }
      }
    }
}

type get_addr_data = {
    output_ch: comm::chan<result::result<[ip_addr]/~,ip_get_addr_err>>
};

crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int,
                     res: *addrinfo) unsafe {
    log(debug, "in get_addr_cb");
    let handle_data = get_data_for_req(handle) as
        *get_addr_data;
    if status == 0i32 {
        if res != (ptr::null::<addrinfo>()) {
            let mut out_vec = []/~;
            log(debug, #fmt("initial addrinfo: %?", res));
            let mut curr_addr = res;
            loop {
                let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) {
                    ipv4(copy((
                        *ll::addrinfo_as_sockaddr_in(curr_addr))))
                }
                else if ll::is_ipv6_addrinfo(curr_addr) {
                    ipv6(copy((
                        *ll::addrinfo_as_sockaddr_in6(curr_addr))))
                }
                else {
                    log(debug, "curr_addr is not of family AF_INET or "+
                        "AF_INET6. Error.");
                    (*handle_data).output_ch.send(
                        result::err(get_addr_unknown_error));
                    break;
                };
                out_vec += [new_ip_addr]/~;

                let next_addr = ll::get_next_addrinfo(curr_addr);
                if next_addr == ptr::null::<addrinfo>() as *addrinfo {
                    log(debug, "null next_addr encountered. no mas");
                    break;
                }
                else {
                    curr_addr = next_addr;
                    log(debug, #fmt("next_addr addrinfo: %?", curr_addr));
                }
            }
            log(debug, #fmt("successful process addrinfo result, len: %?",
                            vec::len(out_vec)));
            (*handle_data).output_ch.send(result::ok(out_vec));
        }
        else {
            log(debug, "addrinfo pointer is NULL");
            (*handle_data).output_ch.send(
                result::err(get_addr_unknown_error));
        }
    }
    else {
        log(debug, "status != 0 error in get_addr_cb");
        (*handle_data).output_ch.send(
            result::err(get_addr_unknown_error));
    }
    if res != (ptr::null::<addrinfo>()) {
        uv_freeaddrinfo(res);
    }
    log(debug, "leaving get_addr_cb");
}

#[doc="
"]
enum ip_get_addr_err {
    get_addr_unknown_error
}

#[doc="
"]
fn get_addr(++node: str, iotask: iotask)
        -> result::result<[ip_addr]/~, ip_get_addr_err> unsafe {
    comm::listen {|output_ch|
        str::unpack_slice(node) {|node_ptr, len|
            log(debug, #fmt("slice len %?", len));
            let handle = create_uv_getaddrinfo_t();
            let handle_ptr = ptr::addr_of(handle);
            let handle_data: get_addr_data = {
                output_ch: output_ch
            };
            let handle_data_ptr = ptr::addr_of(handle_data);
            interact(iotask) {|loop_ptr|
                let result = uv_getaddrinfo(
                    loop_ptr,
                    handle_ptr,
                    get_addr_cb,
                    node_ptr,
                    ptr::null(),
                    ptr::null());
                alt result {
                  0i32 {
                    set_data_for_req(handle_ptr, handle_data_ptr);
                  }
                  _ {
                    output_ch.send(result::err(get_addr_unknown_error));
                  }
                }
            };
            output_ch.recv()
        }
    }
}

mod v4 {
    #[doc = "
    Convert a str to `ip_addr`

    # Failure

    Fails if the string is not a valid IPv4 address

    # Arguments

    * ip - a string of the format `x.x.x.x`

    # Returns

    * an `ip_addr` of the `ipv4` variant
    "]
    fn parse_addr(ip: str) -> ip_addr {
        alt try_parse_addr(ip) {
          result::ok(addr) { copy(addr) }
          result::err(err_data) {
            fail err_data.err_msg
          }
        }
    }
    // the simple, old style numberic representation of
    // ipv4
    type ipv4_rep = { a: u8, b: u8, c: u8, d:u8 };
    impl x for ipv4_rep {
        // this is pretty dastardly, i know
        unsafe fn as_u32() -> u32 {
            *((ptr::addr_of(self)) as *u32)
        }
    }
    fn parse_to_ipv4_rep(ip: str) -> result::result<ipv4_rep, str> {
        let parts = vec::map(str::split_char(ip, '.'), {|s|
            alt uint::from_str(s) {
              some(n) if n <= 255u { n }
              _ { 256u }
            }
        });
        if vec::len(parts) != 4u {
                result::err(#fmt("'%s' doesn't have 4 parts", ip))
                }
        else if vec::contains(parts, 256u) {
                result::err(#fmt("invalid octal in addr '%s'", ip))
                }
        else {
            result::ok({a: parts[0] as u8, b: parts[1] as u8,
                        c: parts[2] as u8, d: parts[3] as u8})
        }
    }
    fn try_parse_addr(ip: str) -> result::result<ip_addr,parse_addr_err> {
        unsafe {
            let INADDR_NONE = ll::get_INADDR_NONE();
            let ip_rep_result = parse_to_ipv4_rep(ip);
            if result::is_err(ip_rep_result) {
                let err_str = result::get_err(ip_rep_result);
                ret result::err({err_msg: err_str})
            }
            // ipv4_rep.as_u32 is unsafe :/
            let input_is_inaddr_none =
                result::get(ip_rep_result).as_u32() == INADDR_NONE;

            let new_addr = uv_ip4_addr(ip, 22);
            let reformatted_name = uv_ip4_name(&new_addr);
            log(debug, #fmt("try_parse_addr: input ip: %s reparsed ip: %s",
                            ip, reformatted_name));
            let ref_ip_rep_result = parse_to_ipv4_rep(reformatted_name);
            if result::is_err(ref_ip_rep_result) {
                let err_str = result::get_err(ref_ip_rep_result);
                ret result::err({err_msg: err_str})
            }
            if result::get(ref_ip_rep_result).as_u32() == INADDR_NONE &&
                 !input_is_inaddr_none {
                ret result::err(
                    {err_msg: "uv_ip4_name produced invalid result."})
            }
            else {
                result::ok(ipv4(copy(new_addr)))
            }
        }
    }
}
mod v6 {
    #[doc = "
    Convert a str to `ip_addr`

    # Failure

    Fails if the string is not a valid IPv6 address

    # Arguments

    * ip - an ipv6 string. See RFC2460 for spec.

    # Returns

    * an `ip_addr` of the `ipv6` variant
    "]
    fn parse_addr(ip: str) -> ip_addr {
        alt try_parse_addr(ip) {
          result::ok(addr) { copy(addr) }
          result::err(err_data) {
            fail err_data.err_msg
          }
        }
    }
    fn try_parse_addr(ip: str) -> result::result<ip_addr,parse_addr_err> {
        unsafe {
            // need to figure out how to establish a parse failure..
            let new_addr = uv_ip6_addr(ip, 22);
            let reparsed_name = uv_ip6_name(&new_addr);
            log(debug, #fmt("v6::try_parse_addr ip: '%s' reparsed '%s'",
                            ip, reparsed_name));
            // '::' appears to be uv_ip6_name() returns for bogus
            // parses..
            if  ip != "::" && reparsed_name == "::" {
                result::err({err_msg:#fmt("failed to parse '%s'",
                                           ip)})
            }
            else {
                result::ok(ipv6(new_addr))
            }
        }
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_ip_ipv4_parse_and_format_ip() {
        let localhost_str = "127.0.0.1";
        assert (format_addr(v4::parse_addr(localhost_str))
                == localhost_str)
    }
    #[test]
    fn test_ip_ipv6_parse_and_format_ip() {
        let localhost_str = "::1";
        let format_result = format_addr(v6::parse_addr(localhost_str));
        log(debug, #fmt("results: expected: '%s' actual: '%s'",
            localhost_str, format_result));
        assert format_result == localhost_str;
    }
    #[test]
    fn test_ip_ipv4_bad_parse() {
        alt v4::try_parse_addr("b4df00d") {
          result::err(err_info) {
            log(debug, #fmt("got error as expected %?", err_info));
            assert true;
          }
          result::ok(addr) {
            fail #fmt("Expected failure, but got addr %?", addr);
          }
        }
    }
    #[test]
    #[ignore(target_os="win32")]
    fn test_ip_ipv6_bad_parse() {
        alt v6::try_parse_addr("::,~2234k;") {
          result::err(err_info) {
            log(debug, #fmt("got error as expected %?", err_info));
            assert true;
          }
          result::ok(addr) {
            fail #fmt("Expected failure, but got addr %?", addr);
          }
        }
    }
    #[test]
    fn test_ip_get_addr() {
        let localhost_name = "localhost";
        let iotask = uv::global_loop::get();
        let ga_result = get_addr(localhost_name, iotask);
        if result::is_err(ga_result) {
            fail "got err result from net::ip::get_addr();"
        }
        // note really sure how to realiably test/assert
        // this.. mostly just wanting to see it work, atm.
        let results = result::unwrap(ga_result);
        log(debug, #fmt("test_get_addr: Number of results for %s: %?",
                        localhost_name, vec::len(results)));
        for vec::each(results) {|r|
            let ipv_prefix = alt r {
              ipv4(_) {
                "IPv4"
              }
              ipv6(_) {
                "IPv6"
              }
            };
            log(debug, #fmt("test_get_addr: result %s: '%s'",
                            ipv_prefix, format_addr(r)));
        }
        // at least one result.. this is going to vary from system
        // to system, based on stuff like the contents of /etc/hosts
        assert vec::len(results) > 0;
    }
    #[test]
    fn test_ip_get_addr_bad_input() {
        let localhost_name = "sjkl234m,./sdf";
        let iotask = uv::global_loop::get();
        let ga_result = get_addr(localhost_name, iotask);
        assert result::is_err(ga_result);
    }
}<commit_msg>std: adding some basic docs for net::ip::get_addr<commit_after>#[doc="
Types/fns concerning Internet Protocol (IP), versions 4 & 6
"];

import vec;
import uint;
import iotask = uv::iotask::iotask;
import interact = uv::iotask::interact;
import comm::methods;

import sockaddr_in = uv::ll::sockaddr_in;
import sockaddr_in6 = uv::ll::sockaddr_in6;
import addrinfo = uv::ll::addrinfo;
import uv_getaddrinfo_t = uv::ll::uv_getaddrinfo_t;
import uv_ip4_addr = uv::ll::ip4_addr;
import uv_ip4_name = uv::ll::ip4_name;
import uv_ip6_addr = uv::ll::ip6_addr;
import uv_ip6_name = uv::ll::ip6_name;
import uv_getaddrinfo = uv::ll::getaddrinfo;
import uv_freeaddrinfo = uv::ll::freeaddrinfo;
import create_uv_getaddrinfo_t = uv::ll::getaddrinfo_t;
import set_data_for_req = uv::ll::set_data_for_req;
import get_data_for_req = uv::ll::get_data_for_req;
import ll = uv::ll;

export ip_addr, parse_addr_err;
export format_addr;
export v4, v6;
export get_addr;

#[doc = "An IP address"]
enum ip_addr {
    #[doc="An IPv4 address"]
    ipv4(sockaddr_in),
    ipv6(sockaddr_in6)
}

#[doc="
Human-friendly feedback on why a parse_addr attempt failed
"]
type parse_addr_err = {
    err_msg: str
};

#[doc="
Convert a `ip_addr` to a str

# Arguments

* ip - a `std::net::ip::ip_addr`
"]
fn format_addr(ip: ip_addr) -> str {
    alt ip {
      ipv4(addr) {
        unsafe {
            let result = uv_ip4_name(&addr);
            if result == "" {
                fail "failed to convert inner sockaddr_in address to str"
            }
            result
        }
      }
      ipv6(addr) {
        unsafe {
            let result = uv_ip6_name(&addr);
            if result == "" {
                fail "failed to convert inner sockaddr_in address to str"
            }
            result
        }
      }
    }
}

#[doc="
Represents errors returned from `net::ip::get_addr()`
"]
enum ip_get_addr_err {
    get_addr_unknown_error
}

#[doc="
Attempts name resolution on the provided `node` string

# Arguments

* `node` - a string representing some host address
* `iotask` - a `uv::iotask` used to interact with the underlying event loop

# Returns

A `result<[ip_addr]/~, ip_get_addr_err>` instance that will contain
a vector of `ip_addr` results, in the case of success, or an error
object in the case of failure
"]
fn get_addr(++node: str, iotask: iotask)
        -> result::result<[ip_addr]/~, ip_get_addr_err> unsafe {
    comm::listen {|output_ch|
        str::unpack_slice(node) {|node_ptr, len|
            log(debug, #fmt("slice len %?", len));
            let handle = create_uv_getaddrinfo_t();
            let handle_ptr = ptr::addr_of(handle);
            let handle_data: get_addr_data = {
                output_ch: output_ch
            };
            let handle_data_ptr = ptr::addr_of(handle_data);
            interact(iotask) {|loop_ptr|
                let result = uv_getaddrinfo(
                    loop_ptr,
                    handle_ptr,
                    get_addr_cb,
                    node_ptr,
                    ptr::null(),
                    ptr::null());
                alt result {
                  0i32 {
                    set_data_for_req(handle_ptr, handle_data_ptr);
                  }
                  _ {
                    output_ch.send(result::err(get_addr_unknown_error));
                  }
                }
            };
            output_ch.recv()
        }
    }
}

mod v4 {
    #[doc = "
    Convert a str to `ip_addr`

    # Failure

    Fails if the string is not a valid IPv4 address

    # Arguments

    * ip - a string of the format `x.x.x.x`

    # Returns

    * an `ip_addr` of the `ipv4` variant
    "]
    fn parse_addr(ip: str) -> ip_addr {
        alt try_parse_addr(ip) {
          result::ok(addr) { copy(addr) }
          result::err(err_data) {
            fail err_data.err_msg
          }
        }
    }
    // the simple, old style numberic representation of
    // ipv4
    type ipv4_rep = { a: u8, b: u8, c: u8, d:u8 };
    impl x for ipv4_rep {
        // this is pretty dastardly, i know
        unsafe fn as_u32() -> u32 {
            *((ptr::addr_of(self)) as *u32)
        }
    }
    fn parse_to_ipv4_rep(ip: str) -> result::result<ipv4_rep, str> {
        let parts = vec::map(str::split_char(ip, '.'), {|s|
            alt uint::from_str(s) {
              some(n) if n <= 255u { n }
              _ { 256u }
            }
        });
        if vec::len(parts) != 4u {
                result::err(#fmt("'%s' doesn't have 4 parts", ip))
                }
        else if vec::contains(parts, 256u) {
                result::err(#fmt("invalid octal in addr '%s'", ip))
                }
        else {
            result::ok({a: parts[0] as u8, b: parts[1] as u8,
                        c: parts[2] as u8, d: parts[3] as u8})
        }
    }
    fn try_parse_addr(ip: str) -> result::result<ip_addr,parse_addr_err> {
        unsafe {
            let INADDR_NONE = ll::get_INADDR_NONE();
            let ip_rep_result = parse_to_ipv4_rep(ip);
            if result::is_err(ip_rep_result) {
                let err_str = result::get_err(ip_rep_result);
                ret result::err({err_msg: err_str})
            }
            // ipv4_rep.as_u32 is unsafe :/
            let input_is_inaddr_none =
                result::get(ip_rep_result).as_u32() == INADDR_NONE;

            let new_addr = uv_ip4_addr(ip, 22);
            let reformatted_name = uv_ip4_name(&new_addr);
            log(debug, #fmt("try_parse_addr: input ip: %s reparsed ip: %s",
                            ip, reformatted_name));
            let ref_ip_rep_result = parse_to_ipv4_rep(reformatted_name);
            if result::is_err(ref_ip_rep_result) {
                let err_str = result::get_err(ref_ip_rep_result);
                ret result::err({err_msg: err_str})
            }
            if result::get(ref_ip_rep_result).as_u32() == INADDR_NONE &&
                 !input_is_inaddr_none {
                ret result::err(
                    {err_msg: "uv_ip4_name produced invalid result."})
            }
            else {
                result::ok(ipv4(copy(new_addr)))
            }
        }
    }
}
mod v6 {
    #[doc = "
    Convert a str to `ip_addr`

    # Failure

    Fails if the string is not a valid IPv6 address

    # Arguments

    * ip - an ipv6 string. See RFC2460 for spec.

    # Returns

    * an `ip_addr` of the `ipv6` variant
    "]
    fn parse_addr(ip: str) -> ip_addr {
        alt try_parse_addr(ip) {
          result::ok(addr) { copy(addr) }
          result::err(err_data) {
            fail err_data.err_msg
          }
        }
    }
    fn try_parse_addr(ip: str) -> result::result<ip_addr,parse_addr_err> {
        unsafe {
            // need to figure out how to establish a parse failure..
            let new_addr = uv_ip6_addr(ip, 22);
            let reparsed_name = uv_ip6_name(&new_addr);
            log(debug, #fmt("v6::try_parse_addr ip: '%s' reparsed '%s'",
                            ip, reparsed_name));
            // '::' appears to be uv_ip6_name() returns for bogus
            // parses..
            if  ip != "::" && reparsed_name == "::" {
                result::err({err_msg:#fmt("failed to parse '%s'",
                                           ip)})
            }
            else {
                result::ok(ipv6(new_addr))
            }
        }
    }
}

type get_addr_data = {
    output_ch: comm::chan<result::result<[ip_addr]/~,ip_get_addr_err>>
};

crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int,
                     res: *addrinfo) unsafe {
    log(debug, "in get_addr_cb");
    let handle_data = get_data_for_req(handle) as
        *get_addr_data;
    if status == 0i32 {
        if res != (ptr::null::<addrinfo>()) {
            let mut out_vec = []/~;
            log(debug, #fmt("initial addrinfo: %?", res));
            let mut curr_addr = res;
            loop {
                let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) {
                    ipv4(copy((
                        *ll::addrinfo_as_sockaddr_in(curr_addr))))
                }
                else if ll::is_ipv6_addrinfo(curr_addr) {
                    ipv6(copy((
                        *ll::addrinfo_as_sockaddr_in6(curr_addr))))
                }
                else {
                    log(debug, "curr_addr is not of family AF_INET or "+
                        "AF_INET6. Error.");
                    (*handle_data).output_ch.send(
                        result::err(get_addr_unknown_error));
                    break;
                };
                out_vec += [new_ip_addr]/~;

                let next_addr = ll::get_next_addrinfo(curr_addr);
                if next_addr == ptr::null::<addrinfo>() as *addrinfo {
                    log(debug, "null next_addr encountered. no mas");
                    break;
                }
                else {
                    curr_addr = next_addr;
                    log(debug, #fmt("next_addr addrinfo: %?", curr_addr));
                }
            }
            log(debug, #fmt("successful process addrinfo result, len: %?",
                            vec::len(out_vec)));
            (*handle_data).output_ch.send(result::ok(out_vec));
        }
        else {
            log(debug, "addrinfo pointer is NULL");
            (*handle_data).output_ch.send(
                result::err(get_addr_unknown_error));
        }
    }
    else {
        log(debug, "status != 0 error in get_addr_cb");
        (*handle_data).output_ch.send(
            result::err(get_addr_unknown_error));
    }
    if res != (ptr::null::<addrinfo>()) {
        uv_freeaddrinfo(res);
    }
    log(debug, "leaving get_addr_cb");
}

#[cfg(test)]
mod test {
    #[test]
    fn test_ip_ipv4_parse_and_format_ip() {
        let localhost_str = "127.0.0.1";
        assert (format_addr(v4::parse_addr(localhost_str))
                == localhost_str)
    }
    #[test]
    fn test_ip_ipv6_parse_and_format_ip() {
        let localhost_str = "::1";
        let format_result = format_addr(v6::parse_addr(localhost_str));
        log(debug, #fmt("results: expected: '%s' actual: '%s'",
            localhost_str, format_result));
        assert format_result == localhost_str;
    }
    #[test]
    fn test_ip_ipv4_bad_parse() {
        alt v4::try_parse_addr("b4df00d") {
          result::err(err_info) {
            log(debug, #fmt("got error as expected %?", err_info));
            assert true;
          }
          result::ok(addr) {
            fail #fmt("Expected failure, but got addr %?", addr);
          }
        }
    }
    #[test]
    #[ignore(target_os="win32")]
    fn test_ip_ipv6_bad_parse() {
        alt v6::try_parse_addr("::,~2234k;") {
          result::err(err_info) {
            log(debug, #fmt("got error as expected %?", err_info));
            assert true;
          }
          result::ok(addr) {
            fail #fmt("Expected failure, but got addr %?", addr);
          }
        }
    }
    #[test]
    fn test_ip_get_addr() {
        let localhost_name = "localhost";
        let iotask = uv::global_loop::get();
        let ga_result = get_addr(localhost_name, iotask);
        if result::is_err(ga_result) {
            fail "got err result from net::ip::get_addr();"
        }
        // note really sure how to realiably test/assert
        // this.. mostly just wanting to see it work, atm.
        let results = result::unwrap(ga_result);
        log(debug, #fmt("test_get_addr: Number of results for %s: %?",
                        localhost_name, vec::len(results)));
        for vec::each(results) {|r|
            let ipv_prefix = alt r {
              ipv4(_) {
                "IPv4"
              }
              ipv6(_) {
                "IPv6"
              }
            };
            log(debug, #fmt("test_get_addr: result %s: '%s'",
                            ipv_prefix, format_addr(r)));
        }
        // at least one result.. this is going to vary from system
        // to system, based on stuff like the contents of /etc/hosts
        assert vec::len(results) > 0;
    }
    #[test]
    fn test_ip_get_addr_bad_input() {
        let localhost_name = "sjkl234m,./sdf";
        let iotask = uv::global_loop::get();
        let ga_result = get_addr(localhost_name, iotask);
        assert result::is_err(ga_result);
    }
}<|endoftext|>


<commit_before>use super::{Region, RegionIndex};
use std::mem;
use rustc::infer::InferCtxt;
use rustc::mir::{Location, Mir};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::fx::FxHashSet;

pub struct InferenceContext {
    definitions: IndexVec<RegionIndex, VarDefinition>,
    constraints: IndexVec<ConstraintIndex, Constraint>,
    errors: IndexVec<InferenceErrorIndex, InferenceError>,
}

pub struct InferenceError {
    pub constraint_point: Location,
    pub name: (), // TODO(nashenas88) RegionName
}

newtype_index!(InferenceErrorIndex);

struct VarDefinition {
    name: (), // TODO(nashenas88) RegionName
    value: Region,
    capped: bool,
}

impl VarDefinition {
    pub fn new(value: Region) -> Self {
        Self {
            name: (),
            value,
            capped: false,
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Constraint {
    sub: RegionIndex,
    sup: RegionIndex,
    point: Location,
}

newtype_index!(ConstraintIndex);

impl InferenceContext {
    pub fn new(values: IndexVec<RegionIndex, Region>) -> Self {
        Self {
            definitions: values.into_iter().map(VarDefinition::new).collect(),
            constraints: IndexVec::new(),
            errors: IndexVec::new(),
        }
    }

    #[allow(dead_code)]
    pub fn cap_var(&mut self, v: RegionIndex) {
        self.definitions[v].capped = true;
    }

    #[allow(dead_code)]
    pub fn add_live_point(&mut self, v: RegionIndex, point: Location) {
        debug!("add_live_point({:?}, {:?})", v, point);
        let definition = &mut self.definitions[v];
        if definition.value.add_point(point) {
            if definition.capped {
                self.errors.push(InferenceError {
                    constraint_point: point,
                    name: definition.name,
                });
            }
        }
    }

    #[allow(dead_code)]
    pub fn add_outlives(&mut self, sup: RegionIndex, sub: RegionIndex, point: Location) {
        debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point);
        self.constraints.push(Constraint { sup, sub, point });
    }

    #[allow(dead_code)]
    pub fn region(&self, v: RegionIndex) -> &Region {
        &self.definitions[v].value
    }

    pub fn solve<'a, 'gcx, 'tcx>(
        &mut self,
        infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
        mir: &'a Mir<'tcx>,
    ) -> IndexVec<InferenceErrorIndex, InferenceError>
    where
        'gcx: 'tcx + 'a,
        'tcx: 'a,
    {
        let mut changed = true;
        let mut dfs = Dfs::new(infcx, mir);
        while changed {
            changed = false;
            for constraint in &self.constraints {
                let sub = &self.definitions[constraint.sub].value.clone();
                let sup_def = &mut self.definitions[constraint.sup];
                debug!("constraint: {:?}", constraint);
                debug!("    sub (before): {:?}", sub);
                debug!("    sup (before): {:?}", sup_def.value);

                if dfs.copy(sub, &mut sup_def.value, constraint.point) {
                    changed = true;
                    if sup_def.capped {
                        // This is kind of a hack, but when we add a
                        // constraint, the "point" is always the point
                        // AFTER the action that induced the
                        // constraint. So report the error on the
                        // action BEFORE that.
                        assert!(constraint.point.statement_index > 0);
                        let p = Location {
                            block: constraint.point.block,
                            statement_index: constraint.point.statement_index - 1,
                        };

                        self.errors.push(InferenceError {
                            constraint_point: p,
                            name: sup_def.name,
                        });
                    }
                }

                debug!("    sup (after) : {:?}", sup_def.value);
                debug!("    changed     : {:?}", changed);
            }
            debug!("\n");
        }

        mem::replace(&mut self.errors, IndexVec::new())
    }
}

struct Dfs<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> {
    #[allow(dead_code)]
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
    mir: &'a Mir<'tcx>,
}

impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> {
    fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
        Self { infcx, mir }
    }

    fn copy(
        &mut self,
        from_region: &Region,
        to_region: &mut Region,
        start_point: Location,
    ) -> bool {
        let mut changed = false;

        let mut stack = vec![];
        let mut visited = FxHashSet();

        stack.push(start_point);
        while let Some(p) = stack.pop() {
            debug!("        dfs: p={:?}", p);

            if !from_region.may_contain(p) {
                debug!("            not in from-region");
                continue;
            }

            if !visited.insert(p) {
                debug!("            already visited");
                continue;
            }

            changed |= to_region.add_point(p);

            let block_data = &self.mir[p.block];
            let successor_points = if p.statement_index < block_data.statements.len() {
                vec![Location {
                    statement_index: p.statement_index + 1,
                    ..p
                }]
            } else {
                block_data.terminator()
                    .successors()
                    .iter()
                    .map(|&basic_block| Location {
                        statement_index: 0,
                        block: basic_block,
                    })
                    .collect::<Vec<_>>()
            };

            if successor_points.is_empty() {
                // TODO handle free regions
                // If we reach the END point in the graph, then copy
                // over any skolemized end points in the `from_region`
                // and make sure they are included in the `to_region`.
                // for region_decl in self.infcx.tcx.tables.borrow().free_region_map() {
                //     // TODO(nashenas88) figure out skolemized_end points
                //     let block = self.env.graph.skolemized_end(region_decl.name);
                //     let skolemized_end_point = Location {
                //         block,
                //         statement_index: 0,
                //     };
                //     changed |= to_region.add_point(skolemized_end_point);
                // }
            } else {
                stack.extend(successor_points);
            }
        }

        changed
    }
}
<commit_msg>TODO -> FIXME<commit_after>use super::{Region, RegionIndex};
use std::mem;
use rustc::infer::InferCtxt;
use rustc::mir::{Location, Mir};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::fx::FxHashSet;

pub struct InferenceContext {
    definitions: IndexVec<RegionIndex, VarDefinition>,
    constraints: IndexVec<ConstraintIndex, Constraint>,
    errors: IndexVec<InferenceErrorIndex, InferenceError>,
}

pub struct InferenceError {
    pub constraint_point: Location,
    pub name: (), // FIXME(nashenas88) RegionName
}

newtype_index!(InferenceErrorIndex);

struct VarDefinition {
    name: (), // FIXME(nashenas88) RegionName
    value: Region,
    capped: bool,
}

impl VarDefinition {
    pub fn new(value: Region) -> Self {
        Self {
            name: (),
            value,
            capped: false,
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Constraint {
    sub: RegionIndex,
    sup: RegionIndex,
    point: Location,
}

newtype_index!(ConstraintIndex);

impl InferenceContext {
    pub fn new(values: IndexVec<RegionIndex, Region>) -> Self {
        Self {
            definitions: values.into_iter().map(VarDefinition::new).collect(),
            constraints: IndexVec::new(),
            errors: IndexVec::new(),
        }
    }

    #[allow(dead_code)]
    pub fn cap_var(&mut self, v: RegionIndex) {
        self.definitions[v].capped = true;
    }

    #[allow(dead_code)]
    pub fn add_live_point(&mut self, v: RegionIndex, point: Location) {
        debug!("add_live_point({:?}, {:?})", v, point);
        let definition = &mut self.definitions[v];
        if definition.value.add_point(point) {
            if definition.capped {
                self.errors.push(InferenceError {
                    constraint_point: point,
                    name: definition.name,
                });
            }
        }
    }

    #[allow(dead_code)]
    pub fn add_outlives(&mut self, sup: RegionIndex, sub: RegionIndex, point: Location) {
        debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point);
        self.constraints.push(Constraint { sup, sub, point });
    }

    #[allow(dead_code)]
    pub fn region(&self, v: RegionIndex) -> &Region {
        &self.definitions[v].value
    }

    pub fn solve<'a, 'gcx, 'tcx>(
        &mut self,
        infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
        mir: &'a Mir<'tcx>,
    ) -> IndexVec<InferenceErrorIndex, InferenceError>
    where
        'gcx: 'tcx + 'a,
        'tcx: 'a,
    {
        let mut changed = true;
        let mut dfs = Dfs::new(infcx, mir);
        while changed {
            changed = false;
            for constraint in &self.constraints {
                let sub = &self.definitions[constraint.sub].value.clone();
                let sup_def = &mut self.definitions[constraint.sup];
                debug!("constraint: {:?}", constraint);
                debug!("    sub (before): {:?}", sub);
                debug!("    sup (before): {:?}", sup_def.value);

                if dfs.copy(sub, &mut sup_def.value, constraint.point) {
                    changed = true;
                    if sup_def.capped {
                        // This is kind of a hack, but when we add a
                        // constraint, the "point" is always the point
                        // AFTER the action that induced the
                        // constraint. So report the error on the
                        // action BEFORE that.
                        assert!(constraint.point.statement_index > 0);
                        let p = Location {
                            block: constraint.point.block,
                            statement_index: constraint.point.statement_index - 1,
                        };

                        self.errors.push(InferenceError {
                            constraint_point: p,
                            name: sup_def.name,
                        });
                    }
                }

                debug!("    sup (after) : {:?}", sup_def.value);
                debug!("    changed     : {:?}", changed);
            }
            debug!("\n");
        }

        mem::replace(&mut self.errors, IndexVec::new())
    }
}

struct Dfs<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> {
    #[allow(dead_code)]
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
    mir: &'a Mir<'tcx>,
}

impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> {
    fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
        Self { infcx, mir }
    }

    fn copy(
        &mut self,
        from_region: &Region,
        to_region: &mut Region,
        start_point: Location,
    ) -> bool {
        let mut changed = false;

        let mut stack = vec![];
        let mut visited = FxHashSet();

        stack.push(start_point);
        while let Some(p) = stack.pop() {
            debug!("        dfs: p={:?}", p);

            if !from_region.may_contain(p) {
                debug!("            not in from-region");
                continue;
            }

            if !visited.insert(p) {
                debug!("            already visited");
                continue;
            }

            changed |= to_region.add_point(p);

            let block_data = &self.mir[p.block];
            let successor_points = if p.statement_index < block_data.statements.len() {
                vec![Location {
                    statement_index: p.statement_index + 1,
                    ..p
                }]
            } else {
                block_data.terminator()
                    .successors()
                    .iter()
                    .map(|&basic_block| Location {
                        statement_index: 0,
                        block: basic_block,
                    })
                    .collect::<Vec<_>>()
            };

            if successor_points.is_empty() {
                // FIXME handle free regions
                // If we reach the END point in the graph, then copy
                // over any skolemized end points in the `from_region`
                // and make sure they are included in the `to_region`.
                // for region_decl in self.infcx.tcx.tables.borrow().free_region_map() {
                //     // FIXME(nashenas88) figure out skolemized_end points
                //     let block = self.env.graph.skolemized_end(region_decl.name);
                //     let skolemized_end_point = Location {
                //         block,
                //         statement_index: 0,
                //     };
                //     changed |= to_region.add_point(skolemized_end_point);
                // }
            } else {
                stack.extend(successor_points);
            }
        }

        changed
    }
}
<|endoftext|>


<commit_before><commit_msg>Add some new structs for building trees with alternative siblings (ie, for cases where we want to take a bunch of nodes and re-parent them)<commit_after>use std::rc::*;

use super::treenode::*;
use super::values::*;

///
/// A TreeRef works as a reference to another tree node with a different sibling
///
pub struct TreeRef {
    ref_to: Rc<TreeNode>,
    new_sibling: Option<Rc<TreeNode>>
}

impl TreeNode for TreeRef {
    ///
    /// Retrieves a reference to the child of this tree node (or None if this node has no child)
    ///
    fn get_child_ref(&self) -> Option<&Rc<TreeNode>> {
        (*self.ref_to).get_child_ref()
    }

    ///
    /// Retrieves a reference to the sibling of this tree node (or None if this node has no sibling)
    ///
    fn get_sibling_ref(&self) -> Option<&Rc<TreeNode>> {
        self.new_sibling.as_ref()
    }

    ///
    /// Retrieves the tag attached to this tree node
    ///
    fn get_tag(&self) -> &str {
        (*self.ref_to).get_tag()
    }

    ///
    /// Retrieves the value attached to this node
    ///
    fn get_value(&self) -> &TreeValue {
        (*self.ref_to).get_value()
    }
}

///
/// Trait provided by types that can generate treenodes with new siblings
///
pub trait ToTreeRef {
    ///
    /// Creates a new tree node that is identical to an existing one apart from its sibling
    ///
    fn with_sibling_ref(&self, new_sibling: &Rc<TreeNode>) -> Rc<TreeNode>;

    ///
    /// Creates a new tree node that is identical to an existing one apart from having no sibling
    ///
    fn with_no_sibling_ref(&self) -> Rc<TreeNode>;
}

impl ToTreeRef for Rc<TreeNode> {
    ///
    /// Creates a new tree node that is identical to an existing one apart from its sibling
    ///
    fn with_sibling_ref(&self, new_sibling: &Rc<TreeNode>) -> Rc<TreeNode> {
        Rc::new(TreeRef { ref_to: self.to_owned(), new_sibling: Some(new_sibling.to_owned()) })
    }

    ///
    /// Creates a new tree node that is identical to an existing one apart from having no sibling
    ///
    fn with_no_sibling_ref(&self) -> Rc<TreeNode> {
        Rc::new(TreeRef { ref_to: self.to_owned(), new_sibling: None })
    }
}

///
/// Trait providing 'sugar' functions for calling ToTreeRef style funtions on things implementing ToTreeNode
///
pub trait ToTreeRefSugar {
    ///
    /// Creates a new tree node with a particular sibling
    ///
    fn with_sibling<TSibling: ToTreeNode>(&self, new_sibling: TSibling) -> Rc<TreeNode>;

    ///
    /// Creates a new tree node with no sibling
    ///
    fn with_no_sibling(&self) -> Rc<TreeNode>;
}

impl<TNode: ToTreeNode> ToTreeRefSugar for TNode {
    ///
    /// Creates a new tree node with a particular sibling
    ///
    fn with_sibling<TSibling: ToTreeNode>(&self, new_sibling: TSibling) -> Rc<TreeNode> {
        let sibling_node = new_sibling.to_tree_node();
        self.to_tree_node().with_sibling_ref(&sibling_node)
    }

    ///
    /// Creates a new tree node with no sibling
    ///
    fn with_no_sibling(&self) -> Rc<TreeNode> {
        self.to_tree_node().with_no_sibling_ref()
    }
}

#[cfg(test)]
mod tree_ref_tests {
    use super::*;
    use super::super::treenode::*;

    #[test]
    fn create_with_sibling() {
        let root            = "root".to_tree_node();
        let with_sibling    = root.with_sibling("sibling");
        let no_sibling      = with_sibling.with_no_sibling();

        assert!(root.get_tag() == "root");
        assert!(root.get_sibling_ref().is_none());
        assert!(with_sibling.get_tag() == "root");
        assert!(!with_sibling.get_sibling_ref().is_none());
        assert!(no_sibling.get_sibling_ref().is_none());
    }
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;

use schemes::{Result, KScheme, Resource, Url, VecResource};

pub struct InterruptScheme;

static IRQ_NAME: [&'static str; 15] = [
    "Programmable Interval Timer",
    "Keyboard",
    "Cascade",
    "Serial 2 and 4",
    "Serial 1 and 3",
    "Parallel 2",
    "Floppy",
    "Parallel 1",
    "Realtime Clock",
    "PCI 1",
    "PCI 2",
    "PCI 3",
    "Mouse",
    "Coprocessor",
    "IDE Primary",
    "IDE Secondary",
];

impl KScheme for InterruptScheme {
    fn scheme(&self) -> &str {
        "interrupt"
    }

    fn open(&mut self, _: &Url, _: usize) -> Result<Box<Resource>> {
        let mut string = format!("{:<6}{:<16}{}", "INT", "COUNT", "DESCRIPTION");

        {
            let interrupts = ::env().interrupts.lock();
            for interrupt in 0..interrupts.len() {
                let count = interrupts[interrupt];

                if count > 0 {
                    let description = match interrupt {
                        i @ 0x20 ... 0x30 => IRQ_NAME[i - 0x20],
                        0x80 => "System Call",
                        0x0 => "Divide by zero exception",
                        0x1 => "Debug exception",
                        0x2 => "Non-maskable interrupt",
                        0x3 => "Breakpoint exception",
                        0x4 => "Overflow exception",
                        0x5 => "Bound range exceeded exception",
                        0x6 => "Invalid opcode exception",
                        0x7 => "Device not available exception",
                        0x8 => "Double fault",
                        0xA => "Invalid TSS exception",
                        0xB => "Segment not present exception",
                        0xC => "Stack-segment fault",
                        0xD => "General protection fault",
                        0xE => "Page fault",
                        0x10 => "x87 floating-point exception",
                        0x11 => "Alignment check exception",
                        0x12 => "Machine check exception",
                        0x13 => "SIMD floating-point exception",
                        0x14 => "Virtualization exception",
                        0x1E => "Security exception",
                        _ => "Unknown Interrupt",
                    };

                    string = string + "\n" + &format!("{:<6X}{:<16}{}", interrupt, count, description);
                }
            }
        }

        Ok(box VecResource::new(Url::from_str("interrupt:"), string.into_bytes()))
    }
}
<commit_msg>Fix type mismatch<commit_after>use alloc::boxed::Box;

use schemes::{Result, KScheme, Resource, Url, VecResource};

pub struct InterruptScheme;

static IRQ_NAME: [&'static str; 16] = [
    "Programmable Interval Timer",
    "Keyboard",
    "Cascade",
    "Serial 2 and 4",
    "Serial 1 and 3",
    "Parallel 2",
    "Floppy",
    "Parallel 1",
    "Realtime Clock",
    "PCI 1",
    "PCI 2",
    "PCI 3",
    "Mouse",
    "Coprocessor",
    "IDE Primary",
    "IDE Secondary",
];

impl KScheme for InterruptScheme {
    fn scheme(&self) -> &str {
        "interrupt"
    }

    fn open(&mut self, _: &Url, _: usize) -> Result<Box<Resource>> {
        let mut string = format!("{:<6}{:<16}{}", "INT", "COUNT", "DESCRIPTION");

        {
            let interrupts = ::env().interrupts.lock();
            for interrupt in 0..interrupts.len() {
                let count = interrupts[interrupt];

                if count > 0 {
                    let description = match interrupt {
                        i @ 0x20 ... 0x30 => IRQ_NAME[i - 0x20],
                        0x80 => "System Call",
                        0x0 => "Divide by zero exception",
                        0x1 => "Debug exception",
                        0x2 => "Non-maskable interrupt",
                        0x3 => "Breakpoint exception",
                        0x4 => "Overflow exception",
                        0x5 => "Bound range exceeded exception",
                        0x6 => "Invalid opcode exception",
                        0x7 => "Device not available exception",
                        0x8 => "Double fault",
                        0xA => "Invalid TSS exception",
                        0xB => "Segment not present exception",
                        0xC => "Stack-segment fault",
                        0xD => "General protection fault",
                        0xE => "Page fault",
                        0x10 => "x87 floating-point exception",
                        0x11 => "Alignment check exception",
                        0x12 => "Machine check exception",
                        0x13 => "SIMD floating-point exception",
                        0x14 => "Virtualization exception",
                        0x1E => "Security exception",
                        _ => "Unknown Interrupt",
                    };

                    string = string + "\n" + &format!("{:<6X}{:<16}{}", interrupt, count, description);
                }
            }
        }

        Ok(box VecResource::new(Url::from_str("interrupt:"), string.into_bytes()))
    }
}
<|endoftext|>


<commit_before><commit_msg>fix doc errors in containers.rs<commit_after><|endoftext|>


<commit_before><commit_msg>Working on FLASHCALW driver implementation for ATSAM4L. Implemented the Flash Properties<commit_after>/// FLASHCALW Driver for the SAM4L.

use helpers::*;
use core::mem;

use pm;

// Listing of the FLASHCALW register memory map.
// Section 14.10 of the datasheet
#[repr(C, packed)]
#[allow(dead_code)]
struct Registers {
    control:                          usize,
    command:                          usize,
    status:                           usize,
    parameter:                        usize,
    version:                          usize,
    general_purpose_fuse_register_hi: usize,
    general_purpose_fuse_register_lo: usize,
}

const FLASHCALW_BASE_ADDRS : *mut Registers = 0x400A0000 as *mut Registers;

// This is the pico cache registers...
// TODO: does this get it's own driver... yea....
/*
struct Picocache_Registers {
    picocache_control:                      usize,
    picocache_status:                       usize,
    picocache_maintenance_register_0:       usize,
    picocache_maintenance_register_1:       usize,
    picocache_montior_configuration:        usize,
    picocache_monitor_enable:               usize,
    picocache_monitor_control:              usize,
    picocache_monitor_status:               usize,
    version:                                usize
}
*/

// There are 18 recognized commands possible to command the flash
// Table 14-5.
#[derive(Clone, Copy)]
pub enum FlashCMD {
    NOP,
    WP,
    EP,
    CPB,
    LP,
    UP,
    EA,
    WGPB,
    EGPB,
    SSB,
    PGPFB,
    EAGPF,
    QPR,
    WUP,
    EUP,
    QPRUP,
    HSEN,
    HSDIS,
}

//The two Flash speeds
#[derive(Clone, Copy)]
pub enum Speed {
    Standard,
    HighSpeed
}

// The FLASHCALW controller
//TODO: finishing beefing up...
pub struct FLASHCALW {
    registers: *mut Registers,
    // might make these more specific
    ahb_clock: pm::Clock,
    hramc1_clock: pm::Clock,
    pb_clock: pm::Clock,
    //client: TakeCell...

}

//static instance for the board. Only one FLASHCALW needed / on board.
pub static mut flash_controller : FLASHCALW =
    FLASHCALW::new(FLASHCALW_BASE_ADDRS, pm::HSBClock::FLASHCALW,
        pm::HSBClock::FLASHCALW, pm::PBBClock::FLASHCALW);

// Few constants relating to module configuration.
const FLASH_PAGE_SIZE : usize = 512;
const FLASH_NB_OF_REGIONS : usize = 16;
const FLASHCALW_REGIONS : usize = FLASH_NB_OF_REGIONS;

// TODO: should export this to a board specific module or so... something that gives me size.
const FLASHCALW_SIZE : usize = 512;

impl FLASHCALW {
    const fn new(base_addr: *mut Registers, ahb_clk: pm::HSBClock,
    hramc1_clk: pm::HSBClock, pb_clk: pm::PBBClock) -> FLASHCALW {
        FLASHCALW {
            registers: base_addr,
            ahb_clock: pm::Clock::HSB(ahb_clk),
            hramc1_clock: pm::Clock::HSB(hramc1_clk),
            pb_clock: pm::Clock::HSB(pb_clk),
        }
    }

    /// FLASH properties.
    pub fn get_flash_size(&self) -> u32 {
        FLASHCALW_SIZE
    }

    pub fn get_page_count(&self) -> u32 {
        flashcalw_get_flash_size() / FLASH_PAGE_SIZE
    }

    pub fn get_page_count_per_region(&self) -> u32 {
        flashcalw_get_page_count() / FLASH_NB_OF_REGIONS
    }

    pub fn get_page_number(&self) -> u32 {
        1
        // DUMMY IMPLEMENTATION
    }

    // TODO: implement get_page_number().
    pub fn get_page_region(&self, page_number : i32) -> u32 {
        (if page_number >= 0
            { page_number }
        else
            { flashcalw_get_page_number() as i32 }
        / flashcalw_get_page_count_per_region())
    }

    pub fn get_region_first_page_number(&self, region : u32) -> u32 {
        region * flashcalw_get_page_count_per_region()
    }

    /// FLASHC Control
        //TODO:

    ///FLASHCALW Protection Mechanisms
    pub fn is_security_bit_active(&self) -> bool {
        //think about this more ( get a better design hmmm...)
        (self.registers.status & 0x16) == 1
    }

    pub fn set_security_bit(&self) {
        self.registers.status |=
    }

}

<|endoftext|>


<commit_before><commit_msg>confirm windows build of examples<commit_after><|endoftext|>


<commit_before><commit_msg>updated build.rs to use 'git describe'<commit_after><|endoftext|>


<commit_before><commit_msg>Rewrite from TcpListener to lazy-socket<commit_after><|endoftext|>


<commit_before><commit_msg>add test<commit_after>// build-pass

#![feature(const_trait_impl)]

trait Func<T> {
    type Output;

    fn call_once(self, arg: T) -> Self::Output;
}

struct Closure;

impl const Func<&usize> for Closure {
    type Output = usize;

    fn call_once(self, arg: &usize) -> Self::Output {
        *arg
    }
}

enum Bug<T = [(); Closure.call_once(&0) ]> {
    V(T),
}

fn main() {}
<|endoftext|>


<commit_before><commit_msg>Bump cli version from 0.0.1 to 0.0.2<commit_after><|endoftext|>


<commit_before><commit_msg>Add functions and tests.<commit_after><|endoftext|>


<commit_before><commit_msg>arm: syntax<commit_after><|endoftext|>


<commit_before><commit_msg>Tidy up the Vulkan debug logging to reduce unnecessary clutter<commit_after><|endoftext|>


<commit_before><commit_msg>Strip out email<commit_after><|endoftext|>


<commit_before><commit_msg>Add a test Hello World Iron server<commit_after>use iron::prelude::*;
use iron::status;

/// Test hello world server
pub fn hello_world(_: &mut Request) -> IronResult<Response> {
        Ok(Response::with((status::Ok, "Hello World!")))
}
<|endoftext|>


<commit_before>use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    /// Transform the StoreId object into a PathBuf, error if the base of the StoreId is not
    /// specified.
    pub fn into_pathbuf(self) -> Result<PathBuf> {
        let mut base = try!(self.base.ok_or(SEK::StoreIdHasNoBaseError.into_error()));
        base.push(self.id);
        Ok(base)
    }

    pub fn exists(&self) -> bool {
        // TODO: hiding error here.
        self.clone().into_pathbuf().map(|pb| pb.exists()).unwrap_or(false)
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<commit_msg>Remove StoreId::is_file()<commit_after>use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    /// Transform the StoreId object into a PathBuf, error if the base of the StoreId is not
    /// specified.
    pub fn into_pathbuf(self) -> Result<PathBuf> {
        let mut base = try!(self.base.ok_or(SEK::StoreIdHasNoBaseError.into_error()));
        base.push(self.id);
        Ok(base)
    }

    pub fn exists(&self) -> bool {
        // TODO: hiding error here.
        self.clone().into_pathbuf().map(|pb| pb.exists()).unwrap_or(false)
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use glob::Paths;

/// The Index into the Store
pub type StoreId = PathBuf;

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        self
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(mut self) -> $crate::storeid::StoreId {
                    self.0
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    paths: Paths,
}

impl StoreIdIterator {

    pub fn new(paths: Paths) -> StoreIdIterator {
        StoreIdIterator {
            paths: paths,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.paths.next().and_then(|o| o.ok())
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(),
        "/test/test~0.2.0-alpha+leet1337");
    }

}
<commit_msg>Fix test: StoreId does not start with "/" anymore<commit_after>use std::path::PathBuf;
use glob::Paths;

/// The Index into the Store
pub type StoreId = PathBuf;

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        self
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(mut self) -> $crate::storeid::StoreId {
                    self.0
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    paths: Paths,
}

impl StoreIdIterator {

    pub fn new(paths: Paths) -> StoreIdIterator {
        StoreIdIterator {
            paths: paths,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.paths.next().and_then(|o| o.ok())
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<|endoftext|>


<commit_before><commit_msg>Add solution to problem 72<commit_after>#![feature(core, step_by)]
#[macro_use] extern crate libeuler;

use std::collections::{HashSet, HashMap};

use libeuler::prime::SieveOfAtkin;
/// Consider the fraction, n/d, where n and d are positive integers. If n<d and HCF(n,d)=1, it is
/// called a reduced proper fraction.
///
/// If we list the set of reduced proper fractions for d ≤ 8 in ascending order of size, we get:
///
/// 1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6,
/// 6/7, 7/8
///
/// It can be seen that there are 21 elements in this set.
///
/// How many elements would be contained in the set of reduced proper fractions for d ≤ 1,000,000?
fn main() {
    solutions! {
        inputs: (max_denom: u64 = 1_000_000)

        sol naive {
            let sieve = SieveOfAtkin::new(max_denom * 2);
            let mut nums = (0..(max_denom+1)).collect::<Vec<u64>>();

            let mut result = 0;
            for denom in 2..(max_denom + 1) {
                if nums[denom as usize] == denom {
                    for next in (denom..(max_denom + 1)).step_by(denom) {
                        nums[next as usize] = nums[next as usize] / denom * (denom - 1);
                    }
                }

                result += nums[denom as usize];
            }

            result
        }
    }
}

fn load_powers(memo: &mut HashMap<Vec<u64>, HashSet<u64>>, mut factors: Vec<u64>) -> HashSet<u64> {
    if factors.len() == 0 {
        return {
            let mut ret = HashSet::new();
            ret.insert(1);
            ret
        };
    }

    if memo.contains_key(&factors) {
        return memo[&factors].clone();
    }

    let mut retval = HashSet::new();

    let f = factors.clone();
    while factors.len() > 0 {
        let fact = factors.pop().unwrap();
        for pow in load_powers(memo, factors.clone()) {
            retval.insert(pow);
            retval.insert(pow * fact);
        }
    }

    memo.insert(f, retval.clone());

    retval
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate nom;
extern crate flate2;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

use flate2::read::GzDecoder;
use nom::{be_u8, be_u16, be_u32, be_u64, print, IResult, Needed};

use errors::*;

#[allow(unused_doc_comment)]
mod errors {
    error_chain!{
        foreign_links {
            Io(::std::io::Error);
        }
    }
}

pub struct Message;

pub fn parse_reader<R: Read>(reader: R) -> Result<Vec<Message>> {
    unimplemented!()
}

pub fn parse_gzip<P: AsRef<Path>>(path: P) -> Result<Vec<Message>> {
    let file = File::open(path)?;
    let reader = GzDecoder::new(file)?;
    parse_reader(reader)
}

pub fn parse_file<P: AsRef<Path>>(path: P) -> Result<Vec<Message>> {
    let file = File::open(path)?;
    parse_reader(file)
}

#[derive(Debug, Clone)]
struct SystemEvent {
    tracking_number: u16,
    timestamp: u64,
    event_code: EventCode
}

#[derive(Debug, Clone, Copy)]
enum EventCode {
    StartOfMessages,
    StartOfSystemHours,
    StartOfMarketHours,
    EndOfMarketHours,
    EndOfSystemHours,
    EndOfMessages
}

named!(parse_system_event<SystemEvent>, do_parse!(
    length: be_u16 >> char!('S') >> tag!([0, 0]) >>
    tracking_number: be_u16 >>
    timestamp: be_u48 >>
    event_code: alt!(
        char!('O') => { |_| EventCode::StartOfMessages } |
        char!('S') => { |_| EventCode::StartOfSystemHours } |
        char!('Q') => { |_| EventCode::StartOfMarketHours } |
        char!('M') => { |_| EventCode::EndOfMarketHours } |
        char!('E') => { |_| EventCode::EndOfSystemHours } |
        char!('C') => { |_| EventCode::EndOfMessages }
    ) >>
    (SystemEvent { tracking_number, timestamp, event_code })
));

#[inline]
pub fn be_u48(i: &[u8]) -> IResult<&[u8], u64> {
    if i.len() < 6 {
        IResult::Incomplete(Needed::Size(6))
    } else {
        let res =
            ((i[0] as u64) << 40) +
            ((i[1] as u64) << 32) +
            ((i[2] as u64) << 24) +
            ((i[3] as u64) << 16) +
            ((i[4] as u64) << 8) +
            i[5] as u64;
        IResult::Done(&i[6..], res)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn hex_to_bytes(bytes: &[u8]) -> Vec<u8> {
        fn h2b(h: u8) -> Option<u8> {
            match h {
                v@b'0'...b'9' => Some(v - b'0'),
                v@b'a'...b'f' => Some(v - b'a' + 10),
                b' ' => None,
                _ => panic!("Invalid hex: {}", h as char)
            }
        }
        bytes.iter()
            .filter_map(|b| h2b(*b))
            .collect::<Vec<_>>()
            .chunks(2)
            .map(|slice| (slice[0] << 4) + slice[1])
            .collect()
    }

    #[test]
    fn system_event() {
        let code = b"000c 53 0000 0000 286aab3b3a99 4f";
        let bytes = hex_to_bytes(&code[..]);
        let (_, out) = parse_system_event(&bytes[..]).unwrap();
        println!("{:?}", out);
    }
}
<commit_msg>add streaming parsing<commit_after>#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate nom;
extern crate flate2;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

use flate2::read::GzDecoder;
use nom::{be_u8, be_u16, be_u32, be_u64, print, IResult, Needed};

use errors::*;

const BUFSIZE: usize = 10 * 1024;

#[allow(unused_doc_comment)]
pub mod errors {
    error_chain!{
        foreign_links {
            Io(::std::io::Error);
            Nom(::nom::Err);
        }
    }
}

pub struct MessageStream<R: Read> {
    reader: R,
    buffer: Box<[u8; BUFSIZE]>, // 10Mb buffer
    bufstart: usize,
    bufend: usize
}

impl<R: Read> MessageStream<R> {
    fn new(reader: R) -> MessageStream<R> {
        MessageStream {
            reader,
            buffer: Box::new([0; BUFSIZE]),
            bufstart: 0,
            bufend: 0
        }
    }

    fn fetch_more_bytes(&mut self) -> Result<usize> {
        println!("bufstart: {:?}, bufend: {:?}", self.bufstart, self.bufend);
        if self.bufend == BUFSIZE {
            // we need more data from the reader
            // first, copy the remnants back to the beginning of the buffer
            // (this should only be a few bytes)
            assert!(self.bufstart as usize > BUFSIZE / 2); // safety check
            assert!(BUFSIZE - self.bufstart < 50);         // extra careful check
            {
                let (mut left, right) = self.buffer.split_at_mut(self.bufstart);
                &left[..right.len()].copy_from_slice(&right[..]);
                self.bufstart = 0;
                self.bufend = right.len();
            }

        }
        Ok(self.reader.read(&mut self.buffer[self.bufend..])?)
    }
}

impl<R: Read> Iterator for MessageStream<R> {
    type Item = Result<Message>;

    fn next(&mut self) -> Option<Result<Message>> {
        use IResult::*;
        match parse_message(&self.buffer[self.bufstart..self.bufend]) {
            Done(rest, msg) => {
                self.bufstart = self.bufend - rest.len();
                return Some(Ok(msg))
            }
            Error(e) => return Some(Err(errors::Error::from(e))),
            Incomplete(_) => {
                println!("Incomplete")
                // fall through to below... necessary to appease borrow checker
            }
        }
        match self.fetch_more_bytes() {
            Ok(0) => Some(Err("Unexpected EOF".into())),
            Ok(ct) => {
                self.bufend += ct;
                self.next()
            }
            Err(e) => Some(Err(e))
        }
    }
}

pub fn parse_reader<R: Read>(reader: R) -> MessageStream<R> {
    // We will do the parsing in a streaming fashion because these
    // files are BIG and we don't want to load it all into memory
    MessageStream::new(reader)
}

pub fn parse_gzip<P: AsRef<Path>>(path: P) -> Result<MessageStream<GzDecoder<File>>> {
    let file = File::open(path)?;
    let reader = GzDecoder::new(file)?;
    Ok(parse_reader(reader))
}

pub fn parse_file<P: AsRef<Path>>(path: P) -> Result<MessageStream<File>> {
    let reader = File::open(path)?;
    Ok(parse_reader(reader))
}

#[derive(Debug, Clone, PartialEq)]
pub enum Message {
    SystemEvent {
        tracking_number: u16,
        timestamp: u64,
        event_code: EventCode
    },
    Unknown {
        length: u16,
        tag: char,
        content: Vec<u8>
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EventCode {
    StartOfMessages,
    StartOfSystemHours,
    StartOfMarketHours,
    EndOfMarketHours,
    EndOfSystemHours,
    EndOfMessages
}

named!(parse_message<Message>, do_parse!(
    length: be_u16 >>
    msg: switch!(be_u8,
        b'S' => call!(parse_system_event) |
        other => map!(take!(length - 1),
                      |slice| Message::Unknown {
                          length,
                          tag: other as char,
                          content: Vec::from(slice)
                      })) >>
    (msg)
));

named!(parse_system_event<Message>, do_parse!(
    tag!([0, 0]) >>
    tracking_number: be_u16 >>
    timestamp: be_u48 >>
    event_code: alt!(
        char!('O') => { |_| EventCode::StartOfMessages } |
        char!('S') => { |_| EventCode::StartOfSystemHours } |
        char!('Q') => { |_| EventCode::StartOfMarketHours } |
        char!('M') => { |_| EventCode::EndOfMarketHours } |
        char!('E') => { |_| EventCode::EndOfSystemHours } |
        char!('C') => { |_| EventCode::EndOfMessages }
    ) >>
    (Message::SystemEvent { tracking_number, timestamp, event_code })
));

#[inline]
pub fn be_u48(i: &[u8]) -> IResult<&[u8], u64> {
    if i.len() < 6 {
        IResult::Incomplete(Needed::Size(6))
    } else {
        let res =
            ((i[0] as u64) << 40) +
            ((i[1] as u64) << 32) +
            ((i[2] as u64) << 24) +
            ((i[3] as u64) << 16) +
            ((i[4] as u64) << 8) +
            i[5] as u64;
        IResult::Done(&i[6..], res)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn hex_to_bytes(bytes: &[u8]) -> Vec<u8> {
        fn h2b(h: u8) -> Option<u8> {
            match h {
                v@b'0'...b'9' => Some(v - b'0'),
                v@b'a'...b'f' => Some(v - b'a' + 10),
                b' ' => None,
                _ => panic!("Invalid hex: {}", h as char)
            }
        }
        bytes.iter()
            .filter_map(|b| h2b(*b))
            .collect::<Vec<_>>()
            .chunks(2)
            .map(|slice| (slice[0] << 4) + slice[1])
            .collect()
    }

    #[test]
    fn system_event() {
        let code = b"0000 0000 286aab3b3a99 4f";
        let bytes = hex_to_bytes(&code[..]);
        let (_, out) = parse_system_event(&bytes[..]).unwrap();
        if let Message::SystemEvent{..} = out {
        } else {
            panic!("Expected SystemEvent,  found {:?}", out)
        }
    }

    #[test]
    fn full_parse() {
        let mut iter = parse_file("data/01302016.NASDAQ_ITCH50").unwrap();
        println!("{:?}", iter.next().unwrap().unwrap());
        println!("{:?}", iter.next().unwrap().unwrap());
        println!("{:?}", iter.next().unwrap().unwrap());
        println!("{:?}", iter.next().unwrap().unwrap());
    }
}
<|endoftext|>


<commit_before><commit_msg>build: Fix creating package tarballs<commit_after><|endoftext|>


<commit_before><commit_msg>implement `Clone` for raw pointers<commit_after><|endoftext|>