<commit_before>use std::io;
use std::ffi::{CString, OsStr, OsString};
use std::os::unix::io::RawFd;
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::path::Path;
use std::mem;

use libc::consts::os::posix88::EPERM;
use libc::{c_char, ssize_t, size_t, c_int, c_void};
use util::{path_to_c, allocate_loop};

const EXTATTR_NAMESPACE_USER_STRING: &'static str = "user";
const EXTATTR_NAMESPACE_SYSTEM_STRING: &'static str = "system";
const EXTATTR_NAMESPACE_NAMES: [&'static str; 3] = ["empty",
                                                    EXTATTR_NAMESPACE_USER_STRING,
                                                    EXTATTR_NAMESPACE_SYSTEM_STRING];
const EXTATTR_NAMESPACE_USER: c_int = 1;
const EXTATTR_NAMESPACE_SYSTEM: c_int = 2;

extern "C" {
    pub fn extattr_list_fd(fd: c_int,
                           attrnamespace: c_int,
                           data: *mut c_void,
                           nbytes: size_t)
                           -> ssize_t;
    pub fn extattr_get_fd(fd: c_int,
                          attrnamespace: c_int,
                          attrname: *const c_char,
                          data: *mut c_void,
                          nbytes: size_t)
                          -> ssize_t;
    pub fn extattr_delete_fd(fd: c_int, attrname: c_int, attrname: *const c_char) -> c_int;
    pub fn extattr_set_fd(fd: c_int,
                          attrname: c_int,
                          attrname: *const c_char,
                          data: *const c_void,
                          nbytes: size_t)
                          -> ssize_t;

    pub fn extattr_list_link(path: *const c_char,
                             attrnamespace: c_int,
                             data: *mut c_void,
                             nbytes: size_t)
                             -> ssize_t;
    pub fn extattr_get_link(path: *const c_char,
                            attrnamespace: c_int,
                            attrname: *const c_char,
                            data: *mut c_void,
                            nbytes: size_t)
                            -> ssize_t;
    pub fn extattr_delete_link(path: *const c_char,
                               attrname: c_int,
                               attrname: *const c_char)
                               -> c_int;
    pub fn extattr_set_link(path: *const c_char,
                            attrname: c_int,
                            attrname: *const c_char,
                            data: *const c_void,
                            nbytes: size_t)
                            -> ssize_t;
}

pub struct XAttrs {
    user_attrs: Box<[u8]>,
    system_attrs: Box<[u8]>,
    offset: usize,
}

impl Clone for XAttrs {
    fn clone(&self) -> Self {
        XAttrs {
            user_attrs: Vec::from(&*self.user_attrs).into_boxed_slice(),
            system_attrs: Vec::from(&*self.system_attrs).into_boxed_slice(),
            offset: self.offset,
        }
    }

    fn clone_from(&mut self, other: &XAttrs) {
        self.offset = other.offset;

        let mut data = mem::replace(&mut self.user_attrs, Box::new([])).into_vec();
        data.extend(other.user_attrs.iter().cloned());
        self.user_attrs = data.into_boxed_slice();

        data = mem::replace(&mut self.system_attrs, Box::new([])).into_vec();
        data.extend(other.system_attrs.iter().cloned());
        self.system_attrs = data.into_boxed_slice();
    }
}

impl Iterator for XAttrs {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        if self.user_attrs.is_empty() && self.system_attrs.is_empty() {
            return None;
        }

        if self.offset == self.user_attrs.len() + self.system_attrs.len() {
            return None;
        }

        let data = if self.offset < self.system_attrs.len() {
            &self.system_attrs[self.offset..]
        } else {
            &self.user_attrs[self.offset - self.system_attrs.len()..]
        };

        let siz = data[0] as usize;

        self.offset += siz + 1;
        if self.offset < self.system_attrs.len() {
            Some(prefix_namespace(OsStr::from_bytes(&data[1..siz + 1]),
                                  EXTATTR_NAMESPACE_SYSTEM))
        } else {
            Some(prefix_namespace(OsStr::from_bytes(&data[1..siz + 1]), EXTATTR_NAMESPACE_USER))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.user_attrs.len() + self.system_attrs.len() == self.offset {
            (0, Some(0))
        } else {
            (1, None)
        }
    }
}

fn name_to_ns(name: &OsStr) -> io::Result<(c_int, CString)> {
    let mut groups = name.as_bytes().splitn(2, |&b| b == b'.').take(2);
    let nsname = match groups.next() {
        Some(s) => s,
        None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "couldn't find namespace")),
    };

    let propname = match groups.next() {
        Some(s) => s,
        None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "couldn't find attribute")),
    };

    let ns_int = match EXTATTR_NAMESPACE_NAMES.iter().position(|&s| s.as_bytes() == nsname) {
        Some(i) => i,
        None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "no matching namespace")),
    };

    Ok((ns_int as c_int, try!(CString::new(propname))))
}

fn prefix_namespace(attr: &OsStr, ns: c_int) -> OsString {
    let nsname = EXTATTR_NAMESPACE_NAMES[ns as usize];
    let mut v = Vec::with_capacity(nsname.as_bytes().len() + attr.as_bytes().len() + 1);
    v.extend(nsname.as_bytes());
    v.extend(".".as_bytes());
    v.extend(attr.as_bytes());
    OsString::from_vec(v)
}

pub fn get_fd(fd: RawFd, name: &OsStr) -> io::Result<Vec<u8>> {
    let (ns, name) = try!(name_to_ns(name));
    unsafe {
        allocate_loop(|buf, len| {
            extattr_get_fd(fd, ns, name.as_ptr(), buf as *mut c_void, len as size_t)
        })
    }
}

pub fn set_fd(fd: RawFd, name: &OsStr, value: &[u8]) -> io::Result<()> {
    let (ns, name) = try!(name_to_ns(name));
    let ret = unsafe {
        extattr_set_fd(fd,
                       ns,
                       name.as_ptr(),
                       value.as_ptr() as *const c_void,
                       value.len() as size_t)
    };
    if ret == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

pub fn remove_fd(fd: RawFd, name: &OsStr) -> io::Result<()> {
    let (ns, name) = try!(name_to_ns(name));
    let ret = unsafe { extattr_delete_fd(fd, ns, name.as_ptr()) };
    if ret != 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

pub fn list_fd(fd: RawFd) -> io::Result<XAttrs> {
    let sysvec = unsafe {
        let res = allocate_loop(|buf, len| {
            extattr_list_fd(fd,
                            EXTATTR_NAMESPACE_SYSTEM,
                            buf as *mut c_void,
                            len as size_t)
        });
        // On FreeBSD, system attributes require root privileges to view. However,
        // to mimic the behavior of listxattr in linux and osx, we need to query
        // them anyway and return empty results if we get EPERM
        match res {
            Ok(v) => v,
            Err(err) => {
                if err.raw_os_error() == Some(EPERM) {
                    Vec::new()
                } else {
                    return Err(err);
                }
            }
        }
    };

    let uservec = unsafe {
        let res = allocate_loop(|buf, len| {
            extattr_list_fd(fd,
                            EXTATTR_NAMESPACE_USER,
                            buf as *mut c_void,
                            len as size_t)
        });
        match res {
            Ok(v) => v,
            Err(err) => return Err(err),
        }
    };

    Ok(XAttrs {
        system_attrs: sysvec.into_boxed_slice(),
        user_attrs: uservec.into_boxed_slice(),
        offset: 0,
    })
}

pub fn get_path(path: &Path, name: &OsStr) -> io::Result<Vec<u8>> {
    let (ns, name) = try!(name_to_ns(name));
    let path = try!(path_to_c(path));
    unsafe {
        allocate_loop(|buf, len| {
            extattr_get_link(path.as_ptr(),
                             ns,
                             name.as_ptr(),
                             buf as *mut c_void,
                             len as size_t)
        })
    }
}

pub fn set_path(path: &Path, name: &OsStr, value: &[u8]) -> io::Result<()> {
    let (ns, name) = try!(name_to_ns(name));
    let path = try!(path_to_c(path));
    let ret = unsafe {
        extattr_set_link(path.as_ptr(),
                         ns,
                         name.as_ptr(),
                         value.as_ptr() as *const c_void,
                         value.len() as size_t)
    };
    if ret == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

pub fn remove_path(path: &Path, name: &OsStr) -> io::Result<()> {
    let (ns, name) = try!(name_to_ns(name));
    let path = try!(path_to_c(path));
    let ret = unsafe { extattr_delete_link(path.as_ptr(), ns, name.as_ptr()) };
    if ret != 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

pub fn list_path(path: &Path) -> io::Result<XAttrs> {
    let path = try!(path_to_c(path));
    let sysvec = unsafe {
        let res = allocate_loop(|buf, len| {
            extattr_list_link(path.as_ptr(),
                              EXTATTR_NAMESPACE_SYSTEM,
                              buf as *mut c_void,
                              len as size_t)
        });
        // On FreeBSD, system attributes require root privileges to view. However,
        // to mimic the behavior of listxattr in linux and osx, we need to query
        // them anyway and return empty results if we get EPERM
        match res {
            Ok(v) => v,
            Err(err) => {
                if err.raw_os_error() == Some(EPERM) {
                    Vec::new()
                } else {
                    return Err(err);
                }
            }
        }
    };

    let uservec = unsafe {
        let res = allocate_loop(|buf, len| {
            extattr_list_link(path.as_ptr(),
                              EXTATTR_NAMESPACE_USER,
                              buf as *mut c_void,
                              len as size_t)
        });
        match res {
            Ok(v) => v,
            Err(err) => return Err(err),
        }
    };

    Ok(XAttrs {
        system_attrs: sysvec.into_boxed_slice(),
        user_attrs: uservec.into_boxed_slice(),
        offset: 0,
    })
}
<commit_msg>format<commit_after>use std::io;
use std::ffi::{CString, OsStr, OsString};
use std::os::unix::io::RawFd;
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::path::Path;
use std::mem;

use libc::consts::os::posix88::EPERM;
use libc::{c_char, ssize_t, size_t, c_int, c_void};
use util::{path_to_c, allocate_loop};

const EXTATTR_NAMESPACE_USER_STRING: &'static str = "user";
const EXTATTR_NAMESPACE_SYSTEM_STRING: &'static str = "system";
const EXTATTR_NAMESPACE_NAMES: [&'static str; 3] =
    ["empty", EXTATTR_NAMESPACE_USER_STRING, EXTATTR_NAMESPACE_SYSTEM_STRING];
const EXTATTR_NAMESPACE_USER: c_int = 1;
const EXTATTR_NAMESPACE_SYSTEM: c_int = 2;

extern "C" {
    pub fn extattr_list_fd(fd: c_int,
                           attrnamespace: c_int,
                           data: *mut c_void,
                           nbytes: size_t)
                           -> ssize_t;
    pub fn extattr_get_fd(fd: c_int,
                          attrnamespace: c_int,
                          attrname: *const c_char,
                          data: *mut c_void,
                          nbytes: size_t)
                          -> ssize_t;
    pub fn extattr_delete_fd(fd: c_int, attrname: c_int, attrname: *const c_char) -> c_int;
    pub fn extattr_set_fd(fd: c_int,
                          attrname: c_int,
                          attrname: *const c_char,
                          data: *const c_void,
                          nbytes: size_t)
                          -> ssize_t;

    pub fn extattr_list_link(path: *const c_char,
                             attrnamespace: c_int,
                             data: *mut c_void,
                             nbytes: size_t)
                             -> ssize_t;
    pub fn extattr_get_link(path: *const c_char,
                            attrnamespace: c_int,
                            attrname: *const c_char,
                            data: *mut c_void,
                            nbytes: size_t)
                            -> ssize_t;
    pub fn extattr_delete_link(path: *const c_char,
                               attrname: c_int,
                               attrname: *const c_char)
                               -> c_int;
    pub fn extattr_set_link(path: *const c_char,
                            attrname: c_int,
                            attrname: *const c_char,
                            data: *const c_void,
                            nbytes: size_t)
                            -> ssize_t;
}

pub struct XAttrs {
    user_attrs: Box<[u8]>,
    system_attrs: Box<[u8]>,
    offset: usize,
}

impl Clone for XAttrs {
    fn clone(&self) -> Self {
        XAttrs {
            user_attrs: Vec::from(&*self.user_attrs).into_boxed_slice(),
            system_attrs: Vec::from(&*self.system_attrs).into_boxed_slice(),
            offset: self.offset,
        }
    }

    fn clone_from(&mut self, other: &XAttrs) {
        self.offset = other.offset;

        let mut data = mem::replace(&mut self.user_attrs, Box::new([])).into_vec();
        data.extend(other.user_attrs.iter().cloned());
        self.user_attrs = data.into_boxed_slice();

        data = mem::replace(&mut self.system_attrs, Box::new([])).into_vec();
        data.extend(other.system_attrs.iter().cloned());
        self.system_attrs = data.into_boxed_slice();
    }
}

impl Iterator for XAttrs {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        if self.user_attrs.is_empty() && self.system_attrs.is_empty() {
            return None;
        }

        if self.offset == self.user_attrs.len() + self.system_attrs.len() {
            return None;
        }

        let data = if self.offset < self.system_attrs.len() {
            &self.system_attrs[self.offset..]
        } else {
            &self.user_attrs[self.offset - self.system_attrs.len()..]
        };

        let siz = data[0] as usize;

        self.offset += siz + 1;
        if self.offset < self.system_attrs.len() {
            Some(prefix_namespace(OsStr::from_bytes(&data[1..siz + 1]),
                                  EXTATTR_NAMESPACE_SYSTEM))
        } else {
            Some(prefix_namespace(OsStr::from_bytes(&data[1..siz + 1]), EXTATTR_NAMESPACE_USER))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.user_attrs.len() + self.system_attrs.len() == self.offset {
            (0, Some(0))
        } else {
            (1, None)
        }
    }
}

fn name_to_ns(name: &OsStr) -> io::Result<(c_int, CString)> {
    let mut groups = name.as_bytes().splitn(2, |&b| b == b'.').take(2);
    let nsname = match groups.next() {
        Some(s) => s,
        None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "couldn't find namespace")),
    };

    let propname = match groups.next() {
        Some(s) => s,
        None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "couldn't find attribute")),
    };

    let ns_int = match EXTATTR_NAMESPACE_NAMES.iter().position(|&s| s.as_bytes() == nsname) {
        Some(i) => i,
        None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "no matching namespace")),
    };

    Ok((ns_int as c_int, try!(CString::new(propname))))
}

fn prefix_namespace(attr: &OsStr, ns: c_int) -> OsString {
    let nsname = EXTATTR_NAMESPACE_NAMES[ns as usize];
    let mut v = Vec::with_capacity(nsname.as_bytes().len() + attr.as_bytes().len() + 1);
    v.extend(nsname.as_bytes());
    v.extend(".".as_bytes());
    v.extend(attr.as_bytes());
    OsString::from_vec(v)
}

pub fn get_fd(fd: RawFd, name: &OsStr) -> io::Result<Vec<u8>> {
    let (ns, name) = try!(name_to_ns(name));
    unsafe {
        allocate_loop(|buf, len| {
            extattr_get_fd(fd, ns, name.as_ptr(), buf as *mut c_void, len as size_t)
        })
    }
}

pub fn set_fd(fd: RawFd, name: &OsStr, value: &[u8]) -> io::Result<()> {
    let (ns, name) = try!(name_to_ns(name));
    let ret = unsafe {
        extattr_set_fd(fd,
                       ns,
                       name.as_ptr(),
                       value.as_ptr() as *const c_void,
                       value.len() as size_t)
    };
    if ret == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

pub fn remove_fd(fd: RawFd, name: &OsStr) -> io::Result<()> {
    let (ns, name) = try!(name_to_ns(name));
    let ret = unsafe { extattr_delete_fd(fd, ns, name.as_ptr()) };
    if ret != 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

pub fn list_fd(fd: RawFd) -> io::Result<XAttrs> {
    let sysvec = unsafe {
        let res = allocate_loop(|buf, len| {
            extattr_list_fd(fd,
                            EXTATTR_NAMESPACE_SYSTEM,
                            buf as *mut c_void,
                            len as size_t)
        });
        // On FreeBSD, system attributes require root privileges to view. However,
        // to mimic the behavior of listxattr in linux and osx, we need to query
        // them anyway and return empty results if we get EPERM
        match res {
            Ok(v) => v,
            Err(err) => {
                if err.raw_os_error() == Some(EPERM) {
                    Vec::new()
                } else {
                    return Err(err);
                }
            }
        }
    };

    let uservec = unsafe {
        let res = allocate_loop(|buf, len| {
            extattr_list_fd(fd,
                            EXTATTR_NAMESPACE_USER,
                            buf as *mut c_void,
                            len as size_t)
        });
        match res {
            Ok(v) => v,
            Err(err) => return Err(err),
        }
    };

    Ok(XAttrs {
        system_attrs: sysvec.into_boxed_slice(),
        user_attrs: uservec.into_boxed_slice(),
        offset: 0,
    })
}

pub fn get_path(path: &Path, name: &OsStr) -> io::Result<Vec<u8>> {
    let (ns, name) = try!(name_to_ns(name));
    let path = try!(path_to_c(path));
    unsafe {
        allocate_loop(|buf, len| {
            extattr_get_link(path.as_ptr(),
                             ns,
                             name.as_ptr(),
                             buf as *mut c_void,
                             len as size_t)
        })
    }
}

pub fn set_path(path: &Path, name: &OsStr, value: &[u8]) -> io::Result<()> {
    let (ns, name) = try!(name_to_ns(name));
    let path = try!(path_to_c(path));
    let ret = unsafe {
        extattr_set_link(path.as_ptr(),
                         ns,
                         name.as_ptr(),
                         value.as_ptr() as *const c_void,
                         value.len() as size_t)
    };
    if ret == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

pub fn remove_path(path: &Path, name: &OsStr) -> io::Result<()> {
    let (ns, name) = try!(name_to_ns(name));
    let path = try!(path_to_c(path));
    let ret = unsafe { extattr_delete_link(path.as_ptr(), ns, name.as_ptr()) };
    if ret != 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

pub fn list_path(path: &Path) -> io::Result<XAttrs> {
    let path = try!(path_to_c(path));
    let sysvec = unsafe {
        let res = allocate_loop(|buf, len| {
            extattr_list_link(path.as_ptr(),
                              EXTATTR_NAMESPACE_SYSTEM,
                              buf as *mut c_void,
                              len as size_t)
        });
        // On FreeBSD, system attributes require root privileges to view. However,
        // to mimic the behavior of listxattr in linux and osx, we need to query
        // them anyway and return empty results if we get EPERM
        match res {
            Ok(v) => v,
            Err(err) => {
                if err.raw_os_error() == Some(EPERM) {
                    Vec::new()
                } else {
                    return Err(err);
                }
            }
        }
    };

    let uservec = unsafe {
        let res = allocate_loop(|buf, len| {
            extattr_list_link(path.as_ptr(),
                              EXTATTR_NAMESPACE_USER,
                              buf as *mut c_void,
                              len as size_t)
        });
        match res {
            Ok(v) => v,
            Err(err) => return Err(err),
        }
    };

    Ok(XAttrs {
        system_attrs: sysvec.into_boxed_slice(),
        user_attrs: uservec.into_boxed_slice(),
        offset: 0,
    })
}
<|endoftext|>


<commit_before>
extern crate rand;
extern crate test;

use ndarray::{arr2, arr1, stack};
use dataframe::*;
use test::Bencher;
use ndarray::Array;
use rand::distributions::Range;
use ndarray_rand::RandomExt;
use std::rc::Rc;
use rand::{thread_rng, Rng};
use std::collections::{HashMap, BTreeMap};
use chrono::*;
use util::types::*;
use util::error::*;
use adapters::aggregate::*;
use adapters::transform::*;
use util::traits::*;
use std::f64::NAN;
use ndarray::Axis;
use adapters::join::*;
use mixedtypes::*;
use util::readcsv::*;
#[test]
fn outer_left_join() {
    let a = arr2(&[["Alice"], ["Bob"]]);
    let left: DataFrame<InnerType, OuterType> =
        DataFrame::new(a).index(&[1, 2]).unwrap().columns(&["a"]).unwrap();
    let b = arr2(&[["Programmer"]]);
    let right: DataFrame<InnerType, OuterType> =
        DataFrame::new(b).index(&[1]).unwrap().columns(&["b"]).unwrap();
    let res = left.outer_left_join(&right).as_df();
    let expected_data = arr2(&[[InnerType::Str(String::from("Alice")),
                                InnerType::Str(String::from("Programmer"))],
                               [InnerType::Str(String::from("Bob")), InnerType::Empty]]);
    let expected =
        DataFrame::new(expected_data).index(&[1, 2]).unwrap().columns(&["a", "b"]).unwrap();
    assert_eq!(res.unwrap(), expected);

}
#[test]
fn inner_join() {
    let a = arr2(&[["Alice"], ["Bob"], ["Suchin"]]);
    let left: DataFrame<InnerType, OuterType> =
        DataFrame::new(a).index(&[1, 2, 3]).unwrap().columns(&["a"]).unwrap();
    let b = arr2(&[["Programmer"], ["Data Scientist"]]);
    let right = DataFrame::new(b).index(&[1, 3]).unwrap().columns(&["b"]).unwrap();
    let res = left.inner_left_join(&right).as_df();
    let expected_data = arr2(&[[InnerType::Str(String::from("Alice")),
                                InnerType::Str(String::from("Programmer"))],
                               [InnerType::Str(String::from("Suchin")),
                                InnerType::Str(String::from("Data Scientist"))]]);
    let expected =
        DataFrame::new(expected_data).index(&[1, 3]).unwrap().columns(&["a", "b"]).unwrap();
    assert_eq!(res.unwrap(), expected);
}

#[test]
fn dataframe_creation() {
    let a = arr2(&[[2., 3.], [3., 4.]]);
    let df: Result<DataFrame<f64, String>> = DataFrame::new(a).columns(&["a", "b"]);
    assert!(df.is_ok())
}

#[test]
fn dataframe_creation_failure() {
    let a = Array::random((2, 5), Range::new(0., 10.));
    let df: Result<DataFrame<f64, String>> = DataFrame::new(a).columns(&["1", "2"]);
    assert!(df.is_err())
}

#[test]
fn dataframe_select() {
    let a = arr2(&[[2., 3.], [3., 4.]]);
    let df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
    let select_idx = vec!["a"];
    let z = df.select(&select_idx[..], UtahAxis::Column).as_df();
    let col = df.data.column(0).clone();
    let expected = DataFrame::from_array(col.to_owned(), UtahAxis::Column)
        .columns(&["a"])
        .unwrap();
    assert_eq!(z.unwrap(), expected);

    let select_idx = vec!["0"];
    let z = df.select(&select_idx[..], UtahAxis::Row).as_df();
    let col = df.data.row(0).clone();
    let expected = DataFrame::from_array(col.to_owned(), UtahAxis::Row)
        .index(&["0"])
        .unwrap()
        .columns(&["a", "b"])
        .unwrap();
    assert_eq!(z.unwrap(), expected);
}

#[test]
fn dataframe_remove() {
    let a = arr2(&[[2., 3.], [3., 4.]]);
    let df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
    let remove_idx = vec!["a"];
    let z = df.remove(&remove_idx[..], UtahAxis::Column).as_df();
    let col = df.data.column(1).clone();
    let expected = DataFrame::from_array(col.to_owned(), UtahAxis::Column)
        .columns(&["b"])
        .unwrap();
    assert_eq!(z.unwrap(), expected);

    let remove_idx = vec!["0"];
    let z = df.remove(&remove_idx[..], UtahAxis::Row).as_df();
    let row = df.data.row(1).clone();
    let expected = DataFrame::from_array(row.to_owned(), UtahAxis::Row)
        .index(&["1"])
        .unwrap()
        .columns(&["a", "b"])
        .unwrap();
    assert_eq!(z.unwrap(), expected);
}

#[test]
fn dataframe_append() {
    {
        let a = arr2(&[[2., 3.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let col = df.select(&["a"], UtahAxis::Column).as_array().unwrap();
        let z = df.append("c", col.view(), UtahAxis::Column).as_df();
        let b = arr2(&[[2., 3., 2.], [3., 3., 4.]]);
        let expected = DataFrame::new(b)
            .columns(&["c", "a", "b"])
            .unwrap();
        assert_eq!(z.unwrap(), expected);
    }
    {
        let a = arr2(&[[2., 3.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let col = df.select(&["1"], UtahAxis::Row).as_array().unwrap();
        let z = df.append("2", col.view(), UtahAxis::Row).as_df();
        let b = arr2(&[[3., 4.], [2., 3.], [3., 4.]]);
        let expected = DataFrame::new(b)
            .columns(&["a", "b"])
            .unwrap()
            .index(&["2", "0", "1"])
            .unwrap();
        assert_eq!(z.unwrap(), expected);
    }
}

#[test]
fn dataframe_mapdf() {
    {
        let a = arr2(&[[2., 3.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: Vec<(String, Row<f64>)> = df.map(|x| x * 2.0, UtahAxis::Row).collect();
        let b = arr2(&[[4., 6.], [6., 8.]]);
        let mut expected = Vec::new();
        expected.push(("0".to_string(), b.row(0).to_owned()));
        expected.push(("1".to_string(), b.row(1).to_owned()));
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2., 3.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: Vec<(String, Row<f64>)> = df.map(|x| x * 2.0, UtahAxis::Column).collect();
        let b = arr2(&[[4., 6.], [6., 8.]]);
        let mut expected = Vec::new();
        expected.push(("a".to_string(), b.row(0).to_owned()));
        expected.push(("b".to_string(), b.row(1).to_owned()));
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_mean() {
    {
        let a = arr2(&[[2., 6.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<f64, String> = df.mean(UtahAxis::Row).as_df().unwrap();
        let b = arr2(&[[4.], [3.5]]);
        let mut expected = DataFrame::new(b);
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2., 6.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<f64, String> = df.mean(UtahAxis::Column).as_df().unwrap();
        let b = arr2(&[[2.5, 5.]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_sum() {
    {
        let a = arr2(&[[2., 6.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<f64, String> = df.sumdf(UtahAxis::Row).as_df().unwrap();
        let b = arr2(&[[8.], [7.]]);
        let mut expected = DataFrame::new(b);
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2., 6.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<f64, String> = df.sumdf(UtahAxis::Column).as_df().unwrap();
        let b = arr2(&[[5., 10.]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_max() {

    {
        let a = arr2(&[[2, 6], [3, 4]]);
        let mut df: DataFrame<i32, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<i32, String> = df.maxdf(UtahAxis::Row).as_df().unwrap();
        let b = arr2(&[[6], [4]]);
        let mut expected = DataFrame::new(b);
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2, 6], [3, 4]]);
        let mut df: DataFrame<i32, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<i32, String> = df.maxdf(UtahAxis::Column).as_df().unwrap();
        let b = arr2(&[[3, 6]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_min() {
    {
        let a = arr2(&[[2, 6], [3, 4]]);
        let mut df: DataFrame<i32, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<i32, String> = df.mindf(UtahAxis::Column).as_df().unwrap();
        let b = arr2(&[[2, 4]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2, 6], [3, 4]]);
        let mut df: DataFrame<i32, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<i32, String> = df.mindf(UtahAxis::Row).as_df().unwrap();
        let b = arr2(&[[2], [3]]);
        let mut expected = DataFrame::new(b);
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_impute() {
    {
        let a = arr2(&[[2., NAN], [3., 8.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        df.impute(ImputeStrategy::Mean, UtahAxis::Column).as_df();
        let b = arr2(&[[2., 8.], [3., 8.]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(df, expected);
    }

}

#[test]
fn read_csv() {
    {
        let df: Result<DataFrame<InnerType, OuterType>> = DataFrame::read_csv("~/src/tests/test.\
                                                                               csv");
        let b =
            arr2(&[[InnerType::Float(8.), InnerType::Str("b".to_string()), InnerType::Float(4.)]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b", "c"]).unwrap();
        assert_eq!(df.unwrap(), expected);
    }

}
<commit_msg>removed csv test<commit_after>
extern crate rand;
extern crate test;

use ndarray::{arr2, arr1, stack};
use dataframe::*;
use test::Bencher;
use ndarray::Array;
use rand::distributions::Range;
use ndarray_rand::RandomExt;
use std::rc::Rc;
use rand::{thread_rng, Rng};
use std::collections::{HashMap, BTreeMap};
use chrono::*;
use util::types::*;
use util::error::*;
use adapters::aggregate::*;
use adapters::transform::*;
use util::traits::*;
use std::f64::NAN;
use ndarray::Axis;
use adapters::join::*;
use mixedtypes::*;
use util::readcsv::*;
#[test]
fn outer_left_join() {
    let a = arr2(&[["Alice"], ["Bob"]]);
    let left: DataFrame<InnerType, OuterType> =
        DataFrame::new(a).index(&[1, 2]).unwrap().columns(&["a"]).unwrap();
    let b = arr2(&[["Programmer"]]);
    let right: DataFrame<InnerType, OuterType> =
        DataFrame::new(b).index(&[1]).unwrap().columns(&["b"]).unwrap();
    let res = left.outer_left_join(&right).as_df();
    let expected_data = arr2(&[[InnerType::Str(String::from("Alice")),
                                InnerType::Str(String::from("Programmer"))],
                               [InnerType::Str(String::from("Bob")), InnerType::Empty]]);
    let expected =
        DataFrame::new(expected_data).index(&[1, 2]).unwrap().columns(&["a", "b"]).unwrap();
    assert_eq!(res.unwrap(), expected);

}
#[test]
fn inner_join() {
    let a = arr2(&[["Alice"], ["Bob"], ["Suchin"]]);
    let left: DataFrame<InnerType, OuterType> =
        DataFrame::new(a).index(&[1, 2, 3]).unwrap().columns(&["a"]).unwrap();
    let b = arr2(&[["Programmer"], ["Data Scientist"]]);
    let right = DataFrame::new(b).index(&[1, 3]).unwrap().columns(&["b"]).unwrap();
    let res = left.inner_left_join(&right).as_df();
    let expected_data = arr2(&[[InnerType::Str(String::from("Alice")),
                                InnerType::Str(String::from("Programmer"))],
                               [InnerType::Str(String::from("Suchin")),
                                InnerType::Str(String::from("Data Scientist"))]]);
    let expected =
        DataFrame::new(expected_data).index(&[1, 3]).unwrap().columns(&["a", "b"]).unwrap();
    assert_eq!(res.unwrap(), expected);
}

#[test]
fn dataframe_creation() {
    let a = arr2(&[[2., 3.], [3., 4.]]);
    let df: Result<DataFrame<f64, String>> = DataFrame::new(a).columns(&["a", "b"]);
    assert!(df.is_ok())
}

#[test]
fn dataframe_creation_failure() {
    let a = Array::random((2, 5), Range::new(0., 10.));
    let df: Result<DataFrame<f64, String>> = DataFrame::new(a).columns(&["1", "2"]);
    assert!(df.is_err())
}

#[test]
fn dataframe_select() {
    let a = arr2(&[[2., 3.], [3., 4.]]);
    let df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
    let select_idx = vec!["a"];
    let z = df.select(&select_idx[..], UtahAxis::Column).as_df();
    let col = df.data.column(0).clone();
    let expected = DataFrame::from_array(col.to_owned(), UtahAxis::Column)
        .columns(&["a"])
        .unwrap();
    assert_eq!(z.unwrap(), expected);

    let select_idx = vec!["0"];
    let z = df.select(&select_idx[..], UtahAxis::Row).as_df();
    let col = df.data.row(0).clone();
    let expected = DataFrame::from_array(col.to_owned(), UtahAxis::Row)
        .index(&["0"])
        .unwrap()
        .columns(&["a", "b"])
        .unwrap();
    assert_eq!(z.unwrap(), expected);
}

#[test]
fn dataframe_remove() {
    let a = arr2(&[[2., 3.], [3., 4.]]);
    let df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
    let remove_idx = vec!["a"];
    let z = df.remove(&remove_idx[..], UtahAxis::Column).as_df();
    let col = df.data.column(1).clone();
    let expected = DataFrame::from_array(col.to_owned(), UtahAxis::Column)
        .columns(&["b"])
        .unwrap();
    assert_eq!(z.unwrap(), expected);

    let remove_idx = vec!["0"];
    let z = df.remove(&remove_idx[..], UtahAxis::Row).as_df();
    let row = df.data.row(1).clone();
    let expected = DataFrame::from_array(row.to_owned(), UtahAxis::Row)
        .index(&["1"])
        .unwrap()
        .columns(&["a", "b"])
        .unwrap();
    assert_eq!(z.unwrap(), expected);
}

#[test]
fn dataframe_append() {
    {
        let a = arr2(&[[2., 3.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let col = df.select(&["a"], UtahAxis::Column).as_array().unwrap();
        let z = df.append("c", col.view(), UtahAxis::Column).as_df();
        let b = arr2(&[[2., 3., 2.], [3., 3., 4.]]);
        let expected = DataFrame::new(b)
            .columns(&["c", "a", "b"])
            .unwrap();
        assert_eq!(z.unwrap(), expected);
    }
    {
        let a = arr2(&[[2., 3.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let col = df.select(&["1"], UtahAxis::Row).as_array().unwrap();
        let z = df.append("2", col.view(), UtahAxis::Row).as_df();
        let b = arr2(&[[3., 4.], [2., 3.], [3., 4.]]);
        let expected = DataFrame::new(b)
            .columns(&["a", "b"])
            .unwrap()
            .index(&["2", "0", "1"])
            .unwrap();
        assert_eq!(z.unwrap(), expected);
    }
}

#[test]
fn dataframe_mapdf() {
    {
        let a = arr2(&[[2., 3.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: Vec<(String, Row<f64>)> = df.map(|x| x * 2.0, UtahAxis::Row).collect();
        let b = arr2(&[[4., 6.], [6., 8.]]);
        let mut expected = Vec::new();
        expected.push(("0".to_string(), b.row(0).to_owned()));
        expected.push(("1".to_string(), b.row(1).to_owned()));
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2., 3.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: Vec<(String, Row<f64>)> = df.map(|x| x * 2.0, UtahAxis::Column).collect();
        let b = arr2(&[[4., 6.], [6., 8.]]);
        let mut expected = Vec::new();
        expected.push(("a".to_string(), b.row(0).to_owned()));
        expected.push(("b".to_string(), b.row(1).to_owned()));
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_mean() {
    {
        let a = arr2(&[[2., 6.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<f64, String> = df.mean(UtahAxis::Row).as_df().unwrap();
        let b = arr2(&[[4.], [3.5]]);
        let mut expected = DataFrame::new(b);
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2., 6.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<f64, String> = df.mean(UtahAxis::Column).as_df().unwrap();
        let b = arr2(&[[2.5, 5.]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_sum() {
    {
        let a = arr2(&[[2., 6.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<f64, String> = df.sumdf(UtahAxis::Row).as_df().unwrap();
        let b = arr2(&[[8.], [7.]]);
        let mut expected = DataFrame::new(b);
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2., 6.], [3., 4.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<f64, String> = df.sumdf(UtahAxis::Column).as_df().unwrap();
        let b = arr2(&[[5., 10.]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_max() {

    {
        let a = arr2(&[[2, 6], [3, 4]]);
        let mut df: DataFrame<i32, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<i32, String> = df.maxdf(UtahAxis::Row).as_df().unwrap();
        let b = arr2(&[[6], [4]]);
        let mut expected = DataFrame::new(b);
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2, 6], [3, 4]]);
        let mut df: DataFrame<i32, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<i32, String> = df.maxdf(UtahAxis::Column).as_df().unwrap();
        let b = arr2(&[[3, 6]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_min() {
    {
        let a = arr2(&[[2, 6], [3, 4]]);
        let mut df: DataFrame<i32, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<i32, String> = df.mindf(UtahAxis::Column).as_df().unwrap();
        let b = arr2(&[[2, 4]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(z, expected);
    }
    {
        let a = arr2(&[[2, 6], [3, 4]]);
        let mut df: DataFrame<i32, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        let z: DataFrame<i32, String> = df.mindf(UtahAxis::Row).as_df().unwrap();
        let b = arr2(&[[2], [3]]);
        let mut expected = DataFrame::new(b);
        assert_eq!(z, expected);
    }
}

#[test]
fn dataframe_impute() {
    {
        let a = arr2(&[[2., NAN], [3., 8.]]);
        let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"]).unwrap();
        df.impute(ImputeStrategy::Mean, UtahAxis::Column).as_df();
        let b = arr2(&[[2., 8.], [3., 8.]]);
        let mut expected = DataFrame::new(b).columns(&["a", "b"]).unwrap();
        assert_eq!(df, expected);
    }

}

// #[test]
// fn read_csv() {
//     {
//         let df: Result<DataFrame<InnerType, OuterType>> = DataFrame::read_csv("./test.csv");
//         let b =
//             arr2(&[[InnerType::Float(8.), InnerType::Str("b".to_string()), InnerType::Float(4.)]]);
//         let mut expected = DataFrame::new(b).columns(&["a", "b", "c"]).unwrap();
//         assert_eq!(df.unwrap(), expected);
//     }
//
// }
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;

use device::Device;

use OomError;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Pool from which descriptor sets are allocated from.
///
/// A pool has a maximum number of descriptor sets and a maximum number of descriptors (one value
/// per descriptor type) it can allocate.
pub struct DescriptorPool {
    pool: Mutex<vk::DescriptorPool>,
    device: Arc<Device>,
}

impl DescriptorPool {
    /// Initializes a new pool.
    // FIXME: capacity of the pool
    pub fn new(device: &Arc<Device>) -> Result<Arc<DescriptorPool>, OomError> {
        let vk = device.pointers();

        // FIXME: arbitrary
        let pool_sizes = vec![
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_SAMPLED_IMAGE,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                descriptorCount: 10,
            },
        ];

        let pool = unsafe {
            let infos = vk::DescriptorPoolCreateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
                pNext: ptr::null(),
                flags: vk::DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,   // TODO:
                maxSets: 100,       // TODO: let user choose
                poolSizeCount: pool_sizes.len() as u32,
                pPoolSizes: pool_sizes.as_ptr(),
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateDescriptorPool(device.internal_object(), &infos,
                                                      ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(DescriptorPool {
            pool: Mutex::new(pool),
            device: device.clone(),
        }))
    }

    /// Returns the device this pool was created from.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl SynchronizedVulkanObject for DescriptorPool {
    type Object = vk::DescriptorPool;

    #[inline]
    fn internal_object_guard(&self) -> MutexGuard<vk::DescriptorPool> {
        self.pool.lock().unwrap()
    }
}

impl Drop for DescriptorPool {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            let pool = self.pool.lock().unwrap();
            vk.DestroyDescriptorPool(self.device.internal_object(), *pool, ptr::null());
        }
    }
}

#[cfg(test)]
mod tests {
    use descriptor_set::DescriptorPool;

    #[test]
    fn create() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = DescriptorPool::new(&device).unwrap();
    }

    #[test]
    fn device() {
        let (device, _) = gfx_dev_and_queue!();
        let pool = DescriptorPool::new(&device).unwrap();
        assert_eq!(&**pool.device() as *const _, &*device as *const _);
    }
}
<commit_msg>Continue to descriptor pool hack<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;

use device::Device;

use OomError;
use SynchronizedVulkanObject;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Pool from which descriptor sets are allocated from.
///
/// A pool has a maximum number of descriptor sets and a maximum number of descriptors (one value
/// per descriptor type) it can allocate.
pub struct DescriptorPool {
    pool: Mutex<vk::DescriptorPool>,
    device: Arc<Device>,
}

impl DescriptorPool {
    /// Initializes a new pool.
    // FIXME: capacity of the pool
    pub fn new(device: &Arc<Device>) -> Result<Arc<DescriptorPool>, OomError> {
        let vk = device.pointers();

        // FIXME: arbitrary
        let pool_sizes = vec![
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_STORAGE_BUFFER,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_SAMPLED_IMAGE,
                descriptorCount: 10,
            },
            vk::DescriptorPoolSize {
                ty: vk::DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                descriptorCount: 10,
            },
        ];

        let pool = unsafe {
            let infos = vk::DescriptorPoolCreateInfo {
                sType: vk::STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
                pNext: ptr::null(),
                flags: vk::DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,   // TODO:
                maxSets: 100,       // TODO: let user choose
                poolSizeCount: pool_sizes.len() as u32,
                pPoolSizes: pool_sizes.as_ptr(),
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateDescriptorPool(device.internal_object(), &infos,
                                                      ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(DescriptorPool {
            pool: Mutex::new(pool),
            device: device.clone(),
        }))
    }

    /// Returns the device this pool was created from.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl SynchronizedVulkanObject for DescriptorPool {
    type Object = vk::DescriptorPool;

    #[inline]
    fn internal_object_guard(&self) -> MutexGuard<vk::DescriptorPool> {
        self.pool.lock().unwrap()
    }
}

impl Drop for DescriptorPool {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            let pool = self.pool.lock().unwrap();
            vk.DestroyDescriptorPool(self.device.internal_object(), *pool, ptr::null());
        }
    }
}

#[cfg(test)]
mod tests {
    use descriptor_set::DescriptorPool;

    #[test]
    fn create() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = DescriptorPool::new(&device).unwrap();
    }

    #[test]
    fn device() {
        let (device, _) = gfx_dev_and_queue!();
        let pool = DescriptorPool::new(&device).unwrap();
        assert_eq!(&**pool.device() as *const _, &*device as *const _);
    }
}
<|endoftext|>


<commit_before>use crate::sync::mpsc::chan;
use crate::sync::mpsc::error::{ClosedError, SendError, TrySendError};
use crate::sync::semaphore;

use std::fmt;
use std::task::{Context, Poll};

/// Send values to the associated `Receiver`.
///
/// Instances are created by the [`channel`](fn.channel.html) function.
pub struct Sender<T> {
    chan: chan::Tx<T, Semaphore>,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            chan: self.chan.clone(),
        }
    }
}

impl<T> fmt::Debug for Sender<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("Sender")
            .field("chan", &self.chan)
            .finish()
    }
}

/// Receive values from the associated `Sender`.
///
/// Instances are created by the [`channel`](fn.channel.html) function.
pub struct Receiver<T> {
    /// The channel receiver
    chan: chan::Rx<T, Semaphore>,
}

impl<T> fmt::Debug for Receiver<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("Receiver")
            .field("chan", &self.chan)
            .finish()
    }
}

/// Create a bounded mpsc channel for communicating between asynchronous tasks,
/// returning the sender/receiver halves.
///
/// All data sent on `Sender` will become available on `Receiver` in the same
/// order as it was sent.
///
/// The `Sender` can be cloned to `send` to the same channel from multiple code
/// locations. Only one `Receiver` is supported.
///
/// If the `Receiver` is disconnected while trying to `send`, the `send` method
/// will return a `SendError`. Similarly, if `Sender` is disconnected while
/// trying to `recv`, the `recv` method will return a `RecvError`.
///
/// # Examples
///
/// ```rust
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
///     let (mut tx, mut rx) = mpsc::channel(100);
///
///     tokio::spawn(async move {
///         for i in 0..10 {
///             if let Err(_) = tx.send(i).await {
///                 println!("receiver dropped");
///                 return;
///             }
///         }
///     });
///
///     while let Some(i) = rx.recv().await {
///         println!("got = {}", i);
///     }
/// }
/// ```
pub fn channel<T>(buffer: usize) -> (Sender<T>, Receiver<T>) {
    assert!(buffer > 0, "mpsc bounded channel requires buffer > 0");
    let semaphore = (semaphore::Semaphore::new(buffer), buffer);
    let (tx, rx) = chan::channel(semaphore);

    let tx = Sender::new(tx);
    let rx = Receiver::new(rx);

    (tx, rx)
}

/// Channel semaphore is a tuple of the semaphore implementation and a `usize`
/// representing the channel bound.
type Semaphore = (semaphore::Semaphore, usize);

impl<T> Receiver<T> {
    pub(crate) fn new(chan: chan::Rx<T, Semaphore>) -> Receiver<T> {
        Receiver { chan }
    }

    /// Receive the next value for this receiver.
    ///
    /// `None` is returned when all `Sender` halves have dropped, indicating
    /// that no further values can be sent on the channel.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::mpsc;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (mut tx, mut rx) = mpsc::channel(100);
    ///
    ///     tokio::spawn(async move {
    ///         tx.send("hello").await.unwrap();
    ///     });
    ///
    ///     assert_eq!(Some("hello"), rx.recv().await);
    ///     assert_eq!(None, rx.recv().await);
    /// }
    /// ```
    ///
    /// Values are buffered:
    ///
    /// ```
    /// use tokio::sync::mpsc;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (mut tx, mut rx) = mpsc::channel(100);
    ///
    ///     tx.send("hello").await.unwrap();
    ///     tx.send("world").await.unwrap();
    ///
    ///     assert_eq!(Some("hello"), rx.recv().await);
    ///     assert_eq!(Some("world"), rx.recv().await);
    /// }
    /// ```
    pub async fn recv(&mut self) -> Option<T> {
        use crate::future::poll_fn;

        poll_fn(|cx| self.poll_recv(cx)).await
    }

    #[doc(hidden)] // TODO: document
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        self.chan.recv(cx)
    }

    /// Closes the receiving half of a channel, without dropping it.
    ///
    /// This prevents any further messages from being sent on the channel while
    /// still enabling the receiver to drain messages that are buffered.
    pub fn close(&mut self) {
        self.chan.close();
    }
}

impl<T> Unpin for Receiver<T> {}

cfg_stream! {
    impl<T> futures_core::Stream for Receiver<T> {
        type Item = T;

        fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
            self.poll_recv(cx)
        }
    }
}

impl<T> Sender<T> {
    pub(crate) fn new(chan: chan::Tx<T, Semaphore>) -> Sender<T> {
        Sender { chan }
    }

    #[doc(hidden)] // TODO: document
    pub fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ClosedError>> {
        self.chan.poll_ready(cx).map_err(|_| ClosedError::new())
    }

    /// Attempts to send a message on this `Sender`, returning the message
    /// if there was an error.
    pub fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> {
        self.chan.try_send(message)?;
        Ok(())
    }

    /// Send a value, waiting until there is capacity.
    ///
    /// # Examples
    ///
    /// In the following example, each call to `send` will block until the
    /// previously sent value was received.
    ///
    /// ```rust
    /// use tokio::sync::mpsc;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (mut tx, mut rx) = mpsc::channel(1);
    ///
    ///     tokio::spawn(async move {
    ///         for i in 0..10 {
    ///             if let Err(_) = tx.send(i).await {
    ///                 println!("receiver dropped");
    ///                 return;
    ///             }
    ///         }
    ///     });
    ///
    ///     while let Some(i) = rx.recv().await {
    ///         println!("got = {}", i);
    ///     }
    /// }
    /// ```
    pub async fn send(&mut self, value: T) -> Result<(), SendError<T>> {
        use crate::future::poll_fn;

        if poll_fn(|cx| self.poll_ready(cx)).await.is_err() {
            return Err(SendError(value));
        }

        match self.try_send(value) {
            Ok(()) => Ok(()),
            Err(TrySendError::Full(_)) => unreachable!(),
            Err(TrySendError::Closed(value)) => Err(SendError(value)),
        }
    }
}
<commit_msg>doc: expand `mpsc::Sender::send` API documentation (#1865)<commit_after>use crate::sync::mpsc::chan;
use crate::sync::mpsc::error::{ClosedError, SendError, TrySendError};
use crate::sync::semaphore;

use std::fmt;
use std::task::{Context, Poll};

/// Send values to the associated `Receiver`.
///
/// Instances are created by the [`channel`](fn.channel.html) function.
pub struct Sender<T> {
    chan: chan::Tx<T, Semaphore>,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            chan: self.chan.clone(),
        }
    }
}

impl<T> fmt::Debug for Sender<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("Sender")
            .field("chan", &self.chan)
            .finish()
    }
}

/// Receive values from the associated `Sender`.
///
/// Instances are created by the [`channel`](fn.channel.html) function.
pub struct Receiver<T> {
    /// The channel receiver
    chan: chan::Rx<T, Semaphore>,
}

impl<T> fmt::Debug for Receiver<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("Receiver")
            .field("chan", &self.chan)
            .finish()
    }
}

/// Create a bounded mpsc channel for communicating between asynchronous tasks,
/// returning the sender/receiver halves.
///
/// All data sent on `Sender` will become available on `Receiver` in the same
/// order as it was sent.
///
/// The `Sender` can be cloned to `send` to the same channel from multiple code
/// locations. Only one `Receiver` is supported.
///
/// If the `Receiver` is disconnected while trying to `send`, the `send` method
/// will return a `SendError`. Similarly, if `Sender` is disconnected while
/// trying to `recv`, the `recv` method will return a `RecvError`.
///
/// # Examples
///
/// ```rust
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
///     let (mut tx, mut rx) = mpsc::channel(100);
///
///     tokio::spawn(async move {
///         for i in 0..10 {
///             if let Err(_) = tx.send(i).await {
///                 println!("receiver dropped");
///                 return;
///             }
///         }
///     });
///
///     while let Some(i) = rx.recv().await {
///         println!("got = {}", i);
///     }
/// }
/// ```
pub fn channel<T>(buffer: usize) -> (Sender<T>, Receiver<T>) {
    assert!(buffer > 0, "mpsc bounded channel requires buffer > 0");
    let semaphore = (semaphore::Semaphore::new(buffer), buffer);
    let (tx, rx) = chan::channel(semaphore);

    let tx = Sender::new(tx);
    let rx = Receiver::new(rx);

    (tx, rx)
}

/// Channel semaphore is a tuple of the semaphore implementation and a `usize`
/// representing the channel bound.
type Semaphore = (semaphore::Semaphore, usize);

impl<T> Receiver<T> {
    pub(crate) fn new(chan: chan::Rx<T, Semaphore>) -> Receiver<T> {
        Receiver { chan }
    }

    /// Receive the next value for this receiver.
    ///
    /// `None` is returned when all `Sender` halves have dropped, indicating
    /// that no further values can be sent on the channel.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::mpsc;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (mut tx, mut rx) = mpsc::channel(100);
    ///
    ///     tokio::spawn(async move {
    ///         tx.send("hello").await.unwrap();
    ///     });
    ///
    ///     assert_eq!(Some("hello"), rx.recv().await);
    ///     assert_eq!(None, rx.recv().await);
    /// }
    /// ```
    ///
    /// Values are buffered:
    ///
    /// ```
    /// use tokio::sync::mpsc;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (mut tx, mut rx) = mpsc::channel(100);
    ///
    ///     tx.send("hello").await.unwrap();
    ///     tx.send("world").await.unwrap();
    ///
    ///     assert_eq!(Some("hello"), rx.recv().await);
    ///     assert_eq!(Some("world"), rx.recv().await);
    /// }
    /// ```
    pub async fn recv(&mut self) -> Option<T> {
        use crate::future::poll_fn;

        poll_fn(|cx| self.poll_recv(cx)).await
    }

    #[doc(hidden)] // TODO: document
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        self.chan.recv(cx)
    }

    /// Closes the receiving half of a channel, without dropping it.
    ///
    /// This prevents any further messages from being sent on the channel while
    /// still enabling the receiver to drain messages that are buffered.
    pub fn close(&mut self) {
        self.chan.close();
    }
}

impl<T> Unpin for Receiver<T> {}

cfg_stream! {
    impl<T> futures_core::Stream for Receiver<T> {
        type Item = T;

        fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
            self.poll_recv(cx)
        }
    }
}

impl<T> Sender<T> {
    pub(crate) fn new(chan: chan::Tx<T, Semaphore>) -> Sender<T> {
        Sender { chan }
    }

    #[doc(hidden)] // TODO: document
    pub fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ClosedError>> {
        self.chan.poll_ready(cx).map_err(|_| ClosedError::new())
    }

    /// Attempts to immediately send a message on this `Sender`
    ///
    /// This method differs from [`send`] by returning immediately if the channel's
    /// buffer is full or no receiver is waiting to acquire some data. Compared
    /// with [`send`], this function has two failure cases instead of one (one for
    /// disconnection, one for a full buffer).
    ///
    /// This function may be paired with [`poll_ready`] in order to wait for
    /// channel capacity before trying to send a value.
    ///
    /// # Errors
    ///
    /// If the channel capacity has been reached, i.e., the channel has `n`
    /// buffered values where `n` is the argument passed to [`channel`], then an
    /// error is returned.
    ///
    /// If the receive half of the channel is closed, either due to [`close`]
    /// being called or the [`Receiver`] handle dropping, the function returns
    /// an error. The error includes the value passed to `send`.
    ///
    /// [`send`]: Sender::send
    /// [`poll_ready`]: Sender::poll_ready
    /// [`channel`]: channel
    /// [`close`]: Receiver::close
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::mpsc;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     // Create a channel with buffer size 1
    ///     let (mut tx1, mut rx) = mpsc::channel(1);
    ///     let mut tx2 = tx1.clone();
    ///
    ///     tokio::spawn(async move {
    ///         tx1.send(1).await.unwrap();
    ///         tx1.send(2).await.unwrap();
    ///         // task waits until the receiver receives a value.
    ///     });
    ///
    ///     tokio::spawn(async move {
    ///         // This will return an error and send
    ///         // no message if the buffer is full
    ///         let _ = tx2.try_send(3);
    ///     });
    ///
    ///     let mut msg;
    ///     msg = rx.recv().await.unwrap();
    ///     println!("message {} received", msg);
    ///
    ///     msg = rx.recv().await.unwrap();
    ///     println!("message {} received", msg);
    ///
    ///     // Third message may have never been sent
    ///     match rx.recv().await {
    ///         Some(msg) => println!("message {} received", msg),
    ///         None => println!("the third message was never sent"),
    ///     }
    /// }
    /// ```
    pub fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> {
        self.chan.try_send(message)?;
        Ok(())
    }

    /// Send a value, waiting until there is capacity.
    ///
    /// A successful send occurs when it is determined that the other end of the
    /// channel has not hung up already. An unsuccessful send would be one where
    /// the corresponding receiver has already been closed. Note that a return
    /// value of `Err` means that the data will never be received, but a return
    /// value of `Ok` does not mean that the data will be received. It is
    /// possible for the corresponding receiver to hang up immediately after
    /// this function returns `Ok`.
    ///
    /// # Errors
    ///
    /// If the receive half of the channel is closed, either due to [`close`]
    /// being called or the [`Receiver`] handle dropping, the function returns
    /// an error. The error includes the value passed to `send`.
    ///
    /// [`close`]: Receiver::close
    /// [`Receiver`]: Receiver
    ///
    /// # Examples
    ///
    /// In the following example, each call to `send` will block until the
    /// previously sent value was received.
    ///
    /// ```rust
    /// use tokio::sync::mpsc;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (mut tx, mut rx) = mpsc::channel(1);
    ///
    ///     tokio::spawn(async move {
    ///         for i in 0..10 {
    ///             if let Err(_) = tx.send(i).await {
    ///                 println!("receiver dropped");
    ///                 return;
    ///             }
    ///         }
    ///     });
    ///
    ///     while let Some(i) = rx.recv().await {
    ///         println!("got = {}", i);
    ///     }
    /// }
    /// ```
    pub async fn send(&mut self, value: T) -> Result<(), SendError<T>> {
        use crate::future::poll_fn;

        if poll_fn(|cx| self.poll_ready(cx)).await.is_err() {
            return Err(SendError(value));
        }

        match self.try_send(value) {
            Ok(()) => Ok(()),
            Err(TrySendError::Full(_)) => unreachable!(),
            Err(TrySendError::Closed(value)) => Err(SendError(value)),
        }
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;

pub enum UsageToken<'u> {
    Name(&'u str, Option<bool>),
    Short(char),
    Long(&'u str),
    Help(&'u str),
    Multiple,
}

pub struct UsageParser<'u> {
    usage: &'u str,
    chars: Chars<'u>,
    s: usize,
    e: usize,
}

impl<'u> UsageParser<'u> {
    pub fn with_usage(u: &'u str) -> UsageParser<'u> {
        UsageParser {
            usage: u,
            chars: u.chars(),
            s: 0,
            e: 0,
        }
    }

}

impl<'u> Iterator for UsageParser<'u> {
    type Item = UsageToken<'u>;

    fn next(&mut self) -> Option<UsageToken<'u>> {
        loop {
            match self.chars.next() {
                Some(c) if c == '[' || c == '<'  => {
                    // self.s = self.e + 1;
                    if self.e != 0 {
                        self.e += 1;
                    }
                    self.s = self.e + 1;
                    let closing = match c {
                        '[' => ']',
                        '<' => '>',
                        _   => unreachable!()
                    };
                    while let Some(c) =  self.chars.next() {
                        self.e += 1;
                        if c == closing { break }
                    }
                    if self.e > self.usage.len() { return None }

                    // self.e += 1;

                    let name = &self.usage[self.s..self.e];

                    return Some(UsageToken::Name(name, if c == '<' { Some(true)} else {None}));
                },
                Some('\'') => {
                    self.s = self.e + 2;
                    self.e = self.usage.len() - 1;

                    while let Some(_) = self.chars.next() { continue }

                    return Some(UsageToken::Help(&self.usage[self.s..self.e]));
                },
                Some('-')  => {
                    self.e += 1;
                    match self.chars.next() {
                        Some('-') => {
                            if self.e != 1 {
                                self.e += 1;
                            }

                            self.s = self.e + 1;

                            while let Some(c) = self.chars.next() {
                                self.e += 1;
                                if c == ' ' || c == '=' || c == '.' { break }
                            }
                            if self.e > self.usage.len() { return None }

                            return Some(UsageToken::Long(&self.usage[self.s..self.e]))
                        },
                        Some(c)  => {
                            // When short is first don't increment e
                            if self.e != 1 {
                                self.e += 1;
                            }
                            // Short
                            if !c.is_alphanumeric() {
                                return None
                            }
                            return Some(UsageToken::Short(c))
                        },
                        _      => {
                            return None
                        }
                    }
                },
                Some('.') => {
                    self.e += 1;
                    let mut mult = false;
                    for _ in 0..2 {
                        self.e += 1;
                        match self.chars.next() {
                            // longs consume one '.' so they match '.. ' whereas shorts can match '...'
                            Some('.') | Some(' ')  => { mult = true; },
                            _          => { mult = false; break; }
                        }
                    }
                    if mult { return Some(UsageToken::Multiple) }
                },
                Some(' ') | Some('=') | Some(']') | Some('>') => {
                    self.e += 1;
                    continue
                },
                _  => {
                    return None
                }
            }
        }
    }
}
<commit_msg>fix(from_usage): tabs and spaces should be treated equally<commit_after>use std::str::Chars;

pub enum UsageToken<'u> {
    Name(&'u str, Option<bool>),
    Short(char),
    Long(&'u str),
    Help(&'u str),
    Multiple,
}

pub struct UsageParser<'u> {
    usage: &'u str,
    chars: Chars<'u>,
    s: usize,
    e: usize,
}

impl<'u> UsageParser<'u> {
    pub fn with_usage(u: &'u str) -> UsageParser<'u> {
        UsageParser {
            usage: u,
            chars: u.chars(),
            s: 0,
            e: 0,
        }
    }

}

impl<'u> Iterator for UsageParser<'u> {
    type Item = UsageToken<'u>;

    fn next(&mut self) -> Option<UsageToken<'u>> {
        loop {
            match self.chars.next() {
                Some(c) if c == '[' || c == '<'  => {
                    // self.s = self.e + 1;
                    if self.e != 0 {
                        self.e += 1;
                    }
                    self.s = self.e + 1;
                    let closing = match c {
                        '[' => ']',
                        '<' => '>',
                        _   => unreachable!()
                    };
                    while let Some(c) =  self.chars.next() {
                        self.e += 1;
                        if c == closing { break }
                    }
                    if self.e > self.usage.len() { return None }

                    // self.e += 1;

                    let name = &self.usage[self.s..self.e];

                    return Some(UsageToken::Name(name, if c == '<' { Some(true)} else {None}));
                },
                Some('\'') => {
                    self.s = self.e + 2;
                    self.e = self.usage.len() - 1;

                    while let Some(_) = self.chars.next() { continue }

                    return Some(UsageToken::Help(&self.usage[self.s..self.e]));
                },
                Some('-')  => {
                    self.e += 1;
                    match self.chars.next() {
                        Some('-') => {
                            if self.e != 1 {
                                self.e += 1;
                            }

                            self.s = self.e + 1;

                            while let Some(c) = self.chars.next() {
                                self.e += 1;
                                if c == ' ' || c == '=' || c == '.' { break }
                            }
                            if self.e > self.usage.len() { return None }

                            return Some(UsageToken::Long(&self.usage[self.s..self.e]))
                        },
                        Some(c)  => {
                            // When short is first don't increment e
                            if self.e != 1 {
                                self.e += 1;
                            }
                            // Short
                            if !c.is_alphanumeric() {
                                return None
                            }
                            return Some(UsageToken::Short(c))
                        },
                        _      => {
                            return None
                        }
                    }
                },
                Some('.') => {
                    self.e += 1;
                    let mut mult = false;
                    for _ in 0..2 {
                        self.e += 1;
                        match self.chars.next() {
                            // longs consume one '.' so they match '.. ' whereas shorts can match '...'
                            Some('.') | Some(' ')  => { mult = true; },
                            _          => { mult = false; break; }
                        }
                    }
                    if mult { return Some(UsageToken::Multiple) }
                },
                Some(' ') | Some('=') | Some(']') | Some('>') | Some('\t') => {
                    self.e += 1;
                    continue
                },
                _  => {
                    return None
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//
// rslex - a lexer generator for rust
//
// regexp.rs
// Regexp parsing and representation
//
// Andrei de A. Formiga, 2013-08-09
//

extern mod std;

use parser::LookaheadBuffer;
use parser::skip_whitespace;
use parser::EOF;

#[deriving(Eq)]
enum Token { LBrack, RBrack, Id(~str), LParen, RParen, Asterisk,
             Plus, Bar, Dash, String(~str), Eof }

enum Ast { Symb(~str), Union(~Ast, ~Ast),
           Conc(~Ast, ~Ast), Star(~Ast), CharClass(char, char), Epsilon }

fn parse_string(buffer: &mut LookaheadBuffer, delim: char) -> ~str {
    let mut res : ~str = ~"";
    let mut c = buffer.next_char();
    while c != delim {
        if (c == EOF) {
            fail!(fmt!("Unexpected end of file. Expected closing %c", delim));
        }
        res.push_char(c);
        c = buffer.next_char();
    }
    res
}

#[test]
fn test_parse_string() {
    let mut b1 = std::io::with_str_reader("abc'* ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_string(&mut b1, '\''), &~"abc"));
    assert!(b1.next_char() == '*');

    let mut b2 = std::io::with_str_reader("abc'def\"  ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_string(&mut b2, '"'), &~"abc'def"));
    assert!(b2.next_char() == ' ');
}

#[test]
#[should_fail]
fn unclosed_string() {
    let mut b1 = std::io::with_str_reader("abc'def  ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_string(&mut b1, '"'), &~"abc'def"));
}

#[inline]
fn is_id_char(c: char) -> bool {
    std::char::is_alphanumeric(c) || c == '_'
}

fn parse_id(buffer: &mut LookaheadBuffer, first: char) -> ~str {
    let mut res : ~str = ~"";
    res.push_char(first);
    let mut c = buffer.next_char();
    while is_id_char(c) {
        res.push_char(c);
        c = buffer.next_char();
    }
    buffer.return_char(c);
    res
}

#[test]
fn test_parse_id() {
    let mut b1 = std::io::with_str_reader("abc'* ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_id(&mut b1, 'x'), &~"xabc"));
    assert!(b1.next_char() == '\'');

    let mut b2 = std::io::with_str_reader("bc_def   ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_id(&mut b2, 'a'), &~"abc_def"));

    let mut b3 = std::io::with_str_reader("_times|'xy')*   ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_id(&mut b3, 'n'), &~"n_times"));
    assert!(b3.next_char() == '|');

    let mut b4 = std::io::with_str_reader(" +xy)*   ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_id(&mut b4, 'n'), &~"n"));
    assert!(b4.next_char() == ' ');
    assert!(b4.next_char() == '+');
    assert!(b4.next_char() == 'x');
    assert!(std::str::eq(&parse_id(&mut b4, 'x'), &~"xy"));
}

#[inline]
fn match_next_token(buffer: &mut LookaheadBuffer, t: ~Token) {
    let rt = get_next_token(buffer);
    if rt != t {
        fail!(fmt!("Unexpeced token: expected %?, got %?\n", t, rt));
    }
}

fn get_next_token(buffer: &mut LookaheadBuffer) -> ~Token {
    skip_whitespace(buffer);
    match buffer.next_char() {
        '[' => ~LBrack,
        ']' => ~RBrack,
        '(' => ~LParen,
        ')' => ~RParen,
        '*' => ~Asterisk,
        '+' => ~Plus,
        '|' => ~Bar,
        '-' => ~Dash,
        '\'' => ~String(parse_string(buffer, '\'')),
        '"' => ~String(parse_string(buffer, '"')),
        c if std::char::is_alphabetic(c) => ~Id(parse_id(buffer, c)),
        EOF => ~Eof,
        c => fail!(fmt!("Unexpected character: %c\n", c))
    }
}

#[test]
fn test_get_next_token() {
    let mut b1 = std::io::with_str_reader("'return'", LookaheadBuffer::new);
    assert!(get_next_token(&mut b1) == ~String(~"return"));

    let mut b2 = std::io::with_str_reader("return", LookaheadBuffer::new);
    assert!(get_next_token(&mut b2) == ~Id(~"return"));

    let mut b3 = std::io::with_str_reader("(['a'-'z'])(['A'-'Z'])*", LookaheadBuffer::new);
    assert!(get_next_token(&mut b3) == ~LParen);
    assert!(get_next_token(&mut b3) == ~LBrack);
    assert!(get_next_token(&mut b3) == ~String(~"a"));
    assert!(get_next_token(&mut b3) == ~Dash);
    assert!(get_next_token(&mut b3) == ~String(~"z"));
    assert!(get_next_token(&mut b3) == ~RBrack);
    assert!(get_next_token(&mut b3) == ~RParen);
    assert!(get_next_token(&mut b3) == ~LParen);
    assert!(get_next_token(&mut b3) == ~LBrack);
    assert!(get_next_token(&mut b3) == ~String(~"A"));
    assert!(get_next_token(&mut b3) == ~Dash);
    assert!(get_next_token(&mut b3) == ~String(~"Z"));
    assert!(get_next_token(&mut b3) == ~RBrack);
    assert!(get_next_token(&mut b3) == ~RParen);
    assert!(get_next_token(&mut b3) == ~Asterisk);

    let mut b4 = std::io::with_str_reader("letter (letter | digit)*", LookaheadBuffer::new);
    assert!(get_next_token(&mut b4) == ~Id(~"letter"));
    assert!(get_next_token(&mut b4) == ~LParen);
    assert!(get_next_token(&mut b4) == ~Id(~"letter"));
    assert!(get_next_token(&mut b4) == ~Bar);
    assert!(get_next_token(&mut b4) == ~Id(~"digit"));
    assert!(get_next_token(&mut b4) == ~RParen);
    assert!(get_next_token(&mut b4) == ~Asterisk);
}

// regexp := union
// union  := union '|' concat | concat
// concat := concat factor | factor
// factor := (regexp) | regexp'*' | regexp'+' | class | id | str
// class  := '[' (char | range)* ']'
// range  := char'-'char

// parse a regexp from buffer until one of the terminators in term occurs
pub fn parse_regexp(buffer: &mut LookaheadBuffer, term: &[~str]) -> ~Ast {
    parse_union(buffer, term)
}

fn parse_union(buffer: &mut LookaheadBuffer, term: &[~str]) -> ~Ast {
    let left = parse_concat(buffer, term);
    if get_next_token(buffer) == ~Bar {
        let right = parse_union(buffer, term);
        ~Union(left, right)
    }
    else {
        left
    }
}

fn parse_concat(buffer: &mut LookaheadBuffer, term: &[~str]) -> ~Ast {
    ~Epsilon
}

fn parse_factor(buffer: &mut LookaheadBuffer, term: &[~str]) -> ~Ast {
    let pre = match get_next_token(buffer) {
        ~LParen => { let e = parse_regexp(buffer, term);
                     match_next_token(buffer, ~RParen);
                     e }
        _ => ~Epsilon
    };
    pre
}
<commit_msg>Fleshed out a bit of the regexp parsing.<commit_after>//
// rslex - a lexer generator for rust
//
// regexp.rs
// Regexp parsing and representation
//
// Andrei de A. Formiga, 2013-08-09
//

extern mod std;

use parser::LookaheadBuffer;
use parser::skip_whitespace;
use parser::EOF;

#[deriving(Eq)]
enum Token { LBrack, RBrack, Id(~str), LParen, RParen, Asterisk,
             Plus, Bar, Dash, String(~str), Eof }

enum Ast { Symb(~str), Str(~str), Union(~Ast, ~Ast),
           Conc(~Ast, ~Ast), Star(~Ast), OnePlus(~Ast),
           CharClass(char, char), Epsilon }

fn parse_string(buffer: &mut LookaheadBuffer, delim: char) -> ~str {
    let mut res : ~str = ~"";
    let mut c = buffer.next_char();
    while c != delim {
        if (c == EOF) {
            fail!(fmt!("Unexpected end of file. Expected closing %c", delim));
        }
        res.push_char(c);
        c = buffer.next_char();
    }
    res
}

#[test]
fn test_parse_string() {
    let mut b1 = std::io::with_str_reader("abc'* ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_string(&mut b1, '\''), &~"abc"));
    assert!(b1.next_char() == '*');

    let mut b2 = std::io::with_str_reader("abc'def\"  ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_string(&mut b2, '"'), &~"abc'def"));
    assert!(b2.next_char() == ' ');
}

#[test]
#[should_fail]
fn unclosed_string() {
    let mut b1 = std::io::with_str_reader("abc'def  ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_string(&mut b1, '"'), &~"abc'def"));
}

#[inline]
fn is_id_char(c: char) -> bool {
    std::char::is_alphanumeric(c) || c == '_'
}

fn parse_id(buffer: &mut LookaheadBuffer, first: char) -> ~str {
    let mut res : ~str = ~"";
    res.push_char(first);
    let mut c = buffer.next_char();
    while is_id_char(c) {
        res.push_char(c);
        c = buffer.next_char();
    }
    buffer.return_char(c);
    res
}

#[test]
fn test_parse_id() {
    let mut b1 = std::io::with_str_reader("abc'* ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_id(&mut b1, 'x'), &~"xabc"));
    assert!(b1.next_char() == '\'');

    let mut b2 = std::io::with_str_reader("bc_def   ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_id(&mut b2, 'a'), &~"abc_def"));

    let mut b3 = std::io::with_str_reader("_times|'xy')*   ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_id(&mut b3, 'n'), &~"n_times"));
    assert!(b3.next_char() == '|');

    let mut b4 = std::io::with_str_reader(" +xy)*   ", LookaheadBuffer::new);
    assert!(std::str::eq(&parse_id(&mut b4, 'n'), &~"n"));
    assert!(b4.next_char() == ' ');
    assert!(b4.next_char() == '+');
    assert!(b4.next_char() == 'x');
    assert!(std::str::eq(&parse_id(&mut b4, 'x'), &~"xy"));
}

#[inline]
fn match_next_token(buffer: &mut LookaheadBuffer, t: ~Token) {
    let rt = get_next_token(buffer);
    if rt != t {
        fail!(fmt!("Unexpeced token: expected %?, got %?\n", t, rt));
    }
}

fn get_next_token(buffer: &mut LookaheadBuffer) -> ~Token {
    skip_whitespace(buffer);
    match buffer.next_char() {
        '[' => ~LBrack,
        ']' => ~RBrack,
        '(' => ~LParen,
        ')' => ~RParen,
        '*' => ~Asterisk,
        '+' => ~Plus,
        '|' => ~Bar,
        '-' => ~Dash,
        '\'' => ~String(parse_string(buffer, '\'')),
        '"' => ~String(parse_string(buffer, '"')),
        c if std::char::is_alphabetic(c) => ~Id(parse_id(buffer, c)),
        EOF => ~Eof,
        c => fail!(fmt!("Unexpected character: %c\n", c))
    }
}

#[test]
fn test_get_next_token() {
    let mut b1 = std::io::with_str_reader("'return'", LookaheadBuffer::new);
    assert!(get_next_token(&mut b1) == ~String(~"return"));

    let mut b2 = std::io::with_str_reader("return", LookaheadBuffer::new);
    assert!(get_next_token(&mut b2) == ~Id(~"return"));

    let mut b3 = std::io::with_str_reader("(['a'-'z'])(['A'-'Z'])*", LookaheadBuffer::new);
    assert!(get_next_token(&mut b3) == ~LParen);
    assert!(get_next_token(&mut b3) == ~LBrack);
    assert!(get_next_token(&mut b3) == ~String(~"a"));
    assert!(get_next_token(&mut b3) == ~Dash);
    assert!(get_next_token(&mut b3) == ~String(~"z"));
    assert!(get_next_token(&mut b3) == ~RBrack);
    assert!(get_next_token(&mut b3) == ~RParen);
    assert!(get_next_token(&mut b3) == ~LParen);
    assert!(get_next_token(&mut b3) == ~LBrack);
    assert!(get_next_token(&mut b3) == ~String(~"A"));
    assert!(get_next_token(&mut b3) == ~Dash);
    assert!(get_next_token(&mut b3) == ~String(~"Z"));
    assert!(get_next_token(&mut b3) == ~RBrack);
    assert!(get_next_token(&mut b3) == ~RParen);
    assert!(get_next_token(&mut b3) == ~Asterisk);

    let mut b4 = std::io::with_str_reader("letter (letter | digit)*", LookaheadBuffer::new);
    assert!(get_next_token(&mut b4) == ~Id(~"letter"));
    assert!(get_next_token(&mut b4) == ~LParen);
    assert!(get_next_token(&mut b4) == ~Id(~"letter"));
    assert!(get_next_token(&mut b4) == ~Bar);
    assert!(get_next_token(&mut b4) == ~Id(~"digit"));
    assert!(get_next_token(&mut b4) == ~RParen);
    assert!(get_next_token(&mut b4) == ~Asterisk);
}

// regexp := union
// union  := union '|' concat | concat
// concat := concat factor | factor
// factor := (regexp) | regexp'*' | regexp'+' | class | id | str
// class  := '[' (char | range)* ']'
// range  := char'-'char

// parse a regexp from buffer until one of the terminators in term occurs
pub fn parse_regexp(buffer: &mut LookaheadBuffer, term: &[~str]) -> ~Ast {
    parse_union(buffer, term)
}

fn parse_union(buffer: &mut LookaheadBuffer, term: &[~str]) -> ~Ast {
    let left = parse_concat(buffer, term);
    if get_next_token(buffer) == ~Bar {
        let right = parse_union(buffer, term);
        ~Union(left, right)
    }
    else {
        left
    }
}

fn parse_concat(buffer: &mut LookaheadBuffer, term: &[~str]) -> ~Ast {
    let left = parse_factor(buffer, term);
    let right = parse_factor(buffer, term);
    ~Conc(left, right)
}

fn trailing_closure(buffer: &mut LookaheadBuffer) -> Option<char> {
    skip_whitespace(buffer);
    match buffer.next_char() {
        '*' => Some('*'),
        '+' => Some('+'),
        c => { buffer.return_char(c); None }
    }
}

fn parse_character_class(buffer: &mut LookaheadBuffer) -> ~Ast {
    ~Epsilon         // TODO
}

fn parse_factor(buffer: &mut LookaheadBuffer, term: &[~str]) -> ~Ast {
    let pre = match get_next_token(buffer) {
        ~LParen => { let e = parse_regexp(buffer, term);
                     match_next_token(buffer, ~RParen);
                     e }
        ~LBrack => parse_character_class(buffer),
        ~Id(s) => ~Symb(s),
        ~String(s) => ~Str(s),  // TODO: check for END
        _ => ~Epsilon        // TODO: error
    };
    match trailing_closure(buffer) {
        Some('*') => ~Star(pre),
        Some('+') => ~OnePlus(pre),
        Some(_) => fail!("Unexpected closure character"),
        None => pre
    }
}
<|endoftext|>