<commit_before>use {NixResult, NixError, NixPath};
use super::{consts, sa_family_t};
use errno::Errno;
use libc;
use std::{fmt, hash, mem, net, ptr};
use std::ffi::{CStr, OsStr};
use std::num::Int;
use std::path::Path;
use std::os::unix::OsStrExt;

/*
 *
 * ===== AddressFamily =====
 *
 */

#[repr(i32)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum AddressFamily {
    Unix = consts::AF_UNIX,
    Inet = consts::AF_INET,
    Inet6 = consts::AF_INET6,
}

#[derive(Copy)]
pub enum InetAddr {
    V4(libc::sockaddr_in),
    V6(libc::sockaddr_in6),
}

impl InetAddr {
    pub fn from_std(std: &net::SocketAddr) -> InetAddr {
        InetAddr::new(IpAddr::from_std(&std.ip()), std.port())
    }

    pub fn new(ip: IpAddr, port: u16) -> InetAddr {
        match ip {
            IpAddr::V4(ref ip) => {
                InetAddr::V4(libc::sockaddr_in {
                    sin_family: AddressFamily::Inet as sa_family_t,
                    sin_port: port.to_be(),
                    sin_addr: ip.0,
                    .. unsafe { mem::zeroed() }
                })
            }
            IpAddr::V6(ref ip) => {
                InetAddr::V6(libc::sockaddr_in6 {
                    sin6_family: AddressFamily::Inet6 as sa_family_t,
                    sin6_port: port.to_be(),
                    sin6_addr: ip.0,
                    .. unsafe { mem::zeroed() }
                })
            }
        }
    }

    /// Gets the IP address associated with this socket address.
    pub fn ip(&self) -> IpAddr {
        match *self {
            InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
            InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
        }
    }

    /// Gets the port number associated with this socket address
    pub fn port(&self) -> u16 {
        match *self {
            InetAddr::V6(ref sa) => Int::from_be(sa.sin6_port),
            InetAddr::V4(ref sa) => Int::from_be(sa.sin_port),
        }
    }

    pub fn to_std(&self) -> net::SocketAddr {
        net::SocketAddr::new(self.ip().to_std(), self.port())
    }

    pub fn to_str(&self) -> String {
        format!("{}", self)
    }
}

impl PartialEq for InetAddr {
    fn eq(&self, other: &InetAddr) -> bool {
        match (*self, *other) {
            (InetAddr::V4(ref a), InetAddr::V4(ref b)) => {
                a.sin_port == b.sin_port &&
                    a.sin_addr.s_addr == b.sin_addr.s_addr
            }
            (InetAddr::V6(ref a), InetAddr::V6(ref b)) => {
                a.sin6_port == b.sin6_port &&
                    a.sin6_addr.s6_addr == b.sin6_addr.s6_addr &&
                    a.sin6_flowinfo == b.sin6_flowinfo &&
                    a.sin6_scope_id == b.sin6_scope_id
            }
            _ => false,
        }
    }
}

impl Eq for InetAddr {
}

impl hash::Hash for InetAddr {
    fn hash<H: hash::Hasher>(&self, s: &mut H) {
        match *self {
            InetAddr::V4(ref a) => {
                ( a.sin_family,
                  a.sin_port,
                  a.sin_addr.s_addr ).hash(s)
            }
            InetAddr::V6(ref a) => {
                ( a.sin6_family,
                  a.sin6_port,
                  &a.sin6_addr.s6_addr,
                  a.sin6_flowinfo,
                  a.sin6_scope_id ).hash(s)
            }
        }
    }
}

impl Clone for InetAddr {
    fn clone(&self) -> InetAddr {
        *self
    }
}

impl fmt::Display for InetAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
            InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
        }
    }
}

/*
 *
 * ===== IpAddr =====
 *
 */

pub enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}

impl IpAddr {
    /// Create a new IpAddr that contains an IPv4 address.
    ///
    /// The result will represent the IP address a.b.c.d
    pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
        IpAddr::V4(Ipv4Addr::new(a, b, c, d))
    }

    /// Create a new IpAddr that contains an IPv6 address.
    ///
    /// The result will represent the IP address a:b:c:d:e:f
    pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
        IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
    }

    pub fn from_std(std: &net::IpAddr) -> IpAddr {
        match *std {
            net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
            net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
        }
    }

    pub fn to_std(&self) -> net::IpAddr {
        match *self {
            IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
            IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
        }
    }
}

impl fmt::Display for IpAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            IpAddr::V4(ref v4) => v4.fmt(f),
            IpAddr::V6(ref v6) => v6.fmt(f)
        }
    }
}

/*
 *
 * ===== Ipv4Addr =====
 *
 */

#[derive(Copy)]
pub struct Ipv4Addr(pub libc::in_addr);

impl Ipv4Addr {
    pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
        let ip = (((a as u32) << 24) |
                  ((b as u32) << 16) |
                  ((c as u32) <<  8) |
                  ((d as u32) <<  0)).to_be();

        Ipv4Addr(libc::in_addr { s_addr: ip })
    }

    pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
        let bits = std.octets();
        Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
    }

    pub fn any() -> Ipv4Addr {
        Ipv4Addr(libc::in_addr { s_addr: consts::INADDR_ANY })
    }

    pub fn octets(&self) -> [u8; 4] {
        let bits = Int::from_be(self.0.s_addr);
        [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
    }

    pub fn to_std(&self) -> net::Ipv4Addr {
        let bits = self.octets();
        net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
    }
}

impl PartialEq for Ipv4Addr {
    fn eq(&self, other: &Ipv4Addr) -> bool {
        self.0.s_addr == other.0.s_addr
    }
}

impl Eq for Ipv4Addr {
}

impl hash::Hash for Ipv4Addr {
    fn hash<H: hash::Hasher>(&self, s: &mut H) {
        self.0.s_addr.hash(s)
    }
}

impl Clone for Ipv4Addr {
    fn clone(&self) -> Ipv4Addr {
        *self
    }
}

impl fmt::Display for Ipv4Addr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let octets = self.octets();
        write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
    }
}

/*
 *
 * ===== Ipv6Addr =====
 *
 */

#[derive(Copy)]
pub struct Ipv6Addr(pub libc::in6_addr);

impl Ipv6Addr {
    pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
        Ipv6Addr(libc::in6_addr {
            s6_addr: [
                a.to_be(),
                b.to_be(),
                c.to_be(),
                d.to_be(),
                e.to_be(),
                f.to_be(),
                g.to_be(),
                h.to_be(),
            ]
        })
    }

    pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
        let s = std.segments();
        Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
    }

    /// Return the eight 16-bit segments that make up this address
    pub fn segments(&self) -> [u16; 8] {
        [Int::from_be(self.0.s6_addr[0]),
         Int::from_be(self.0.s6_addr[1]),
         Int::from_be(self.0.s6_addr[2]),
         Int::from_be(self.0.s6_addr[3]),
         Int::from_be(self.0.s6_addr[4]),
         Int::from_be(self.0.s6_addr[5]),
         Int::from_be(self.0.s6_addr[6]),
         Int::from_be(self.0.s6_addr[7])]
    }

    pub fn to_std(&self) -> net::Ipv6Addr {
        let s = self.segments();
        net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
    }
}

impl fmt::Display for Ipv6Addr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.to_std().fmt(fmt)
    }
}

/*
 *
 * ===== UnixAddr =====
 *
 */

#[derive(Copy)]
pub struct UnixAddr(pub libc::sockaddr_un);

impl UnixAddr {
    pub fn new<P: ?Sized + NixPath>(path: &P) -> NixResult<UnixAddr> {
        try!(path.with_nix_path(|osstr| {
            unsafe {
                let bytes = osstr.as_bytes();

                let mut ret = libc::sockaddr_un {
                    sun_family: AddressFamily::Unix as sa_family_t,
                    .. mem::zeroed()
                };

                if bytes.len() >= ret.sun_path.len() {
                    return Err(NixError::Sys(Errno::ENAMETOOLONG));
                }

                ptr::copy(
                    ret.sun_path.as_mut_ptr(),
                    bytes.as_ptr() as *const i8,
                    bytes.len());

                Ok(UnixAddr(ret))
            }
        }))
    }

    pub fn path(&self) -> &Path {
        unsafe {
            let bytes = CStr::from_ptr(self.0.sun_path.as_ptr()).to_bytes();
            Path::new(<OsStr as OsStrExt>::from_bytes(bytes))
        }
    }
}

impl PartialEq for UnixAddr {
    fn eq(&self, other: &UnixAddr) -> bool {
        unsafe {
            0 == libc::strcmp(self.0.sun_path.as_ptr(), other.0.sun_path.as_ptr())
        }
    }
}

impl Eq for UnixAddr {
}

impl hash::Hash for UnixAddr {
    fn hash<H: hash::Hasher>(&self, s: &mut H) {
        ( self.0.sun_family, self.path() ).hash(s)
    }
}

impl Clone for UnixAddr {
    fn clone(&self) -> UnixAddr {
        *self
    }
}

impl fmt::Display for UnixAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.path().display().fmt(f)
    }
}

/*
 *
 * ===== Sock addr =====
 *
 */

/// Represents a socket address
#[derive(Copy)]
pub enum SockAddr {
    Inet(InetAddr),
    Unix(UnixAddr)
}

impl SockAddr {
    pub fn new_inet(addr: InetAddr) -> SockAddr {
        SockAddr::Inet(addr)
    }

    pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> NixResult<SockAddr> {
        Ok(SockAddr::Unix(try!(UnixAddr::new(path))))
    }

    pub fn family(&self) -> AddressFamily {
        match *self {
            SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
            SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
            SockAddr::Unix(..) => AddressFamily::Unix,
        }
    }

    pub fn to_str(&self) -> String {
        format!("{}", self)
    }

    pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
        match *self {
            SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t),
            SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t),
            SockAddr::Unix(UnixAddr(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_un>() as libc::socklen_t),
        }
    }
}

impl PartialEq for SockAddr {
    fn eq(&self, other: &SockAddr) -> bool {
        match (*self, *other) {
            (SockAddr::Inet(ref a), SockAddr::Inet(ref b)) => {
                a == b
            }
            (SockAddr::Unix(ref a), SockAddr::Unix(ref b)) => {
                a == b
            }
            _ => false,
        }
    }
}

impl Eq for SockAddr {
}

impl hash::Hash for SockAddr {
    fn hash<H: hash::Hasher>(&self, s: &mut H) {
        match *self {
            SockAddr::Inet(ref a) => a.hash(s),
            SockAddr::Unix(ref a) => a.hash(s),
        }
    }
}

impl Clone for SockAddr {
    fn clone(&self) -> SockAddr {
        *self
    }
}

impl fmt::Display for SockAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SockAddr::Inet(ref inet) => inet.fmt(f),
            SockAddr::Unix(ref unix) => unix.fmt(f),
        }
    }
}
<commit_msg>Derive FromPrimitive for AddressFamily.<commit_after>use {NixResult, NixError, NixPath};
use super::{consts, sa_family_t};
use errno::Errno;
use libc;
use std::{fmt, hash, mem, net, ptr};
use std::ffi::{CStr, OsStr};
use std::num::Int;
use std::path::Path;
use std::os::unix::OsStrExt;

/*
 *
 * ===== AddressFamily =====
 *
 */

#[repr(i32)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, FromPrimitive)]
pub enum AddressFamily {
    Unix = consts::AF_UNIX,
    Inet = consts::AF_INET,
    Inet6 = consts::AF_INET6,
}

#[derive(Copy)]
pub enum InetAddr {
    V4(libc::sockaddr_in),
    V6(libc::sockaddr_in6),
}

impl InetAddr {
    pub fn from_std(std: &net::SocketAddr) -> InetAddr {
        InetAddr::new(IpAddr::from_std(&std.ip()), std.port())
    }

    pub fn new(ip: IpAddr, port: u16) -> InetAddr {
        match ip {
            IpAddr::V4(ref ip) => {
                InetAddr::V4(libc::sockaddr_in {
                    sin_family: AddressFamily::Inet as sa_family_t,
                    sin_port: port.to_be(),
                    sin_addr: ip.0,
                    .. unsafe { mem::zeroed() }
                })
            }
            IpAddr::V6(ref ip) => {
                InetAddr::V6(libc::sockaddr_in6 {
                    sin6_family: AddressFamily::Inet6 as sa_family_t,
                    sin6_port: port.to_be(),
                    sin6_addr: ip.0,
                    .. unsafe { mem::zeroed() }
                })
            }
        }
    }

    /// Gets the IP address associated with this socket address.
    pub fn ip(&self) -> IpAddr {
        match *self {
            InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
            InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
        }
    }

    /// Gets the port number associated with this socket address
    pub fn port(&self) -> u16 {
        match *self {
            InetAddr::V6(ref sa) => Int::from_be(sa.sin6_port),
            InetAddr::V4(ref sa) => Int::from_be(sa.sin_port),
        }
    }

    pub fn to_std(&self) -> net::SocketAddr {
        net::SocketAddr::new(self.ip().to_std(), self.port())
    }

    pub fn to_str(&self) -> String {
        format!("{}", self)
    }
}

impl PartialEq for InetAddr {
    fn eq(&self, other: &InetAddr) -> bool {
        match (*self, *other) {
            (InetAddr::V4(ref a), InetAddr::V4(ref b)) => {
                a.sin_port == b.sin_port &&
                    a.sin_addr.s_addr == b.sin_addr.s_addr
            }
            (InetAddr::V6(ref a), InetAddr::V6(ref b)) => {
                a.sin6_port == b.sin6_port &&
                    a.sin6_addr.s6_addr == b.sin6_addr.s6_addr &&
                    a.sin6_flowinfo == b.sin6_flowinfo &&
                    a.sin6_scope_id == b.sin6_scope_id
            }
            _ => false,
        }
    }
}

impl Eq for InetAddr {
}

impl hash::Hash for InetAddr {
    fn hash<H: hash::Hasher>(&self, s: &mut H) {
        match *self {
            InetAddr::V4(ref a) => {
                ( a.sin_family,
                  a.sin_port,
                  a.sin_addr.s_addr ).hash(s)
            }
            InetAddr::V6(ref a) => {
                ( a.sin6_family,
                  a.sin6_port,
                  &a.sin6_addr.s6_addr,
                  a.sin6_flowinfo,
                  a.sin6_scope_id ).hash(s)
            }
        }
    }
}

impl Clone for InetAddr {
    fn clone(&self) -> InetAddr {
        *self
    }
}

impl fmt::Display for InetAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
            InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
        }
    }
}

/*
 *
 * ===== IpAddr =====
 *
 */

pub enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}

impl IpAddr {
    /// Create a new IpAddr that contains an IPv4 address.
    ///
    /// The result will represent the IP address a.b.c.d
    pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
        IpAddr::V4(Ipv4Addr::new(a, b, c, d))
    }

    /// Create a new IpAddr that contains an IPv6 address.
    ///
    /// The result will represent the IP address a:b:c:d:e:f
    pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
        IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
    }

    pub fn from_std(std: &net::IpAddr) -> IpAddr {
        match *std {
            net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
            net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
        }
    }

    pub fn to_std(&self) -> net::IpAddr {
        match *self {
            IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
            IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
        }
    }
}

impl fmt::Display for IpAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            IpAddr::V4(ref v4) => v4.fmt(f),
            IpAddr::V6(ref v6) => v6.fmt(f)
        }
    }
}

/*
 *
 * ===== Ipv4Addr =====
 *
 */

#[derive(Copy)]
pub struct Ipv4Addr(pub libc::in_addr);

impl Ipv4Addr {
    pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
        let ip = (((a as u32) << 24) |
                  ((b as u32) << 16) |
                  ((c as u32) <<  8) |
                  ((d as u32) <<  0)).to_be();

        Ipv4Addr(libc::in_addr { s_addr: ip })
    }

    pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
        let bits = std.octets();
        Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
    }

    pub fn any() -> Ipv4Addr {
        Ipv4Addr(libc::in_addr { s_addr: consts::INADDR_ANY })
    }

    pub fn octets(&self) -> [u8; 4] {
        let bits = Int::from_be(self.0.s_addr);
        [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
    }

    pub fn to_std(&self) -> net::Ipv4Addr {
        let bits = self.octets();
        net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
    }
}

impl PartialEq for Ipv4Addr {
    fn eq(&self, other: &Ipv4Addr) -> bool {
        self.0.s_addr == other.0.s_addr
    }
}

impl Eq for Ipv4Addr {
}

impl hash::Hash for Ipv4Addr {
    fn hash<H: hash::Hasher>(&self, s: &mut H) {
        self.0.s_addr.hash(s)
    }
}

impl Clone for Ipv4Addr {
    fn clone(&self) -> Ipv4Addr {
        *self
    }
}

impl fmt::Display for Ipv4Addr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let octets = self.octets();
        write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
    }
}

/*
 *
 * ===== Ipv6Addr =====
 *
 */

#[derive(Copy)]
pub struct Ipv6Addr(pub libc::in6_addr);

impl Ipv6Addr {
    pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
        Ipv6Addr(libc::in6_addr {
            s6_addr: [
                a.to_be(),
                b.to_be(),
                c.to_be(),
                d.to_be(),
                e.to_be(),
                f.to_be(),
                g.to_be(),
                h.to_be(),
            ]
        })
    }

    pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
        let s = std.segments();
        Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
    }

    /// Return the eight 16-bit segments that make up this address
    pub fn segments(&self) -> [u16; 8] {
        [Int::from_be(self.0.s6_addr[0]),
         Int::from_be(self.0.s6_addr[1]),
         Int::from_be(self.0.s6_addr[2]),
         Int::from_be(self.0.s6_addr[3]),
         Int::from_be(self.0.s6_addr[4]),
         Int::from_be(self.0.s6_addr[5]),
         Int::from_be(self.0.s6_addr[6]),
         Int::from_be(self.0.s6_addr[7])]
    }

    pub fn to_std(&self) -> net::Ipv6Addr {
        let s = self.segments();
        net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
    }
}

impl fmt::Display for Ipv6Addr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.to_std().fmt(fmt)
    }
}

/*
 *
 * ===== UnixAddr =====
 *
 */

#[derive(Copy)]
pub struct UnixAddr(pub libc::sockaddr_un);

impl UnixAddr {
    pub fn new<P: ?Sized + NixPath>(path: &P) -> NixResult<UnixAddr> {
        try!(path.with_nix_path(|osstr| {
            unsafe {
                let bytes = osstr.as_bytes();

                let mut ret = libc::sockaddr_un {
                    sun_family: AddressFamily::Unix as sa_family_t,
                    .. mem::zeroed()
                };

                if bytes.len() >= ret.sun_path.len() {
                    return Err(NixError::Sys(Errno::ENAMETOOLONG));
                }

                ptr::copy(
                    ret.sun_path.as_mut_ptr(),
                    bytes.as_ptr() as *const i8,
                    bytes.len());

                Ok(UnixAddr(ret))
            }
        }))
    }

    pub fn path(&self) -> &Path {
        unsafe {
            let bytes = CStr::from_ptr(self.0.sun_path.as_ptr()).to_bytes();
            Path::new(<OsStr as OsStrExt>::from_bytes(bytes))
        }
    }
}

impl PartialEq for UnixAddr {
    fn eq(&self, other: &UnixAddr) -> bool {
        unsafe {
            0 == libc::strcmp(self.0.sun_path.as_ptr(), other.0.sun_path.as_ptr())
        }
    }
}

impl Eq for UnixAddr {
}

impl hash::Hash for UnixAddr {
    fn hash<H: hash::Hasher>(&self, s: &mut H) {
        ( self.0.sun_family, self.path() ).hash(s)
    }
}

impl Clone for UnixAddr {
    fn clone(&self) -> UnixAddr {
        *self
    }
}

impl fmt::Display for UnixAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.path().display().fmt(f)
    }
}

/*
 *
 * ===== Sock addr =====
 *
 */

/// Represents a socket address
#[derive(Copy)]
pub enum SockAddr {
    Inet(InetAddr),
    Unix(UnixAddr)
}

impl SockAddr {
    pub fn new_inet(addr: InetAddr) -> SockAddr {
        SockAddr::Inet(addr)
    }

    pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> NixResult<SockAddr> {
        Ok(SockAddr::Unix(try!(UnixAddr::new(path))))
    }

    pub fn family(&self) -> AddressFamily {
        match *self {
            SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
            SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
            SockAddr::Unix(..) => AddressFamily::Unix,
        }
    }

    pub fn to_str(&self) -> String {
        format!("{}", self)
    }

    pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
        match *self {
            SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t),
            SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t),
            SockAddr::Unix(UnixAddr(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_un>() as libc::socklen_t),
        }
    }
}

impl PartialEq for SockAddr {
    fn eq(&self, other: &SockAddr) -> bool {
        match (*self, *other) {
            (SockAddr::Inet(ref a), SockAddr::Inet(ref b)) => {
                a == b
            }
            (SockAddr::Unix(ref a), SockAddr::Unix(ref b)) => {
                a == b
            }
            _ => false,
        }
    }
}

impl Eq for SockAddr {
}

impl hash::Hash for SockAddr {
    fn hash<H: hash::Hasher>(&self, s: &mut H) {
        match *self {
            SockAddr::Inet(ref a) => a.hash(s),
            SockAddr::Unix(ref a) => a.hash(s),
        }
    }
}

impl Clone for SockAddr {
    fn clone(&self) -> SockAddr {
        *self
    }
}

impl fmt::Display for SockAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SockAddr::Inet(ref inet) => inet.fmt(f),
            SockAddr::Unix(ref unix) => unix.fmt(f),
        }
    }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]

#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_variables)]

#[macro_use] extern crate lazy_static;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::{ Path, PathBuf };

lazy_static! {
    static ref HOME: PathBuf = std::env::home_dir().unwrap();

    static ref build_props: PathBuf = PathBuf::from("project/build.properties");

    static ref sbt_launch_dir: PathBuf = { let mut p = PathBuf::from(&*HOME); p.push(".sbt/launchers"); p };

    static ref script_name: String = {
        let n = std::env::args().nth(0).unwrap();
        let n = Path::new(&n).file_name().unwrap().to_str().unwrap();
        n.to_string()
    };

}

const sbt_launch_ivy_release_repo: &'static str = "http://repo.typesafe.com/typesafe/ivy-releases";
const sbt_launch_mvn_release_repo: &'static str = "http://repo.scala-sbt.org/scalasbt/maven-releases";

macro_rules! echoerr(($($arg:tt)*) => (writeln!(&mut ::std::io::stderr(), $($arg)*).unwrap();));

fn die(s: &str) { println!("Aborting: {}", s); std::process::exit(1) }

fn build_props_sbt() -> String {
    if let Ok(f) = File::open(&*build_props) {
        let f = BufReader::new(f);
        for line in f.lines() {
            let line = line.unwrap();
            if line.starts_with("sbt.version") {
                let line = line.replace("=", " ");
                let line = line.replace("\r", " ");
                return line.split_whitespace().nth(1).unwrap().to_owned();
            }
        }
    }
    "".to_owned()
}

fn jar_file(version: &str) -> PathBuf {
    let mut p = PathBuf::from(&*sbt_launch_dir);
    p.push(version);
    p.push("sbt-launch.jar");
    p
}

fn url_base(version: &str) -> &'static str { match version {
    s if s.starts_with("0.7.")  => "http://simple-build-tool.googlecode.com",
    s if s.starts_with("0.10.") => sbt_launch_ivy_release_repo,
    "0.11.1" | "0.11.2"         => sbt_launch_ivy_release_repo,
 // "0.*-yyyymmdd-hhMMss"       => sbt_launch_ivy_snapshot_repo, // https://repo.scala-sbt.org/scalasbt/ivy-snapshots
    s if s.starts_with("0.")    => sbt_launch_ivy_release_repo,
 // "*-yyyymmdd-hhMMss"         => sbt_launch_mvn_snapshot_repo, // http://repo.scala-sbt.org/scalasbt/maven-snapshots
    _                           => sbt_launch_mvn_release_repo,
} }

fn make_url(version: &str) -> String {
    let base = url_base(version);
    match version {
        s if s.starts_with("0.7.")  => format!("{}/files/sbt-launch-0.7.7.jar", base),
        s if s.starts_with("0.10.") => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        "0.11.1" | "0.11.2"         => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        s if s.starts_with("0.")    => format!("{}/org.scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        _                           => format!("{}/org/scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
    }
}

fn download_url(sbt_version: &str, url: &str, jar: &Path) -> bool {
    echoerr!("Downloading sbt launcher for {}:", sbt_version);
    echoerr!("  From  {}", url);
    echoerr!("    To  {}", jar.display());

    std::fs::create_dir_all(jar.parent().unwrap()).unwrap();

    extern crate hyper;
    let mut r = BufReader::new(hyper::client::Client::new().get(url).send().unwrap());
    let mut buf = [0; 16384];
    let mut jar2 = std::io::BufWriter::new(File::create(jar).unwrap());
    while {
        let bc = r.read(&mut buf).unwrap();
        jar2.write(&buf[0..bc]).unwrap();
        bc > 0
    } {}
    jar2.flush().unwrap();
    File::open(jar).is_ok()
}

struct App {
           sbt_jar: PathBuf,
       sbt_version: String,
           verbose: bool,
          java_cmd: String,
    extra_jvm_opts: Vec<String>,
         java_args: Vec<String>,
      sbt_commands: Vec<String>,
     residual_args: Vec<String>,
}

impl App {
    fn new() -> App {
        App {
                 sbt_jar: PathBuf::new(),
             sbt_version: Default::default(),
                 verbose: Default::default(),
                java_cmd: "java".into(),
          extra_jvm_opts: vec!["-Xms512m".into(), "-Xmx1536m".into(), "-Xss2m".into()],
               java_args: Default::default(),
            sbt_commands: Default::default(),
           residual_args: Default::default(),
        }
    }

    fn vlog(&self, s: &str) -> bool { if self.verbose { echoerr!("{}", s); true } else { false } }

    fn set_sbt_version(&mut self) {
        self.sbt_version=build_props_sbt();
        // sbt_version="${sbt_explicit_version:-$(build_props_sbt)}"
        // [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version
    }

    fn add_java(&mut self, s: &str) {
        self.vlog(&format!("[add_java] arg = {}", s));
        self.java_args.push(s.into());
    }

    fn add_residual(&mut self, s: &str) {
        self.vlog(&format!("[residual] arg = {}", s));
        self.residual_args.push(s.into());
    }

    fn add_debugger(&mut self, port: u16) {
        self.add_java("-Xdebug");
        self.add_java(&format!("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address={}", port));
    }

    fn process_args(&mut self) {
        fn require_arg(tpe: &str, opt: &str, arg: &str) {
            if arg.is_empty() || &arg[0..1] == "-" {
                die(&format!("{} requires <{}> argument", opt, tpe));
            }
        }
        let args = std::env::args();
        let mut args = args.skip(1); // skip the path of the executable
        while let Some(arg) = args.next() {
            let mut next = || -> String { args.next().unwrap_or("".into()) };
            let arg = arg.as_ref();
            match arg {
                "-v"         => self.verbose = true,
                "-jvm-debug" => { let next = next(); require_arg("port", arg, &next); self.add_debugger(next.parse().unwrap()) },
                s            => self.add_residual(s),
            }
        }
    }

    fn acquire_sbt_jar(&mut self) -> bool {
        ({
            self.sbt_jar = jar_file(&self.sbt_version);
            File::open(self.sbt_jar.as_path()).is_ok()
        }) || ({
            self.sbt_jar = PathBuf::from(&*HOME);
            self.sbt_jar.push(format!(".ivy2/local/org.scala-sbt/sbt-launch/{}/jars/sbt-launch.jar", self.sbt_version));
            File::open(self.sbt_jar.as_path()).is_ok()
        }) || ({
            self.sbt_jar = jar_file(&self.sbt_version);
            download_url(&self.sbt_version, &make_url(&self.sbt_version), &self.sbt_jar)
        })
    }

    fn exec_runner<S: AsRef<OsStr>>(&self, args: &[S]) {
        self.vlog("# Executing command line:") && {
            for arg in args {
                let arg = arg.as_ref();
                if !arg.is_empty() {
                    let arg = arg.to_string_lossy();
                    if arg.contains(" ") {
                        echoerr!("\"{}\"", arg);
                    } else {
                        echoerr!("{}", arg);
                    }
                }
            }
            self.vlog("")
        };

        use std::os::unix::process::CommandExt;
        let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
        println!("error: {}", err);
        if let Some(err) = err.raw_os_error() {
            std::process::exit(err);
        }
        std::process::exit(-1)
    }

    fn run(&mut self) {
        let argument_count = self.residual_args.len();

        self.set_sbt_version();

        if argument_count == 0 {
            self.vlog(&format!("Starting {}: invoke with -help for other options", *script_name));
            self.residual_args = vec!["shell".into()];
        }

        // no jar? download it.
        File::open(self.sbt_jar.as_path()).is_ok() || self.acquire_sbt_jar() || {
            // still no jar? uh-oh.
            println!("Download failed. Obtain the jar manually and place it at {}", self.sbt_jar.display());
            std::process::exit(1);
        };

        let mut exec_args: Vec<&OsStr> = Vec::new();
        exec_args.push(self.java_cmd.as_ref());
        exec_args.append(&mut self.extra_jvm_opts.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.java_args.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut vec!["-jar".as_ref(), self.sbt_jar.as_ref()]);
        exec_args.append(&mut self.sbt_commands.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.residual_args.iter().map(AsRef::as_ref).collect());

        self.exec_runner(&exec_args)
    }
}

fn main() {
    let mut app = App::new();
    app.process_args();
    app.run()
}
<commit_msg>Comment allows out<commit_after>#![allow(non_upper_case_globals)]

//#![allow(dead_code)]
//#![allow(unused_assignments)]
//#![allow(unused_variables)]

#[macro_use] extern crate lazy_static;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::{ Path, PathBuf };

lazy_static! {
    static ref HOME: PathBuf = std::env::home_dir().unwrap();

    static ref build_props: PathBuf = PathBuf::from("project/build.properties");

    static ref sbt_launch_dir: PathBuf = { let mut p = PathBuf::from(&*HOME); p.push(".sbt/launchers"); p };

    static ref script_name: String = {
        let n = std::env::args().nth(0).unwrap();
        let n = Path::new(&n).file_name().unwrap().to_str().unwrap();
        n.to_string()
    };

}

const sbt_launch_ivy_release_repo: &'static str = "http://repo.typesafe.com/typesafe/ivy-releases";
const sbt_launch_mvn_release_repo: &'static str = "http://repo.scala-sbt.org/scalasbt/maven-releases";

macro_rules! echoerr(($($arg:tt)*) => (writeln!(&mut ::std::io::stderr(), $($arg)*).unwrap();));

fn die(s: &str) { println!("Aborting: {}", s); std::process::exit(1) }

fn build_props_sbt() -> String {
    if let Ok(f) = File::open(&*build_props) {
        let f = BufReader::new(f);
        for line in f.lines() {
            let line = line.unwrap();
            if line.starts_with("sbt.version") {
                let line = line.replace("=", " ");
                let line = line.replace("\r", " ");
                return line.split_whitespace().nth(1).unwrap().to_owned();
            }
        }
    }
    "".to_owned()
}

fn jar_file(version: &str) -> PathBuf {
    let mut p = PathBuf::from(&*sbt_launch_dir);
    p.push(version);
    p.push("sbt-launch.jar");
    p
}

fn url_base(version: &str) -> &'static str { match version {
    s if s.starts_with("0.7.")  => "http://simple-build-tool.googlecode.com",
    s if s.starts_with("0.10.") => sbt_launch_ivy_release_repo,
    "0.11.1" | "0.11.2"         => sbt_launch_ivy_release_repo,
 // "0.*-yyyymmdd-hhMMss"       => sbt_launch_ivy_snapshot_repo, // https://repo.scala-sbt.org/scalasbt/ivy-snapshots
    s if s.starts_with("0.")    => sbt_launch_ivy_release_repo,
 // "*-yyyymmdd-hhMMss"         => sbt_launch_mvn_snapshot_repo, // http://repo.scala-sbt.org/scalasbt/maven-snapshots
    _                           => sbt_launch_mvn_release_repo,
} }

fn make_url(version: &str) -> String {
    let base = url_base(version);
    match version {
        s if s.starts_with("0.7.")  => format!("{}/files/sbt-launch-0.7.7.jar", base),
        s if s.starts_with("0.10.") => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        "0.11.1" | "0.11.2"         => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        s if s.starts_with("0.")    => format!("{}/org.scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        _                           => format!("{}/org/scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
    }
}

fn download_url(sbt_version: &str, url: &str, jar: &Path) -> bool {
    echoerr!("Downloading sbt launcher for {}:", sbt_version);
    echoerr!("  From  {}", url);
    echoerr!("    To  {}", jar.display());

    std::fs::create_dir_all(jar.parent().unwrap()).unwrap();

    extern crate hyper;
    let mut r = BufReader::new(hyper::client::Client::new().get(url).send().unwrap());
    let mut buf = [0; 16384];
    let mut jar2 = std::io::BufWriter::new(File::create(jar).unwrap());
    while {
        let bc = r.read(&mut buf).unwrap();
        jar2.write(&buf[0..bc]).unwrap();
        bc > 0
    } {}
    jar2.flush().unwrap();
    File::open(jar).is_ok()
}

struct App {
           sbt_jar: PathBuf,
       sbt_version: String,
           verbose: bool,
          java_cmd: String,
    extra_jvm_opts: Vec<String>,
         java_args: Vec<String>,
      sbt_commands: Vec<String>,
     residual_args: Vec<String>,
}

impl App {
    fn new() -> App {
        App {
                 sbt_jar: PathBuf::new(),
             sbt_version: Default::default(),
                 verbose: Default::default(),
                java_cmd: "java".into(),
          extra_jvm_opts: vec!["-Xms512m".into(), "-Xmx1536m".into(), "-Xss2m".into()],
               java_args: Default::default(),
            sbt_commands: Default::default(),
           residual_args: Default::default(),
        }
    }

    fn vlog(&self, s: &str) -> bool { if self.verbose { echoerr!("{}", s); true } else { false } }

    fn set_sbt_version(&mut self) {
        self.sbt_version=build_props_sbt();
        // sbt_version="${sbt_explicit_version:-$(build_props_sbt)}"
        // [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version
    }

    fn add_java(&mut self, s: &str) {
        self.vlog(&format!("[add_java] arg = {}", s));
        self.java_args.push(s.into());
    }

    fn add_residual(&mut self, s: &str) {
        self.vlog(&format!("[residual] arg = {}", s));
        self.residual_args.push(s.into());
    }

    fn add_debugger(&mut self, port: u16) {
        self.add_java("-Xdebug");
        self.add_java(&format!("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address={}", port));
    }

    fn process_args(&mut self) {
        fn require_arg(tpe: &str, opt: &str, arg: &str) {
            if arg.is_empty() || &arg[0..1] == "-" {
                die(&format!("{} requires <{}> argument", opt, tpe));
            }
        }
        let args = std::env::args();
        let mut args = args.skip(1); // skip the path of the executable
        while let Some(arg) = args.next() {
            let mut next = || -> String { args.next().unwrap_or("".into()) };
            let arg = arg.as_ref();
            match arg {
                "-v"         => self.verbose = true,
                "-jvm-debug" => { let next = next(); require_arg("port", arg, &next); self.add_debugger(next.parse().unwrap()) },
                s            => self.add_residual(s),
            }
        }
    }

    fn acquire_sbt_jar(&mut self) -> bool {
        ({
            self.sbt_jar = jar_file(&self.sbt_version);
            File::open(self.sbt_jar.as_path()).is_ok()
        }) || ({
            self.sbt_jar = PathBuf::from(&*HOME);
            self.sbt_jar.push(format!(".ivy2/local/org.scala-sbt/sbt-launch/{}/jars/sbt-launch.jar", self.sbt_version));
            File::open(self.sbt_jar.as_path()).is_ok()
        }) || ({
            self.sbt_jar = jar_file(&self.sbt_version);
            download_url(&self.sbt_version, &make_url(&self.sbt_version), &self.sbt_jar)
        })
    }

    fn exec_runner<S: AsRef<OsStr>>(&self, args: &[S]) {
        self.vlog("# Executing command line:") && {
            for arg in args {
                let arg = arg.as_ref();
                if !arg.is_empty() {
                    let arg = arg.to_string_lossy();
                    if arg.contains(" ") {
                        echoerr!("\"{}\"", arg);
                    } else {
                        echoerr!("{}", arg);
                    }
                }
            }
            self.vlog("")
        };

        use std::os::unix::process::CommandExt;
        let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
        println!("error: {}", err);
        if let Some(err) = err.raw_os_error() {
            std::process::exit(err);
        }
        std::process::exit(-1)
    }

    fn run(&mut self) {
        let argument_count = self.residual_args.len();

        self.set_sbt_version();

        if argument_count == 0 {
            self.vlog(&format!("Starting {}: invoke with -help for other options", *script_name));
            self.residual_args = vec!["shell".into()];
        }

        // no jar? download it.
        File::open(self.sbt_jar.as_path()).is_ok() || self.acquire_sbt_jar() || {
            // still no jar? uh-oh.
            println!("Download failed. Obtain the jar manually and place it at {}", self.sbt_jar.display());
            std::process::exit(1);
        };

        let mut exec_args: Vec<&OsStr> = Vec::new();
        exec_args.push(self.java_cmd.as_ref());
        exec_args.append(&mut self.extra_jvm_opts.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.java_args.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut vec!["-jar".as_ref(), self.sbt_jar.as_ref()]);
        exec_args.append(&mut self.sbt_commands.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.residual_args.iter().map(AsRef::as_ref).collect());

        self.exec_runner(&exec_args)
    }
}

fn main() {
    let mut app = App::new();
    app.process_args();
    app.run()
}
<|endoftext|>


<commit_before>use crate::poll;
use crate::{event, Interests, Registry, Token};

use std::sync::{Arc, Mutex};
use std::{fmt, io};

use std::net::{self, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.

use winapi::um::winsock2::{bind, closesocket, SOCKET_ERROR, SOCK_DGRAM};

use crate::sys::windows::init;

use super::{new_socket, socket_addr};

use super::selector::SockState;
use super::InternalState;

pub struct UdpSocket {
    internal: Arc<Mutex<Option<InternalState>>>,
    io: net::UdpSocket,
}

macro_rules! wouldblock {
    ($self:ident, $method:ident, $($args:expr),* )  => {{
        let result = $self.io.$method($($args),*);
        if let Err(ref e) = result {
            if e.kind() == io::ErrorKind::WouldBlock {
                let internal = $self.internal.lock().unwrap();
                if internal.is_some() {
                    let selector = internal.as_ref().unwrap().selector.clone();
                    let token = internal.as_ref().unwrap().token;
                    let interests = internal.as_ref().unwrap().interests;
                    drop(internal);
                    selector.reregister(
                        $self,
                        token,
                        interests,
                    )?;
                }
            }
        }
        result
    }};
}

impl UdpSocket {
    pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> {
        init();
        new_socket(addr, SOCK_DGRAM).and_then(|socket| {
            let (raw_addr, raw_addr_length) = socket_addr(&addr);
            syscall!(
                bind(socket, raw_addr, raw_addr_length,),
                PartialEq::eq,
                SOCKET_ERROR
            )
            .map_err(|err| {
                // Close the socket if we hit an error, ignoring the error
                // from closing since we can't pass back two errors.
                let _ = unsafe { closesocket(socket) };
                err
            })
            .map(|_| UdpSocket {
                internal: Arc::new(Mutex::new(None)),
                io: unsafe { net::UdpSocket::from_raw_socket(socket as StdSocket) },
            })
        })
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.local_addr()
    }

    pub fn try_clone(&self) -> io::Result<UdpSocket> {
        self.io.try_clone().map(|io| UdpSocket {
            internal: Arc::new(Mutex::new(None)),
            io,
        })
    }

    pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
        self.io.send_to(buf, target)
    }

    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
        self.io.recv_from(buf)
    }

    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
        self.io.peek_from(buf)
    }

    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
        wouldblock!(self, send, buf)
    }

    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
        wouldblock!(self, recv, buf)
    }

    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
        wouldblock!(self, peek, buf)
    }

    pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
        wouldblock!(self, connect, addr)
    }

    pub fn broadcast(&self) -> io::Result<bool> {
        self.io.broadcast()
    }

    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
        self.io.set_broadcast(on)
    }

    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
        self.io.multicast_loop_v4()
    }

    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
        self.io.set_multicast_loop_v4(on)
    }

    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
        self.io.multicast_ttl_v4()
    }

    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
        self.io.set_multicast_ttl_v4(ttl)
    }

    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
        self.io.multicast_loop_v6()
    }

    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
        self.io.set_multicast_loop_v6(on)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.io.ttl()
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.io.set_ttl(ttl)
    }

    pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
        self.io.join_multicast_v4(&multiaddr, &interface)
    }

    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
        self.io.join_multicast_v6(multiaddr, interface)
    }

    pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
        self.io.leave_multicast_v4(&multiaddr, &interface)
    }

    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
        self.io.leave_multicast_v6(multiaddr, interface)
    }

    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.io.take_error()
    }
}

impl super::SocketState for UdpSocket {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl event::Source for UdpSocket {
    fn register(&self, registry: &Registry, token: Token, interests: Interests) -> io::Result<()> {
        {
            let mut internal = self.internal.lock().unwrap();
            if internal.is_none() {
                *internal = Some(InternalState::new(
                    poll::selector(registry).clone_inner(),
                    token,
                    interests,
                ));
            }
        }
        let result = poll::selector(registry).register(self, token, interests);
        match result {
            Ok(_) => {}
            Err(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
        }
        result
    }

    fn reregister(
        &self,
        registry: &Registry,
        token: Token,
        interests: Interests,
    ) -> io::Result<()> {
        let result = poll::selector(registry).reregister(self, token, interests);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                internal.as_mut().unwrap().token = token;
                internal.as_mut().unwrap().interests = interests;
            }
            Err(_) => {}
        };
        result
    }

    fn deregister(&self, registry: &Registry) -> io::Result<()> {
        let result = poll::selector(registry).deregister(self);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
            Err(_) => {}
        };
        result
    }
}

impl fmt::Debug for UdpSocket {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.io, f)
    }
}

impl FromRawSocket for UdpSocket {
    unsafe fn from_raw_socket(rawsocket: RawSocket) -> UdpSocket {
        UdpSocket {
            internal: Arc::new(Mutex::new(None)),
            io: net::UdpSocket::from_raw_socket(rawsocket),
        }
    }
}

impl IntoRawSocket for UdpSocket {
    fn into_raw_socket(self) -> RawSocket {
        self.io.as_raw_socket()
    }
}

impl AsRawSocket for UdpSocket {
    fn as_raw_socket(&self) -> RawSocket {
        self.io.as_raw_socket()
    }
}
<commit_msg>Fix issue in #1062<commit_after>use crate::poll;
use crate::{event, Interests, Registry, Token};

use std::sync::{Arc, Mutex};
use std::{fmt, io};

use std::net::{self, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.

use winapi::um::winsock2::{bind, closesocket, SOCKET_ERROR, SOCK_DGRAM};

use crate::sys::windows::init;

use super::{new_socket, socket_addr};

use super::selector::SockState;
use super::InternalState;

pub struct UdpSocket {
    internal: Arc<Mutex<Option<InternalState>>>,
    io: net::UdpSocket,
}

macro_rules! wouldblock {
    ($self:ident, $method:ident, $($args:expr),* )  => {{
        let result = $self.io.$method($($args),*);
        if let Err(ref e) = result {
            if e.kind() == io::ErrorKind::WouldBlock {
                let internal = $self.internal.lock().unwrap();
                if internal.is_some() {
                    let selector = internal.as_ref().unwrap().selector.clone();
                    let token = internal.as_ref().unwrap().token;
                    let interests = internal.as_ref().unwrap().interests;
                    drop(internal);
                    selector.reregister(
                        $self,
                        token,
                        interests,
                    )?;
                }
            }
        }
        result
    }};
}

impl UdpSocket {
    pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> {
        init();
        new_socket(addr, SOCK_DGRAM).and_then(|socket| {
            let (raw_addr, raw_addr_length) = socket_addr(&addr);
            syscall!(
                bind(socket, raw_addr, raw_addr_length,),
                PartialEq::eq,
                SOCKET_ERROR
            )
            .map_err(|err| {
                // Close the socket if we hit an error, ignoring the error
                // from closing since we can't pass back two errors.
                let _ = unsafe { closesocket(socket) };
                err
            })
            .map(|_| UdpSocket {
                internal: Arc::new(Mutex::new(None)),
                io: unsafe { net::UdpSocket::from_raw_socket(socket as StdSocket) },
            })
        })
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.local_addr()
    }

    pub fn try_clone(&self) -> io::Result<UdpSocket> {
        self.io.try_clone().map(|io| UdpSocket {
            internal: Arc::new(Mutex::new(None)),
            io,
        })
    }

    pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
        wouldblock!(self, send_to, buf, target)
    }

    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
        wouldblock!(self, recv_from, buf)
    }

    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
        wouldblock!(self, peek_from, buf)
    }

    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
        wouldblock!(self, send, buf)
    }

    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
        wouldblock!(self, recv, buf)
    }

    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
        wouldblock!(self, peek, buf)
    }

    pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
        self.io.connect(addr)
    }

    pub fn broadcast(&self) -> io::Result<bool> {
        self.io.broadcast()
    }

    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
        self.io.set_broadcast(on)
    }

    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
        self.io.multicast_loop_v4()
    }

    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
        self.io.set_multicast_loop_v4(on)
    }

    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
        self.io.multicast_ttl_v4()
    }

    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
        self.io.set_multicast_ttl_v4(ttl)
    }

    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
        self.io.multicast_loop_v6()
    }

    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
        self.io.set_multicast_loop_v6(on)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.io.ttl()
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.io.set_ttl(ttl)
    }

    pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
        self.io.join_multicast_v4(&multiaddr, &interface)
    }

    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
        self.io.join_multicast_v6(multiaddr, interface)
    }

    pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
        self.io.leave_multicast_v4(&multiaddr, &interface)
    }

    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
        self.io.leave_multicast_v6(multiaddr, interface)
    }

    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.io.take_error()
    }
}

impl super::SocketState for UdpSocket {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl event::Source for UdpSocket {
    fn register(&self, registry: &Registry, token: Token, interests: Interests) -> io::Result<()> {
        {
            let mut internal = self.internal.lock().unwrap();
            if internal.is_none() {
                *internal = Some(InternalState::new(
                    poll::selector(registry).clone_inner(),
                    token,
                    interests,
                ));
            }
        }
        let result = poll::selector(registry).register(self, token, interests);
        match result {
            Ok(_) => {}
            Err(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
        }
        result
    }

    fn reregister(
        &self,
        registry: &Registry,
        token: Token,
        interests: Interests,
    ) -> io::Result<()> {
        let result = poll::selector(registry).reregister(self, token, interests);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                internal.as_mut().unwrap().token = token;
                internal.as_mut().unwrap().interests = interests;
            }
            Err(_) => {}
        };
        result
    }

    fn deregister(&self, registry: &Registry) -> io::Result<()> {
        let result = poll::selector(registry).deregister(self);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
            Err(_) => {}
        };
        result
    }
}

impl fmt::Debug for UdpSocket {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.io, f)
    }
}

impl FromRawSocket for UdpSocket {
    unsafe fn from_raw_socket(rawsocket: RawSocket) -> UdpSocket {
        UdpSocket {
            internal: Arc::new(Mutex::new(None)),
            io: net::UdpSocket::from_raw_socket(rawsocket),
        }
    }
}

impl IntoRawSocket for UdpSocket {
    fn into_raw_socket(self) -> RawSocket {
        self.io.as_raw_socket()
    }
}

impl AsRawSocket for UdpSocket {
    fn as_raw_socket(&self) -> RawSocket {
        self.io.as_raw_socket()
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]
#[macro_use]
extern crate error_chain;
extern crate reqwest;
extern crate rocket;
extern crate toml;
extern crate semver;

use std::collections::HashMap;
use std::fmt::{self, Display, Formatter};
use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::process;

use rocket::request::FromParam;
use semver::Version;

mod errors {
    // Create the Error, ErrorKind, ResultExt, and Result types
    error_chain! { }
}

use errors::ResultExt;

#[derive(Eq, PartialEq, PartialOrd, Ord)]
enum Status {
    OutOfDate,
    UpToDate,
    Unknown,
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            Status::Unknown => write!(f, "unknown"),
            Status::OutOfDate => write!(f, "outofdate"),
            Status::UpToDate => write!(f, "uptodate"),
        }
    }
}

struct MyParam<'r> {
    deps_type: &'r str,
    ext: &'r str,
}

impl<'r> FromParam<'r> for MyParam<'r> {
    type Error = &'r str;

    fn from_param(param: &'r str) -> Result<MyParam<'r>, &'r str> {
        let (status_type, ext) = match param.find('.') {
            Some(i) if i > 0 => (&param[..i], &param[(i + 1)..]),
            _ => return Err(param),
        };

        Ok(MyParam {
            deps_type: match status_type {
                "dev-status" => "dev-dependencies",
                "status" => "dependencies",
                _ => return Err(param),
            },
            ext: match ext {
                "png" => "png",
                "svg" => "svg",
                _ => return Err(param),
            },
        })
    }
}

#[get("/<owner>/<name>/<params>")]
fn index(owner: &str, name: &str, params: MyParam) -> io::Result<File> {
    // TODO: HEADER 'Cache-Control': 'no-cache, no-store, must-revalidate',
    // TODO: HEADER 'Expires': new Date().toUTCString()
    let status = match get_deps_status(owner, name, params.deps_type) {
        Ok(status) => status,
        Err(ref e) => {
            println!("error: {}", e);

            for e in e.iter().skip(1) {
                println!("caused by: {}", e);
            }

            // The backtrace is not always generated. Try to run this example
            // with `RUST_BACKTRACE=1`.
            if let Some(backtrace) = e.backtrace() {
                println!("backtrace: {:?}", backtrace);
            }
            Status::Unknown
        }
    };
    File::open(format!("public/img/status/{}.{}", status, params.ext))
}

fn get_deps_status(owner: &str, name: &str, deps_type: &str) -> errors::Result<Status> {
    let cargo_url = format!("https://raw.githubusercontent.com/{}/{}/master/Cargo.toml",
                            owner,
                            name);

    let mut resp = reqwest::get(cargo_url.as_str())
        .chain_err(|| "Unable to download Cargo.toml")?;

    let mut buffer = String::new();
    match resp.status() {
        &reqwest::StatusCode::Ok => {
            resp.read_to_string(&mut buffer)
                .chain_err(|| "Unable to read Cargo.toml body")?;
            deps_status_from_cargo(owner, name, buffer, deps_type)
                .chain_err(|| "Unable verify status")
        },
        _ => {
            bail!("Bad status code retreiving Cargo.toml");
        }
    }
}

fn deps_status_from_cargo(owner: &str, name: &str, cargo: String, deps_type: &str) -> errors::Result<Status> {

    let root = cargo.as_str()
        .parse::<toml::Value>()
        .chain_err(|| "Unable to parse manifest")?;

    let dependencies = match root.get(deps_type)
        .and_then(|val| val.as_table()) {
        Some(dependencies) => dependencies,
        None => return Ok(Status::UpToDate),
    };

    // TODO:
    // 1- Download the Cargo.toml of the project into /tmp/owner/name/Cargo.toml
    // 2- Create a dummy /tmp/owner/name/src/lib.rs (avoid `cargo update` complaint)
    let tmp_dir = format!("/tmp/{}/{}", owner, name);
    let tmp_manifest = format!("{}/Cargo.toml", tmp_dir);
    let tmp_lockfile = format!("{}/Cargo.lock", tmp_dir);
    let tmp_src_dir = format!("{}/src", tmp_dir);
    let tmp_src_lib = format!("{}/lib.rs", tmp_src_dir);

    fs::create_dir_all(tmp_src_dir.as_str())
        .and_then(|_| File::create(tmp_manifest.as_str()))
        .and_then(|mut file| file.write_all(cargo.as_bytes()))
        .and_then(|_| File::create(tmp_src_lib.as_str()))
        .chain_err(|| "Unable to create tmp file structure")?;

    // 3- `cargo update --manifest-path /tmp/owner/name/Cargo.toml`
    process::Command::new("cargo")
        .arg("update")
        .arg("--manifest-path")
        .arg(tmp_manifest.as_str())
        .output()
        .chain_err(|| "Unable to exec cargo update")?;

    // 4- Parse the /tmp/owner/name/Cargo.lock generated
    let mut buffer = String::new();
    File::open(tmp_lockfile)
        .and_then(|mut f| f.read_to_string(&mut buffer))
        .chain_err(|| "Unable to read Cargo.lock")?;

    let tmp_root_lockfile = buffer.as_str()
        .parse::<toml::Value>()
        .chain_err(|| "Unable to parse Cargo.lock")?;

    let tmp_root_table = match tmp_root_lockfile.get("root") {
        Some(root) => root,
        None => bail!("Unable to find root in lockfile"),
    };

    let updated_raw_deps = match tmp_root_table.get("dependencies") {
        Some(&toml::Value::Array(ref raw_deps)) => raw_deps,
        Some(_) => unreachable!(),
        None => bail!("Unable to find dependencies in lockfile"),
    };

    let mut updated_deps = HashMap::new();
    for updated_raw_dep in updated_raw_deps {
        let raw_dep_vec: Vec<_> = updated_raw_dep.as_str().unwrap_or("").split(' ').collect();
        if raw_dep_vec.len() < 2 {
            bail!("Invalid dependency found");
        }
        updated_deps.insert(raw_dep_vec[0], raw_dep_vec[1]);
    }

    // 5- Compare each deps with semver
    let status = dependencies.iter().fold(Status::UpToDate, |oldest, (dep, version_value)| {
        let updated_version = match updated_deps.get::<str>(&dep.to_string()) {
            Some(updated_version) => updated_version,
            None => unreachable!(),
        };
        let version = match version_value.as_str() {
            Some(version) => version,
            None => return oldest,
        };

        if Version::parse(updated_version) > Version::parse(version) {
            Status::OutOfDate
        } else if Status::OutOfDate == oldest {
            Status::OutOfDate
        } else {
            Status::UpToDate
        }
    });

    Ok(status)
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}
<commit_msg>Remove TODO<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]
#[macro_use]
extern crate error_chain;
extern crate reqwest;
extern crate rocket;
extern crate toml;
extern crate semver;

use std::collections::HashMap;
use std::fmt::{self, Display, Formatter};
use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::process;

use rocket::request::FromParam;
use semver::Version;

mod errors {
    // Create the Error, ErrorKind, ResultExt, and Result types
    error_chain! { }
}

use errors::ResultExt;

#[derive(Eq, PartialEq, PartialOrd, Ord)]
enum Status {
    OutOfDate,
    UpToDate,
    Unknown,
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            Status::Unknown => write!(f, "unknown"),
            Status::OutOfDate => write!(f, "outofdate"),
            Status::UpToDate => write!(f, "uptodate"),
        }
    }
}

struct MyParam<'r> {
    deps_type: &'r str,
    ext: &'r str,
}

impl<'r> FromParam<'r> for MyParam<'r> {
    type Error = &'r str;

    fn from_param(param: &'r str) -> Result<MyParam<'r>, &'r str> {
        let (status_type, ext) = match param.find('.') {
            Some(i) if i > 0 => (&param[..i], &param[(i + 1)..]),
            _ => return Err(param),
        };

        Ok(MyParam {
            deps_type: match status_type {
                "dev-status" => "dev-dependencies",
                "status" => "dependencies",
                _ => return Err(param),
            },
            ext: match ext {
                "png" => "png",
                "svg" => "svg",
                _ => return Err(param),
            },
        })
    }
}

#[get("/<owner>/<name>/<params>")]
fn index(owner: &str, name: &str, params: MyParam) -> io::Result<File> {
    // TODO: HEADER 'Cache-Control': 'no-cache, no-store, must-revalidate',
    // TODO: HEADER 'Expires': new Date().toUTCString()
    let status = match get_deps_status(owner, name, params.deps_type) {
        Ok(status) => status,
        Err(ref e) => {
            println!("error: {}", e);

            for e in e.iter().skip(1) {
                println!("caused by: {}", e);
            }

            // The backtrace is not always generated. Try to run this example
            // with `RUST_BACKTRACE=1`.
            if let Some(backtrace) = e.backtrace() {
                println!("backtrace: {:?}", backtrace);
            }
            Status::Unknown
        }
    };
    File::open(format!("public/img/status/{}.{}", status, params.ext))
}

fn get_deps_status(owner: &str, name: &str, deps_type: &str) -> errors::Result<Status> {
    let cargo_url = format!("https://raw.githubusercontent.com/{}/{}/master/Cargo.toml",
                            owner,
                            name);

    let mut resp = reqwest::get(cargo_url.as_str())
        .chain_err(|| "Unable to download Cargo.toml")?;

    let mut buffer = String::new();
    match resp.status() {
        &reqwest::StatusCode::Ok => {
            resp.read_to_string(&mut buffer)
                .chain_err(|| "Unable to read Cargo.toml body")?;
            deps_status_from_cargo(owner, name, buffer, deps_type)
                .chain_err(|| "Unable verify status")
        },
        _ => {
            bail!("Bad status code retreiving Cargo.toml");
        }
    }
}

fn deps_status_from_cargo(owner: &str, name: &str, cargo: String, deps_type: &str) -> errors::Result<Status> {

    let root = cargo.as_str()
        .parse::<toml::Value>()
        .chain_err(|| "Unable to parse manifest")?;

    let dependencies = match root.get(deps_type)
        .and_then(|val| val.as_table()) {
        Some(dependencies) => dependencies,
        None => return Ok(Status::UpToDate),
    };

    // 1- Download the Cargo.toml of the project into /tmp/owner/name/Cargo.toml
    // 2- Create a dummy /tmp/owner/name/src/lib.rs (avoid `cargo update` complaint)
    let tmp_dir = format!("/tmp/{}/{}", owner, name);
    let tmp_manifest = format!("{}/Cargo.toml", tmp_dir);
    let tmp_lockfile = format!("{}/Cargo.lock", tmp_dir);
    let tmp_src_dir = format!("{}/src", tmp_dir);
    let tmp_src_lib = format!("{}/lib.rs", tmp_src_dir);

    fs::create_dir_all(tmp_src_dir.as_str())
        .and_then(|_| File::create(tmp_manifest.as_str()))
        .and_then(|mut file| file.write_all(cargo.as_bytes()))
        .and_then(|_| File::create(tmp_src_lib.as_str()))
        .chain_err(|| "Unable to create tmp file structure")?;

    // 3- `cargo update --manifest-path /tmp/owner/name/Cargo.toml`
    process::Command::new("cargo")
        .arg("update")
        .arg("--manifest-path")
        .arg(tmp_manifest.as_str())
        .output()
        .chain_err(|| "Unable to exec cargo update")?;

    // 4- Parse the /tmp/owner/name/Cargo.lock generated
    let mut buffer = String::new();
    File::open(tmp_lockfile)
        .and_then(|mut f| f.read_to_string(&mut buffer))
        .chain_err(|| "Unable to read Cargo.lock")?;

    let tmp_root_lockfile = buffer.as_str()
        .parse::<toml::Value>()
        .chain_err(|| "Unable to parse Cargo.lock")?;

    let tmp_root_table = match tmp_root_lockfile.get("root") {
        Some(root) => root,
        None => bail!("Unable to find root in lockfile"),
    };

    let updated_raw_deps = match tmp_root_table.get("dependencies") {
        Some(&toml::Value::Array(ref raw_deps)) => raw_deps,
        Some(_) => unreachable!(),
        None => bail!("Unable to find dependencies in lockfile"),
    };

    let mut updated_deps = HashMap::new();
    for updated_raw_dep in updated_raw_deps {
        let raw_dep_vec: Vec<_> = updated_raw_dep.as_str().unwrap_or("").split(' ').collect();
        if raw_dep_vec.len() < 2 {
            bail!("Invalid dependency found");
        }
        updated_deps.insert(raw_dep_vec[0], raw_dep_vec[1]);
    }

    // 5- Compare each deps with semver
    let status = dependencies.iter().fold(Status::UpToDate, |oldest, (dep, version_value)| {
        let updated_version = match updated_deps.get::<str>(&dep.to_string()) {
            Some(updated_version) => updated_version,
            None => unreachable!(),
        };
        let version = match version_value.as_str() {
            Some(version) => version,
            None => return oldest,
        };

        if Version::parse(updated_version) > Version::parse(version) {
            Status::OutOfDate
        } else if Status::OutOfDate == oldest {
            Status::OutOfDate
        } else {
            Status::UpToDate
        }
    });

    Ok(status)
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}
<|endoftext|>


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

#[derive(Debug)]
struct SearchTree<T> {
    left: Option<Box<SearchTree<T>>>,
    right: Option<Box<SearchTree<T>>>,
    key: T,
}

impl<T> SearchTree<T> where T: std::fmt::Debug + std::cmp::Eq + std::cmp::PartialOrd {
    fn inorder_tree(self) {
        self.left.map(|x| x.inorder_tree());
        println!("self.key = {:#?}", self.key);
        self.right.map(|x| x.inorder_tree());
    }

    fn search_tree(self, key: T ) -> Option<SearchTree<T>> {
        if self.key == key {
            return Some(self);
        }

        if key < self.key {
            match self.left {
                Some(tree) => tree.search_tree(key),
                None => None
            }
        } else {
            match self.right {
                Some(tree) => tree.search_tree(key),
                None => None
            }
        }
    }
}

fn main() {
    let left = SearchTree {
        left: None,
        right: None,
        key: 32,
    };

    let right = SearchTree {
        left: None,
        right: None,
        key: 43,
    };

    let root = SearchTree {
        left: Some(Box::new(left)),
        right: Some(Box::new(right)),
        key: 40,
    };

//    root.inorder_tree();

    let tree = root.search_tree(43);
    match tree {
        Some(t) => println!("t.key = {:#?}", t.key),
        None => println!(" None "),

    }

}
<commit_msg>lifetime<commit_after>use std::boxed::Box;

#[derive(Debug)]
struct SearchTree<'a, T: 'a> {
    left: Option<Box<&'a SearchTree<'a,T>>>,
    right: Option<Box<&'a SearchTree<'a,T>>>,
    key: T,
}
fn do_nothing() {

}
impl<'a, T> SearchTree<'a, T> where T: std::fmt::Debug + std::cmp::Eq + std::cmp::PartialOrd {
    fn inorder_tree(&self) {
        match self.left {
            Some(ref tree) => tree.inorder_tree(),
            None => do_nothing(),
        }
        println!("self.key = {:#?}", self.key);
        match self.right {
            Some(ref tree) => tree.inorder_tree(),
            None => do_nothing(),
        }
    }

    fn search_tree(&'a self, key: T ) -> Option<&'a SearchTree<'a, T>> {
        if self.key == key {
            return Some(&self);
        }

        if key < self.key {
            match self.left {
                Some(ref tree) => tree.search_tree(key),
                None => None
            }
        } else {
            match self.right {
                Some(ref tree) => tree.search_tree(key),
                None => None
            }
        }
    }
}

fn main() {
    let left = SearchTree {
        left: None,
        right: None,
        key: 32,
    };

    let right = SearchTree {
        left: None,
        right: None,
        key: 43,
    };

    let root = SearchTree {
        left: Some(Box::new(&left)),
        right: Some(Box::new(&right)),
        key: 40,
    };

    root.inorder_tree();

    let tree = root.search_tree(43);
    match tree {
        Some(t) => println!("t.key = {:#?}", t.key),
        None => println!(" None "),

    }

    let x = create_box_value();
    println!("x = {:#?}", x);

}

fn create_box_value<'a>() -> Box<i32> {
    Box::new(32)
}
<|endoftext|>


<commit_before>extern crate sdl;
extern crate rand;

use rand::distributions::{IndependentSample, Range};
use sdl::video::{SurfaceFlag, VideoFlag, Color};
use sdl::event::{Event, Key, Mouse};

fn init(screen_width: isize, screen_height: isize) -> sdl::video::Surface {
    sdl::init(&[sdl::InitFlag::Video]);
    sdl::wm::set_caption("mines", "mines");

    let screen = match sdl::video::set_video_mode(screen_width, screen_height, 32,
                                                  &[SurfaceFlag::HWSurface],
                                                  &[VideoFlag::DoubleBuf]) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to set video mode: {}", err)
    };
    screen
}

fn draw_square(x: i16, y: i16, w: u16, (r,g,b): (u8, u8, u8), screen: &sdl::video::Surface) {
    screen.fill_rect(Some(sdl::Rect {x: x, y: y, w: w, h: w}), Color::RGB(r, g, b));
}

fn draw_num(n: u8, x: i16, y: i16, size: u16, screen: &sdl::video::Surface) {
    draw_square(x,
        y,
        size,
        (255, 255, 255),
        screen
    );
    let mut n = n;
    let sub = (size-1) as i16/3;
    let pack = (size as i16-sub*3)as i16/2;
    let color = if n == 1 {
        (100,100,255)
    }else if n == 2 {
        (0,255,0)
    }else if n == 3 {
        (255,0,0)
    }else if n == 4 {
        (0,0,255)
    }else if n == 5 {
        (200,50,0)
    }else if n == 6 {
        (0,255,255)
    }else if n == 7 {
        (0,0,0)
    }else {
        (150,150,150)
    };

    loop {
        if n == 0 {break;}
        else if n == 1{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            break;
        }else if n == 2{
            draw_square(x+pack, y+pack, sub as u16-1,  color, screen);
            draw_square(sub*2+x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            break;
        }else if n == 3{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 2;
        }else if n == 4{
            draw_square(x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            draw_square(sub*2+x+pack, y+pack, sub as u16-1, color, screen);
            n = 2;
        }else if n == 5{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 4;
        }else if n == 6{
            draw_square(x+pack, sub+y+pack, sub as u16-1, color, screen);
            draw_square(sub*2+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 4;
        }else if n == 7{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 6;
        }else if n == 8{
            draw_square(sub+x+pack, y+pack, sub as u16-1, color, screen);
            draw_square(sub+x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            n = 6;
        }
    }
}

fn draw_field(ref field: &Vec<Vec<(bool,bool,bool)>>,
              length: i16,
              screen: &sdl::video::Surface) {
    let mut n = 0;
    for ref i in field.iter() {
        let mut m = 0;
        for ref sq in i.iter() {
            let hidden = sq.0;
            let mine = sq.1;
            let flag = sq.2;

            if hidden {
                draw_square(m*length+1,
                    n*length+1,
                    (length-1) as u16,
                    (180, 180, 180),
                    screen
                );
                if flag {
                    draw_square(m*length+4,
                        n*length+4,
                        (length-7) as u16,
                        (255, 0, 0),
                        screen
                    );
                }
            }else{
                if mine {
                    draw_square(m*length+1,
                        n*length+1,
                        (length-1) as u16,
                        (0, 0, 0),
                        screen
                    );
                }else{
                    draw_num(
                        count_field(m as usize, n as usize, field),
                        m as i16*length as i16+1,
                        n as i16*length as i16+1,
                        (length-1) as u16,
                        screen
                    );
                }
            }
            m += 1;
        }
        n += 1;
    }
}

fn make_mine(ref mut field: &mut Vec<Vec<(bool,bool,bool)>>, x: i16, y: i16, size: i16) {
    let i = (x/size) as usize;
    let j = (y/size) as usize;
    let (h, mine, f) = field[i][j];
    field[i][j] = (h, !mine, f);
}

fn random_field(r: f32, field: &mut Vec<Vec<(bool,bool,bool)>>) {
    let bt = Range::new(0.,1.);
    let mut rng = rand::thread_rng();
    for i in 0..field.len() {
        for j in 0..field[0].len() {
            if bt.ind_sample(&mut rng) < r {
                field[i][j] = (true, true, false);
            }else{
                field[i][j] = (true, false, false);
            }
        }
    }
}

fn show_spot(ref mut field: &mut Vec<Vec<(bool,bool,bool)>>, x: i16, y: i16, size: i16) {
    let i = (x/size) as usize;
    let j = (y/size) as usize;
    let (_, m, flag) = field[i][j];
    if !flag {
        field[i][j] = (false, m, flag);
    }
}

fn flag_spot(ref mut field: &mut Vec<Vec<(bool,bool,bool)>>, x: i16, y: i16, size: i16) {
    let i = (x/size) as usize;
    let j = (y/size) as usize;
    let (hidden, m, flag) = field[i][j];
    if hidden {
        field[i][j] = (hidden, m, !flag);
    }
}

fn count_field(x: usize, y: usize, field: &Vec<Vec<(bool,bool,bool)>>) -> u8 {
    let w = field[0].len();
    let h = field.len();
    let mut n = 0;
    for i in 0..3 {
        if y+i == 0 || y+i == h+1 {continue;}
        for j in 0..3 {
            if i == 1 && j == 1 {continue;}
            if x+j == 0 || x+j == w+1 {continue;}
            if field[y+i-1][x+j-1].1 {n += 1}
        }
    }
    n
}

fn main() {
    const WIDTH: usize = 30;
    const HEIGHT: usize = 20;
    const SIZE: usize = 35;

    let field = &mut vec![vec![(true, false, false); WIDTH]; HEIGHT];

    let screen = init((SIZE*WIDTH) as isize + 1, (SIZE*HEIGHT) as isize + 1);
    loop {
        match sdl::event::poll_event() {
            Event::Quit => break,
            Event::MouseButton(b, down, mx, my) => {
                if down {
                    if b == Mouse::Left {
                        show_spot(field, my as i16, mx as i16, SIZE as i16);
                    }
                    else if b == Mouse::Right {
                        flag_spot(field, my as i16, mx as i16, SIZE as i16);
                    }
                }
            },
            Event::Key(k, down, _, _) => {
                if down {
                    if k == Key::Escape {
                        break;
                    }
                    if k == Key::R {
                        random_field(0.1, field);
                    }
                }
            }
            _ => {}
        }
        draw_field(&field, SIZE as i16, &screen);
        screen.flip();
    }

    sdl::quit();
}
<commit_msg>started refactoring<commit_after>extern crate sdl;
extern crate rand;

use rand::distributions::{IndependentSample, Range};
use sdl::video::{SurfaceFlag, VideoFlag, Color};
use sdl::event::{Event, Key, Mouse};

#[derive(Copy, Clone)]
struct Spot {
    //x: usize,
    //y: usize,
    hidden: bool,
    mine: bool,
    flag: bool,
    //n: i8;
}

struct Field {
    width: usize,
    height: usize,
    field: Vec<Vec<Spot>>,
}

impl Field {
    fn new(r: f32, w: usize, h: usize) -> Field {
        //TODO: make it so the field isn't rebuilt
        let bt = Range::new(0.,1.);
        let mut rng = rand::thread_rng();
        let mut field = vec![vec![Spot{hidden:false,mine:false,flag:false}; w]; h];
        for i in 0..h {
            for j in 0..w {
                if bt.ind_sample(&mut rng) < r {
                    field[i][j] = Spot{hidden: true, mine: true, flag: false};
                }else{
                    field[i][j] = Spot{hidden: true, mine: false, flag: false};
                }
            }
        }
        Field {width: w, height: h, field: field}
    }

    fn swap_mine(&mut self, x: usize, y: usize) {
        let f = self.field[x][y];
        self.field[x][y].mine = !f.mine;
    }

    fn show_spot(&mut self, x: usize, y: usize) {
        let f = self.field[x][y];
        if !f.hidden {
            for i in 0..3{
                for j in 0..3{
                    if i == 0 && j == 0 {continue;}
                    if x+i == 0 || x+i>self.width {continue;}
                    if y+j == 0 || y+j>self.height {continue;}
                    println!("{} {}", x, y);
                    self.show_spot(x+i-1, y+j-1);
                }
            }
        }
        if !f.flag {
            self.field[x][y].hidden = false;
        }
    }

    fn flag_spot(&mut self, x: usize, y: usize) {
        let f = self.field[x][y];
        if f.hidden {
            self.field[x][y].flag = !f.flag;
        }
    }

    fn count_field(self, x: usize, y: usize) -> u8 {
        let mut n = 0;
        for i in 0..3 {
            if y+i == 0 || y+i == self.height+1 {continue;}
            for j in 0..3 {
                if i == 1 && j == 1 {continue;}
                if x+j == 0 || x+j == self.width+1 {continue;}
                if self.field[y+i-1][x+j-1].mine {n += 1}
            }
        }
        n
    }
}

struct Screen<'a> {
    width: isize,
    height: isize,
    spot_length: usize,
    surface: & 'a sdl::video::Surface,
}

impl <'a>Screen<'a> {
    fn new(w: isize, h: isize, l: usize) -> Screen<'a> {
        sdl::init(&[sdl::InitFlag::Video]);
        sdl::wm::set_caption("mines", "mines");

        let s = match sdl::video::set_video_mode(w, h, 32,
                                                 &[SurfaceFlag::HWSurface],
                                                 &[VideoFlag::DoubleBuf]) {
            Ok(s) => &s,
            Err(err) => panic!("failed to set video mode: {}", err)
        };
        Screen {width: w, height: h, spot_length: l, surface: s}
    }

    fn draw_square(self, x: i16, y: i16, w: u16, (r,g,b): (u8, u8, u8)) {
        self.surface.fill_rect(Some(sdl::Rect {x: x, y: y, w: w, h: w}), Color::RGB(r, g, b));
    }

    fn draw_num(self, n: u8, x: i16, y: i16, size: u16) {
        self.draw_square(x, y, size,
            (255, 255, 255)
        );
        let mut n = n;
        let sub = (size-1) as i16/3;
        let pack = (size as i16-sub*3)as i16/2;
        let color = if n == 1 {
            (100,100,255)
        }else if n == 2 {
            (0,255,0)
        }else if n == 3 {
            (255,0,0)
        }else if n == 4 {
            (0,0,255)
        }else if n == 5 {
            (200,50,0)
        }else if n == 6 {
            (0,255,255)
        }else if n == 7 {
            (0,0,0)
        }else {
            (150,150,150)
        };

        loop {
            if n == 0 {break;}
            else if n == 1{
                self.draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color);
                break;
            }else if n == 2{
                self.draw_square(x+pack, y+pack, sub as u16-1,  color);
                self.draw_square(sub*2+x+pack, sub*2+y+pack, sub as u16-1, color);
                break;
            }else if n == 3{
                self.draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color);
                n = 2;
            }else if n == 4{
                self.draw_square(x+pack, sub*2+y+pack, sub as u16-1, color);
                self.draw_square(sub*2+x+pack, y+pack, sub as u16-1, color);
                n = 2;
            }else if n == 5{
                self.draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color);
                n = 4;
            }else if n == 6{
                self.draw_square(x+pack, sub+y+pack, sub as u16-1, color);
                self.draw_square(sub*2+x+pack, sub+y+pack, sub as u16-1, color);
                n = 4;
            }else if n == 7{
                self.draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color);
                n = 6;
            }else if n == 8{
                self.draw_square(sub+x+pack, y+pack, sub as u16-1, color);
                self.draw_square(sub+x+pack, sub*2+y+pack, sub as u16-1, color);
                n = 6;
            }
        }
    }
    fn draw_field(self, length: i16, field: Field) {
        let mut n = 0;
        for ref i in field.field.iter() {
            let mut m = 0;
            for ref sq in i.iter() {
                if sq.hidden {
                    self.draw_square(m*length+1,
                        n*length+1,
                        (length-1) as u16,
                        (180, 180, 180)
                    );
                    if sq.flag {
                        self.draw_square(m*length+4,
                            n*length+4,
                            (length-7) as u16,
                            (255, 0, 0)
                        );
                    }
                }else{
                    if sq.mine {
                        self.draw_square(m*length+1,
                            n*length+1,
                            (length-1) as u16,
                            (0, 0, 0)
                        );
                    }else{
                        self.draw_num(
                            field.count_field(m as usize, n as usize),
                            m as i16*length as i16+1,
                            n as i16*length as i16+1,
                            (length-1) as u16
                        );
                    }
                }
                m += 1;
            }
            n += 1;
        }
    }
}

fn main() {
    const WIDTH: usize = 30;
    const HEIGHT: usize = 20;
    const SIZE: usize = 35;

    let mut field = Field::new(0.1, WIDTH, HEIGHT);

    let screen = Screen::new((SIZE*WIDTH) as isize + 1, (SIZE*HEIGHT) as isize + 1, SIZE);

    loop {
        match sdl::event::poll_event() {
            Event::Quit => break,
            Event::MouseButton(b, down, mx, my) => {
                if down {
                    if b == Mouse::Left {
                        field.show_spot(my as usize/SIZE, mx as usize/SIZE);
                    }
                    else if b == Mouse::Right {
                        field.flag_spot(my as usize/SIZE, mx as usize/SIZE);
                    }
                }
            },
            Event::Key(k, down, _, _) => {
                if down {
                    if k == Key::Escape {
                        break;
                    }
                    if k == Key::R {
                        field = Field::new(0.1, WIDTH, HEIGHT);
                    }
                }
            },
            _ => {}
        }
        screen.draw_field(SIZE as i16, field);
        screen.surface.flip();
    }

    sdl::quit();
}
<|endoftext|>


<commit_before>// main

mod util;
#[macro_use]
mod token;
mod preprocess;
mod parse;
mod sema;
mod gen_ir;
mod irdump;
mod liveness;
mod opt;
mod regalloc;
mod gen_x86;

use crate::gen_x86::*;
use crate::gen_ir::*;
use crate::irdump::*;
use crate::parse::*;
use crate::liveness::*;
use crate::opt::*;
use crate::regalloc::*;
use crate::sema::*;
use crate::token::*;
use std::env;
use std::cell::RefCell;
use std::rc::Rc;

fn print_node(n: Rc<RefCell<Node>>, offset: usize) {
    for _i in 0..offset {
        eprint!(" ");
    }

    let node = n.borrow().clone();
    eprintln!("{:?} {} '{}' {:?}", node.op, node.val, node.name, node.ty.borrow().ty);
    //eprintln!("{:?}", node);
    if node.rhs.is_some() {
        print_node(node.rhs.clone().unwrap(), offset+2);
    }
    if node.lhs.is_some() {
        print_node(node.lhs.clone().unwrap(), offset+2);
    }
    if node.expr.is_some() {
        print_node(node.expr.clone().unwrap(), offset+2);
    }
    //eprintln!(">> {}", node.stmts.len());
    for i in node.stmts.iter() {
        print_node(i.clone(), offset+2);
    }

    if node.cond.is_some() { print_node(node.cond.clone().unwrap(), offset+2); }
    if node.then.is_some() { print_node(node.then.clone().unwrap(), offset+2); }
    if node.els.is_some() { print_node(node.els.clone().unwrap(), offset+2); }
    if node.init.is_some() { print_node(node.init.clone().unwrap(), offset+2); }
    if node.inc.is_some() { print_node(node.inc.clone().unwrap(), offset+2); }
    if node.body.is_some() { print_node(node.body.clone().unwrap(), offset+2); }

    for i in node.args.iter() {
        print_node(i.clone(), offset+2);
    }
}

fn usage() {
    panic!("Usage: rcc [-test] [-dump-ir1] [-dump-ir2] <file>");
}

fn main() {
    let argv: Vec<String> = env::args().collect();
    if argv.len() == 1 {
        usage();
    }

    let path: String;
    let mut dump_node = false;
    let mut dump_ir1 = false;
    let mut dump_ir2 = false;

    if argv.len() == 3 && argv[1] == "-dump-node" {
        dump_node = true;
        path = argv[2].clone();
    } else if argv.len() == 3 && argv[1] == "-dump-ir1" {
        dump_ir1 = true;
        path = argv[2].clone();
    } else if argv.len() == 3 && argv[1] == "-dump-ir2" {
        dump_ir2 = true;
        path = argv[2].clone();
    } else {
        if argv.len() != 2 {
            usage();
        }
        path = argv[1].clone();
    }

    // Token -> Node -> IR -> asm
    // token -> parse -> sema -> gen_ir(irdump) -> regalloc -> gen_x86

    // Tokenize and parse.
    let tokens = tokenize(path, true);
    //for i in tokens.iter() { eprintln!(">> {:?} {:?}", i.ty, i.name); }
    let prog = &mut parse(&tokens);
    if dump_node {
        for i in prog.funcs.iter() {
            let n = i.borrow().node.clone();
            print_node(n.clone(), 0);
        }
        return;
    }

    sema(prog);
    gen_ir(prog);

    if dump_ir1 {
        dump_ir(prog.funcs.clone());
        return;
    }

    optimize(prog);
    liveness(prog);
    alloc_regs(prog);

    if dump_ir2 {
        dump_ir(prog.funcs.clone());
        return;
    }

    let asm = gen_x86(prog);

    print!("{}", asm);
    return;
}
<commit_msg>Update an usage message.<commit_after>// main

mod util;
#[macro_use]
mod token;
mod preprocess;
mod parse;
mod sema;
mod gen_ir;
mod irdump;
mod liveness;
mod opt;
mod regalloc;
mod gen_x86;

use crate::gen_x86::*;
use crate::gen_ir::*;
use crate::irdump::*;
use crate::parse::*;
use crate::liveness::*;
use crate::opt::*;
use crate::regalloc::*;
use crate::sema::*;
use crate::token::*;
use std::env;
use std::cell::RefCell;
use std::rc::Rc;

fn print_node(n: Rc<RefCell<Node>>, offset: usize) {
    for _i in 0..offset {
        eprint!(" ");
    }

    let node = n.borrow().clone();
    eprintln!("{:?} {} '{}' {:?}", node.op, node.val, node.name, node.ty.borrow().ty);
    //eprintln!("{:?}", node);
    if node.rhs.is_some() {
        print_node(node.rhs.clone().unwrap(), offset+2);
    }
    if node.lhs.is_some() {
        print_node(node.lhs.clone().unwrap(), offset+2);
    }
    if node.expr.is_some() {
        print_node(node.expr.clone().unwrap(), offset+2);
    }
    //eprintln!(">> {}", node.stmts.len());
    for i in node.stmts.iter() {
        print_node(i.clone(), offset+2);
    }

    if node.cond.is_some() { print_node(node.cond.clone().unwrap(), offset+2); }
    if node.then.is_some() { print_node(node.then.clone().unwrap(), offset+2); }
    if node.els.is_some() { print_node(node.els.clone().unwrap(), offset+2); }
    if node.init.is_some() { print_node(node.init.clone().unwrap(), offset+2); }
    if node.inc.is_some() { print_node(node.inc.clone().unwrap(), offset+2); }
    if node.body.is_some() { print_node(node.body.clone().unwrap(), offset+2); }

    for i in node.args.iter() {
        print_node(i.clone(), offset+2);
    }
}

fn usage() {
    println!("Usage: r9ir [-test] [-dump-ir1] [-dump-ir2] <file>");
}

fn main() {
    let argv: Vec<String> = env::args().collect();
    if argv.len() == 1 {
        usage();
        return;
    }

    let path: String;
    let mut dump_node = false;
    let mut dump_ir1 = false;
    let mut dump_ir2 = false;

    if argv.len() == 3 && argv[1] == "-dump-node" {
        dump_node = true;
        path = argv[2].clone();
    } else if argv.len() == 3 && argv[1] == "-dump-ir1" {
        dump_ir1 = true;
        path = argv[2].clone();
    } else if argv.len() == 3 && argv[1] == "-dump-ir2" {
        dump_ir2 = true;
        path = argv[2].clone();
    } else {
        if argv.len() != 2 {
            usage();
            return;
        }
        path = argv[1].clone();
    }

    // Token -> Node -> IR -> asm
    // token -> parse -> sema -> gen_ir(irdump) -> regalloc -> gen_x86

    // Tokenize and parse.
    let tokens = tokenize(path, true);
    //for i in tokens.iter() { eprintln!(">> {:?} {:?}", i.ty, i.name); }
    let prog = &mut parse(&tokens);
    if dump_node {
        for i in prog.funcs.iter() {
            let n = i.borrow().node.clone();
            print_node(n.clone(), 0);
        }
        return;
    }

    sema(prog);
    gen_ir(prog);

    if dump_ir1 {
        dump_ir(prog.funcs.clone());
        return;
    }

    optimize(prog);
    liveness(prog);
    alloc_regs(prog);

    if dump_ir2 {
        dump_ir(prog.funcs.clone());
        return;
    }

    let asm = gen_x86(prog);

    print!("{}", asm);
    return;
}
<|endoftext|>