<commit_before>//! Networking primitives
//!
use std::fmt;
use std::str::FromStr;
use std::old_io::net::ip::SocketAddr as StdSocketAddr;
use std::old_io::net::ip::ParseError;
use io::{IoHandle, NonBlock};
use error::MioResult;
use buf::{Buf, MutBuf};
use os;

pub use std::old_io::net::ip::{IpAddr, Port};
pub use std::old_io::net::ip::Ipv4Addr as IPv4Addr;
pub use std::old_io::net::ip::Ipv6Addr as IPv6Addr;

use self::SockAddr::{InetAddr,UnixAddr};
use self::AddressFamily::{Unix,Inet,Inet6};

pub trait Socket : IoHandle {
    fn linger(&self) -> MioResult<usize> {
        os::linger(self.desc())
    }

    fn set_linger(&self, dur_s: usize) -> MioResult<()> {
        os::set_linger(self.desc(), dur_s)
    }

    fn set_reuseaddr(&self, val: bool) -> MioResult<()> {
        os::set_reuseaddr(self.desc(), val)
    }

    fn set_reuseport(&self, val: bool) -> MioResult<()> {
        os::set_reuseport(self.desc(), val)
    }
}

pub trait MulticastSocket : Socket {
    fn join_multicast_group(&self, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
        os::join_multicast_group(self.desc(), addr, interface)
    }

    fn leave_multicast_group(&self, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
        os::leave_multicast_group(self.desc(), addr, interface)
    }

    fn set_multicast_ttl(&self, val: u8) -> MioResult<()> {
        os::set_multicast_ttl(self.desc(), val)
    }
}

pub trait UnconnectedSocket {
    fn send_to(&mut self, buf: &mut Buf, tgt: &SockAddr) -> MioResult<NonBlock<()>>;
    fn recv_from(&mut self, buf: &mut MutBuf) -> MioResult<NonBlock<SockAddr>>;
}

// Types of sockets
#[derive(Copy)]
pub enum AddressFamily {
    Inet,
    Inet6,
    Unix,
}

pub enum SockAddr {
    UnixAddr(Path),
    InetAddr(IpAddr, Port)
}

impl SockAddr {
    pub fn parse(s: &str) -> Result<SockAddr, ParseError> {
        let addr = FromStr::from_str(s);
        addr.map(|a : StdSocketAddr| InetAddr(a.ip, a.port))
    }

    pub fn family(&self) -> AddressFamily {
        match *self {
            UnixAddr(..) => Unix,
            InetAddr(IPv4Addr(..), _) => Inet,
            InetAddr(IPv6Addr(..), _) => Inet6
        }
    }

    pub fn from_path(p: Path) -> SockAddr {
        UnixAddr(p)
    }

    #[inline]
    pub fn consume_std(addr: StdSocketAddr) -> SockAddr {
        InetAddr(addr.ip, addr.port)
    }

    #[inline]
    pub fn from_std(addr: &StdSocketAddr) -> SockAddr {
        InetAddr(addr.ip.clone(), addr.port)
    }

    pub fn to_std(&self) -> Option<StdSocketAddr> {
        match *self {
            InetAddr(ref addr, port) => Some(StdSocketAddr {
                ip: addr.clone(),
                port: port
            }),
            _ => None
        }
    }

    pub fn into_std(self) -> Option<StdSocketAddr> {
        match self {
            InetAddr(addr, port) => Some(StdSocketAddr {
                ip: addr,
                port: port
            }),
            _ => None
        }
    }
}

impl FromStr for SockAddr {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<SockAddr, ParseError> {
        SockAddr::parse(s)
    }
}

impl fmt::Debug for SockAddr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InetAddr(ip, port) => write!(fmt, "{}:{}", ip, port),
            _ => write!(fmt, "not implemented")
        }
    }
}

#[derive(Copy)]
pub enum SocketType {
    Dgram,
    Stream,
}

/// TCP networking primitives
///
pub mod tcp {
    use os;
    use error::MioResult;
    use buf::{Buf, MutBuf};
    use io;
    use io::{IoHandle, IoAcceptor, IoReader, IoWriter, NonBlock};
    use io::NonBlock::{Ready, WouldBlock};
    use net::{Socket, SockAddr};
    use net::SocketType::Stream;
    use net::AddressFamily::{self, Inet, Inet6};

    #[derive(Debug)]
    pub struct TcpSocket {
        desc: os::IoDesc
    }

    impl TcpSocket {
        pub fn v4() -> MioResult<TcpSocket> {
            TcpSocket::new(Inet)
        }

        pub fn v6() -> MioResult<TcpSocket> {
            TcpSocket::new(Inet6)
        }

        fn new(family: AddressFamily) -> MioResult<TcpSocket> {
            Ok(TcpSocket { desc: try!(os::socket(family, Stream)) })
        }

        /// Connects the socket to the specified address. When the operation
        /// completes, the handler will be notified with the supplied token.
        ///
        /// The goal of this method is to ensure that the event loop will always
        /// notify about the connection, even if the connection happens
        /// immediately. Otherwise, every consumer of the event loop would have
        /// to worry about possibly-immediate connection.
        pub fn connect(&self, addr: &SockAddr) -> MioResult<()> {
            debug!("socket connect; addr={:?}", addr);

            // Attempt establishing the context. This may not complete immediately.
            if try!(os::connect(&self.desc, addr)) {
                // On some OSs, connecting to localhost succeeds immediately. In
                // this case, queue the writable callback for execution during the
                // next event loop tick.
                debug!("socket connected immediately; addr={:?}", addr);
            }

            Ok(())
        }

        pub fn bind(self, addr: &SockAddr) -> MioResult<TcpListener> {
            try!(os::bind(&self.desc, addr));
            Ok(TcpListener { desc: self.desc })
        }

        pub fn getpeername(&self) -> MioResult<SockAddr> {
            os::getpeername(&self.desc)
        }

        pub fn getsockname(&self) -> MioResult<SockAddr> {
            os::getsockname(&self.desc)
        }
    }

    impl IoHandle for TcpSocket {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl IoReader for TcpSocket {
        fn read<B: MutBuf>(&self, buf: &mut B) -> MioResult<NonBlock<(usize)>> {
            io::read(self, buf)
        }

        fn read_slice(&self, buf: &mut[u8]) -> MioResult<NonBlock<usize>> {
            io::read_slice(self, buf)
        }
    }

    impl IoWriter for TcpSocket {
        fn write<B: Buf>(&self, buf: &mut B) -> MioResult<NonBlock<(usize)>> {
            io::write(self, buf)
        }

        fn write_slice(&self, buf: &[u8]) -> MioResult<NonBlock<usize>> {
            io::write_slice(self, buf)
        }
    }

    impl Socket for TcpSocket {
    }

    #[derive(Debug)]
    pub struct TcpListener {
        desc: os::IoDesc,
    }

    impl TcpListener {
        pub fn listen(self, backlog: usize) -> MioResult<TcpAcceptor> {
            try!(os::listen(self.desc(), backlog));
            Ok(TcpAcceptor { desc: self.desc })
        }
    }

    impl IoHandle for TcpListener {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    #[derive(Debug)]
    pub struct TcpAcceptor {
        desc: os::IoDesc,
    }

    impl TcpAcceptor {
        pub fn new(addr: &SockAddr, backlog: usize) -> MioResult<TcpAcceptor> {
            let sock = try!(TcpSocket::new(addr.family()));
            let listener = try!(sock.bind(addr));
            listener.listen(backlog)
        }
    }

    impl IoHandle for TcpAcceptor {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl Socket for TcpAcceptor {
    }

    impl IoAcceptor for TcpAcceptor {
        type Output = TcpSocket;

        fn accept(&mut self) -> MioResult<NonBlock<TcpSocket>> {
            match os::accept(self.desc()) {
                Ok(sock) => Ok(Ready(TcpSocket { desc: sock })),
                Err(e) => {
                    if e.is_would_block() {
                        return Ok(WouldBlock);
                    }

                    return Err(e);
                }
            }
        }
    }
}

pub mod udp {
    use os;
    use error::MioResult;
    use buf::{Buf, MutBuf};
    use io::{IoHandle, IoReader, IoWriter, NonBlock};
    use io::NonBlock::{Ready, WouldBlock};
    use io;
    use net::{AddressFamily, Socket, MulticastSocket, SockAddr};
    use net::SocketType::Dgram;
    use net::AddressFamily::Inet;
    use super::UnconnectedSocket;

    #[derive(Debug)]
    pub struct UdpSocket {
        desc: os::IoDesc
    }

    impl UdpSocket {
        pub fn v4() -> MioResult<UdpSocket> {
            UdpSocket::new(Inet)
        }

        fn new(family: AddressFamily) -> MioResult<UdpSocket> {
            Ok(UdpSocket { desc: try!(os::socket(family, Dgram)) })
        }

        pub fn bind(&self, addr: &SockAddr) -> MioResult<()> {
            try!(os::bind(&self.desc, addr));
            Ok(())
        }

        pub fn connect(&self, addr: &SockAddr) -> MioResult<bool> {
            os::connect(&self.desc, addr)
        }

        pub fn bound(addr: &SockAddr) -> MioResult<UdpSocket> {
            let sock = try!(UdpSocket::new(addr.family()));
            try!(sock.bind(addr));
            Ok(sock)
        }
    }

    impl IoHandle for UdpSocket {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl Socket for UdpSocket {
    }

    impl MulticastSocket for UdpSocket {
    }

    impl IoReader for UdpSocket {
        fn read<B: MutBuf>(&self, buf: &mut B) -> MioResult<NonBlock<(usize)>> {
            io::read(self, buf)
        }

        fn read_slice(&self, buf: &mut[u8]) -> MioResult<NonBlock<usize>> {
            io::read_slice(self, buf)
        }
    }

    impl IoWriter for UdpSocket {
        fn write<B: Buf>(&self, buf: &mut B) -> MioResult<NonBlock<(usize)>> {
            io::write(self, buf)
        }

        fn write_slice(&self, buf: &[u8]) -> MioResult<NonBlock<usize>> {
            io::write_slice(self, buf)
        }
    }

    // Unconnected socket sender -- trait unique to sockets
    impl UnconnectedSocket for UdpSocket {
        fn send_to(&mut self, buf: &mut Buf, tgt: &SockAddr) -> MioResult<NonBlock<()>> {
            match os::sendto(&self.desc, buf.bytes(), tgt) {
                Ok(cnt) => {
                    buf.advance(cnt);
                    Ok(Ready(()))
                }
                Err(e) => {
                    if e.is_would_block() {
                        Ok(WouldBlock)
                    } else {
                        Err(e)
                    }
                }
            }
        }

        fn recv_from(&mut self, buf: &mut MutBuf) -> MioResult<NonBlock<SockAddr>> {
            match os::recvfrom(&self.desc, buf.mut_bytes()) {
                Ok((cnt, saddr)) => {
                    buf.advance(cnt);
                    Ok(Ready(saddr))
                }
                Err(e) => {
                    if e.is_would_block() {
                        Ok(WouldBlock)
                    } else {
                        Err(e)
                    }
                }
            }
        }
    }
}

/// Named pipes
pub mod pipe {
    use os;
    use error::MioResult;
    use buf::{Buf, MutBuf};
    use io;
    use io::{IoHandle, IoAcceptor, IoReader, IoWriter, NonBlock};
    use io::NonBlock::{Ready, WouldBlock};
    use net::{Socket, SockAddr, SocketType};
    use net::SocketType::Stream;
    use net::AddressFamily::Unix;

    #[derive(Debug)]
    pub struct UnixSocket {
        desc: os::IoDesc
    }

    impl UnixSocket {
        pub fn stream() -> MioResult<UnixSocket> {
            UnixSocket::new(Stream)
        }

        fn new(socket_type: SocketType) -> MioResult<UnixSocket> {
            Ok(UnixSocket { desc: try!(os::socket(Unix, socket_type)) })
        }

        pub fn connect(&self, addr: &SockAddr) -> MioResult<()> {
            debug!("socket connect; addr={:?}", addr);

            // Attempt establishing the context. This may not complete immediately.
            if try!(os::connect(&self.desc, addr)) {
                // On some OSs, connecting to localhost succeeds immediately. In
                // this case, queue the writable callback for execution during the
                // next event loop tick.
                debug!("socket connected immediately; addr={:?}", addr);
            }

            Ok(())
        }

        pub fn bind(self, addr: &SockAddr) -> MioResult<UnixListener> {
            try!(os::bind(&self.desc, addr));
            Ok(UnixListener { desc: self.desc })
        }
    }

    impl IoHandle for UnixSocket {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl IoReader for UnixSocket {
        fn read<B: MutBuf>(&self, buf: &mut B) -> MioResult<NonBlock<usize>> {
            io::read(self, buf)
        }

        fn read_slice(&self, buf: &mut[u8]) -> MioResult<NonBlock<usize>> {
            io::read_slice(self, buf)
        }
    }

    impl IoWriter for UnixSocket {
        fn write<B: Buf>(&self, buf: &mut B) -> MioResult<NonBlock<usize>> {
            io::write(self, buf)
        }

        fn write_slice(&self, buf: &[u8]) -> MioResult<NonBlock<usize>> {
            io::write_slice(self, buf)
        }
    }

    impl Socket for UnixSocket {
    }

    #[derive(Debug)]
    pub struct UnixListener {
        desc: os::IoDesc,
    }

    impl UnixListener {
        pub fn listen(self, backlog: usize) -> MioResult<UnixAcceptor> {
            try!(os::listen(self.desc(), backlog));
            Ok(UnixAcceptor { desc: self.desc })
        }
    }

    impl IoHandle for UnixListener {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    #[derive(Debug)]
    pub struct UnixAcceptor {
        desc: os::IoDesc,
    }

    impl UnixAcceptor {
        pub fn new(addr: &SockAddr, backlog: usize) -> MioResult<UnixAcceptor> {
            let sock = try!(UnixSocket::stream());
            let listener = try!(sock.bind(addr));
            listener.listen(backlog)
        }
    }

    impl IoHandle for UnixAcceptor {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl Socket for UnixAcceptor {
    }

    impl IoAcceptor for UnixAcceptor {
        type Output = UnixSocket;

        fn accept(&mut self) -> MioResult<NonBlock<UnixSocket>> {
            match os::accept(self.desc()) {
                Ok(sock) => Ok(Ready(UnixSocket { desc: sock })),
                Err(e) => {
                    if e.is_would_block() {
                        return Ok(WouldBlock);
                    }

                    return Err(e);
                }
            }
        }
    }
}
<commit_msg>Use generics vs. trait objs with UDP types<commit_after>//! Networking primitives
//!
use std::fmt;
use std::str::FromStr;
use std::old_io::net::ip::SocketAddr as StdSocketAddr;
use std::old_io::net::ip::ParseError;
use io::{IoHandle, NonBlock};
use error::MioResult;
use buf::{Buf, MutBuf};
use os;

pub use std::old_io::net::ip::{IpAddr, Port};
pub use std::old_io::net::ip::Ipv4Addr as IPv4Addr;
pub use std::old_io::net::ip::Ipv6Addr as IPv6Addr;

use self::SockAddr::{InetAddr,UnixAddr};
use self::AddressFamily::{Unix,Inet,Inet6};

pub trait Socket : IoHandle {
    fn linger(&self) -> MioResult<usize> {
        os::linger(self.desc())
    }

    fn set_linger(&self, dur_s: usize) -> MioResult<()> {
        os::set_linger(self.desc(), dur_s)
    }

    fn set_reuseaddr(&self, val: bool) -> MioResult<()> {
        os::set_reuseaddr(self.desc(), val)
    }

    fn set_reuseport(&self, val: bool) -> MioResult<()> {
        os::set_reuseport(self.desc(), val)
    }
}

pub trait MulticastSocket : Socket {
    fn join_multicast_group(&self, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
        os::join_multicast_group(self.desc(), addr, interface)
    }

    fn leave_multicast_group(&self, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
        os::leave_multicast_group(self.desc(), addr, interface)
    }

    fn set_multicast_ttl(&self, val: u8) -> MioResult<()> {
        os::set_multicast_ttl(self.desc(), val)
    }
}

pub trait UnconnectedSocket {
    fn send_to<B: Buf>(&mut self, buf: &mut B, tgt: &SockAddr) -> MioResult<NonBlock<()>>;

    fn recv_from<B: MutBuf>(&mut self, buf: &mut B) -> MioResult<NonBlock<SockAddr>>;
}

// Types of sockets
#[derive(Copy)]
pub enum AddressFamily {
    Inet,
    Inet6,
    Unix,
}

pub enum SockAddr {
    UnixAddr(Path),
    InetAddr(IpAddr, Port)
}

impl SockAddr {
    pub fn parse(s: &str) -> Result<SockAddr, ParseError> {
        let addr = FromStr::from_str(s);
        addr.map(|a : StdSocketAddr| InetAddr(a.ip, a.port))
    }

    pub fn family(&self) -> AddressFamily {
        match *self {
            UnixAddr(..) => Unix,
            InetAddr(IPv4Addr(..), _) => Inet,
            InetAddr(IPv6Addr(..), _) => Inet6
        }
    }

    pub fn from_path(p: Path) -> SockAddr {
        UnixAddr(p)
    }

    #[inline]
    pub fn consume_std(addr: StdSocketAddr) -> SockAddr {
        InetAddr(addr.ip, addr.port)
    }

    #[inline]
    pub fn from_std(addr: &StdSocketAddr) -> SockAddr {
        InetAddr(addr.ip.clone(), addr.port)
    }

    pub fn to_std(&self) -> Option<StdSocketAddr> {
        match *self {
            InetAddr(ref addr, port) => Some(StdSocketAddr {
                ip: addr.clone(),
                port: port
            }),
            _ => None
        }
    }

    pub fn into_std(self) -> Option<StdSocketAddr> {
        match self {
            InetAddr(addr, port) => Some(StdSocketAddr {
                ip: addr,
                port: port
            }),
            _ => None
        }
    }
}

impl FromStr for SockAddr {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<SockAddr, ParseError> {
        SockAddr::parse(s)
    }
}

impl fmt::Debug for SockAddr {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InetAddr(ip, port) => write!(fmt, "{}:{}", ip, port),
            _ => write!(fmt, "not implemented")
        }
    }
}

#[derive(Copy)]
pub enum SocketType {
    Dgram,
    Stream,
}

/// TCP networking primitives
///
pub mod tcp {
    use os;
    use error::MioResult;
    use buf::{Buf, MutBuf};
    use io;
    use io::{IoHandle, IoAcceptor, IoReader, IoWriter, NonBlock};
    use io::NonBlock::{Ready, WouldBlock};
    use net::{Socket, SockAddr};
    use net::SocketType::Stream;
    use net::AddressFamily::{self, Inet, Inet6};

    #[derive(Debug)]
    pub struct TcpSocket {
        desc: os::IoDesc
    }

    impl TcpSocket {
        pub fn v4() -> MioResult<TcpSocket> {
            TcpSocket::new(Inet)
        }

        pub fn v6() -> MioResult<TcpSocket> {
            TcpSocket::new(Inet6)
        }

        fn new(family: AddressFamily) -> MioResult<TcpSocket> {
            Ok(TcpSocket { desc: try!(os::socket(family, Stream)) })
        }

        /// Connects the socket to the specified address. When the operation
        /// completes, the handler will be notified with the supplied token.
        ///
        /// The goal of this method is to ensure that the event loop will always
        /// notify about the connection, even if the connection happens
        /// immediately. Otherwise, every consumer of the event loop would have
        /// to worry about possibly-immediate connection.
        pub fn connect(&self, addr: &SockAddr) -> MioResult<()> {
            debug!("socket connect; addr={:?}", addr);

            // Attempt establishing the context. This may not complete immediately.
            if try!(os::connect(&self.desc, addr)) {
                // On some OSs, connecting to localhost succeeds immediately. In
                // this case, queue the writable callback for execution during the
                // next event loop tick.
                debug!("socket connected immediately; addr={:?}", addr);
            }

            Ok(())
        }

        pub fn bind(self, addr: &SockAddr) -> MioResult<TcpListener> {
            try!(os::bind(&self.desc, addr));
            Ok(TcpListener { desc: self.desc })
        }

        pub fn getpeername(&self) -> MioResult<SockAddr> {
            os::getpeername(&self.desc)
        }

        pub fn getsockname(&self) -> MioResult<SockAddr> {
            os::getsockname(&self.desc)
        }
    }

    impl IoHandle for TcpSocket {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl IoReader for TcpSocket {
        fn read<B: MutBuf>(&self, buf: &mut B) -> MioResult<NonBlock<(usize)>> {
            io::read(self, buf)
        }

        fn read_slice(&self, buf: &mut[u8]) -> MioResult<NonBlock<usize>> {
            io::read_slice(self, buf)
        }
    }

    impl IoWriter for TcpSocket {
        fn write<B: Buf>(&self, buf: &mut B) -> MioResult<NonBlock<(usize)>> {
            io::write(self, buf)
        }

        fn write_slice(&self, buf: &[u8]) -> MioResult<NonBlock<usize>> {
            io::write_slice(self, buf)
        }
    }

    impl Socket for TcpSocket {
    }

    #[derive(Debug)]
    pub struct TcpListener {
        desc: os::IoDesc,
    }

    impl TcpListener {
        pub fn listen(self, backlog: usize) -> MioResult<TcpAcceptor> {
            try!(os::listen(self.desc(), backlog));
            Ok(TcpAcceptor { desc: self.desc })
        }
    }

    impl IoHandle for TcpListener {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    #[derive(Debug)]
    pub struct TcpAcceptor {
        desc: os::IoDesc,
    }

    impl TcpAcceptor {
        pub fn new(addr: &SockAddr, backlog: usize) -> MioResult<TcpAcceptor> {
            let sock = try!(TcpSocket::new(addr.family()));
            let listener = try!(sock.bind(addr));
            listener.listen(backlog)
        }
    }

    impl IoHandle for TcpAcceptor {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl Socket for TcpAcceptor {
    }

    impl IoAcceptor for TcpAcceptor {
        type Output = TcpSocket;

        fn accept(&mut self) -> MioResult<NonBlock<TcpSocket>> {
            match os::accept(self.desc()) {
                Ok(sock) => Ok(Ready(TcpSocket { desc: sock })),
                Err(e) => {
                    if e.is_would_block() {
                        return Ok(WouldBlock);
                    }

                    return Err(e);
                }
            }
        }
    }
}

pub mod udp {
    use os;
    use error::MioResult;
    use buf::{Buf, MutBuf};
    use io::{IoHandle, IoReader, IoWriter, NonBlock};
    use io::NonBlock::{Ready, WouldBlock};
    use io;
    use net::{AddressFamily, Socket, MulticastSocket, SockAddr};
    use net::SocketType::Dgram;
    use net::AddressFamily::Inet;
    use super::UnconnectedSocket;

    #[derive(Debug)]
    pub struct UdpSocket {
        desc: os::IoDesc
    }

    impl UdpSocket {
        pub fn v4() -> MioResult<UdpSocket> {
            UdpSocket::new(Inet)
        }

        fn new(family: AddressFamily) -> MioResult<UdpSocket> {
            Ok(UdpSocket { desc: try!(os::socket(family, Dgram)) })
        }

        pub fn bind(&self, addr: &SockAddr) -> MioResult<()> {
            try!(os::bind(&self.desc, addr));
            Ok(())
        }

        pub fn connect(&self, addr: &SockAddr) -> MioResult<bool> {
            os::connect(&self.desc, addr)
        }

        pub fn bound(addr: &SockAddr) -> MioResult<UdpSocket> {
            let sock = try!(UdpSocket::new(addr.family()));
            try!(sock.bind(addr));
            Ok(sock)
        }
    }

    impl IoHandle for UdpSocket {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl Socket for UdpSocket {
    }

    impl MulticastSocket for UdpSocket {
    }

    impl IoReader for UdpSocket {
        fn read<B: MutBuf>(&self, buf: &mut B) -> MioResult<NonBlock<(usize)>> {
            io::read(self, buf)
        }

        fn read_slice(&self, buf: &mut[u8]) -> MioResult<NonBlock<usize>> {
            io::read_slice(self, buf)
        }
    }

    impl IoWriter for UdpSocket {
        fn write<B: Buf>(&self, buf: &mut B) -> MioResult<NonBlock<(usize)>> {
            io::write(self, buf)
        }

        fn write_slice(&self, buf: &[u8]) -> MioResult<NonBlock<usize>> {
            io::write_slice(self, buf)
        }
    }

    // Unconnected socket sender -- trait unique to sockets
    impl UnconnectedSocket for UdpSocket {
        fn send_to<B: Buf>(&mut self, buf: &mut B, tgt: &SockAddr) -> MioResult<NonBlock<()>> {
            match os::sendto(&self.desc, buf.bytes(), tgt) {
                Ok(cnt) => {
                    buf.advance(cnt);
                    Ok(Ready(()))
                }
                Err(e) => {
                    if e.is_would_block() {
                        Ok(WouldBlock)
                    } else {
                        Err(e)
                    }
                }
            }
        }

        fn recv_from<B: MutBuf>(&mut self, buf: &mut B) -> MioResult<NonBlock<SockAddr>> {
            match os::recvfrom(&self.desc, buf.mut_bytes()) {
                Ok((cnt, saddr)) => {
                    buf.advance(cnt);
                    Ok(Ready(saddr))
                }
                Err(e) => {
                    if e.is_would_block() {
                        Ok(WouldBlock)
                    } else {
                        Err(e)
                    }
                }
            }
        }
    }
}

/// Named pipes
pub mod pipe {
    use os;
    use error::MioResult;
    use buf::{Buf, MutBuf};
    use io;
    use io::{IoHandle, IoAcceptor, IoReader, IoWriter, NonBlock};
    use io::NonBlock::{Ready, WouldBlock};
    use net::{Socket, SockAddr, SocketType};
    use net::SocketType::Stream;
    use net::AddressFamily::Unix;

    #[derive(Debug)]
    pub struct UnixSocket {
        desc: os::IoDesc
    }

    impl UnixSocket {
        pub fn stream() -> MioResult<UnixSocket> {
            UnixSocket::new(Stream)
        }

        fn new(socket_type: SocketType) -> MioResult<UnixSocket> {
            Ok(UnixSocket { desc: try!(os::socket(Unix, socket_type)) })
        }

        pub fn connect(&self, addr: &SockAddr) -> MioResult<()> {
            debug!("socket connect; addr={:?}", addr);

            // Attempt establishing the context. This may not complete immediately.
            if try!(os::connect(&self.desc, addr)) {
                // On some OSs, connecting to localhost succeeds immediately. In
                // this case, queue the writable callback for execution during the
                // next event loop tick.
                debug!("socket connected immediately; addr={:?}", addr);
            }

            Ok(())
        }

        pub fn bind(self, addr: &SockAddr) -> MioResult<UnixListener> {
            try!(os::bind(&self.desc, addr));
            Ok(UnixListener { desc: self.desc })
        }
    }

    impl IoHandle for UnixSocket {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl IoReader for UnixSocket {
        fn read<B: MutBuf>(&self, buf: &mut B) -> MioResult<NonBlock<usize>> {
            io::read(self, buf)
        }

        fn read_slice(&self, buf: &mut[u8]) -> MioResult<NonBlock<usize>> {
            io::read_slice(self, buf)
        }
    }

    impl IoWriter for UnixSocket {
        fn write<B: Buf>(&self, buf: &mut B) -> MioResult<NonBlock<usize>> {
            io::write(self, buf)
        }

        fn write_slice(&self, buf: &[u8]) -> MioResult<NonBlock<usize>> {
            io::write_slice(self, buf)
        }
    }

    impl Socket for UnixSocket {
    }

    #[derive(Debug)]
    pub struct UnixListener {
        desc: os::IoDesc,
    }

    impl UnixListener {
        pub fn listen(self, backlog: usize) -> MioResult<UnixAcceptor> {
            try!(os::listen(self.desc(), backlog));
            Ok(UnixAcceptor { desc: self.desc })
        }
    }

    impl IoHandle for UnixListener {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    #[derive(Debug)]
    pub struct UnixAcceptor {
        desc: os::IoDesc,
    }

    impl UnixAcceptor {
        pub fn new(addr: &SockAddr, backlog: usize) -> MioResult<UnixAcceptor> {
            let sock = try!(UnixSocket::stream());
            let listener = try!(sock.bind(addr));
            listener.listen(backlog)
        }
    }

    impl IoHandle for UnixAcceptor {
        fn desc(&self) -> &os::IoDesc {
            &self.desc
        }
    }

    impl Socket for UnixAcceptor {
    }

    impl IoAcceptor for UnixAcceptor {
        type Output = UnixSocket;

        fn accept(&mut self) -> MioResult<NonBlock<UnixSocket>> {
            match os::accept(self.desc()) {
                Ok(sock) => Ok(Ready(UnixSocket { desc: sock })),
                Err(e) => {
                    if e.is_would_block() {
                        return Ok(WouldBlock);
                    }

                    return Err(e);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add direct channel example<commit_after>extern crate ears;

use std::io::stdin;
use std::io::stdout;
use std::io::Write;

use ears::{Music, AudioController};

fn main() {
    // Read the inputs
    let stdin = stdin();

    print!("Insert the path to an audio file: ");
    stdout().flush().ok();

    let mut line = String::new();
    stdin.read_line(&mut line).ok();
    loop {
        match &line[line.len()-1..] {
            "\n" => { line.pop(); () },
            "\r" => { line.pop(); () },
            _ => { break; },
        }
    }

    // Try to create the music
    let mut music = Music::new(&line[..]).expect("Error loading music.");

    // Play it
    music.play();
    music.set_looping(true);

    let mut toggle = false;

    loop {
        music.set_direct_channel(toggle);

        let direct_channel_enabled = music.get_direct_channel();

        if direct_channel_enabled != toggle {
            println!("Failed to enabled direct channel mode.");
            println!("Extension may not be available.");
        } else {
            match direct_channel_enabled {
                true => println!("Direct channel enabled."),
                false => println!("Direct channel disabled."),
            };
        }

        println!("Press enter to toggle direct channel mode, or 'x' to quit");
        let mut cmd = String::new();
        stdin.read_line(&mut cmd).ok();

        match &cmd[..1] {
            "x" => { music.stop(); break },
            _ => toggle = !toggle,
        };
    }
}
<|endoftext|>


<commit_before><commit_msg>Introduce Errors module.<commit_after>use bson;
use mongodb;

use iron::IronError;
use iron::status::Status;

use serde_json;

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

    foreign_links {
        BsonEncoder(bson::EncoderError);
        BsonDecoder(bson::DecoderError);
        Mongo(mongodb::Error);
        Serde(serde_json::Error);
    }
}

impl From<Error> for IronError {
    fn from(err: Error) -> IronError {
        IronError::new(err, Status::InternalServerError)
    }
}
<|endoftext|>


<commit_before><commit_msg>added some tests<commit_after>extern crate postgres;

use super::*;
use postgres::types;

#[test]
fn test_color() {
    assert_eq!("\x1B[33m\x1B[1m\x1B[33m\x1B[37mfoo\x1B[33m\x1B[0m", color_text("foo", Color::BoldWhite));
}

#[test]
fn test_alignment() {
    assert_eq!(get_alignment(&types::Type::Int4), Align::Right);
}

#[test]
fn test_padding() {
    assert_eq!("     ", pad_gen(5, " "));
    assert_eq!("-----", pad_gen(5, "-"));
}

#[test]
fn test_formatting() {
    assert_eq!("foo   ", format_field("foo", 6, Align::Left));
    assert_eq!("   foo", format_field("foo", 6, Align::Right));
    assert_eq!(" foo  ", format_field("foo", 6, Align::Center));
}
<|endoftext|>


<commit_before>use core::ops::Drop;

use common::memory::*;

use graphics::color::*;
use graphics::size::*;

pub struct BMP {
    pub data: usize,
    pub size: Size
}

impl BMP {
    pub fn new() -> BMP {
        BMP {
            data: 0,
            size: Size { width: 0, height: 0}
        }
    }

    pub fn from_data(file_data: usize) -> BMP {
        let data;
        let size;
        unsafe {
            if file_data > 0
                && *(file_data as *const u8) == 'B' as u8
                && *((file_data + 1) as *const u8) == 'M' as u8
            {
                let file_size = *((file_data + 0x2) as *const u32) as usize;
                let offset = *((file_data + 0xA) as *const u32) as usize;
                let width = *((file_data + 0x12) as *const u32) as usize;
                let height = *((file_data + 0x16) as *const u32) as usize;
                let depth = *((file_data + 0x1C) as *const u16) as usize;

                let bytes = (depth + 7)/8;
                let row_bytes = (depth * width + 31)/32 * 4;

                data = alloc(width * height * 4);
                size = Size {
                    width: width,
                    height: height
                };
                for y in 0..height {
                    for x in 0..width {
                        let pixel_offset = offset + (height - y - 1) * row_bytes + x * bytes;

                        let pixel_data;
                        if pixel_offset < file_size {
                            pixel_data = *((file_data + pixel_offset) as *const u32);
                        }else{
                            pixel_data = 0;
                        }

                        if bytes == 3 {
                            *((data + (y*width + x)*4) as *mut u32) = Color::new((pixel_data >> 16) as u8, (pixel_data >> 8) as u8, pixel_data as u8).data;
                        }else if bytes == 4 {
                            *((data + (y*width + x)*4) as *mut u32) = Color::alpha((pixel_data >> 24) as u8, (pixel_data >> 16) as u8, (pixel_data >> 8) as u8, pixel_data as u8).data;
                        }
                    }
                }
            }else{
                data = 0;
                size = Size {
                    width: 0,
                    height: 0
                };
            }
        }

        return BMP {
            data: data,
            size: size
        };
    }
}

impl Drop for BMP {
    fn drop(&mut self){
        unsafe {
            if self.data > 0 {
                unalloc(self.data);
                self.data = 0;
                self.size = Size {
                    width: 0,
                    height: 0
                };
            }
        }
    }
}
<commit_msg>Fix loading BMP files<commit_after>use core::ops::Drop;
use core::ptr;

use common::debug::*;
use common::memory::*;

use graphics::color::*;
use graphics::size::*;

pub struct BMP {
    pub data: usize,
    pub size: Size
}

impl BMP {
    pub fn new() -> BMP {
        BMP {
            data: 0,
            size: Size { width: 0, height: 0}
        }
    }

    pub fn from_data(file_data: usize) -> BMP {
        let data;
        let size;
        unsafe {
            if file_data > 0
                && *(file_data as *const u8) == 'B' as u8
                && ptr::read((file_data + 1) as *const u8) == 'M' as u8
            {
                let file_size = ptr::read((file_data + 0x2) as *const u32) as usize;
                let offset = ptr::read((file_data + 0xA) as *const u32) as usize;
                let header_size = ptr::read((file_data + 0xE) as *const u32) as usize;
                d("Size ");
                dd(header_size);
                dl();
                let width = ptr::read((file_data + 0x12) as *const u32) as usize;
                d("Width ");
                dd(width);
                dl();
                let height = ptr::read((file_data + 0x16) as *const u32) as usize;
                d("Height ");
                dd(height);
                dl();
                let depth = ptr::read((file_data + 0x1C) as *const u16) as usize;
                d("Depth ");
                dd(depth);
                dl();

                let bytes = (depth + 7)/8;
                let row_bytes = (depth * width + 31)/32 * 4;

                let mut red_mask = 0xFF0000;
                let mut green_mask = 0xFF00;
                let mut blue_mask = 0xFF;
                let mut alpha_mask = 0xFF000000;
                if ptr::read((file_data + 0x1E) as *const u32) == 3 {
                    red_mask = ptr::read((file_data + 0x36) as *const u32) as usize;
                    green_mask = ptr::read((file_data + 0x3A) as *const u32) as usize;
                    blue_mask = ptr::read((file_data + 0x3E) as *const u32) as usize;
                    alpha_mask = ptr::read((file_data + 0x42) as *const u32) as usize;
                }

                let mut red_shift = 0;
                while red_mask > 0 && red_shift < 32 && (red_mask >> red_shift) & 1 == 0 {
                    red_shift += 1;
                }

                let mut green_shift = 0;
                while green_mask > 0 && green_shift < 32 && (green_mask >> green_shift) & 1 == 0 {
                    green_shift += 1;
                }

                let mut blue_shift = 0;
                while blue_mask > 0 && blue_shift < 32 && (blue_mask >> blue_shift) & 1 == 0 {
                    blue_shift += 1;
                }

                let mut alpha_shift = 0;
                while alpha_mask > 0 && alpha_shift < 32 && (alpha_mask >> alpha_shift) & 1 == 0 {
                    alpha_shift += 1;
                }

                data = alloc(width * height * 4);
                size = Size {
                    width: width,
                    height: height
                };
                for y in 0..height {
                    for x in 0..width {
                        let pixel_offset = offset + (height - y - 1) * row_bytes + x * bytes;

                        let pixel_data;
                        if pixel_offset < file_size {
                            pixel_data = ptr::read((file_data + pixel_offset) as *const u32) as usize;
                        }else{
                            pixel_data = 0;
                        }

                        let red = ((pixel_data & red_mask) >> red_shift) as u8;
                        let green = ((pixel_data & green_mask) >> green_shift) as u8;
                        let blue = ((pixel_data & blue_mask) >> blue_shift) as u8;
                        if bytes == 3 {
                            ptr::write((data + (y*width + x)*4) as *mut u32, Color::new(red, green, blue).data);
                        }else if bytes == 4 {
                            let alpha = ((pixel_data & alpha_mask) >> alpha_shift) as u8;
                            ptr::write((data + (y*width + x)*4) as *mut u32, Color::alpha(red, green, blue, alpha).data);
                        }
                    }
                }
            }else{
                data = 0;
                size = Size {
                    width: 0,
                    height: 0
                };
            }
        }

        return BMP {
            data: data,
            size: size
        };
    }
}

impl Drop for BMP {
    fn drop(&mut self){
        unsafe {
            if self.data > 0 {
                unalloc(self.data);
                self.data = 0;
                self.size = Size {
                    width: 0,
                    height: 0
                };
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>reformat log<commit_after><|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::option::{Option, Some, None};
use core::vec;
use lib::llvm::{ValueRef, TypeRef};
use middle::trans::_match;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::machine;
use middle::trans::type_of;
use middle::ty;
use syntax::ast;
use util::ppaux::ty_to_str;

// XXX: should this be done with boxed traits instead of ML-style?
pub enum Repr {
    CEnum,
    Univariant(Struct, Destructor),
    General(~[Struct])
}

enum Destructor {
    DtorPresent,
    DtorAbsent,
    NoDtor
}

struct Struct {
    size: u64,
    align: u64,
    fields: ~[ty::t]
}

pub fn represent_node(bcx: block, node: ast::node_id)
    -> Repr {
    represent_type(bcx.ccx(), node_id_type(bcx, node))
}

pub fn represent_type(cx: @CrateContext, t: ty::t) -> Repr {
    debug!("Representing: %s", ty_to_str(cx.tcx, t));
    // XXX: cache this
    match ty::get(t).sty {
        ty::ty_tup(ref elems) => {
            Univariant(mk_struct(cx, *elems), NoDtor)
        }
        ty::ty_rec(ref fields) => {
            // XXX: Are these in the right order?
            Univariant(mk_struct(cx, fields.map(|f| f.mt.ty)), DtorAbsent)
        }
        ty::ty_struct(def_id, ref substs) => {
            let fields = ty::lookup_struct_fields(cx.tcx, def_id);
            let dt = ty::ty_dtor(cx.tcx, def_id).is_present();
            Univariant(mk_struct(cx, fields.map(|field| {
                ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
            })), if dt { DtorPresent } else { DtorAbsent })
        }
        ty::ty_enum(def_id, ref substs) => {
            struct Case { discr: i64, tys: ~[ty::t] };

            let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| {
                let arg_tys = do vi.args.map |&raw_ty| {
                    ty::subst(cx.tcx, substs, raw_ty)
                };
                Case { discr: vi.disr_val /*bad*/as i64, tys: arg_tys }
            };
            if cases.len() == 0 {
                // Uninhabitable; represent as unit
                Univariant(mk_struct(cx, ~[]), NoDtor)
            } else if cases.len() == 1 && cases[0].discr == 0 {
                // struct, tuple, newtype, etc.
                Univariant(mk_struct(cx, cases[0].tys), NoDtor)
            } else if cases.all(|c| c.tys.len() == 0) {
                CEnum
            } else {
                if !cases.alli(|i,c| c.discr == (i as i64)) {
                    cx.sess.bug(fmt!("non-C-like enum %s with specified \
                                      discriminants",
                                     ty::item_path_str(cx.tcx, def_id)))
                }
                General(cases.map(|c| mk_struct(cx, c.tys)))
            }
        }
        _ => cx.sess.bug(~"adt::represent_type called on non-ADT type")
    }
}

fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct {
    let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
    let llty_rec = T_struct(lltys);
    Struct {
        size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
        align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
        fields: vec::from_slice(tys)
    }
}

pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, true)
}
pub fn fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, false)
}
fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
    -> ~[TypeRef] {
    match *r {
        CEnum => ~[T_enum_discrim(cx)],
        Univariant(ref st, dt) => {
            let f = if sizing {
                st.fields.map(|&ty| type_of::sizing_type_of(cx, ty))
            } else {
                st.fields.map(|&ty| type_of::type_of(cx, ty))
            };
            match dt {
                NoDtor => f,
                DtorAbsent => ~[T_struct(f)],
                DtorPresent => ~[T_struct(f), T_i8()]
            }
        }
        General(ref sts) => {
            ~[T_enum_discrim(cx),
              T_array(T_i8(), sts.map(|st| st.size).max() /*bad*/as uint)]
        }
    }
}

pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef) ->
    (_match::branch_kind, Option<ValueRef>) {
    // XXX: LoadRangeAssert
    match *r {
        CEnum => {
            (_match::switch, Some(Load(bcx, GEPi(bcx, scrutinee, [0, 0]))))
        }
        Univariant(*) => {
            (_match::single, None)
        }
        General(*) => {
            (_match::switch, Some(Load(bcx, GEPi(bcx, scrutinee, [0, 0]))))
        }
    }
}

pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
    match *r {
        CEnum => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
        Univariant(*) => {
            bcx.ccx().sess.bug(~"no cases for univariants or structs")
        }
        General(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
    }
}

pub fn trans_set_discr(bcx: block, r: &Repr, val: ValueRef, discr: int) {
    match *r {
        CEnum => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
        Univariant(_, DtorPresent) => {
            assert discr == 0;
            Store(bcx, C_u8(1), GEPi(bcx, val, [0, 1]))
        }
        Univariant(*) => {
            assert discr == 0;
        }
        General(*) => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
    }
}

pub fn num_args(r: &Repr, discr: int) -> uint {
    match *r {
        CEnum => 0,
        Univariant(ref st, _dt) => { assert discr == 0; st.fields.len() }
        General(ref cases) => cases[discr as uint].fields.len()
    }
}

pub fn trans_GEP(bcx: block, r: &Repr, val: ValueRef, discr: int, ix: uint)
    -> ValueRef {
    // Note: if this ever needs to generate conditionals (e.g., if we
    // decide to do some kind of cdr-coding-like non-unique repr
    // someday), it'll need to return a possibly-new bcx as well.
    match *r {
        CEnum => {
            bcx.ccx().sess.bug(~"element access in C-like enum")
        }
        Univariant(ref st, dt) => {
            assert discr == 0;
            let val = match dt {
                NoDtor => val,
                DtorPresent | DtorAbsent => GEPi(bcx, val, [0, 0])
            };
            struct_GEP(bcx, st, val, ix, false)
        }
        General(ref cases) => {
            struct_GEP(bcx, &cases[discr as uint],
                       GEPi(bcx, val, [0, 1]), ix, true)
        }
    }
}

fn struct_GEP(bcx: block, st: &Struct, val: ValueRef, ix: uint,
              needs_cast: bool) -> ValueRef {
    let ccx = bcx.ccx();

    let val = if needs_cast {
        let real_llty = T_struct(st.fields.map(
            |&ty| type_of::type_of(ccx, ty)));
        PointerCast(bcx, val, T_ptr(real_llty))
    } else {
        val
    };

    GEPi(bcx, val, [0, ix])
}

pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
                   vals: &[ValueRef]) -> ValueRef {
    match *r {
        CEnum => {
            assert vals.len() == 0;
            C_int(ccx, discr)
        }
        Univariant(ref st, _dt) => {
            assert discr == 0;
            // consts are never destroyed, so the dtor flag is not needed
            C_struct(build_const_struct(ccx, st, vals))
        }
        General(ref cases) => {
            let case = &cases[discr as uint];
            let max_sz = cases.map(|s| s.size).max();
            let body = build_const_struct(ccx, case, vals);

            C_struct([C_int(ccx, discr),
                      C_packed_struct([C_struct(body)]),
                      padding(max_sz - case.size)])
        }
    }
}

fn padding(size: u64) -> ValueRef {
    C_undef(T_array(T_i8(), size /*bad*/as uint))
}

fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef])
    -> ~[ValueRef] {
    assert vals.len() == st.fields.len();

    let mut offset = 0;
    let mut cfields = ~[];
    for st.fields.eachi |i, &ty| {
        let llty = type_of::sizing_type_of(ccx, ty);
        let type_align = machine::llalign_of_min(ccx, llty)
            /*bad*/as u64;
        let val_align = machine::llalign_of_min(ccx, val_ty(vals[i]))
            /*bad*/as u64;
        let target_offset = roundup(offset, type_align);
        offset = roundup(offset, val_align);
        if (offset != target_offset) {
            cfields.push(padding(target_offset - offset));
            offset = target_offset;
        }
        assert !is_undef(vals[i]);
        // If that assert fails, could change it to wrap in a struct?
        cfields.push(vals[i]);
    }

    return cfields;
}

#[always_inline]
fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }

pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef)
    -> int {
    match *r {
        CEnum(*) => const_to_int(val) as int,
        Univariant(*) => 0,
        General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int,
    }
}

pub fn const_get_element(ccx: @CrateContext, r: &Repr, val: ValueRef,
                         _discr: int, ix: uint) -> ValueRef {
    // Not to be confused with common::const_get_elt.
    match *r {
        CEnum(*) => ccx.sess.bug(~"element access in C-like enum const"),
        Univariant(*) => const_struct_field(ccx, val, ix),
        General(*) => const_struct_field(ccx, const_get_elt(ccx, val,
                                                            [1, 0]), ix)
    }
}

fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
    -> ValueRef {
    // Get the ix-th non-undef element of the struct.
    let mut real_ix = 0; // actual position in the struct
    let mut ix = ix; // logical index relative to real_ix
    let mut field;
    loop {
        loop {
            field = const_get_elt(ccx, val, [real_ix]);
            if !is_undef(field) {
                break;
            }
            real_ix = real_ix + 1;
        }
        if ix == 0 {
            return field;
        }
        ix = ix - 1;
        real_ix = real_ix + 1;
    }
}
<commit_msg>Re-add discriminant range annotations<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::libc::c_ulonglong;
use core::option::{Option, Some, None};
use core::vec;
use lib::llvm::{ValueRef, TypeRef, True, False};
use middle::trans::_match;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::machine;
use middle::trans::type_of;
use middle::ty;
use syntax::ast;
use util::ppaux::ty_to_str;

// XXX: should this be done with boxed traits instead of ML-style?
pub enum Repr {
    CEnum(int, int), /* discriminant range */
    Univariant(Struct, Destructor),
    General(~[Struct])
}

enum Destructor {
    DtorPresent,
    DtorAbsent,
    NoDtor
}

struct Struct {
    size: u64,
    align: u64,
    fields: ~[ty::t]
}

pub fn represent_node(bcx: block, node: ast::node_id)
    -> Repr {
    represent_type(bcx.ccx(), node_id_type(bcx, node))
}

pub fn represent_type(cx: @CrateContext, t: ty::t) -> Repr {
    debug!("Representing: %s", ty_to_str(cx.tcx, t));
    // XXX: cache this
    match ty::get(t).sty {
        ty::ty_tup(ref elems) => {
            Univariant(mk_struct(cx, *elems), NoDtor)
        }
        ty::ty_rec(ref fields) => {
            // XXX: Are these in the right order?
            Univariant(mk_struct(cx, fields.map(|f| f.mt.ty)), DtorAbsent)
        }
        ty::ty_struct(def_id, ref substs) => {
            let fields = ty::lookup_struct_fields(cx.tcx, def_id);
            let dt = ty::ty_dtor(cx.tcx, def_id).is_present();
            Univariant(mk_struct(cx, fields.map(|field| {
                ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
            })), if dt { DtorPresent } else { DtorAbsent })
        }
        ty::ty_enum(def_id, ref substs) => {
            struct Case { discr: int, tys: ~[ty::t] };

            let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| {
                let arg_tys = do vi.args.map |&raw_ty| {
                    ty::subst(cx.tcx, substs, raw_ty)
                };
                Case { discr: vi.disr_val, tys: arg_tys }
            };
            if cases.len() == 0 {
                // Uninhabitable; represent as unit
                Univariant(mk_struct(cx, ~[]), NoDtor)
            } else if cases.len() == 1 && cases[0].discr == 0 {
                // struct, tuple, newtype, etc.
                Univariant(mk_struct(cx, cases[0].tys), NoDtor)
            } else if cases.all(|c| c.tys.len() == 0) {
                let discrs = cases.map(|c| c.discr);
                CEnum(discrs.min(), discrs.max())
            } else {
                if !cases.alli(|i,c| c.discr == (i as int)) {
                    cx.sess.bug(fmt!("non-C-like enum %s with specified \
                                      discriminants",
                                     ty::item_path_str(cx.tcx, def_id)))
                }
                General(cases.map(|c| mk_struct(cx, c.tys)))
            }
        }
        _ => cx.sess.bug(~"adt::represent_type called on non-ADT type")
    }
}

fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct {
    let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
    let llty_rec = T_struct(lltys);
    Struct {
        size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
        align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
        fields: vec::from_slice(tys)
    }
}

pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, true)
}
pub fn fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, false)
}
fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
    -> ~[TypeRef] {
    match *r {
        CEnum(*) => ~[T_enum_discrim(cx)],
        Univariant(ref st, dt) => {
            let f = if sizing {
                st.fields.map(|&ty| type_of::sizing_type_of(cx, ty))
            } else {
                st.fields.map(|&ty| type_of::type_of(cx, ty))
            };
            match dt {
                NoDtor => f,
                DtorAbsent => ~[T_struct(f)],
                DtorPresent => ~[T_struct(f), T_i8()]
            }
        }
        General(ref sts) => {
            ~[T_enum_discrim(cx),
              T_array(T_i8(), sts.map(|st| st.size).max() /*bad*/as uint)]
        }
    }
}

fn load_discr(bcx: block, scrutinee: ValueRef, min: int, max: int)
    -> ValueRef {
    let ptr = GEPi(bcx, scrutinee, [0, 0]);
    // XXX: write tests for the edge cases here
    if max + 1 == min {
        // i.e., if the range is everything.  The lo==hi case would be
        // rejected by the LLVM verifier (it would mean either an
        // empty set, which is impossible, or the entire range of the
        // type, which is pointless).
        Load(bcx, ptr)
    } else {
        // llvm::ConstantRange can deal with ranges that wrap around,
        // so an overflow on (max + 1) is fine.
        LoadRangeAssert(bcx, ptr, min as c_ulonglong,
                        (max + 1) as c_ulonglong,
                        /* signed: */ True)
    }
}

pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef) ->
    (_match::branch_kind, Option<ValueRef>) {
    match *r {
        CEnum(min, max) => {
            (_match::switch, Some(load_discr(bcx, scrutinee, min, max)))
        }
        Univariant(*) => {
            (_match::single, None)
        }
        General(ref cases) => {
            (_match::switch, Some(load_discr(bcx, scrutinee, 0,
                                             (cases.len() - 1) as int)))
        }
    }
}

pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
    match *r {
        CEnum(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
        Univariant(*) => {
            bcx.ccx().sess.bug(~"no cases for univariants or structs")
        }
        General(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
    }
}

pub fn trans_set_discr(bcx: block, r: &Repr, val: ValueRef, discr: int) {
    match *r {
        CEnum(min, max) => {
            assert min <= discr && discr <= max;
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
        Univariant(_, DtorPresent) => {
            assert discr == 0;
            Store(bcx, C_u8(1), GEPi(bcx, val, [0, 1]))
        }
        Univariant(*) => {
            assert discr == 0;
        }
        General(*) => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
    }
}

pub fn num_args(r: &Repr, discr: int) -> uint {
    match *r {
        CEnum(*) => 0,
        Univariant(ref st, _dt) => { assert discr == 0; st.fields.len() }
        General(ref cases) => cases[discr as uint].fields.len()
    }
}

pub fn trans_GEP(bcx: block, r: &Repr, val: ValueRef, discr: int, ix: uint)
    -> ValueRef {
    // Note: if this ever needs to generate conditionals (e.g., if we
    // decide to do some kind of cdr-coding-like non-unique repr
    // someday), it'll need to return a possibly-new bcx as well.
    match *r {
        CEnum(*) => {
            bcx.ccx().sess.bug(~"element access in C-like enum")
        }
        Univariant(ref st, dt) => {
            assert discr == 0;
            let val = match dt {
                NoDtor => val,
                DtorPresent | DtorAbsent => GEPi(bcx, val, [0, 0])
            };
            struct_GEP(bcx, st, val, ix, false)
        }
        General(ref cases) => {
            struct_GEP(bcx, &cases[discr as uint],
                       GEPi(bcx, val, [0, 1]), ix, true)
        }
    }
}

fn struct_GEP(bcx: block, st: &Struct, val: ValueRef, ix: uint,
              needs_cast: bool) -> ValueRef {
    let ccx = bcx.ccx();

    let val = if needs_cast {
        let real_llty = T_struct(st.fields.map(
            |&ty| type_of::type_of(ccx, ty)));
        PointerCast(bcx, val, T_ptr(real_llty))
    } else {
        val
    };

    GEPi(bcx, val, [0, ix])
}

pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
                   vals: &[ValueRef]) -> ValueRef {
    match *r {
        CEnum(min, max) => {
            assert vals.len() == 0;
            assert min <= discr && discr <= max;
            C_int(ccx, discr)
        }
        Univariant(ref st, _dt) => {
            assert discr == 0;
            // consts are never destroyed, so the dtor flag is not needed
            C_struct(build_const_struct(ccx, st, vals))
        }
        General(ref cases) => {
            let case = &cases[discr as uint];
            let max_sz = cases.map(|s| s.size).max();
            let body = build_const_struct(ccx, case, vals);

            C_struct([C_int(ccx, discr),
                      C_packed_struct([C_struct(body)]),
                      padding(max_sz - case.size)])
        }
    }
}

fn padding(size: u64) -> ValueRef {
    C_undef(T_array(T_i8(), size /*bad*/as uint))
}

fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef])
    -> ~[ValueRef] {
    assert vals.len() == st.fields.len();

    let mut offset = 0;
    let mut cfields = ~[];
    for st.fields.eachi |i, &ty| {
        let llty = type_of::sizing_type_of(ccx, ty);
        let type_align = machine::llalign_of_min(ccx, llty)
            /*bad*/as u64;
        let val_align = machine::llalign_of_min(ccx, val_ty(vals[i]))
            /*bad*/as u64;
        let target_offset = roundup(offset, type_align);
        offset = roundup(offset, val_align);
        if (offset != target_offset) {
            cfields.push(padding(target_offset - offset));
            offset = target_offset;
        }
        assert !is_undef(vals[i]);
        // If that assert fails, could change it to wrap in a struct?
        cfields.push(vals[i]);
    }

    return cfields;
}

#[always_inline]
fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }

pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef)
    -> int {
    match *r {
        CEnum(*) => const_to_int(val) as int,
        Univariant(*) => 0,
        General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int,
    }
}

pub fn const_get_element(ccx: @CrateContext, r: &Repr, val: ValueRef,
                         _discr: int, ix: uint) -> ValueRef {
    // Not to be confused with common::const_get_elt.
    match *r {
        CEnum(*) => ccx.sess.bug(~"element access in C-like enum const"),
        Univariant(*) => const_struct_field(ccx, val, ix),
        General(*) => const_struct_field(ccx, const_get_elt(ccx, val,
                                                            [1, 0]), ix)
    }
}

fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
    -> ValueRef {
    // Get the ix-th non-undef element of the struct.
    let mut real_ix = 0; // actual position in the struct
    let mut ix = ix; // logical index relative to real_ix
    let mut field;
    loop {
        loop {
            field = const_get_elt(ccx, val, [real_ix]);
            if !is_undef(field) {
                break;
            }
            real_ix = real_ix + 1;
        }
        if ix == 0 {
            return field;
        }
        ix = ix - 1;
        real_ix = real_ix + 1;
    }
}
<|endoftext|>


<commit_before><commit_msg>Since the secure() and insecure() methods actually have type signatures very similar to the into() method (https://doc.rust-lang.org/std/convert/trait.Into.html#tymethod.into), I changed their names to into_secure and into_insecure to be a little clearer about how they work<commit_after><|endoftext|>


<commit_before><commit_msg>Change the return type of the Windows readline()<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed typo<commit_after><|endoftext|>


<commit_before><commit_msg>touch ups<commit_after><|endoftext|>


<commit_before><commit_msg>Add code for diamond<commit_after>pub fn get_diamond(c: char) -> Vec<String> {
    let middle = c as usize - 'A' as usize;
    let width = 2 * middle + 1;

    (0..width)
        .map(|i| {
            let mut line = vec![b' '; width];

            let offset = if i < middle { i } else { 2 * middle - i };

            line[middle + offset] = b'A' + offset as u8;
            line[middle - offset] = b'A' + offset as u8;

            String::from_utf8(line).unwrap()
        })
        .collect()
}
<|endoftext|>


<commit_before><commit_msg>[Rust] 1.26 allows main function to return Result<commit_after>fn main() -> ::std::result::Result<(), &'static str> {
    Err("main function returns result")
}
<|endoftext|>


<commit_before><commit_msg>Implement Serialize for EventType.<commit_after><|endoftext|>


<commit_before><commit_msg>Panic if region contains invalid data<commit_after><|endoftext|>


<commit_before><commit_msg>`IXAudio2Voice::SetOutputFilterParameters()`<commit_after><|endoftext|>


<commit_before><commit_msg>sh to the rescue, killall dockers<commit_after><|endoftext|>


<commit_before><commit_msg>rewarder is panicking so will wait to after vnc to fix that<commit_after><|endoftext|>


<commit_before><commit_msg>Apparently serde::json needs lowercase first character of enum variants<commit_after><|endoftext|>


<commit_before><commit_msg>Fix imag-view for new error interface<commit_after><|endoftext|>


<commit_before><commit_msg>test(tmux/window): Use cfg(test) not [test]<commit_after><|endoftext|>


<commit_before><commit_msg>Test nested `proc` can access outer owned data<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Regression test for issue #10682
// Nested `proc` usage can't use outer owned data

fn work(_: ~int) {}
fn foo(_: proc()) {}

pub fn main() {
  let a = ~1;
  foo(proc() { foo(proc() { work(a) }) })
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub fn main() {
    if true {
        let _a = ~3;
    }
    if false {
        fail!()
    } else {
        let _a = ~3;
    }
}
<commit_msg>auto merge of #10748 : kballard/rust/issue-10734-rpass, r=alexcrichton<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

static mut drop_count: uint = 0;

#[unsafe_no_drop_flag]
struct Foo {
    dropped: bool
}

impl Drop for Foo {
    fn drop(&mut self) {
        // Test to make sure we haven't dropped already
        assert!(!self.dropped);
        self.dropped = true;
        // And record the fact that we dropped for verification later
        unsafe { drop_count += 1; }
    }
}

pub fn main() {
    // An `if true { expr }` statement should compile the same as `{ expr }`.
    if true {
        let _a = Foo{ dropped: false };
    }
    // Check that we dropped already (as expected from a `{ expr }`).
    unsafe { assert!(drop_count == 1); }

    // An `if false {} else { expr }` statement should compile the same as `{ expr }`.
    if false {
        fail!();
    } else {
        let _a = Foo{ dropped: false };
    }
    // Check that we dropped already (as expected from a `{ expr }`).
    unsafe { assert!(drop_count == 2); }
}
<|endoftext|>


<commit_before><commit_msg>Add a test for #11552<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[deriving(Clone)]
enum Noun
{
    Atom(int),
    Cell(~Noun, ~Noun)
}

fn fas(n: &Noun) -> Noun
{
    match n
    {
        &Cell(~Atom(2), ~Cell(ref a, _)) => (**a).clone(),
        _ => fail!("Invalid fas pattern")
    }
}

pub fn main() {
    fas(&Cell(~Atom(2), ~Cell(~Atom(2), ~Atom(3))));
}
<|endoftext|>


<commit_before><commit_msg>add test for issue #29053<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
    let x: &'static str = "x";

    {
        let y = "y".to_string();
        let ref mut x = &*x;
        *x = &*y;
    }

    assert_eq!(x, "x");
}
<|endoftext|>


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

use types::cef_base_t;

use libc::{self, c_int, c_void, size_t};
use std::mem;
use std::slice;
use std::str;

/// Allows you to downcast a CEF interface to a CEF class instance.
///
/// FIXME(pcwalton): This is currently unsafe. I think the right way to make this safe is to (a)
/// forbid more than one Rust implementation of a given interface (easy to do by manufacturing an
/// impl that will conflict if there is more than one) and then (b) add a dynamic check to make
/// sure the `release` for the object is equal to `servo_release`.
pub trait Downcast<Class> {
    fn downcast(&self) -> &Class;
}

pub fn slice_to_str<F>(s: *const u8, l: usize, f: F) -> c_int where F: FnOnce(&str) -> c_int {
    unsafe {
        let s = slice::from_raw_parts(s, l);
        str::from_utf8(s).map(f).unwrap_or(0)
    }
}

/// Creates a new raw CEF object of the given type and sets up its reference counting machinery.
/// All fields are initialized to zero. It is the caller's responsibility to ensure that the given
/// type is a CEF type with `cef_base_t` as its first member.
pub unsafe fn create_cef_object<Base,Extra>(size: size_t) -> *mut Base {
    let object = libc::calloc(1, (mem::size_of::<Base>() + mem::size_of::<Extra>()) as u64) as
        *mut cef_base_t;
    (*object).size = size;
    (*object).add_ref = Some(servo_add_ref as extern "C" fn(*mut cef_base_t) -> c_int);
    (*object).release = Some(servo_release as extern "C" fn(*mut cef_base_t) -> c_int);
    *ref_count(object) = 1;
    object as *mut Base
}

/// Returns a pointer to the Servo-specific reference count for the given object. This only works
/// on objects that Servo created!
unsafe fn ref_count(object: *mut cef_base_t) -> *mut usize {
    // The reference count should be the first field of the extra data.
    (object as *mut u8).offset((*object).size as isize) as *mut usize
}

/// Increments the reference count on a CEF object. This only works on objects that Servo created!
extern "C" fn servo_add_ref(object: *mut cef_base_t) -> c_int {
    unsafe {
        let count = ref_count(object);
        *count += 1;
        *count as c_int
    }
}

/// Decrements the reference count on a CEF object. If zero, frees it. This only works on objects
/// that Servo created!
extern "C" fn servo_release(object: *mut cef_base_t) -> c_int {
    unsafe {
        let count = ref_count(object);
        *count -= 1;
        let new_count = *count;
        if new_count == 0 {
            servo_free(object);
        }
        (new_count == 0) as c_int
    }
}

unsafe fn servo_free(object: *mut cef_base_t) {
    libc::free(object as *mut c_void);
}

pub unsafe fn add_ref(c_object: *mut cef_base_t) {
    ((*c_object).add_ref.unwrap())(c_object);
}

pub extern "C" fn servo_test() -> c_int {
    1
}
<commit_msg>add no_mangle to servo_test() embedding function<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use types::cef_base_t;

use libc::{self, c_int, c_void, size_t};
use std::mem;
use std::slice;
use std::str;

/// Allows you to downcast a CEF interface to a CEF class instance.
///
/// FIXME(pcwalton): This is currently unsafe. I think the right way to make this safe is to (a)
/// forbid more than one Rust implementation of a given interface (easy to do by manufacturing an
/// impl that will conflict if there is more than one) and then (b) add a dynamic check to make
/// sure the `release` for the object is equal to `servo_release`.
pub trait Downcast<Class> {
    fn downcast(&self) -> &Class;
}

pub fn slice_to_str<F>(s: *const u8, l: usize, f: F) -> c_int where F: FnOnce(&str) -> c_int {
    unsafe {
        let s = slice::from_raw_parts(s, l);
        str::from_utf8(s).map(f).unwrap_or(0)
    }
}

/// Creates a new raw CEF object of the given type and sets up its reference counting machinery.
/// All fields are initialized to zero. It is the caller's responsibility to ensure that the given
/// type is a CEF type with `cef_base_t` as its first member.
pub unsafe fn create_cef_object<Base,Extra>(size: size_t) -> *mut Base {
    let object = libc::calloc(1, (mem::size_of::<Base>() + mem::size_of::<Extra>()) as u64) as
        *mut cef_base_t;
    (*object).size = size;
    (*object).add_ref = Some(servo_add_ref as extern "C" fn(*mut cef_base_t) -> c_int);
    (*object).release = Some(servo_release as extern "C" fn(*mut cef_base_t) -> c_int);
    *ref_count(object) = 1;
    object as *mut Base
}

/// Returns a pointer to the Servo-specific reference count for the given object. This only works
/// on objects that Servo created!
unsafe fn ref_count(object: *mut cef_base_t) -> *mut usize {
    // The reference count should be the first field of the extra data.
    (object as *mut u8).offset((*object).size as isize) as *mut usize
}

/// Increments the reference count on a CEF object. This only works on objects that Servo created!
extern "C" fn servo_add_ref(object: *mut cef_base_t) -> c_int {
    unsafe {
        let count = ref_count(object);
        *count += 1;
        *count as c_int
    }
}

/// Decrements the reference count on a CEF object. If zero, frees it. This only works on objects
/// that Servo created!
extern "C" fn servo_release(object: *mut cef_base_t) -> c_int {
    unsafe {
        let count = ref_count(object);
        *count -= 1;
        let new_count = *count;
        if new_count == 0 {
            servo_free(object);
        }
        (new_count == 0) as c_int
    }
}

unsafe fn servo_free(object: *mut cef_base_t) {
    libc::free(object as *mut c_void);
}

pub unsafe fn add_ref(c_object: *mut cef_base_t) {
    ((*c_object).add_ref.unwrap())(c_object);
}

#[no_mangle]
pub extern "C" fn servo_test() -> c_int {
    1
}
<|endoftext|>


<commit_before><commit_msg>Unit test from #57866.<commit_after>// compile-pass

#![feature(type_alias_enum_variants)]

enum Outer<T> {
    A(T)
}

enum Inner {
    A(i32)
}

type OuterAlias = Outer<Inner>;

fn ice(x: OuterAlias) {
    // Fine
    match x {
        OuterAlias::A(Inner::A(_)) => (),
    }
    // Not fine
    match x {
        OuterAlias::A(Inner::A(y)) => (),
    }
}

fn main() {}
<|endoftext|>