<commit_before>use nix::sys::socket::{InetAddr, UnixAddr, getsockname};
use std::slice;
use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
use std::path::Path;
use std::str::FromStr;
use std::os::unix::io::RawFd;
use libc::c_char;

#[test]
pub fn test_inetv4_addr_to_sock_addr() {
    let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
    let addr = InetAddr::from_std(&actual);

    match addr {
        InetAddr::V4(addr) => {
            let ip: u32 = 0x7f00_0001;
            let port: u16 = 3000;

            assert_eq!(addr.sin_addr.s_addr, ip.to_be());
            assert_eq!(addr.sin_port, port.to_be());
        }
        _ => panic!("nope"),
    }

    assert_eq!(addr.to_str(), "127.0.0.1:3000");

    let inet = addr.to_std();
    assert_eq!(actual, inet);
}

#[test]
pub fn test_inetv6_addr_to_sock_addr() {
    let port: u16 = 3000;
    let flowinfo: u32 = 1;
    let scope_id: u32 = 2;
    let ip: Ipv6Addr = "fe80::1".parse().unwrap();

    let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
    let addr = InetAddr::from_std(&actual);

    match addr {
        InetAddr::V6(addr) => {
            assert_eq!(addr.sin6_port, port.to_be());
            assert_eq!(addr.sin6_flowinfo, flowinfo);
            assert_eq!(addr.sin6_scope_id, scope_id);
        }
        _ => panic!("nope"),
    }

    assert_eq!(actual, addr.to_std());
}

#[test]
pub fn test_path_to_sock_addr() {
    let path = "/foo/bar";
    let actual = Path::new(path);
    let addr = UnixAddr::new(actual).unwrap();

    let expect: &[c_char] = unsafe {
        slice::from_raw_parts(path.as_bytes().as_ptr() as *const c_char, path.len())
    };
    assert_eq!(&addr.0.sun_path[..8], expect);

    assert_eq!(addr.path(), Some(actual));
}

// Test getting/setting abstract addresses (without unix socket creation)
#[cfg(target_os = "linux")]
#[test]
pub fn test_abstract_uds_addr() {
    let empty = String::new();
    let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
    assert_eq!(addr.as_abstract(), Some(empty.as_bytes()));

    let name = String::from("nix\0abstract\0test");
    let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
    assert_eq!(addr.as_abstract(), Some(name.as_bytes()));
    assert_eq!(addr.path(), None);

    // Internally, name is null-prefixed (abstract namespace)
    let internal: &[u8] = unsafe {
        slice::from_raw_parts(addr.0.sun_path.as_ptr() as *const u8, addr.1)
    };
    let mut abstract_name = name.clone();
    abstract_name.insert(0, '\0');
    assert_eq!(internal, abstract_name.as_bytes());
}

#[test]
pub fn test_getsockname() {
    use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};
    use nix::sys::socket::{bind, SockAddr};
    use tempdir::TempDir;

    let tempdir = TempDir::new("test_getsockname").unwrap();
    let sockname = tempdir.path().join("sock");
    let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
               .expect("socket failed");
    let sockaddr = SockAddr::new_unix(&sockname).unwrap();
    bind(sock, &sockaddr).expect("bind failed");
    assert_eq!(sockaddr.to_str(),
               getsockname(sock).expect("getsockname failed").to_str());
}

#[test]
pub fn test_socketpair() {
    use nix::unistd::{read, write};
    use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag};

    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
                     .unwrap();
    write(fd1, b"hello").unwrap();
    let mut buf = [0;5];
    read(fd2, &mut buf).unwrap();

    assert_eq!(&buf[..], b"hello");
}

#[test]
pub fn test_scm_rights() {
    use nix::sys::uio::IoVec;
    use nix::unistd::{pipe, read, write, close};
    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
                           AddressFamily, SockType, SockFlag,
                           ControlMessage, CmsgSpace, MsgFlags};

    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
                     .unwrap();
    let (r, w) = pipe().unwrap();
    let mut received_r: Option<RawFd> = None;

    {
        let iov = [IoVec::from_slice(b"hello")];
        let fds = [r];
        let cmsg = ControlMessage::ScmRights(&fds);
        assert_eq!(sendmsg(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
        close(r).unwrap();
        close(fd1).unwrap();
    }

    {
        let mut buf = [0u8; 5];
        let iov = [IoVec::from_mut_slice(&mut buf[..])];
        let mut cmsgspace: CmsgSpace<[RawFd; 1]> = CmsgSpace::new();
        let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();

        for cmsg in msg.cmsgs() {
            if let ControlMessage::ScmRights(fd) = cmsg {
                assert_eq!(received_r, None);
                assert_eq!(fd.len(), 1);
                received_r = Some(fd[0]);
            } else {
                panic!("unexpected cmsg");
            }
        }
        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
        close(fd2).unwrap();
    }

    let received_r = received_r.expect("Did not receive passed fd");
    // Ensure that the received file descriptor works
    write(w, b"world").unwrap();
    let mut buf = [0u8; 5];
    read(received_r, &mut buf).unwrap();
    assert_eq!(&buf[..], b"world");
    close(received_r).unwrap();
    close(w).unwrap();
}

// Verify `sendmsg` builds a valid `msghdr` when passing an empty
// `cmsgs` argument.  This should result in a msghdr with a nullptr
// msg_control field and a msg_controllen of 0 when calling into the
// raw `sendmsg`.
#[test]
pub fn test_sendmsg_empty_cmsgs() {
    use nix::sys::uio::IoVec;
    use nix::unistd::close;
    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
                           AddressFamily, SockType, SockFlag,
                           CmsgSpace, MsgFlags};

    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
                     .unwrap();

    {
        let iov = [IoVec::from_slice(b"hello")];
        assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5);
        close(fd1).unwrap();
    }

    {
        let mut buf = [0u8; 5];
        let iov = [IoVec::from_mut_slice(&mut buf[..])];
        let mut cmsgspace: CmsgSpace<[RawFd; 1]> = CmsgSpace::new();
        let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();

        for _ in msg.cmsgs() {
            panic!("unexpected cmsg");
        }
        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
        close(fd2).unwrap();
    }
}

// Test creating and using named unix domain sockets
#[test]
pub fn test_unixdomain() {
    use nix::sys::socket::{AddressFamily, SockType, SockFlag};
    use nix::sys::socket::{bind, socket, connect, listen, accept, SockAddr};
    use nix::unistd::{read, write, close};
    use std::thread;
    use tempdir::TempDir;

    let tempdir = TempDir::new("test_unixdomain").unwrap();
    let sockname = tempdir.path().join("sock");
    let s1 = socket(AddressFamily::Unix, SockType::Stream,
                    SockFlag::empty(), None).expect("socket failed");
    let sockaddr = SockAddr::new_unix(&sockname).unwrap();
    bind(s1, &sockaddr).expect("bind failed");
    listen(s1, 10).expect("listen failed");

    let thr = thread::spawn(move || {
        let s2 = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
                 .expect("socket failed");
        connect(s2, &sockaddr).expect("connect failed");
        write(s2, b"hello").expect("write failed");
        close(s2).unwrap();
    });

    let s3 = accept(s1).expect("accept failed");

    let mut buf = [0;5];
    read(s3, &mut buf).unwrap();
    close(s3).unwrap();
    close(s1).unwrap();
    thr.join().unwrap();

    assert_eq!(&buf[..], b"hello");
}

// Test creating and using named system control sockets
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[test]
pub fn test_syscontrol() {
    use nix::Error;
    use nix::errno::Errno;
    use nix::sys::socket::{AddressFamily, socket, SockAddr, SockType, SockFlag, SockProtocol};

    let fd = socket(AddressFamily::System, SockType::Datagram,
                    SockFlag::empty(), SockProtocol::KextControl)
             .expect("socket failed");
    let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed");
    assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Error::Sys(Errno::ENOENT)));

    // requires root privileges
    // connect(fd, &sockaddr).expect("connect failed");
}

/// Test non-blocking mode on new sockets via SockFlag::O_NONBLOCK
#[cfg(any(target_os = "android",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "linux",
          target_os = "netbsd",
          target_os = "openbsd"))]
#[test]
pub fn test_sockflag_nonblock() {
    use libc;
    use nix::fcntl::{fcntl};
    use nix::fcntl::FcntlArg::{F_GETFL};
    use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};

    /* first, try without SockFlag::SOCK_NONBLOCK */
    let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
                 .expect("socket failed");

    let fcntl_res = fcntl(sock, F_GETFL).expect("fcntl failed");

    assert!(fcntl_res & libc::O_NONBLOCK == 0);

    /* next, try with SockFlag::SOCK_NONBLOCK */
    let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::SOCK_NONBLOCK, None)
                 .expect("socket failed");

    let fcntl_res = fcntl(sock, F_GETFL).expect("fcntl failed");

    assert!(fcntl_res & libc::O_NONBLOCK == libc::O_NONBLOCK);
}

/// Test close-on-exec on new sockets via SockFlag::SOCK_CLOEXEC
#[cfg(any(target_os = "android",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "linux",
          target_os = "netbsd",
          target_os = "openbsd"))]
#[test]
pub fn test_sockflag_cloexec() {
    use libc;
    use nix::fcntl::{fcntl};
    use nix::fcntl::FcntlArg::{F_GETFD};
    use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};

    /* first, test without SockFlag::SOCK_CLOEXEC */
    let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
                 .expect("socket failed");

    let fcntl_res = fcntl(sock, F_GETFD).expect("fcntl failed");

    assert!(fcntl_res & libc::FD_CLOEXEC == 0);

    /* next, test without SockFlag::SOCK_CLOEXEC */
    let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::SOCK_CLOEXEC, None)
                 .expect("socket failed");

    let fcntl_res = fcntl(sock, F_GETFD).expect("fcntl failed");

    assert!(fcntl_res & libc::FD_CLOEXEC == libc::FD_CLOEXEC);
}
<commit_msg>Remove tests that weren't mine<commit_after>use nix::sys::socket::{InetAddr, UnixAddr, getsockname};
use std::slice;
use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
use std::path::Path;
use std::str::FromStr;
use std::os::unix::io::RawFd;
use libc::c_char;

#[test]
pub fn test_inetv4_addr_to_sock_addr() {
    let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
    let addr = InetAddr::from_std(&actual);

    match addr {
        InetAddr::V4(addr) => {
            let ip: u32 = 0x7f00_0001;
            let port: u16 = 3000;

            assert_eq!(addr.sin_addr.s_addr, ip.to_be());
            assert_eq!(addr.sin_port, port.to_be());
        }
        _ => panic!("nope"),
    }

    assert_eq!(addr.to_str(), "127.0.0.1:3000");

    let inet = addr.to_std();
    assert_eq!(actual, inet);
}

#[test]
pub fn test_inetv6_addr_to_sock_addr() {
    let port: u16 = 3000;
    let flowinfo: u32 = 1;
    let scope_id: u32 = 2;
    let ip: Ipv6Addr = "fe80::1".parse().unwrap();

    let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
    let addr = InetAddr::from_std(&actual);

    match addr {
        InetAddr::V6(addr) => {
            assert_eq!(addr.sin6_port, port.to_be());
            assert_eq!(addr.sin6_flowinfo, flowinfo);
            assert_eq!(addr.sin6_scope_id, scope_id);
        }
        _ => panic!("nope"),
    }

    assert_eq!(actual, addr.to_std());
}

#[test]
pub fn test_path_to_sock_addr() {
    let path = "/foo/bar";
    let actual = Path::new(path);
    let addr = UnixAddr::new(actual).unwrap();

    let expect: &[c_char] = unsafe {
        slice::from_raw_parts(path.as_bytes().as_ptr() as *const c_char, path.len())
    };
    assert_eq!(&addr.0.sun_path[..8], expect);

    assert_eq!(addr.path(), Some(actual));
}

// Test getting/setting abstract addresses (without unix socket creation)
#[cfg(target_os = "linux")]
#[test]
pub fn test_abstract_uds_addr() {
    let empty = String::new();
    let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
    assert_eq!(addr.as_abstract(), Some(empty.as_bytes()));

    let name = String::from("nix\0abstract\0test");
    let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
    assert_eq!(addr.as_abstract(), Some(name.as_bytes()));
    assert_eq!(addr.path(), None);

    // Internally, name is null-prefixed (abstract namespace)
    let internal: &[u8] = unsafe {
        slice::from_raw_parts(addr.0.sun_path.as_ptr() as *const u8, addr.1)
    };
    let mut abstract_name = name.clone();
    abstract_name.insert(0, '\0');
    assert_eq!(internal, abstract_name.as_bytes());
}

#[test]
pub fn test_getsockname() {
    use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};
    use nix::sys::socket::{bind, SockAddr};
    use tempdir::TempDir;

    let tempdir = TempDir::new("test_getsockname").unwrap();
    let sockname = tempdir.path().join("sock");
    let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
               .expect("socket failed");
    let sockaddr = SockAddr::new_unix(&sockname).unwrap();
    bind(sock, &sockaddr).expect("bind failed");
    assert_eq!(sockaddr.to_str(),
               getsockname(sock).expect("getsockname failed").to_str());
}

#[test]
pub fn test_socketpair() {
    use nix::unistd::{read, write};
    use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag};

    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
                     .unwrap();
    write(fd1, b"hello").unwrap();
    let mut buf = [0;5];
    read(fd2, &mut buf).unwrap();

    assert_eq!(&buf[..], b"hello");
}

#[test]
pub fn test_scm_rights() {
    use nix::sys::uio::IoVec;
    use nix::unistd::{pipe, read, write, close};
    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
                           AddressFamily, SockType, SockFlag,
                           ControlMessage, CmsgSpace, MsgFlags};

    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
                     .unwrap();
    let (r, w) = pipe().unwrap();
    let mut received_r: Option<RawFd> = None;

    {
        let iov = [IoVec::from_slice(b"hello")];
        let fds = [r];
        let cmsg = ControlMessage::ScmRights(&fds);
        assert_eq!(sendmsg(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
        close(r).unwrap();
        close(fd1).unwrap();
    }

    {
        let mut buf = [0u8; 5];
        let iov = [IoVec::from_mut_slice(&mut buf[..])];
        let mut cmsgspace: CmsgSpace<[RawFd; 1]> = CmsgSpace::new();
        let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();

        for cmsg in msg.cmsgs() {
            if let ControlMessage::ScmRights(fd) = cmsg {
                assert_eq!(received_r, None);
                assert_eq!(fd.len(), 1);
                received_r = Some(fd[0]);
            } else {
                panic!("unexpected cmsg");
            }
        }
        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
        close(fd2).unwrap();
    }

    let received_r = received_r.expect("Did not receive passed fd");
    // Ensure that the received file descriptor works
    write(w, b"world").unwrap();
    let mut buf = [0u8; 5];
    read(received_r, &mut buf).unwrap();
    assert_eq!(&buf[..], b"world");
    close(received_r).unwrap();
    close(w).unwrap();
}

// Verify `sendmsg` builds a valid `msghdr` when passing an empty
// `cmsgs` argument.  This should result in a msghdr with a nullptr
// msg_control field and a msg_controllen of 0 when calling into the
// raw `sendmsg`.
#[test]
pub fn test_sendmsg_empty_cmsgs() {
    use nix::sys::uio::IoVec;
    use nix::unistd::close;
    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
                           AddressFamily, SockType, SockFlag,
                           CmsgSpace, MsgFlags};

    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
                     .unwrap();

    {
        let iov = [IoVec::from_slice(b"hello")];
        assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5);
        close(fd1).unwrap();
    }

    {
        let mut buf = [0u8; 5];
        let iov = [IoVec::from_mut_slice(&mut buf[..])];
        let mut cmsgspace: CmsgSpace<[RawFd; 1]> = CmsgSpace::new();
        let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();

        for _ in msg.cmsgs() {
            panic!("unexpected cmsg");
        }
        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
        close(fd2).unwrap();
    }
}

// Test creating and using named unix domain sockets
#[test]
pub fn test_unixdomain() {
    use nix::sys::socket::{AddressFamily, SockType, SockFlag};
    use nix::sys::socket::{bind, socket, connect, listen, accept, SockAddr};
    use nix::unistd::{read, write, close};
    use std::thread;
    use tempdir::TempDir;

    let tempdir = TempDir::new("test_unixdomain").unwrap();
    let sockname = tempdir.path().join("sock");
    let s1 = socket(AddressFamily::Unix, SockType::Stream,
                    SockFlag::empty(), None).expect("socket failed");
    let sockaddr = SockAddr::new_unix(&sockname).unwrap();
    bind(s1, &sockaddr).expect("bind failed");
    listen(s1, 10).expect("listen failed");

    let thr = thread::spawn(move || {
        let s2 = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
                 .expect("socket failed");
        connect(s2, &sockaddr).expect("connect failed");
        write(s2, b"hello").expect("write failed");
        close(s2).unwrap();
    });

    let s3 = accept(s1).expect("accept failed");

    let mut buf = [0;5];
    read(s3, &mut buf).unwrap();
    close(s3).unwrap();
    close(s1).unwrap();
    thr.join().unwrap();

    assert_eq!(&buf[..], b"hello");
}

// Test creating and using named system control sockets
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[test]
pub fn test_syscontrol() {
    use nix::Error;
    use nix::errno::Errno;
    use nix::sys::socket::{AddressFamily, socket, SockAddr, SockType, SockFlag, SockProtocol};

    let fd = socket(AddressFamily::System, SockType::Datagram,
                    SockFlag::empty(), SockProtocol::KextControl)
             .expect("socket failed");
    let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed");
    assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Error::Sys(Errno::ENOENT)));

    // requires root privileges
    // connect(fd, &sockaddr).expect("connect failed");
}
<|endoftext|>


<commit_before>use analysis::rust_type::*;
use analysis::types::*;
use codegen::sys::ffi_type::ffi_type;
use codegen::sys::functions::function_signature;
use env::Env;
use library::*;
use traits::IntoString;
use traits::MaybeRefAs;

pub struct Fields {
    /// Name of union, class, or a record that contains the fields.
    pub name: String,
    /// Is this external type?
    pub external: bool,
    /// Reason for truncating the representation, if any.
    pub truncated: Option<String>,
    derives_copy: bool,
    /// "struct" or "union"
    pub kind: &'static str,
    /// specified GObject cfg condition
    pub cfg_condition: Option<String>,
    pub fields: Vec<FieldInfo>,
}

pub struct FieldInfo {
    /// Rust field name
    pub name: String,
    /// Rust type name
    pub typ: String,
    /// Does access to this field require unsafe block?
    unsafe_access: bool,
    /// Include this field in Debug impl?
    pub debug: bool,
}

impl Fields {
    /// List of derived traits
    pub fn derived_traits(&self) -> Vec<&'static str> {
        let mut traits = Vec::new();
        if self.derives_copy {
            traits.push("Copy");
            traits.push("Clone");
        }
        traits
    }
}

impl FieldInfo {
    /// Generates a string that accesses the field in the context of &self receiver.
    pub fn access_str(&self) -> String {
        let mut s = format!("&self.{}", self.name);
        if self.unsafe_access {
            s = format!("unsafe {{ {} }}", s);
        }
        s
    }
}

pub fn from_record(env: &Env, record: &Record) -> Fields {
    let (fields, truncated) = analyze_fields(env, false, &record.fields);
    Fields {
        name: record.c_type.clone(),
        external: record.is_external(&env.library),
        truncated,
        derives_copy: record.derives_copy(&env.library),
        kind: "struct",
        cfg_condition: None,
        fields,
    }
}

pub fn from_class(env: &Env, klass: &Class) -> Fields {
    let (fields, truncated) = analyze_fields(env, false, &klass.fields);

    Fields {
        name: klass.c_type.clone(),
        external: klass.is_external(&env.library),
        truncated,
        derives_copy: klass.derives_copy(&env.library),
        kind: "struct",
        cfg_condition: get_gobject_cfg_condition(env, &klass.name),
        fields,
    }
}

pub fn from_union(env: &Env, union: &Union) -> Fields {
    let (fields, truncated) = analyze_fields(env, true, &union.fields);
    Fields {
        name: union.c_type.as_ref().unwrap().clone(),
        external: union.is_external(&env.library),
        truncated,
        derives_copy: union.derives_copy(&env.library),
        kind: "union",
        cfg_condition: None,
        fields,
    }
}

fn analyze_fields(env: &Env, unsafe_access: bool, fields: &[Field]) -> (Vec<FieldInfo>, Option<String>) {
    let mut truncated = None;
    let mut infos = Vec::with_capacity(fields.len());

    for field in fields {
        let typ = match field_ffi_type(env, field) {
            e @ Err(..) => {
                truncated = Some(e.into_string());
                break;
            }
            Ok(typ) => typ,
        };
        // Skip private fields from Debug impl. Ignore volatile as well,
        // they are usually used as synchronization primites,
        // so we wouldn't want to introduce additional reads.
        let debug = !field.private && !field.is_volatile() && field.implements_debug(&env.library);

        infos.push(FieldInfo {
            name: field.name.clone(),
            typ,
            debug,
            unsafe_access,
        });
    }

    (infos, truncated)
}

fn field_ffi_type(env: &Env, field: &Field) -> Result {
    if field.is_incomplete(&env.library) {
        return Err(TypeError::Ignored(format!("field {} has incomplete type", &field.name)));
    }
    if let Some(ref c_type) = field.c_type {
        ffi_type(env, field.typ, c_type)
    } else if let Some(func) = env.library.type_(field.typ).maybe_ref_as::<Function>() {
        let (failure, signature) = function_signature(env, func, true);
        let signature = format!("Option<unsafe extern \"C\" fn{}>", signature);
        if failure {
            Err(TypeError::Unimplemented(signature))
        } else {
            Ok(signature)
        }
    } else {
        Err(TypeError::Ignored(format!("field {} has empty c:type", &field.name)))
    }
}

fn get_gobject_cfg_condition(env: &Env, name: &String) -> Option<String> {
    let full_name = format!("{}.{}", env.namespaces.main().name, name);
    if let Some(obj) = env.config.objects.get(&full_name) {
        obj.cfg_condition.clone()
    } else {
        None
    }
}
<commit_msg>sys: generate cfg_condition for records<commit_after>use analysis::rust_type::*;
use analysis::types::*;
use codegen::sys::ffi_type::ffi_type;
use codegen::sys::functions::function_signature;
use env::Env;
use library::*;
use traits::IntoString;
use traits::MaybeRefAs;

pub struct Fields {
    /// Name of union, class, or a record that contains the fields.
    pub name: String,
    /// Is this external type?
    pub external: bool,
    /// Reason for truncating the representation, if any.
    pub truncated: Option<String>,
    derives_copy: bool,
    /// "struct" or "union"
    pub kind: &'static str,
    /// specified GObject cfg condition
    pub cfg_condition: Option<String>,
    pub fields: Vec<FieldInfo>,
}

pub struct FieldInfo {
    /// Rust field name
    pub name: String,
    /// Rust type name
    pub typ: String,
    /// Does access to this field require unsafe block?
    unsafe_access: bool,
    /// Include this field in Debug impl?
    pub debug: bool,
}

impl Fields {
    /// List of derived traits
    pub fn derived_traits(&self) -> Vec<&'static str> {
        let mut traits = Vec::new();
        if self.derives_copy {
            traits.push("Copy");
            traits.push("Clone");
        }
        traits
    }
}

impl FieldInfo {
    /// Generates a string that accesses the field in the context of &self receiver.
    pub fn access_str(&self) -> String {
        let mut s = format!("&self.{}", self.name);
        if self.unsafe_access {
            s = format!("unsafe {{ {} }}", s);
        }
        s
    }
}

pub fn from_record(env: &Env, record: &Record) -> Fields {
    let (fields, truncated) = analyze_fields(env, false, &record.fields);
    Fields {
        name: record.c_type.clone(),
        external: record.is_external(&env.library),
        truncated,
        derives_copy: record.derives_copy(&env.library),
        kind: "struct",
        cfg_condition: get_gobject_cfg_condition(env, &record.name),
        fields,
    }
}

pub fn from_class(env: &Env, klass: &Class) -> Fields {
    let (fields, truncated) = analyze_fields(env, false, &klass.fields);

    Fields {
        name: klass.c_type.clone(),
        external: klass.is_external(&env.library),
        truncated,
        derives_copy: klass.derives_copy(&env.library),
        kind: "struct",
        cfg_condition: get_gobject_cfg_condition(env, &klass.name),
        fields,
    }
}

pub fn from_union(env: &Env, union: &Union) -> Fields {
    let (fields, truncated) = analyze_fields(env, true, &union.fields);
    Fields {
        name: union.c_type.as_ref().unwrap().clone(),
        external: union.is_external(&env.library),
        truncated,
        derives_copy: union.derives_copy(&env.library),
        kind: "union",
        cfg_condition: None,
        fields,
    }
}

fn analyze_fields(env: &Env, unsafe_access: bool, fields: &[Field]) -> (Vec<FieldInfo>, Option<String>) {
    let mut truncated = None;
    let mut infos = Vec::with_capacity(fields.len());

    for field in fields {
        let typ = match field_ffi_type(env, field) {
            e @ Err(..) => {
                truncated = Some(e.into_string());
                break;
            }
            Ok(typ) => typ,
        };
        // Skip private fields from Debug impl. Ignore volatile as well,
        // they are usually used as synchronization primites,
        // so we wouldn't want to introduce additional reads.
        let debug = !field.private && !field.is_volatile() && field.implements_debug(&env.library);

        infos.push(FieldInfo {
            name: field.name.clone(),
            typ,
            debug,
            unsafe_access,
        });
    }

    (infos, truncated)
}

fn field_ffi_type(env: &Env, field: &Field) -> Result {
    if field.is_incomplete(&env.library) {
        return Err(TypeError::Ignored(format!("field {} has incomplete type", &field.name)));
    }
    if let Some(ref c_type) = field.c_type {
        ffi_type(env, field.typ, c_type)
    } else if let Some(func) = env.library.type_(field.typ).maybe_ref_as::<Function>() {
        let (failure, signature) = function_signature(env, func, true);
        let signature = format!("Option<unsafe extern \"C\" fn{}>", signature);
        if failure {
            Err(TypeError::Unimplemented(signature))
        } else {
            Ok(signature)
        }
    } else {
        Err(TypeError::Ignored(format!("field {} has empty c:type", &field.name)))
    }
}

fn get_gobject_cfg_condition(env: &Env, name: &String) -> Option<String> {
    let full_name = format!("{}.{}", env.namespaces.main().name, name);
    if let Some(obj) = env.config.objects.get(&full_name) {
        obj.cfg_condition.clone()
    } else {
        None
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]

extern crate conduit;

use std::fmt::Show;

use conduit::{Request, Response, Handler};

pub trait Middleware {
    #[allow(unused_variable)]
    fn before(&self, req: &mut Request) {}
    #[allow(unused_variable)]
    fn after(&self, req: &mut Request, &mut Response) {}
}

pub trait AroundMiddleware : Handler {
    fn with_handler(&mut self, handler: Box<Handler + 'static>);
}

pub struct MiddlewareBuilder {
    middlewares: Vec<Box<Middleware>>,
    handler: Option<Box<Handler + 'static>>
}

impl MiddlewareBuilder {
    pub fn new(handler: Box<Handler + 'static>) -> MiddlewareBuilder {
        MiddlewareBuilder {
            middlewares: vec!(),
            handler: Some(handler)
        }
    }

    pub fn add<M: Middleware + 'static>(&mut self, middleware: M) {
        self.middlewares.push(box middleware as Box<Middleware>);
    }

    pub fn around<M: AroundMiddleware + 'static>(&mut self, mut middleware: M) {
        let handler = self.handler.take_unwrap();
        middleware.with_handler(handler);
        self.handler = Some(box middleware as Box<Handler + 'static>);
    }
}

impl Handler for MiddlewareBuilder {
    fn call(&self, req: &mut Request) -> Result<Response, Box<Show>> {
        for middleware in self.middlewares.iter() {
            middleware.before(req);
        }

        match (self.handler.get_ref()).call(req) {
            Err(err) => return Err(err),
            Ok(mut res) => {
                for middleware in self.middlewares.iter() {
                   middleware.after(req, &mut res);
                }

                Ok(res)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate semver;

    use super::*;

    use std::any::{Any, AnyRefExt};
    use std::io::net::ip::IpAddr;
    use std::io::MemReader;
    use std::fmt::Show;
    use std::collections::HashMap;

    use conduit;
    use conduit::{Request, Response, Host, Headers, Method, Scheme, Extensions, Handler};

    struct RequestSentinel {
        path: String,
        extensions: HashMap<&'static str, Box<Any>>,
        method: Method
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_str(),
                extensions: HashMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<uint> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    struct MyMiddleware;

    impl Middleware for MyMiddleware {
        fn before(&self, req: &mut Request) {
            req.mut_extensions().insert("test.middleware", box "hello".to_str() as Box<Any>);
        }
    }

    struct MyAroundMiddleware {
        handler: Option<Box<Handler + 'static>>
    }

    impl MyAroundMiddleware {
        fn new() -> MyAroundMiddleware {
            MyAroundMiddleware { handler: None }
        }
    }

    impl Middleware for MyAroundMiddleware {}

    impl AroundMiddleware for MyAroundMiddleware {
        fn with_handler(&mut self, handler: Box<Handler + 'static>) {
            self.handler = Some(handler)
        }
    }

    impl Handler for MyAroundMiddleware {
        fn call(&self, req: &mut Request) -> Result<Response, Box<Show>> {
            req.mut_extensions().insert("test.round-and-round", box "hello".to_str() as Box<Any>);
            self.handler.get_ref().call(req)
        }
    }

    fn get_extension<'a, T: 'static>(req: &'a Request, key: &'static str) -> &'a T {
        req.extensions().find(&key).and_then(|s| s.as_ref::<T>())
            .expect(format!("No {} key found in extensions", key).as_slice())
    }

    fn response(string: String) -> Response {
        Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(string.into_bytes())
        }
    }

    fn handler(req: &mut Request) -> Result<Response, ()> {
        let hello = get_extension::<String>(req, "test.middleware");
        Ok(response(hello.clone()))
    }

    fn middle_handler(req: &mut Request) -> Result<Response, ()> {
        let hello = get_extension::<String>(req, "test.middleware");
        let middle = get_extension::<String>(req, "test.round-and-round");

        Ok(response(format!("{} {}", hello, middle)))
    }

    #[test]
    fn test_simple_middleware() {

        let mut builder = MiddlewareBuilder::new(box handler);
        builder.add(MyMiddleware);

        let mut req = RequestSentinel::new(conduit::Get, "/");
        let mut res = builder.call(&mut req).ok().expect("No response");

        assert_eq!(res.body.read_to_str().ok().expect("No body"), "hello".to_str());
    }

    #[test]
    fn test_around_middleware() {
        let mut builder = MiddlewareBuilder::new(box middle_handler);
        builder.add(MyMiddleware);
        builder.around(MyAroundMiddleware::new());

        let mut req = RequestSentinel::new(conduit::Get, "/");
        let mut res = builder.call(&mut req).ok().expect("No response");

        assert_eq!(res.body.read_to_str().ok().expect("No body"), "hello hello".to_str());
    }
}
<commit_msg>Middlewares can return a new Req/Res<commit_after>#![feature(globs)]

extern crate conduit;

use std::fmt::Show;

use conduit::{Request, Response, Handler};

pub trait Middleware {
    #[allow(unused_variable)]
    fn before<'a>(&self, req: &'a mut Request) -> &'a mut Request {
        req
    }
    #[allow(unused_variable)]
    fn after<'a>(&self, req: &mut Request, res: &'a mut Response) -> &'a mut Response {
        res
    }
}

pub trait AroundMiddleware : Handler {
    fn with_handler(&mut self, handler: Box<Handler + 'static>);
}

pub struct MiddlewareBuilder {
    middlewares: Vec<Box<Middleware>>,
    handler: Option<Box<Handler + 'static>>
}

impl MiddlewareBuilder {
    pub fn new(handler: Box<Handler + 'static>) -> MiddlewareBuilder {
        MiddlewareBuilder {
            middlewares: vec!(),
            handler: Some(handler)
        }
    }

    pub fn add<M: Middleware + 'static>(&mut self, middleware: M) {
        self.middlewares.push(box middleware as Box<Middleware>);
    }

    pub fn around<M: AroundMiddleware + 'static>(&mut self, mut middleware: M) {
        let handler = self.handler.take_unwrap();
        middleware.with_handler(handler);
        self.handler = Some(box middleware as Box<Handler + 'static>);
    }
}

impl Handler for MiddlewareBuilder {
    fn call(&self, req: &mut Request) -> Result<Response, Box<Show>> {
        for middleware in self.middlewares.iter() {
            middleware.before(req);
        }

        match (self.handler.get_ref()).call(req) {
            Err(err) => return Err(err),
            Ok(mut res) => {
                for middleware in self.middlewares.iter() {
                   middleware.after(req, &mut res);
                }

                Ok(res)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate semver;

    use super::*;

    use std::any::{Any, AnyRefExt};
    use std::io::net::ip::IpAddr;
    use std::io::MemReader;
    use std::fmt::Show;
    use std::collections::HashMap;

    use conduit;
    use conduit::{Request, Response, Host, Headers, Method, Scheme, Extensions, Handler};

    struct RequestSentinel {
        path: String,
        extensions: HashMap<&'static str, Box<Any>>,
        method: Method
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_str(),
                extensions: HashMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<uint> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    struct MyMiddleware;

    impl Middleware for MyMiddleware {
        fn before<'a>(&self, req: &'a mut Request) -> &'a mut Request {
            req.mut_extensions().insert("test.middleware", box "hello".to_str() as Box<Any>);
            req
        }
    }

    struct MyAroundMiddleware {
        handler: Option<Box<Handler + 'static>>
    }

    impl MyAroundMiddleware {
        fn new() -> MyAroundMiddleware {
            MyAroundMiddleware { handler: None }
        }
    }

    impl Middleware for MyAroundMiddleware {}

    impl AroundMiddleware for MyAroundMiddleware {
        fn with_handler(&mut self, handler: Box<Handler + 'static>) {
            self.handler = Some(handler)
        }
    }

    impl Handler for MyAroundMiddleware {
        fn call(&self, req: &mut Request) -> Result<Response, Box<Show>> {
            req.mut_extensions().insert("test.round-and-round", box "hello".to_str() as Box<Any>);
            self.handler.get_ref().call(req)
        }
    }

    fn get_extension<'a, T: 'static>(req: &'a Request, key: &'static str) -> &'a T {
        req.extensions().find(&key).and_then(|s| s.as_ref::<T>())
            .expect(format!("No {} key found in extensions", key).as_slice())
    }

    fn response(string: String) -> Response {
        Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(string.into_bytes())
        }
    }

    fn handler(req: &mut Request) -> Result<Response, ()> {
        let hello = get_extension::<String>(req, "test.middleware");
        Ok(response(hello.clone()))
    }

    fn middle_handler(req: &mut Request) -> Result<Response, ()> {
        let hello = get_extension::<String>(req, "test.middleware");
        let middle = get_extension::<String>(req, "test.round-and-round");

        Ok(response(format!("{} {}", hello, middle)))
    }

    #[test]
    fn test_simple_middleware() {

        let mut builder = MiddlewareBuilder::new(box handler);
        builder.add(MyMiddleware);

        let mut req = RequestSentinel::new(conduit::Get, "/");
        let mut res = builder.call(&mut req).ok().expect("No response");

        assert_eq!(res.body.read_to_str().ok().expect("No body"), "hello".to_str());
    }

    #[test]
    fn test_around_middleware() {
        let mut builder = MiddlewareBuilder::new(box middle_handler);
        builder.add(MyMiddleware);
        builder.around(MyAroundMiddleware::new());

        let mut req = RequestSentinel::new(conduit::Get, "/");
        let mut res = builder.call(&mut req).ok().expect("No response");

        assert_eq!(res.body.read_to_str().ok().expect("No body"), "hello hello".to_str());
    }
}
<|endoftext|>


<commit_before>//! Various source mapping utilities

use std::borrow::Cow;
use std::path::{Path, PathBuf};
use std::{fmt, io};

use index::{ByteIndex, ByteOffset, ColumnIndex, LineIndex, LineOffset, RawIndex, RawOffset};
use span::ByteSpan;

#[derive(Clone, Debug)]
pub enum FileName {
    /// A real file on disk
    Real(PathBuf),
    /// A synthetic file, eg. from the REPL
    Virtual(Cow<'static, str>),
}

impl From<PathBuf> for FileName {
    fn from(name: PathBuf) -> FileName {
        FileName::real(name)
    }
}

impl<'a> From<&'a Path> for FileName {
    fn from(name: &Path) -> FileName {
        FileName::real(name)
    }
}

impl From<String> for FileName {
    fn from(name: String) -> FileName {
        FileName::virtual_(name)
    }
}

impl From<&'static str> for FileName {
    fn from(name: &'static str) -> FileName {
        FileName::virtual_(name)
    }
}

impl FileName {
    pub fn real<T: Into<PathBuf>>(name: T) -> FileName {
        FileName::Real(name.into())
    }

    pub fn virtual_<T: Into<Cow<'static, str>>>(name: T) -> FileName {
        FileName::Virtual(name.into())
    }
}

impl fmt::Display for FileName {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FileName::Real(ref path) => write!(fmt, "{}", path.display()),
            FileName::Virtual(ref name) => write!(fmt, "<{}>", name),
        }
    }
}

#[derive(Debug, Fail, PartialEq)]
pub enum LineIndexError {
    #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)]
    OutOfBounds { given: LineIndex, max: LineIndex },
}

#[derive(Debug, Fail, PartialEq)]
pub enum ByteIndexError {
    #[fail(display = "Byte index out of bounds - given: {}, span: {}", given, span)]
    OutOfBounds { given: ByteIndex, span: ByteSpan },
    #[fail(display = "Byte index points within a character boundary - given: {}", given)]
    InvalidCharBoundary { given: ByteIndex },
}

#[derive(Debug, Fail, PartialEq)]
pub enum LocationError {
    #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)]
    LineOutOfBounds { given: LineIndex, max: LineIndex },
    #[fail(display = "Column out of bounds - given: {:?}, max: {:?}", given, max)]
    ColumnOutOfBounds {
        given: ColumnIndex,
        max: ColumnIndex,
    },
}

#[derive(Debug, Fail, PartialEq)]
pub enum SpanError {
    #[fail(display = "Span out of bounds - given: {}, span: {}", given, span)]
    OutOfBounds { given: ByteSpan, span: ByteSpan },
}

#[derive(Debug)]
/// Some source code
pub struct FileMap {
    /// The name of the file that the source came from
    name: FileName,
    /// The complete source code
    src: String,
    /// The span of the source in the `CodeMap`
    span: ByteSpan,
    /// Offsets to the line beginnings in the source
    lines: Vec<ByteOffset>,
}

impl FileMap {
    pub fn anonymous(src: String) -> FileMap {
        Self::new(FileName::virtual_(""), src, ByteIndex::from(1))
    }

    /// Construct a new filemap, creating an index of line start locations
    pub(crate) fn new(name: FileName, src: String, start: ByteIndex) -> FileMap {
        use std::iter;

        let span = ByteSpan::from_offset(start, ByteOffset::from_str(&src));
        let lines = {
            let newline_off = ByteOffset::from_char_utf8('\n');
            let offsets = src.match_indices('\n')
                .map(|(i, _)| ByteOffset(i as RawOffset) + newline_off);

            iter::once(ByteOffset(0)).chain(offsets).collect()
        };

        FileMap {
            name,
            src,
            span,
            lines,
        }
    }

    /// Read some source code from a file, loading it into a filemap
    pub(crate) fn from_disk<P: Into<PathBuf>>(name: P, start: ByteIndex) -> io::Result<FileMap> {
        use std::fs::File;
        use std::io::Read;

        let name = name.into();
        let mut file = File::open(&name)?;
        let mut src = String::new();
        file.read_to_string(&mut src)?;

        Ok(FileMap::new(FileName::Real(name), src, start))
    }

    /// The name of the file that the source came from
    pub fn name(&self) -> &FileName {
        &self.name
    }

    /// The underlying source code
    pub fn src(&self) -> &str {
        &self.src
    }

    /// The span of the source in the `CodeMap`
    pub fn span(&self) -> ByteSpan {
        self.span
    }

    pub fn offset(
        &self,
        line: LineIndex,
        column: ColumnIndex,
    ) -> Result<ByteOffset, LocationError> {
        self.byte_index(line, column)
            .map(|index| index - self.span.start())
    }

    pub fn byte_index(
        &self,
        line: LineIndex,
        column: ColumnIndex,
    ) -> Result<ByteIndex, LocationError> {
        self.line_span(line)
            .map_err(
                |LineIndexError::OutOfBounds { given, max }| LocationError::LineOutOfBounds {
                    given,
                    max,
                },
            )
            .and_then(|span| {
                let distance = ColumnIndex(span.end().0 - span.start().0);
                if column > distance {
                    Err(LocationError::ColumnOutOfBounds {
                        given: column,
                        max: distance,
                    })
                } else {
                    Ok(span.start() + ByteOffset::from(column.0 as i64))
                }
            })
    }

    /// Returns the byte offset to the start of `line`
    pub fn line_offset(&self, index: LineIndex) -> Result<ByteOffset, LineIndexError> {
        self.lines
            .get(index.to_usize())
            .cloned()
            .ok_or_else(|| LineIndexError::OutOfBounds {
                given: index,
                max: LineIndex(self.lines.len() as RawIndex - 1),
            })
    }

    /// Returns the byte index of the start of `line`
    pub fn line_byte_index(&self, index: LineIndex) -> Result<ByteIndex, LineIndexError> {
        self.line_offset(index)
            .map(|offset| self.span.start() + offset)
    }

    /// Returns the byte offset to the start of `line`
    pub fn line_span(&self, line: LineIndex) -> Result<ByteSpan, LineIndexError> {
        let start = self.span.start() + self.line_offset(line)?;
        let end = match self.line_offset(line + LineOffset(1)) {
            Ok(offset_hi) => self.span.start() + offset_hi,
            Err(_) => self.span.end(),
        };

        Ok(ByteSpan::new(end, start))
    }

    /// Returns the line and column location of `byte`
    pub fn location(&self, index: ByteIndex) -> Result<(LineIndex, ColumnIndex), ByteIndexError> {
        let line_index = self.find_line(index)?;
        let line_span = self.line_span(line_index).unwrap(); // line_index should be valid!
        let line_slice = self.src_slice(line_span).unwrap(); // line_span should be valid!
        let byte_col = index - line_span.start();
        let column_index =
            ColumnIndex(line_slice[..byte_col.to_usize()].chars().count() as RawIndex);

        Ok((line_index, column_index))
    }

    /// Returns the line index that the byte index points to
    pub fn find_line(&self, index: ByteIndex) -> Result<LineIndex, ByteIndexError> {
        if index < self.span.start() || index > self.span.end() {
            Err(ByteIndexError::OutOfBounds {
                given: index,
                span: self.span,
            })
        } else {
            let offset = index - self.span.start();

            if self.src.is_char_boundary(offset.to_usize()) {
                match self.lines.binary_search(&offset) {
                    Ok(i) => Ok(LineIndex(i as RawIndex)),
                    Err(i) => Ok(LineIndex(i as RawIndex - 1)),
                }
            } else {
                Err(ByteIndexError::InvalidCharBoundary {
                    given: self.span.start(),
                })
            }
        }
    }

    /// Get the corresponding source string for a span
    ///
    /// Returns `Err` if the span is outside the bounds of the file
    pub fn src_slice(&self, span: ByteSpan) -> Result<&str, SpanError> {
        if self.span.contains(span) {
            let start = (span.start() - self.span.start()).to_usize();
            let end = (span.end() - self.span.start()).to_usize();

            // TODO: check char boundaries
            Ok(&self.src[start..end])
        } else {
            Err(SpanError::OutOfBounds {
                given: span,
                span: self.span,
            })
        }
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use {CodeMap, FileMap, FileName};

    use super::*;

    struct TestData {
        filemap: Arc<FileMap>,
        lines: &'static [&'static str],
    }

    impl TestData {
        fn new() -> TestData {
            let mut codemap = CodeMap::new();
            let lines = &["hello!\n", "howdy\n", "\n", "hi萤\n", "bloop\n"];
            let filemap = codemap.add_filemap(FileName::Virtual("test".into()), lines.concat());

            TestData { filemap, lines }
        }

        fn byte_offsets(&self) -> Vec<ByteOffset> {
            let mut offset = ByteOffset(0);
            let mut byte_offsets = Vec::new();

            for line in self.lines {
                byte_offsets.push(offset);
                offset += ByteOffset::from_str(line);
                byte_offsets.push(offset + -ByteOffset::from_char_utf8('\n'));
            }

            // bump us past the end
            byte_offsets.push(offset);

            byte_offsets
        }

        fn byte_indices(&self) -> Vec<ByteIndex> {
            let mut offsets = vec![ByteIndex::none()];
            offsets.extend(self.byte_offsets().iter().map(|&off| ByteIndex(1) + off));
            let out_of_bounds = *offsets.last().unwrap() + ByteOffset(1);
            offsets.push(out_of_bounds);
            offsets
        }

        fn line_indices(&self) -> Vec<LineIndex> {
            (0..self.lines.len() + 2)
                .map(|i| LineIndex(i as RawIndex))
                .collect()
        }
    }

    #[test]
    fn offset() {
        let test_data = TestData::new();
        assert!(
            test_data
                .filemap
                .offset(
                    (test_data.lines.len() as u32 - 1).into(),
                    (test_data.lines.last().unwrap().len() as u32).into()
                )
                .is_ok()
        );
        assert!(
            test_data
                .filemap
                .offset(
                    (test_data.lines.len() as u32 - 1).into(),
                    (test_data.lines.last().unwrap().len() as u32 + 1).into()
                )
                .is_err()
        );
    }

    #[test]
    fn line_offset() {
        let test_data = TestData::new();
        let offsets: Vec<_> = test_data
            .line_indices()
            .iter()
            .map(|&i| test_data.filemap.line_offset(i))
            .collect();

        assert_eq!(
            offsets,
            vec![
                Ok(ByteOffset(0)),
                Ok(ByteOffset(7)),
                Ok(ByteOffset(13)),
                Ok(ByteOffset(14)),
                Ok(ByteOffset(20)),
                Ok(ByteOffset(26)),
                Err(LineIndexError::OutOfBounds {
                    given: LineIndex(6),
                    max: LineIndex(5),
                }),
            ],
        );
    }

    #[test]
    fn line_byte_index() {
        let test_data = TestData::new();
        let offsets: Vec<_> = test_data
            .line_indices()
            .iter()
            .map(|&i| test_data.filemap.line_byte_index(i))
            .collect();

        assert_eq!(
            offsets,
            vec![
                Ok(test_data.filemap.span().start() + ByteOffset(0)),
                Ok(test_data.filemap.span().start() + ByteOffset(7)),
                Ok(test_data.filemap.span().start() + ByteOffset(13)),
                Ok(test_data.filemap.span().start() + ByteOffset(14)),
                Ok(test_data.filemap.span().start() + ByteOffset(20)),
                Ok(test_data.filemap.span().start() + ByteOffset(26)),
                Err(LineIndexError::OutOfBounds {
                    given: LineIndex(6),
                    max: LineIndex(5),
                }),
            ],
        );
    }

    // #[test]
    // fn line_span() {
    //     let filemap = filemap();
    //     let start = filemap.span().start();

    //     assert_eq!(filemap.line_byte_index(Li(0)), Some(start + BOff(0)));
    //     assert_eq!(filemap.line_byte_index(Li(1)), Some(start + BOff(7)));
    //     assert_eq!(filemap.line_byte_index(Li(2)), Some(start + BOff(13)));
    //     assert_eq!(filemap.line_byte_index(Li(3)), Some(start + BOff(14)));
    //     assert_eq!(filemap.line_byte_index(Li(4)), Some(start + BOff(20)));
    //     assert_eq!(filemap.line_byte_index(Li(5)), Some(start + BOff(26)));
    //     assert_eq!(filemap.line_byte_index(Li(6)), None);
    // }

    #[test]
    fn location() {
        let test_data = TestData::new();
        let lines: Vec<_> = test_data
            .byte_indices()
            .iter()
            .map(|&index| test_data.filemap.location(index))
            .collect();

        assert_eq!(
            lines,
            vec![
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(0),
                    span: test_data.filemap.span(),
                }),
                Ok((LineIndex(0), ColumnIndex(0))),
                Ok((LineIndex(0), ColumnIndex(6))),
                Ok((LineIndex(1), ColumnIndex(0))),
                Ok((LineIndex(1), ColumnIndex(5))),
                Ok((LineIndex(2), ColumnIndex(0))),
                Ok((LineIndex(2), ColumnIndex(0))),
                Ok((LineIndex(3), ColumnIndex(0))),
                Ok((LineIndex(3), ColumnIndex(3))),
                Ok((LineIndex(4), ColumnIndex(0))),
                Ok((LineIndex(4), ColumnIndex(5))),
                Ok((LineIndex(5), ColumnIndex(0))),
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(28),
                    span: test_data.filemap.span(),
                }),
            ],
        );
    }

    #[test]
    fn find_line() {
        let test_data = TestData::new();
        let lines: Vec<_> = test_data
            .byte_indices()
            .iter()
            .map(|&index| test_data.filemap.find_line(index))
            .collect();

        assert_eq!(
            lines,
            vec![
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(0),
                    span: test_data.filemap.span(),
                }),
                Ok(LineIndex(0)),
                Ok(LineIndex(0)),
                Ok(LineIndex(1)),
                Ok(LineIndex(1)),
                Ok(LineIndex(2)),
                Ok(LineIndex(2)),
                Ok(LineIndex(3)),
                Ok(LineIndex(3)),
                Ok(LineIndex(4)),
                Ok(LineIndex(4)),
                Ok(LineIndex(5)),
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(28),
                    span: test_data.filemap.span(),
                }),
            ],
        );
    }
}
<commit_msg>Expose FileMap::new, remove FileMap::anonymous<commit_after>//! Various source mapping utilities

use std::borrow::Cow;
use std::path::{Path, PathBuf};
use std::{fmt, io};

use index::{ByteIndex, ByteOffset, ColumnIndex, LineIndex, LineOffset, RawIndex, RawOffset};
use span::ByteSpan;

#[derive(Clone, Debug)]
pub enum FileName {
    /// A real file on disk
    Real(PathBuf),
    /// A synthetic file, eg. from the REPL
    Virtual(Cow<'static, str>),
}

impl From<PathBuf> for FileName {
    fn from(name: PathBuf) -> FileName {
        FileName::real(name)
    }
}

impl<'a> From<&'a Path> for FileName {
    fn from(name: &Path) -> FileName {
        FileName::real(name)
    }
}

impl From<String> for FileName {
    fn from(name: String) -> FileName {
        FileName::virtual_(name)
    }
}

impl From<&'static str> for FileName {
    fn from(name: &'static str) -> FileName {
        FileName::virtual_(name)
    }
}

impl FileName {
    pub fn real<T: Into<PathBuf>>(name: T) -> FileName {
        FileName::Real(name.into())
    }

    pub fn virtual_<T: Into<Cow<'static, str>>>(name: T) -> FileName {
        FileName::Virtual(name.into())
    }
}

impl fmt::Display for FileName {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FileName::Real(ref path) => write!(fmt, "{}", path.display()),
            FileName::Virtual(ref name) => write!(fmt, "<{}>", name),
        }
    }
}

#[derive(Debug, Fail, PartialEq)]
pub enum LineIndexError {
    #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)]
    OutOfBounds { given: LineIndex, max: LineIndex },
}

#[derive(Debug, Fail, PartialEq)]
pub enum ByteIndexError {
    #[fail(display = "Byte index out of bounds - given: {}, span: {}", given, span)]
    OutOfBounds { given: ByteIndex, span: ByteSpan },
    #[fail(display = "Byte index points within a character boundary - given: {}", given)]
    InvalidCharBoundary { given: ByteIndex },
}

#[derive(Debug, Fail, PartialEq)]
pub enum LocationError {
    #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)]
    LineOutOfBounds { given: LineIndex, max: LineIndex },
    #[fail(display = "Column out of bounds - given: {:?}, max: {:?}", given, max)]
    ColumnOutOfBounds {
        given: ColumnIndex,
        max: ColumnIndex,
    },
}

#[derive(Debug, Fail, PartialEq)]
pub enum SpanError {
    #[fail(display = "Span out of bounds - given: {}, span: {}", given, span)]
    OutOfBounds { given: ByteSpan, span: ByteSpan },
}

#[derive(Debug)]
/// Some source code
pub struct FileMap {
    /// The name of the file that the source came from
    name: FileName,
    /// The complete source code
    src: String,
    /// The span of the source in the `CodeMap`
    span: ByteSpan,
    /// Offsets to the line beginnings in the source
    lines: Vec<ByteOffset>,
}

impl FileMap {
    /// Construct a new filemap, creating an index of line start locations
    pub fn new(name: FileName, src: String, start: ByteIndex) -> FileMap {
        use std::iter;

        let span = ByteSpan::from_offset(start, ByteOffset::from_str(&src));
        let lines = {
            let newline_off = ByteOffset::from_char_utf8('\n');
            let offsets = src.match_indices('\n')
                .map(|(i, _)| ByteOffset(i as RawOffset) + newline_off);

            iter::once(ByteOffset(0)).chain(offsets).collect()
        };

        FileMap {
            name,
            src,
            span,
            lines,
        }
    }

    /// Read some source code from a file, loading it into a filemap
    pub(crate) fn from_disk<P: Into<PathBuf>>(name: P, start: ByteIndex) -> io::Result<FileMap> {
        use std::fs::File;
        use std::io::Read;

        let name = name.into();
        let mut file = File::open(&name)?;
        let mut src = String::new();
        file.read_to_string(&mut src)?;

        Ok(FileMap::new(FileName::Real(name), src, start))
    }

    /// The name of the file that the source came from
    pub fn name(&self) -> &FileName {
        &self.name
    }

    /// The underlying source code
    pub fn src(&self) -> &str {
        &self.src
    }

    /// The span of the source in the `CodeMap`
    pub fn span(&self) -> ByteSpan {
        self.span
    }

    pub fn offset(
        &self,
        line: LineIndex,
        column: ColumnIndex,
    ) -> Result<ByteOffset, LocationError> {
        self.byte_index(line, column)
            .map(|index| index - self.span.start())
    }

    pub fn byte_index(
        &self,
        line: LineIndex,
        column: ColumnIndex,
    ) -> Result<ByteIndex, LocationError> {
        self.line_span(line)
            .map_err(
                |LineIndexError::OutOfBounds { given, max }| LocationError::LineOutOfBounds {
                    given,
                    max,
                },
            )
            .and_then(|span| {
                let distance = ColumnIndex(span.end().0 - span.start().0);
                if column > distance {
                    Err(LocationError::ColumnOutOfBounds {
                        given: column,
                        max: distance,
                    })
                } else {
                    Ok(span.start() + ByteOffset::from(column.0 as i64))
                }
            })
    }

    /// Returns the byte offset to the start of `line`
    pub fn line_offset(&self, index: LineIndex) -> Result<ByteOffset, LineIndexError> {
        self.lines
            .get(index.to_usize())
            .cloned()
            .ok_or_else(|| LineIndexError::OutOfBounds {
                given: index,
                max: LineIndex(self.lines.len() as RawIndex - 1),
            })
    }

    /// Returns the byte index of the start of `line`
    pub fn line_byte_index(&self, index: LineIndex) -> Result<ByteIndex, LineIndexError> {
        self.line_offset(index)
            .map(|offset| self.span.start() + offset)
    }

    /// Returns the byte offset to the start of `line`
    pub fn line_span(&self, line: LineIndex) -> Result<ByteSpan, LineIndexError> {
        let start = self.span.start() + self.line_offset(line)?;
        let end = match self.line_offset(line + LineOffset(1)) {
            Ok(offset_hi) => self.span.start() + offset_hi,
            Err(_) => self.span.end(),
        };

        Ok(ByteSpan::new(end, start))
    }

    /// Returns the line and column location of `byte`
    pub fn location(&self, index: ByteIndex) -> Result<(LineIndex, ColumnIndex), ByteIndexError> {
        let line_index = self.find_line(index)?;
        let line_span = self.line_span(line_index).unwrap(); // line_index should be valid!
        let line_slice = self.src_slice(line_span).unwrap(); // line_span should be valid!
        let byte_col = index - line_span.start();
        let column_index =
            ColumnIndex(line_slice[..byte_col.to_usize()].chars().count() as RawIndex);

        Ok((line_index, column_index))
    }

    /// Returns the line index that the byte index points to
    pub fn find_line(&self, index: ByteIndex) -> Result<LineIndex, ByteIndexError> {
        if index < self.span.start() || index > self.span.end() {
            Err(ByteIndexError::OutOfBounds {
                given: index,
                span: self.span,
            })
        } else {
            let offset = index - self.span.start();

            if self.src.is_char_boundary(offset.to_usize()) {
                match self.lines.binary_search(&offset) {
                    Ok(i) => Ok(LineIndex(i as RawIndex)),
                    Err(i) => Ok(LineIndex(i as RawIndex - 1)),
                }
            } else {
                Err(ByteIndexError::InvalidCharBoundary {
                    given: self.span.start(),
                })
            }
        }
    }

    /// Get the corresponding source string for a span
    ///
    /// Returns `Err` if the span is outside the bounds of the file
    pub fn src_slice(&self, span: ByteSpan) -> Result<&str, SpanError> {
        if self.span.contains(span) {
            let start = (span.start() - self.span.start()).to_usize();
            let end = (span.end() - self.span.start()).to_usize();

            // TODO: check char boundaries
            Ok(&self.src[start..end])
        } else {
            Err(SpanError::OutOfBounds {
                given: span,
                span: self.span,
            })
        }
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use {CodeMap, FileMap, FileName};

    use super::*;

    struct TestData {
        filemap: Arc<FileMap>,
        lines: &'static [&'static str],
    }

    impl TestData {
        fn new() -> TestData {
            let mut codemap = CodeMap::new();
            let lines = &["hello!\n", "howdy\n", "\n", "hi萤\n", "bloop\n"];
            let filemap = codemap.add_filemap(FileName::Virtual("test".into()), lines.concat());

            TestData { filemap, lines }
        }

        fn byte_offsets(&self) -> Vec<ByteOffset> {
            let mut offset = ByteOffset(0);
            let mut byte_offsets = Vec::new();

            for line in self.lines {
                byte_offsets.push(offset);
                offset += ByteOffset::from_str(line);
                byte_offsets.push(offset + -ByteOffset::from_char_utf8('\n'));
            }

            // bump us past the end
            byte_offsets.push(offset);

            byte_offsets
        }

        fn byte_indices(&self) -> Vec<ByteIndex> {
            let mut offsets = vec![ByteIndex::none()];
            offsets.extend(self.byte_offsets().iter().map(|&off| ByteIndex(1) + off));
            let out_of_bounds = *offsets.last().unwrap() + ByteOffset(1);
            offsets.push(out_of_bounds);
            offsets
        }

        fn line_indices(&self) -> Vec<LineIndex> {
            (0..self.lines.len() + 2)
                .map(|i| LineIndex(i as RawIndex))
                .collect()
        }
    }

    #[test]
    fn offset() {
        let test_data = TestData::new();
        assert!(
            test_data
                .filemap
                .offset(
                    (test_data.lines.len() as u32 - 1).into(),
                    (test_data.lines.last().unwrap().len() as u32).into()
                )
                .is_ok()
        );
        assert!(
            test_data
                .filemap
                .offset(
                    (test_data.lines.len() as u32 - 1).into(),
                    (test_data.lines.last().unwrap().len() as u32 + 1).into()
                )
                .is_err()
        );
    }

    #[test]
    fn line_offset() {
        let test_data = TestData::new();
        let offsets: Vec<_> = test_data
            .line_indices()
            .iter()
            .map(|&i| test_data.filemap.line_offset(i))
            .collect();

        assert_eq!(
            offsets,
            vec![
                Ok(ByteOffset(0)),
                Ok(ByteOffset(7)),
                Ok(ByteOffset(13)),
                Ok(ByteOffset(14)),
                Ok(ByteOffset(20)),
                Ok(ByteOffset(26)),
                Err(LineIndexError::OutOfBounds {
                    given: LineIndex(6),
                    max: LineIndex(5),
                }),
            ],
        );
    }

    #[test]
    fn line_byte_index() {
        let test_data = TestData::new();
        let offsets: Vec<_> = test_data
            .line_indices()
            .iter()
            .map(|&i| test_data.filemap.line_byte_index(i))
            .collect();

        assert_eq!(
            offsets,
            vec![
                Ok(test_data.filemap.span().start() + ByteOffset(0)),
                Ok(test_data.filemap.span().start() + ByteOffset(7)),
                Ok(test_data.filemap.span().start() + ByteOffset(13)),
                Ok(test_data.filemap.span().start() + ByteOffset(14)),
                Ok(test_data.filemap.span().start() + ByteOffset(20)),
                Ok(test_data.filemap.span().start() + ByteOffset(26)),
                Err(LineIndexError::OutOfBounds {
                    given: LineIndex(6),
                    max: LineIndex(5),
                }),
            ],
        );
    }

    // #[test]
    // fn line_span() {
    //     let filemap = filemap();
    //     let start = filemap.span().start();

    //     assert_eq!(filemap.line_byte_index(Li(0)), Some(start + BOff(0)));
    //     assert_eq!(filemap.line_byte_index(Li(1)), Some(start + BOff(7)));
    //     assert_eq!(filemap.line_byte_index(Li(2)), Some(start + BOff(13)));
    //     assert_eq!(filemap.line_byte_index(Li(3)), Some(start + BOff(14)));
    //     assert_eq!(filemap.line_byte_index(Li(4)), Some(start + BOff(20)));
    //     assert_eq!(filemap.line_byte_index(Li(5)), Some(start + BOff(26)));
    //     assert_eq!(filemap.line_byte_index(Li(6)), None);
    // }

    #[test]
    fn location() {
        let test_data = TestData::new();
        let lines: Vec<_> = test_data
            .byte_indices()
            .iter()
            .map(|&index| test_data.filemap.location(index))
            .collect();

        assert_eq!(
            lines,
            vec![
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(0),
                    span: test_data.filemap.span(),
                }),
                Ok((LineIndex(0), ColumnIndex(0))),
                Ok((LineIndex(0), ColumnIndex(6))),
                Ok((LineIndex(1), ColumnIndex(0))),
                Ok((LineIndex(1), ColumnIndex(5))),
                Ok((LineIndex(2), ColumnIndex(0))),
                Ok((LineIndex(2), ColumnIndex(0))),
                Ok((LineIndex(3), ColumnIndex(0))),
                Ok((LineIndex(3), ColumnIndex(3))),
                Ok((LineIndex(4), ColumnIndex(0))),
                Ok((LineIndex(4), ColumnIndex(5))),
                Ok((LineIndex(5), ColumnIndex(0))),
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(28),
                    span: test_data.filemap.span(),
                }),
            ],
        );
    }

    #[test]
    fn find_line() {
        let test_data = TestData::new();
        let lines: Vec<_> = test_data
            .byte_indices()
            .iter()
            .map(|&index| test_data.filemap.find_line(index))
            .collect();

        assert_eq!(
            lines,
            vec![
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(0),
                    span: test_data.filemap.span(),
                }),
                Ok(LineIndex(0)),
                Ok(LineIndex(0)),
                Ok(LineIndex(1)),
                Ok(LineIndex(1)),
                Ok(LineIndex(2)),
                Ok(LineIndex(2)),
                Ok(LineIndex(3)),
                Ok(LineIndex(3)),
                Ok(LineIndex(4)),
                Ok(LineIndex(4)),
                Ok(LineIndex(5)),
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(28),
                    span: test_data.filemap.span(),
                }),
            ],
        );
    }
}
<|endoftext|>


<commit_before>#![warn(unused_results)]

extern crate getopts;
extern crate data_encoding;

use std::fs::File;
use std::io::Write;

use getopts::Options;

#[macro_use]
mod tool;
mod base;
mod error;
mod io;

use base::{Base, lookup};
use error::Error;
use io::{ReadShift, Operation, Skip, Wrap, repeat};

fn main() {
    let (program, args): (_, Vec<_>) = {
        let mut i = std::env::args();
        match i.next() {
            None => ("encode".into(), vec![]),
            Some(p) => (p, i.collect()),
        }
    };
    let program = program.rsplit('/').next().unwrap_or(&program);

    if let Err(e) = wrapped_main(program, args) {
        let _ = writeln!(&mut std::io::stderr(), "{}: {}", program, e);
        std::process::exit(1)
    }
}

fn wrapped_main(program: &str, args: Vec<String>) -> Result<(), Error> {
    // Define options.
    let mut opts = Options::new();
    let opts = opts
        .optopt("b", "base", "select base 2, 4, 8, 16 (or hex), 32, 32hex, 64, or 64url if <name> matches. Otherwise, build base using the first character of <name> as padding and the remaining characters as symbols in value order. Default is 64.", "<name>")
        .optflag("d", "decode", "decode data. Default is to encode data.")
        .optopt("i", "input", "use <file> as input. Default is to use standard input.", "<file>")
        .optopt("o", "output", "use <file> as output. Default is to use standard output.", "<file>")
        .optflag("s", "skip", "when decoding, skip newlines. Default is to accept only well-formed input.")
        .optopt("w", "wrap", "when encoding, add newlines every <cols> characters and at the end. Default is to produce well-formed output.", "<cols>")
        ;

    // Deal with --help.
    if args.len() == 1 && (args[0] == "--help" || args[0] == "-h") {
        let brief = format!("Usage: {} [<options>]", program);
        print!("{}", opts.usage(&brief));
        println!("\nExamples:");
        println!("    {}", program);
        println!("    {} -d", program);
        println!("    {} -b32 -d -s", program);
        println!("    {} -b=0123456789abcdef -w76", program);
        return Ok(());
    }

    // Parse options.
    let matches = try!(opts.parse(&args).map_err(Error::ParseOpts));
    check!(matches.free.len() == 0, Error::ExtraArgs);

    // Deal with --base.
    let name = matches.opt_str("b").unwrap_or("64".into());
    let base = try!(base::lookup(name));

    // Deal with --input.
    let mut input: Box<ReadShift>;
    if let Some(file) = matches.opt_str("i") {
        input = Box::new(try!(File::open(&file).map_err(|e| Error::Open(file, e))));
    } else {
        input = Box::new(std::io::stdin());
    };

    // Deal with --output.
    let mut output: Box<Write>;
    if let Some(file) = matches.opt_str("o") {
        output = Box::new(try!(File::create(&file).map_err(|e| Error::Create(file, e))));
    } else {
        // TODO: Change the following lines when Stdout does not go
        // through a LineWriter anymore.
        output = Box::new(unsafe { <File as std::os::unix::io::FromRawFd>::from_raw_fd(1) });
        // output = Box::new(std::io::stdout());
    }
    output = Box::new(std::io::BufWriter::new(output));

    // Deal with --decode, --wrap, and --skip.
    let operation: Operation;
    let size = 8192;
    let imod;
    let omod;
    if matches.opt_present("d") {
        check!(!matches.opt_present("w"), Error::WrapDecode);
        imod = base.encode_len(1);
        omod = base.decode_len(1);
        operation = Box::new(move |i, o| Ok(try!(base.decode_mut(i, o))));
        if matches.opt_present("s") {
            input = Box::new(Skip::new(input));
        }
    } else {
        check!(!matches.opt_present("s"), Error::SkipEncode);
        imod = base.decode_len(1);
        omod = base.encode_len(1);
        operation = Box::new(move |i, o| { base.encode_mut(i, o); Ok(o.len()) });
        let cols = matches.opt_str("w").unwrap_or("0".into());
        let cols = try!(cols.parse().map_err(Error::ParseWrap));
        if cols > 0 {
            output = Box::new(Wrap::new(output, cols));
        }
    }

    // Do the real work.
    repeat(input, output, operation, size, imod, omod)
}
<commit_msg>Add todo for encode example<commit_after>#![warn(unused_results)]

// TODO: Instead of --base <base> and --decode, maybe use --from <base> and --to <base>
// With <base> in 2, 4, 8, 16, hex, 32, 32hex, 64, 64url, raw, <custom>
//      <custom> is <pad><symbols>

extern crate getopts;
extern crate data_encoding;

use std::fs::File;
use std::io::Write;

use getopts::Options;

#[macro_use]
mod tool;
mod base;
mod error;
mod io;

use base::{Base, lookup};
use error::Error;
use io::{ReadShift, Operation, Skip, Wrap, repeat};

fn main() {
    let (program, args): (_, Vec<_>) = {
        let mut i = std::env::args();
        match i.next() {
            None => ("encode".into(), vec![]),
            Some(p) => (p, i.collect()),
        }
    };
    let program = program.rsplit('/').next().unwrap_or(&program);

    if let Err(e) = wrapped_main(program, args) {
        let _ = writeln!(&mut std::io::stderr(), "{}: {}", program, e);
        std::process::exit(1)
    }
}

fn wrapped_main(program: &str, args: Vec<String>) -> Result<(), Error> {
    // Define options.
    let mut opts = Options::new();
    let opts = opts
        .optopt("b", "base", "select base 2, 4, 8, 16 (or hex), 32, 32hex, 64, or 64url if <name> matches. Otherwise, build base using the first character of <name> as padding and the remaining characters as symbols in value order. Default is 64.", "<name>")
        .optflag("d", "decode", "decode data. Default is to encode data.")
        .optopt("i", "input", "use <file> as input. Default is to use standard input.", "<file>")
        .optopt("o", "output", "use <file> as output. Default is to use standard output.", "<file>")
        .optflag("s", "skip", "when decoding, skip newlines. Default is to accept only well-formed input.")
        .optopt("w", "wrap", "when encoding, add newlines every <cols> characters and at the end. Default is to produce well-formed output.", "<cols>")
        ;

    // Deal with --help.
    if args.len() == 1 && (args[0] == "--help" || args[0] == "-h") {
        let brief = format!("Usage: {} [<options>]", program);
        print!("{}", opts.usage(&brief));
        println!("\nExamples:");
        println!("    {}", program);
        println!("    {} -d", program);
        println!("    {} -b32 -d -s", program);
        println!("    {} -b=0123456789abcdef -w76", program);
        return Ok(());
    }

    // Parse options.
    let matches = try!(opts.parse(&args).map_err(Error::ParseOpts));
    check!(matches.free.len() == 0, Error::ExtraArgs);

    // Deal with --base.
    let name = matches.opt_str("b").unwrap_or("64".into());
    let base = try!(base::lookup(name));

    // Deal with --input.
    let mut input: Box<ReadShift>;
    if let Some(file) = matches.opt_str("i") {
        input = Box::new(try!(File::open(&file).map_err(|e| Error::Open(file, e))));
    } else {
        input = Box::new(std::io::stdin());
    };

    // Deal with --output.
    let mut output: Box<Write>;
    if let Some(file) = matches.opt_str("o") {
        output = Box::new(try!(File::create(&file).map_err(|e| Error::Create(file, e))));
    } else {
        // TODO: Change the following lines when Stdout does not go
        // through a LineWriter anymore.
        output = Box::new(unsafe { <File as std::os::unix::io::FromRawFd>::from_raw_fd(1) });
        // output = Box::new(std::io::stdout());
    }
    output = Box::new(std::io::BufWriter::new(output));

    // Deal with --decode, --wrap, and --skip.
    let operation: Operation;
    let size = 8192;
    let imod;
    let omod;
    if matches.opt_present("d") {
        check!(!matches.opt_present("w"), Error::WrapDecode);
        imod = base.encode_len(1);
        omod = base.decode_len(1);
        operation = Box::new(move |i, o| Ok(try!(base.decode_mut(i, o))));
        if matches.opt_present("s") {
            input = Box::new(Skip::new(input));
        }
    } else {
        check!(!matches.opt_present("s"), Error::SkipEncode);
        imod = base.decode_len(1);
        omod = base.encode_len(1);
        operation = Box::new(move |i, o| { base.encode_mut(i, o); Ok(o.len()) });
        let cols = matches.opt_str("w").unwrap_or("0".into());
        let cols = try!(cols.parse().map_err(Error::ParseWrap));
        if cols > 0 {
            output = Box::new(Wrap::new(output, cols));
        }
    }

    // Do the real work.
    repeat(input, output, operation, size, imod, omod)
}
<|endoftext|>


<commit_before>extern crate gauc;
extern crate env_logger;

use gauc::client::*;
use std::{thread, time};

fn main() {
    env_logger::init().unwrap();

    let mut client = Client::new("couchbase://korczis.com/default");

    for i in 0..100 {
        println!("Iteration #{}", i);

        // Store some data
        client.upsert(&format!("foo {}", i), &format!("This is test No. {}!", i), |res| {
            if let Ok(response) = res {
                println!("Created new document, CAS: {}", response.cas)
            }
        });
    }
    for i in 0..100 {
        // Get data
        client.get(&format!("foo {}", i), |res| {
            if let Ok(response) = res {
                println!("{} - {}", response.key.unwrap(), response.value.unwrap())
            }
        });
    }

    let sleep_interval = time::Duration::from_millis(1000);
    thread::sleep(sleep_interval);
}
<commit_msg>Use hey without space<commit_after>extern crate gauc;
extern crate env_logger;

use gauc::client::*;
use std::{thread, time};

fn main() {
    env_logger::init().unwrap();

    let mut client = Client::new("couchbase://korczis.com/default");

    for i in 0..100 {
        println!("Iteration #{}", i);

        // Store some data
        client.upsert(&format!("foo{}", i), &format!("This is test No. {}!", i), |res| {
            if let Ok(response) = res {
                println!("Created new document, CAS: {}", response.cas)
            }
        });
    }
    for i in 0..100 {
        // Get data
        client.get(&format!("foo{}", i), |res| {
            if let Ok(response) = res {
                println!("Got response: {} - {}", response.key.unwrap(), response.value.unwrap())
            }
        });
    }

    let sleep_interval = time::Duration::from_millis(1000);
    thread::sleep(sleep_interval);
}
<|endoftext|>


<commit_before>extern crate coroutine;
extern crate num_cpus;

use std::thread;

use coroutine::{spawn, sched};

fn main() {

    let mut threads = Vec::with_capacity(num_cpus::get());

    for i in 0..num_cpus::get() {
        let t = thread::scoped(move|| {
            spawn(move|| {
                let thread_id = i;
                spawn(move|| {
                    for count in 0..10 {
                        println!("Coroutine running in thread {}: counting {}", thread_id, count);
                        sched();
                    }
                }).join().ok().expect("Failed to join");
            }).join().ok().expect("Failed to join");
        });
        threads.push(t);
    }

    for t in threads.into_iter() {
        t.join();
    }
}
<commit_msg>build with nightly, use unstable `scoped` feature<commit_after>#![feature(scoped)]
extern crate coroutine;
extern crate num_cpus;

use std::thread;

use coroutine::{spawn, sched};

fn main() {

    let mut threads = Vec::with_capacity(num_cpus::get());

    for i in 0..num_cpus::get() {
        let t = thread::scoped(move|| {
            spawn(move|| {
                let thread_id = i;
                spawn(move|| {
                    for count in 0..10 {
                        println!("Coroutine running in thread {}: counting {}", thread_id, count);
                        sched();
                    }
                }).join().ok().expect("Failed to join");
            }).join().ok().expect("Failed to join");
        });
        threads.push(t);
    }

    for t in threads.into_iter() {
        t.join();
    }
}
<|endoftext|>


<commit_before>extern crate odbc_safe;
use odbc_safe::*;
use std::str::from_utf8;

fn main() {

    let env = Environment::new().unwrap();
    let env = env.declare_version_3_8().unwrap();
    let conn = connect(&env);
    print_fields(execute_query(&conn));
    conn.disconnect().unwrap();
}

fn connect<V>(env: &Environment<V>) -> Connection<Connected>
where
    V: Version,
{
    let conn = Connection::with_parent(env).unwrap();
    conn.connect("TestDataSource", "", "").unwrap()
}

fn execute_query<'a>(conn: &'a Connection<Connected>) -> Statement<'a, HasResult> {
    let stmt = Statement::with_parent(conn).unwrap();
    match stmt.exec_direct("SELECT * FROM MOVIES") {
        ReturnNoData::Success(s) | ReturnNoData::Info(s) => s,
        ReturnNoData::NoData(_) | ReturnNoData::Error(_) => panic!("No Result Set"),
    }
}

fn print_fields(mut result_set: Statement<HasResult>) {
    let cols = result_set.num_result_cols().unwrap();
    let mut buffer = [0u8; 512];
    loop {
        result_set = match result_set.fetch() {
            ReturnNoData::Success(r) | ReturnNoData::Info(r) => r,
            ReturnNoData::NoData(_) | ReturnNoData::Error(_) => break,
        };
        for index in 1..(cols + 1) {
            match result_set.get_data(index as u16, &mut buffer as &mut [u8]) {
                ReturnNoData::Success(ind) | ReturnNoData::Info(ind) => {
                    match ind {
                        Indicator::NoTotal => panic!("No Total"),
                        Indicator::Null => println!("NULL"),
                        Indicator::Length(l) => {
                            print!("{}", from_utf8(&buffer[0..l as usize]).unwrap());
                        }
                    }
                }
                ReturnNoData::NoData(_) | ReturnNoData::Error(_) => panic!("No Field Data"),
            }
            print!(" | ");
        }
        println!("");
    }
}
<commit_msg>change odbc version to 3<commit_after>extern crate odbc_safe;
use odbc_safe::*;
use std::str::from_utf8;

fn main() {

    let env = Environment::new().unwrap();
    let env = env.declare_version_3().unwrap();
    let conn = connect(&env);
    print_fields(execute_query(&conn));
    conn.disconnect().unwrap();
}

fn connect<V>(env: &Environment<V>) -> Connection<Connected>
where
    V: Version,
{
    let conn = Connection::with_parent(env).unwrap();
    conn.connect("TestDataSource", "", "").unwrap()
}

fn execute_query<'a>(conn: &'a Connection<Connected>) -> Statement<'a, HasResult> {
    let stmt = Statement::with_parent(conn).unwrap();
    match stmt.exec_direct("SELECT * FROM MOVIES") {
        ReturnNoData::Success(s) | ReturnNoData::Info(s) => s,
        ReturnNoData::NoData(_) | ReturnNoData::Error(_) => panic!("No Result Set"),
    }
}

fn print_fields(mut result_set: Statement<HasResult>) {
    let cols = result_set.num_result_cols().unwrap();
    let mut buffer = [0u8; 512];
    loop {
        result_set = match result_set.fetch() {
            ReturnNoData::Success(r) | ReturnNoData::Info(r) => r,
            ReturnNoData::NoData(_) | ReturnNoData::Error(_) => break,
        };
        for index in 1..(cols + 1) {
            match result_set.get_data(index as u16, &mut buffer as &mut [u8]) {
                ReturnNoData::Success(ind) | ReturnNoData::Info(ind) => {
                    match ind {
                        Indicator::NoTotal => panic!("No Total"),
                        Indicator::Null => println!("NULL"),
                        Indicator::Length(l) => {
                            print!("{}", from_utf8(&buffer[0..l as usize]).unwrap());
                        }
                    }
                }
                ReturnNoData::NoData(_) | ReturnNoData::Error(_) => panic!("No Field Data"),
            }
            print!(" | ");
        }
        println!("");
    }
}
<|endoftext|>


<commit_before>extern crate image;
use std::path::Path;

use simple_logger::SimpleLogger;
use winit::{
    event::Event,
    event_loop::{ControlFlow, EventLoop},
    window::{Icon, WindowBuilder},
};

fn main() {
    SimpleLogger::new().init().unwrap();

    // You'll have to choose an icon size at your own discretion. On X11, the desired size varies
    // by WM, and on Windows, you still have to account for screen scaling. Here we use 32px,
    // since it seems to work well enough in most cases. Be careful about going too high, or
    // you'll be bitten by the low-quality downscaling built into the WM.
    let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png");

    let icon = load_icon(Path::new(path));

    let event_loop = EventLoop::new();

    let window = WindowBuilder::new()
        .with_title("An iconic window!")
        // At present, this only does anything on Windows and X11, so if you want to save load
        // time, you can put icon loading behind a function that returns `None` on other platforms.
        .with_window_icon(Some(icon))
        .build(&event_loop)
        .unwrap();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Wait;

        if let Event::WindowEvent { event, .. } = event {
            use winit::event::WindowEvent::*;
            match event {
                CloseRequested => *control_flow = ControlFlow::Exit,
                DroppedFile(path) => {
                    window.set_window_icon(Some(load_icon(&path)));
                }
                _ => (),
            }
        }
    });
}

fn load_icon(path: &Path) -> Icon {
    let (icon_rgba, icon_width, icon_height) = {
        let image = image::open(path)
            .expect("Failed to open icon path")
            .into_rgba();
        let (width, height) = image.dimensions();
        let rgba = image.into_raw();
        (rgba, width, height)
    };
    Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon")
}
<commit_msg>Fix deprecation warning in the window icon example<commit_after>extern crate image;
use std::path::Path;

use simple_logger::SimpleLogger;
use winit::{
    event::Event,
    event_loop::{ControlFlow, EventLoop},
    window::{Icon, WindowBuilder},
};

fn main() {
    SimpleLogger::new().init().unwrap();

    // You'll have to choose an icon size at your own discretion. On X11, the desired size varies
    // by WM, and on Windows, you still have to account for screen scaling. Here we use 32px,
    // since it seems to work well enough in most cases. Be careful about going too high, or
    // you'll be bitten by the low-quality downscaling built into the WM.
    let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png");

    let icon = load_icon(Path::new(path));

    let event_loop = EventLoop::new();

    let window = WindowBuilder::new()
        .with_title("An iconic window!")
        // At present, this only does anything on Windows and X11, so if you want to save load
        // time, you can put icon loading behind a function that returns `None` on other platforms.
        .with_window_icon(Some(icon))
        .build(&event_loop)
        .unwrap();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Wait;

        if let Event::WindowEvent { event, .. } = event {
            use winit::event::WindowEvent::*;
            match event {
                CloseRequested => *control_flow = ControlFlow::Exit,
                DroppedFile(path) => {
                    window.set_window_icon(Some(load_icon(&path)));
                }
                _ => (),
            }
        }
    });
}

fn load_icon(path: &Path) -> Icon {
    let (icon_rgba, icon_width, icon_height) = {
        let image = image::open(path)
            .expect("Failed to open icon path")
            .into_rgba8();
        let (width, height) = image.dimensions();
        let rgba = image.into_raw();
        (rgba, width, height)
    };
    Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon")
}
<|endoftext|>