<commit_before>use c_types;
use c_ares_sys;

use types::AddressFamily;
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_int;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::str;

// Convert an address family into a more strongly typed AddressFamily.
pub fn address_family(family: c_int) -> Option<AddressFamily> {
    match family {
        c_types::AF_INET => Some(AddressFamily::INET),
        c_types::AF_INET6 => Some(AddressFamily::INET6),
        c_types::AF_UNSPEC => Some(AddressFamily::UNSPEC),
        _ => None,
    }
}

// Get an in_addr from an Ipv4Addr.
#[cfg(unix)]
pub fn ipv4_as_in_addr(ipv4: &Ipv4Addr) -> c_types::in_addr {
    c_types::in_addr {
        s_addr: u32::from(*ipv4).to_be(),
    }
}

#[cfg(windows)]
pub fn ipv4_as_in_addr(ipv4: &Ipv4Addr) -> c_types::in_addr {
    let octets = ipv4.octets();
    let mut in_addr: c_types::in_addr = unsafe { mem::uninitialized() };
    {
        let bytes = unsafe { in_addr.S_un.S_un_b_mut() };
        bytes.s_b1 = octets[0];
        bytes.s_b2 = octets[1];
        bytes.s_b3 = octets[2];
        bytes.s_b4 = octets[3];
    }
    in_addr
}

// Get an Ipv4Addr from an in_addr.
#[cfg(unix)]
pub fn ipv4_from_in_addr(in_addr: &c_types::in_addr) -> Ipv4Addr {
    Ipv4Addr::from(u32::from_be(in_addr.s_addr))
}

#[cfg(windows)]
pub fn ipv4_from_in_addr(in_addr: &c_types::in_addr) -> Ipv4Addr {
    let bytes = unsafe { in_addr.S_un.S_un_b() };
    Ipv4Addr::new(bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4)
}

// Get an in6_addr from an Ipv6Addr.
#[cfg(unix)]
pub fn ipv6_as_in6_addr(ipv6: &Ipv6Addr) -> c_types::in6_addr {
    let octets = ipv6.octets();
    let mut in6_addr: c_types::in6_addr = unsafe { mem::uninitialized() };
    in6_addr.s6_addr.copy_from_slice(&octets);
    in6_addr
}

#[cfg(windows)]
pub fn ipv6_as_in6_addr(ipv6: &Ipv6Addr) -> c_types::in6_addr {
    let octets = ipv6.octets();
    let mut in6_addr: c_types::in6_addr = unsafe { mem::uninitialized() };
    {
        let bytes = unsafe { in6_addr.u.Byte_mut() };
        bytes.copy_from_slice(&octets);
    }
    in6_addr
}

// Get a sockaddr_in from a SocketAddrV4.
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
          target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd",
          target_os = "bitrig"))]
pub fn socket_addrv4_as_sockaddr_in(sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
    let in_addr = ipv4_as_in_addr(sock_v4.ip());
    c_types::sockaddr_in {
        sin_len: mem::size_of::<c_types::sockaddr_in>() as u8,
        sin_family: c_types::AF_INET as c_types::sa_family_t,
        sin_port: sock_v4.port().to_be(),
        sin_addr: in_addr,
        sin_zero: [0; 8],
    }
}

#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
              target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd",
              target_os = "bitrig")))]
pub fn socket_addrv4_as_sockaddr_in(sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
    let in_addr = ipv4_as_in_addr(sock_v4.ip());
    c_types::sockaddr_in {
        sin_family: c_types::AF_INET as c_types::sa_family_t,
        sin_port: sock_v4.port().to_be(),
        sin_addr: in_addr,
        sin_zero: [0; 8],
    }
}

// Get a sockaddr_in6 from a SocketAddrV6.
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
          target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd",
          target_os = "bitrig"))]
pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_len: mem::size_of::<c_types::sockaddr_in6>() as u8,
        sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

#[cfg(all(unix,
          not(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
                  target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd",
                  target_os = "bitrig"))))]
pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

#[cfg(windows)]
pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let mut sockaddr_in6: c_types::sockaddr_in6 = unsafe { mem::uninitialized() };
    sockaddr_in6.sin6_family = c_types::AF_INET6 as c_types::sa_family_t;
    sockaddr_in6.sin6_port = sock_v6.port().to_be();
    sockaddr_in6.sin6_addr = ipv6_as_in6_addr(sock_v6.ip());
    sockaddr_in6.sin6_flowinfo = sock_v6.flowinfo();
    {
        let scope_id = unsafe { sockaddr_in6.u.sin6_scope_id_mut() };
        *scope_id = sock_v6.scope_id();
    }
    sockaddr_in6
}

/// Get the version number of the underlying `c-ares` library.
///
/// The version is returned as both a string and an integer.  The integer is
/// built up as 24bit number, with 8 separate bits used for major number, minor
/// number and patch number.  For example, the version string "1.2.3" is
/// returned as hexadecimal number 0x010203 (decimal 66051).
pub fn version() -> (&'static str, u32) {
    let mut int_version: c_int = 0;
    let str_version = unsafe {
        let ptr = c_ares_sys::ares_version(&mut int_version);
        let buf = CStr::from_ptr(ptr).to_bytes();
        str::from_utf8_unchecked(buf)
    };
    (str_version, int_version as u32)
}
<commit_msg>safety first<commit_after>use c_types;
use c_ares_sys;

use types::AddressFamily;
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_int;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
use std::str;

// Convert an address family into a more strongly typed AddressFamily.
pub fn address_family(family: c_int) -> Option<AddressFamily> {
    match family {
        c_types::AF_INET => Some(AddressFamily::INET),
        c_types::AF_INET6 => Some(AddressFamily::INET6),
        c_types::AF_UNSPEC => Some(AddressFamily::UNSPEC),
        _ => None,
    }
}

// Get an in_addr from an Ipv4Addr.
#[cfg(unix)]
pub fn ipv4_as_in_addr(ipv4: &Ipv4Addr) -> c_types::in_addr {
    c_types::in_addr {
        s_addr: u32::from(*ipv4).to_be(),
    }
}

#[cfg(windows)]
pub fn ipv4_as_in_addr(ipv4: &Ipv4Addr) -> c_types::in_addr {
    let octets = ipv4.octets();
    let mut in_addr: c_types::in_addr = unsafe { mem::zeroed() };
    {
        let bytes = unsafe { in_addr.S_un.S_un_b_mut() };
        bytes.s_b1 = octets[0];
        bytes.s_b2 = octets[1];
        bytes.s_b3 = octets[2];
        bytes.s_b4 = octets[3];
    }
    in_addr
}

// Get an Ipv4Addr from an in_addr.
#[cfg(unix)]
pub fn ipv4_from_in_addr(in_addr: &c_types::in_addr) -> Ipv4Addr {
    Ipv4Addr::from(u32::from_be(in_addr.s_addr))
}

#[cfg(windows)]
pub fn ipv4_from_in_addr(in_addr: &c_types::in_addr) -> Ipv4Addr {
    let bytes = unsafe { in_addr.S_un.S_un_b() };
    Ipv4Addr::new(bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4)
}

// Get an in6_addr from an Ipv6Addr.
#[cfg(unix)]
pub fn ipv6_as_in6_addr(ipv6: &Ipv6Addr) -> c_types::in6_addr {
    let octets = ipv6.octets();
    let mut in6_addr: c_types::in6_addr = unsafe { mem::zeroed() };
    in6_addr.s6_addr.copy_from_slice(&octets);
    in6_addr
}

#[cfg(windows)]
pub fn ipv6_as_in6_addr(ipv6: &Ipv6Addr) -> c_types::in6_addr {
    let octets = ipv6.octets();
    let mut in6_addr: c_types::in6_addr = unsafe { mem::zeroed() };
    {
        let bytes = unsafe { in6_addr.u.Byte_mut() };
        bytes.copy_from_slice(&octets);
    }
    in6_addr
}

// Get a sockaddr_in from a SocketAddrV4.
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
          target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd",
          target_os = "bitrig"))]
pub fn socket_addrv4_as_sockaddr_in(sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
    let in_addr = ipv4_as_in_addr(sock_v4.ip());
    c_types::sockaddr_in {
        sin_len: mem::size_of::<c_types::sockaddr_in>() as u8,
        sin_family: c_types::AF_INET as c_types::sa_family_t,
        sin_port: sock_v4.port().to_be(),
        sin_addr: in_addr,
        sin_zero: [0; 8],
    }
}

#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
              target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd",
              target_os = "bitrig")))]
pub fn socket_addrv4_as_sockaddr_in(sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
    let in_addr = ipv4_as_in_addr(sock_v4.ip());
    c_types::sockaddr_in {
        sin_family: c_types::AF_INET as c_types::sa_family_t,
        sin_port: sock_v4.port().to_be(),
        sin_addr: in_addr,
        sin_zero: [0; 8],
    }
}

// Get a sockaddr_in6 from a SocketAddrV6.
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
          target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd",
          target_os = "bitrig"))]
pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_len: mem::size_of::<c_types::sockaddr_in6>() as u8,
        sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

#[cfg(all(unix,
          not(any(target_os = "macos", target_os = "ios", target_os = "freebsd",
                  target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd",
                  target_os = "bitrig"))))]
pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

#[cfg(windows)]
pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let mut sockaddr_in6: c_types::sockaddr_in6 = unsafe { mem::zeroed() };
    sockaddr_in6.sin6_family = c_types::AF_INET6 as c_types::sa_family_t;
    sockaddr_in6.sin6_port = sock_v6.port().to_be();
    sockaddr_in6.sin6_addr = ipv6_as_in6_addr(sock_v6.ip());
    sockaddr_in6.sin6_flowinfo = sock_v6.flowinfo();
    {
        let scope_id = unsafe { sockaddr_in6.u.sin6_scope_id_mut() };
        *scope_id = sock_v6.scope_id();
    }
    sockaddr_in6
}

/// Get the version number of the underlying `c-ares` library.
///
/// The version is returned as both a string and an integer.  The integer is
/// built up as 24bit number, with 8 separate bits used for major number, minor
/// number and patch number.  For example, the version string "1.2.3" is
/// returned as hexadecimal number 0x010203 (decimal 66051).
pub fn version() -> (&'static str, u32) {
    let mut int_version: c_int = 0;
    let str_version = unsafe {
        let ptr = c_ares_sys::ares_version(&mut int_version);
        let buf = CStr::from_ptr(ptr).to_bytes();
        str::from_utf8_unchecked(buf)
    };
    (str_version, int_version as u32)
}
<|endoftext|>


<commit_before>use unicode_width::UnicodeWidthStr;

/// Computes a sub-string length that fits in the given `width`.
///
/// Takes non-breakable elements from `iter`, while keeping the
/// string width under `width` (and adding the length of `delimiter`
/// between each element).
///
/// Example:
///
/// ```
/// let my_text = "blah...";
/// // This returns the number of bytes for a prefix of `my_text` that
/// // fits within 5 cells.
/// head_bytes(my_text.graphemes(true), 5, "");
/// ```
pub fn head_bytes<'a, I: Iterator<Item = &'a str>>(iter: I, width: usize,
                                               delimiter: &str)
                                               -> usize {
    let delimiter_width = delimiter.width();
    let delimiter_len = delimiter.len();

    let sum = iter.scan(0, |w, token| {
            *w += token.width();
            if *w > width {
                None
            } else {
                // Add a space
                *w += delimiter_width;
                Some(token)
            }
        })
        .map(|token| token.len() + delimiter_len)
        .fold(0, |a, b| a + b);

    // We counted delimiter once too many times,
    // but only if the iterator was non empty.
    if sum == 0 {
        sum
    } else {
        sum - delimiter_len
    }
}
<commit_msg>Don't compile internal doc example<commit_after>use unicode_width::UnicodeWidthStr;

// Computes a sub-string length that fits in the given `width`.
//
// Takes non-breakable elements from `iter`, while keeping the
// string width under `width` (and adding the length of `delimiter`
// between each element).
//
// Example:
//
// ```
// let my_text = "blah...";
// // This returns the number of bytes for a prefix of `my_text` that
// // fits within 5 cells.
// head_bytes(my_text.graphemes(true), 5, "");
// ```
pub fn head_bytes<'a, I: Iterator<Item = &'a str>>(iter: I, width: usize,
                                               delimiter: &str)
                                               -> usize {
    let delimiter_width = delimiter.width();
    let delimiter_len = delimiter.len();

    let sum = iter.scan(0, |w, token| {
            *w += token.width();
            if *w > width {
                None
            } else {
                // Add a space
                *w += delimiter_width;
                Some(token)
            }
        })
        .map(|token| token.len() + delimiter_len)
        .fold(0, |a, b| a + b);

    // We counted delimiter once too many times,
    // but only if the iterator was non empty.
    if sum == 0 {
        sum
    } else {
        sum - delimiter_len
    }
}
<|endoftext|>


<commit_before>use graph::Graph;

use gio;
use glib::Cast;
use gtk::{GtkApplicationExt, Inhibit, WidgetExt};

use std::cell::RefCell;
use std::ops::Index;
use std::rc::Rc;

pub const MAIN_WINDOW_NAME: &str = "main-window";

#[derive(Debug)]
pub struct RotateVec<T> {
    data: Vec<T>,
    start: usize,
}

impl<T> RotateVec<T> {
    pub fn new(d: Vec<T>) -> RotateVec<T> {
        RotateVec { data: d, start: 0 }
    }

    pub fn len(&self) -> usize {
        self.data.len()
    }

    pub fn is_empty(&self) -> bool {
        self.data.is_empty()
    }

    pub fn move_start(&mut self) {
        if self.start > 0 {
            self.start -= 1;
        } else {
            self.start = self.data.len() - 1;
        }
    }

    /*pub fn get(&self, index: usize) -> Option<&T> {
        self.data.get(self.get_real_pos(index))
    }*/

    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
        let pos = self.get_real_pos(index);
        self.data.get_mut(pos)
    }

    fn get_real_pos(&self, index: usize) -> usize {
        if self.start + index >= self.data.len() {
            self.start + index - self.data.len()
        } else {
            index + self.start
        }
    }
}

pub fn format_number(mut nb: u64) -> String {
    if nb < 1000 {
        return format!("{} B", nb);
    }
    nb >>= 10; // / 1_024
    if nb < 100_000 {
        format!("{} kB", nb)
    } else if nb < 10_000_000 {
        format!("{} MB", nb >> 10) // / 1_024
    } else if nb < 10_000_000_000 {
        format!("{} GB", nb >> 20) // / 1_048_576
    } else {
        format!("{} TB", nb >> 30) // / 1_073_741_824
    }
}

pub fn connect_graph(graph: Graph) -> Rc<RefCell<Graph>> {
    let area = graph.area.clone();
    let graph = Rc::new(RefCell::new(graph));
    area.connect_draw(
        clone!(@weak graph => @default-return Inhibit(false), move |w, c| {
            graph.borrow()
                 .draw(c,
                       f64::from(w.get_allocated_width()),
                       f64::from(w.get_allocated_height()));
            Inhibit(false)
        }),
    );
    graph
}

impl<T> Index<usize> for RotateVec<T> {
    type Output = T;

    fn index(&self, index: usize) -> &T {
        &self.data[self.get_real_pos(index)]
    }
}

pub fn get_app() -> gtk::Application {
    gio::Application::get_default()
        .expect("No default application")
        .downcast::<gtk::Application>()
        .expect("Default application has wrong type")
}

pub fn get_main_window() -> Option<gtk::Window> {
    for window in get_app().get_windows() {
        if window.get_widget_name().as_ref().map(|ref s| s.as_str()) == Some(MAIN_WINDOW_NAME) {
            return Some(window);
        }
    }
    None
}
<commit_msg>Formatting fix<commit_after>use graph::Graph;

use gio;
use glib::Cast;
use gtk::{GtkApplicationExt, Inhibit, WidgetExt};

use std::cell::RefCell;
use std::ops::Index;
use std::rc::Rc;

pub const MAIN_WINDOW_NAME: &str = "main-window";

#[derive(Debug)]
pub struct RotateVec<T> {
    data: Vec<T>,
    start: usize,
}

impl<T> RotateVec<T> {
    pub fn new(d: Vec<T>) -> RotateVec<T> {
        RotateVec { data: d, start: 0 }
    }

    pub fn len(&self) -> usize {
        self.data.len()
    }

    pub fn is_empty(&self) -> bool {
        self.data.is_empty()
    }

    pub fn move_start(&mut self) {
        if self.start > 0 {
            self.start -= 1;
        } else {
            self.start = self.data.len() - 1;
        }
    }

    /*pub fn get(&self, index: usize) -> Option<&T> {
        self.data.get(self.get_real_pos(index))
    }*/

    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
        let pos = self.get_real_pos(index);
        self.data.get_mut(pos)
    }

    fn get_real_pos(&self, index: usize) -> usize {
        if self.start + index >= self.data.len() {
            self.start + index - self.data.len()
        } else {
            index + self.start
        }
    }
}

pub fn format_number(mut nb: u64) -> String {
    if nb < 1000 {
        return format!("{} B", nb);
    }
    nb >>= 10; // / 1_024
    if nb < 100_000 {
        format!("{} KiB", nb)
    } else if nb < 10_000_000 {
        format!("{} MiB", nb >> 10) // / 1_024
    } else if nb < 10_000_000_000 {
        format!("{} GiB", nb >> 20) // / 1_048_576
    } else {
        format!("{} TiB", nb >> 30) // / 1_073_741_824
    }
}

pub fn connect_graph(graph: Graph) -> Rc<RefCell<Graph>> {
    let area = graph.area.clone();
    let graph = Rc::new(RefCell::new(graph));
    area.connect_draw(
        clone!(@weak graph => @default-return Inhibit(false), move |w, c| {
            graph.borrow()
                 .draw(c,
                       f64::from(w.get_allocated_width()),
                       f64::from(w.get_allocated_height()));
            Inhibit(false)
        }),
    );
    graph
}

impl<T> Index<usize> for RotateVec<T> {
    type Output = T;

    fn index(&self, index: usize) -> &T {
        &self.data[self.get_real_pos(index)]
    }
}

pub fn get_app() -> gtk::Application {
    gio::Application::get_default()
        .expect("No default application")
        .downcast::<gtk::Application>()
        .expect("Default application has wrong type")
}

pub fn get_main_window() -> Option<gtk::Window> {
    for window in get_app().get_windows() {
        if window.get_widget_name().as_ref().map(|ref s| s.as_str()) == Some(MAIN_WINDOW_NAME) {
            return Some(window);
        }
    }
    None
}
<|endoftext|>


<commit_before>
use ::std;
use ::std::ffi::OsString;
use ::std::os::windows::ffi::OsStringExt;

use ::WCString;
use ::NoNulError;
use ::error;

/// Representation of a borrowed Win32 style "wide" string.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct WCStr {
    inner: [u16]
}

impl WCStr {
    /// Create a ```&WCStr``` from a raw pointer and a length.
    ///
    /// This function is unsafe for the reasons mentioned below.
    ///
    /// This function assumes that the pointer passed in has these properties:
    ///
    /// * It is not null.
    /// * It is a valid pointer.
    /// * It points to an array of ```u16```'s that does not contain any ```nul``` values.
    /// * It points to an array of ```u16```'s that is terminated with a ```nul``` at exactly the offset "```len```".
    ///
    /// This function will assert/panic when ```nul``` is not found at offset "```len```".
    ///
    /// The lifetime of the ```&WCStr``` returned from this function is not guranteed to be correct and
    /// it is up to the caller to determine the appropriate lifetime.
    ///
    /// # ```from_raw_parts()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = unsafe { WCStr::from_raw_parts(a.as_ptr(), a.len() - 1) };
    ///     assert!(s.len() == (a.len() - 1));
    pub unsafe fn from_raw_parts<'a>(ptr: *const u16, len: usize) -> &'a WCStr {
        assert!(*ptr.offset(len as isize) == 0u16);
        std::mem::transmute(std::slice::from_raw_parts(ptr, len + 1))
    }

    /// Create a ```&WCStr``` from a slice of ```u16```'s.
    /// This function will scan the slice for ```nul``` and assume that ```nul``` terminates the string.
    /// If no ```nul``` is found in the slice, it will return ```Err(NoNulError(None))```
    /// # ```frm_slice_with_nul()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = WCStr::from_slice_with_nul(a).unwrap();
    ///     assert!(s.len() == (a.len() - 1));
    pub fn from_slice_with_nul<'a>(slice: &'a [u16]) -> Result<&'a WCStr, NoNulError> {
        match slice.iter().position(|x| *x == 0) {
            None => Err(error::no_nul(None)),
            Some(i) => Ok(unsafe { std::mem::transmute(&slice[..i + 1]) }),
        }
    }

    /// length of the string in u16 units
    pub fn len(&self) -> usize {
        self.inner.len() - 1
    }

    /// Return a raw pointer to this "wide" string.
    ///
    ///  * The pointer remains valid only as long as this string is valid.
    ///  * The pointer points to a contiguous region of memory terminated with ```nul```.
    pub fn as_ptr(&self) -> *const u16 {
        self.inner.as_ptr()
    }

    /// Return this "wide" string as a slice of ```u16```s without a ```nul``` terminator.
    pub fn to_slice(&self) -> &[u16] {
        &self.inner[..self.len()]
    }

    /// Return this "wide" string as a slice of ```u16```s with a ```nul``` terminator.
    pub fn to_slice_with_nul(&self) -> &[u16] {
        &self.inner
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16```
    pub fn to_string(&self) -> Result<String, std::string::FromUtf16Error> {
        String::from_utf16(&self.to_slice())
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16_lossy```
    pub fn to_string_lossy(&self) -> String {
        String::from_utf16_lossy(&self.to_slice())
    }

    /// Convert this "wide" string to an ```OsString``` by using ```OsString::from_wide```
    pub fn to_os_string(&self) -> OsString {
        OsString::from_wide(self.to_slice())
    }
}

impl std::fmt::Debug for WCStr {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        try!(write!(f, "\""));
        for &w in self.to_slice().iter() {
            if w < 0xD800 || w >= 0xE000 {
                for c in std::char::from_u32(w as u32).unwrap().escape_default() {
                    use std::fmt::Write;
                    try!(f.write_char(c));
                }
            }
            else {
                try!(write!(f, "\\u{{{:X}}}", w));
            }
        }
        write!(f, "\"")
    }
}

impl AsRef<WCStr> for WCStr {
    fn as_ref(&self) -> &WCStr {
        self
    }
}

impl AsRef<[u16]> for WCStr {
    fn as_ref(&self) -> &[u16] {
        &self.inner[..self.len()]
    }
}

impl ToOwned for WCStr {
    type Owned = WCString;
    fn to_owned(&self) -> WCString {
        unsafe {
            WCString::from_vec_with_nul_unchecked(self.inner.to_owned())
        }
    }
}

<commit_msg>starts_with<commit_after>
use ::std;
use ::std::ffi::{OsString, OsStr};
use ::std::os::windows::ffi::{OsStringExt, OsStrExt};

use ::WCString;
use ::NoNulError;
use ::error;

/// Representation of a borrowed Win32 style "wide" string.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct WCStr {
    inner: [u16]
}

impl WCStr {
    /// Create a ```&WCStr``` from a raw pointer and a length.
    ///
    /// This function is unsafe for the reasons mentioned below.
    ///
    /// This function assumes that the pointer passed in has these properties:
    ///
    /// * It is not null.
    /// * It is a valid pointer.
    /// * It points to an array of ```u16```'s that does not contain any ```nul``` values.
    /// * It points to an array of ```u16```'s that is terminated with a ```nul``` at exactly the offset "```len```".
    ///
    /// This function will assert/panic when ```nul``` is not found at offset "```len```".
    ///
    /// The lifetime of the ```&WCStr``` returned from this function is not guranteed to be correct and
    /// it is up to the caller to determine the appropriate lifetime.
    ///
    /// # ```from_raw_parts()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = unsafe { WCStr::from_raw_parts(a.as_ptr(), a.len() - 1) };
    ///     assert!(s.len() == (a.len() - 1));
    pub unsafe fn from_raw_parts<'a>(ptr: *const u16, len: usize) -> &'a WCStr {
        assert!(*ptr.offset(len as isize) == 0u16);
        std::mem::transmute(std::slice::from_raw_parts(ptr, len + 1))
    }

    /// Create a ```&WCStr``` from a slice of ```u16```'s.
    /// This function will scan the slice for ```nul``` and assume that ```nul``` terminates the string.
    /// If no ```nul``` is found in the slice, it will return ```Err(NoNulError(None))```
    /// # ```frm_slice_with_nul()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = WCStr::from_slice_with_nul(a).unwrap();
    ///     assert!(s.len() == (a.len() - 1));
    pub fn from_slice_with_nul<'a>(slice: &'a [u16]) -> Result<&'a WCStr, NoNulError> {
        match slice.iter().position(|x| *x == 0) {
            None => Err(error::no_nul(None)),
            Some(i) => Ok(unsafe { std::mem::transmute(&slice[..i + 1]) }),
        }
    }

    /// length of the string in u16 units
    pub fn len(&self) -> usize {
        self.inner.len() - 1
    }

    /// Return a raw pointer to this "wide" string.
    ///
    ///  * The pointer remains valid only as long as this string is valid.
    ///  * The pointer points to a contiguous region of memory terminated with ```nul```.
    pub fn as_ptr(&self) -> *const u16 {
        self.inner.as_ptr()
    }

    /// Return this "wide" string as a slice of ```u16```s without a ```nul``` terminator.
    pub fn to_slice(&self) -> &[u16] {
        &self.inner[..self.len()]
    }

    /// Return this "wide" string as a slice of ```u16```s with a ```nul``` terminator.
    pub fn to_slice_with_nul(&self) -> &[u16] {
        &self.inner
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16```
    pub fn to_string(&self) -> Result<String, std::string::FromUtf16Error> {
        String::from_utf16(self.to_slice())
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16_lossy```
    pub fn to_string_lossy(&self) -> String {
        String::from_utf16_lossy(self.to_slice())
    }

    /// Convert this "wide" string to an ```OsString``` by using ```OsString::from_wide```
    pub fn to_os_string(&self) -> OsString {
        OsString::from_wide(self.to_slice())
    }

    /// starts with a string
    pub fn starts_with<T>(&self, s: T) -> bool
        where T: AsRef<WCStr> {
        let s = s.as_ref();
        let len = self.len();
        if s.len() > len {
            return false;
        }

        self.to_slice().iter().zip(s.to_slice().iter()).all(|(&a, &b)| a == b)
    }

    /// starts with a string
    pub fn starts_with_str<T>(&self, s: T) -> bool
        where T: AsRef<OsStr> {
        let s = s.as_ref();
        let mut s_iter = s.encode_wide();
        let mut t_iter = self.to_slice().iter();

        while let Some(a) = s_iter.next() {
            match t_iter.next() {
                Some(&b) if a == b => (),
                _ => return false,
            }
        }

        true
    }
}

impl std::fmt::Debug for WCStr {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        try!(write!(f, "\""));
        for &w in self.to_slice().iter() {
            if w < 0xD800 || w >= 0xE000 {
                for c in std::char::from_u32(w as u32).unwrap().escape_default() {
                    use std::fmt::Write;
                    try!(f.write_char(c));
                }
            }
            else {
                try!(write!(f, "\\u{{{:X}}}", w));
            }
        }
        write!(f, "\"")
    }
}

impl AsRef<WCStr> for WCStr {
    fn as_ref(&self) -> &WCStr {
        self
    }
}

impl AsRef<[u16]> for WCStr {
    fn as_ref(&self) -> &[u16] {
        &self.inner[..self.len()]
    }
}

impl ToOwned for WCStr {
    type Owned = WCString;
    fn to_owned(&self) -> WCString {
        unsafe {
            WCString::from_vec_with_nul_unchecked(self.inner.to_owned())
        }
    }
}

<|endoftext|>


<commit_before>use super::*;
use std::collections::{BTreeMap, LinkedList};

pub fn identify_terminals<A>(tree_map: &BTreeMap<Vec<usize>, Composition<A>>)
        -> (BTreeMap<Vec<usize>, Composition<(Vec<usize>, usize)>>, BTreeMap<(Vec<usize>, usize), A>)
    where A: Clone,
{
    let mut identified_tree_map = BTreeMap::new();
    let mut terminal_map = BTreeMap::new();

    for (address, composition) in tree_map {
        let vec_compos = &composition.composition;
        let mut identified_compos = Vec::new();
        let mut compos_var_pos = 0;

        for component in vec_compos {
            let mut identified_compon = Vec::new();

            for variable in component {
                match variable {
                    &VarT::Var(x, y) => {
                        identified_compon.push(VarT::Var(x, y));
                    },
                    &VarT::T(ref terminal) => {
                        let terminal_id = (address.clone(), compos_var_pos);
                        identified_compon.push(VarT::T(terminal_id.clone()));
                        terminal_map.insert(terminal_id, terminal.clone());
                    },
                };

                compos_var_pos += 1;
            }

            identified_compos.push(identified_compon);
        }

        identified_tree_map.insert(address.clone(), Composition::from(identified_compos));
    }

    (identified_tree_map, terminal_map)
}

pub fn to_negra_vector<H, T, W>(tree_map: &BTreeMap<Vec<usize>, PMCFGRule<H, T, W>>)
        -> Vec<(String, String, usize)>
    where H: Clone + ToString,
          T: Clone + ToString,
{
    let (term_map, nonterminal_map) = to_term(&tree_map);
    // TODO: Enforce negra grammar restrictions
    let (identified_tree_map, terminal_map) = identify_terminals(&term_map);
    let evaluated_compos = evaluate(&identified_tree_map);

    let mut negra_vector = Vec::new();
    let mut rule_queue = LinkedList::new();
    let mut finished_map = BTreeMap::new();
    let mut rule_counter = 0;

    for component in evaluated_compos.composition {
        for variable in component {
            match variable {
                VarT::Var(_, _) => {
                    panic!("Nonterminals must not appear in a fully evaluated configuration!");
                },
                VarT::T(terminal_id) => {
                    let terminal_symbol = terminal_map.get(&terminal_id).unwrap();
                    let ref address = terminal_id.0;
                    let rule_label = nonterminal_map.get(address).unwrap();
                    let rule_number = get_rule_number(address, &mut rule_queue, &finished_map,
                                                      &mut rule_counter);
                    negra_vector.push((terminal_symbol.to_string(), rule_label.to_string(), rule_number));
                }
            }
        }
    }

    while let Some((address, rule_number)) = rule_queue.pop_front() {
        let mut parent_address = address.clone();

        let parent_number = if let None = parent_address.pop() {
            0
        } else {
            let number = get_rule_number(&parent_address, &mut rule_queue, &finished_map, &mut rule_counter);
            finished_map.insert(parent_address.clone(), number);
            number
        };

        let rule_label = nonterminal_map.get(&address).unwrap();
        negra_vector.push((rule_number.to_string(), rule_label.to_string(), parent_number));
    }

    negra_vector
}

fn get_rule_number(address: &Vec<usize>, rule_queue: &mut LinkedList<(Vec<usize>, usize)>, finished_map: &BTreeMap<Vec<usize>, usize>, rule_counter: &mut usize)
        -> usize
{
    if let Some(rule_number) = finished_map.get(address) {
        return *rule_number
    }

    let rule_number = *rule_counter;
    *rule_counter = *rule_counter + 1;
    rule_queue.push_back((address.clone(), rule_number));
    rule_number
}

#[cfg(test)]
mod tests {
    use super::*;
    use VarT::{Var, T};

    #[test]
    fn test_identify_terminals() {
        let mut tree_map = BTreeMap::new();
        tree_map.insert(vec![], Composition::from(vec![
            vec![Var(0, 0), T("a"), Var(0, 1), T("b")]
        ]));
        tree_map.insert(vec![0], Composition::from(vec![
            vec![Var(1, 0)],
            vec![T("c")]
        ]));
        tree_map.insert(vec![0, 1], Composition::from(vec![
            vec![T("d")]
        ]));

        let mut identified_tree_map = BTreeMap::new();
        identified_tree_map.insert(vec![], Composition::from(vec![
            vec![Var(0, 0), T((vec![], 1)), Var(0, 1), T((vec![], 3))]
        ]));
        identified_tree_map.insert(vec![0], Composition::from(vec![
            vec![Var(1, 0)],
            vec![T((vec![0], 1))]
        ]));
        identified_tree_map.insert(vec![0, 1], Composition::from(vec![
            vec![T((vec![0, 1], 0))]
        ]));

        let mut terminal_map = BTreeMap::new();
        terminal_map.insert((vec![], 1), "a");
        terminal_map.insert((vec![], 3), "b");
        terminal_map.insert((vec![0], 1), "c");
        terminal_map.insert((vec![0, 1], 0), "d");

        assert_eq!((identified_tree_map, terminal_map), identify_terminals(&tree_map));
    }
}<commit_msg>src/pmcfg/negra.rs: added to_negra()<commit_after>use super::*;
use std::collections::{BTreeMap, LinkedList};

pub fn identify_terminals<A>(tree_map: &BTreeMap<Vec<usize>, Composition<A>>)
        -> (BTreeMap<Vec<usize>, Composition<(Vec<usize>, usize)>>, BTreeMap<(Vec<usize>, usize), A>)
    where A: Clone,
{
    let mut identified_tree_map = BTreeMap::new();
    let mut terminal_map = BTreeMap::new();

    for (address, composition) in tree_map {
        let vec_compos = &composition.composition;
        let mut identified_compos = Vec::new();
        let mut compos_var_pos = 0;

        for component in vec_compos {
            let mut identified_compon = Vec::new();

            for variable in component {
                match variable {
                    &VarT::Var(x, y) => {
                        identified_compon.push(VarT::Var(x, y));
                    },
                    &VarT::T(ref terminal) => {
                        let terminal_id = (address.clone(), compos_var_pos);
                        identified_compon.push(VarT::T(terminal_id.clone()));
                        terminal_map.insert(terminal_id, terminal.clone());
                    },
                };

                compos_var_pos += 1;
            }

            identified_compos.push(identified_compon);
        }

        identified_tree_map.insert(address.clone(), Composition::from(identified_compos));
    }

    (identified_tree_map, terminal_map)
}

pub fn to_negra<H, T, W>(tree_map: &BTreeMap<Vec<usize>, PMCFGRule<H, T, W>>, sentence_num: usize)
        -> String
    where H: Clone + ToString,
          T: Clone + ToString,
{
    let negra_vector = to_negra_vector(&tree_map);
    let mut output = format!("#BOS {}\n", sentence_num);

    for (symbol1, symbol2, number) in negra_vector {
        output.push_str(&format!("{}\t{}\t{}\n", symbol1, symbol2, number));
    }

    output.push_str(&format!("#EOS {}", sentence_num));
    output
}

pub fn to_negra_vector<H, T, W>(tree_map: &BTreeMap<Vec<usize>, PMCFGRule<H, T, W>>)
        -> Vec<(String, String, usize)>
    where H: Clone + ToString,
          T: Clone + ToString,
{
    let (term_map, nonterminal_map) = to_term(&tree_map);
    // TODO: Enforce negra grammar restrictions
    let (identified_tree_map, terminal_map) = identify_terminals(&term_map);
    let evaluated_compos = evaluate(&identified_tree_map);

    let mut negra_vector = Vec::new();
    let mut rule_queue = LinkedList::new();
    let mut finished_map = BTreeMap::new();
    let mut rule_counter = 0;

    for component in evaluated_compos.composition {
        for variable in component {
            match variable {
                VarT::Var(_, _) => {
                    panic!("Nonterminals must not appear in a fully evaluated configuration!");
                },
                VarT::T(terminal_id) => {
                    let terminal_symbol = terminal_map.get(&terminal_id).unwrap();
                    let ref address = terminal_id.0;
                    let rule_label = nonterminal_map.get(address).unwrap();
                    let rule_number = get_rule_number(address, &mut rule_queue, &finished_map,
                                                      &mut rule_counter);
                    negra_vector.push((terminal_symbol.to_string(), rule_label.to_string(), rule_number));
                }
            }
        }
    }

    while let Some((address, rule_number)) = rule_queue.pop_front() {
        let mut parent_address = address.clone();

        let parent_number = if let None = parent_address.pop() {
            0
        } else {
            let number = get_rule_number(&parent_address, &mut rule_queue, &finished_map, &mut rule_counter);
            finished_map.insert(parent_address.clone(), number);
            number
        };

        let rule_label = nonterminal_map.get(&address).unwrap();
        negra_vector.push((rule_number.to_string(), rule_label.to_string(), parent_number));
    }

    negra_vector
}

fn get_rule_number(address: &Vec<usize>, rule_queue: &mut LinkedList<(Vec<usize>, usize)>, finished_map: &BTreeMap<Vec<usize>, usize>, rule_counter: &mut usize)
        -> usize
{
    if let Some(rule_number) = finished_map.get(address) {
        return *rule_number
    }

    let rule_number = *rule_counter;
    *rule_counter = *rule_counter + 1;
    rule_queue.push_back((address.clone(), rule_number));
    rule_number
}

#[cfg(test)]
mod tests {
    use super::*;
    use VarT::{Var, T};

    #[test]
    fn test_identify_terminals() {
        let mut tree_map = BTreeMap::new();
        tree_map.insert(vec![], Composition::from(vec![
            vec![Var(0, 0), T("a"), Var(0, 1), T("b")]
        ]));
        tree_map.insert(vec![0], Composition::from(vec![
            vec![Var(1, 0)],
            vec![T("c")]
        ]));
        tree_map.insert(vec![0, 1], Composition::from(vec![
            vec![T("d")]
        ]));

        let mut identified_tree_map = BTreeMap::new();
        identified_tree_map.insert(vec![], Composition::from(vec![
            vec![Var(0, 0), T((vec![], 1)), Var(0, 1), T((vec![], 3))]
        ]));
        identified_tree_map.insert(vec![0], Composition::from(vec![
            vec![Var(1, 0)],
            vec![T((vec![0], 1))]
        ]));
        identified_tree_map.insert(vec![0, 1], Composition::from(vec![
            vec![T((vec![0, 1], 0))]
        ]));

        let mut terminal_map = BTreeMap::new();
        terminal_map.insert((vec![], 1), "a");
        terminal_map.insert((vec![], 3), "b");
        terminal_map.insert((vec![0], 1), "c");
        terminal_map.insert((vec![0, 1], 0), "d");

        assert_eq!((identified_tree_map, terminal_map), identify_terminals(&tree_map));
    }
}<|endoftext|>


<commit_before>use std::result;

use analysis::ref_mode::RefMode;
use env::Env;
use library::{self, Nullable};
use super::conversion_type::ConversionType;
use traits::*;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TypeError {
    Ignored(String),
    Mismatch(String),
    Unimplemented(String),
}

pub type Result = result::Result<String, TypeError>;

fn into_inner(res: Result) -> String {
    use self::TypeError::*;
    match res {
        Ok(s) | Err(Ignored(s)) | Err(Mismatch(s)) | Err(Unimplemented(s)) => s,
    }
}

impl IntoString for Result {
    fn into_string(self) -> String {
        use self::TypeError::*;
        match self {
            Ok(s) => s,
            Err(Ignored(s)) => format!("/*Ignored*/{}", s),
            Err(Mismatch(s)) => format!("/*Metadata mismatch*/{}", s),
            Err(Unimplemented(s)) => format!("/*Unimplemented*/{}", s),
        }
    }
}

impl MapAny<String> for Result {
    fn map_any<F: FnOnce(String) -> String>(self, op: F) -> Result {
        use self::TypeError::*;
        match self {
            Ok(s) => Ok(op(s)),
            Err(Ignored(s)) => Err(Ignored(op(s))),
            Err(Mismatch(s)) => Err(Mismatch(op(s))),
            Err(Unimplemented(s)) => Err(Unimplemented(op(s))),
        }
    }
}

pub fn rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::None)
}

pub fn bounds_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::ByRefFake)
}

fn rust_type_full(
    env: &Env,
    type_id: library::TypeId,
    nullable: Nullable,
    ref_mode: RefMode,
) -> Result {
    use library::Type::*;
    use library::Fundamental::*;
    let ok = |s: &str| Ok(s.into());
    let err = |s: &str| Err(TypeError::Unimplemented(s.into()));
    let mut skip_option = false;
    let type_ = env.library.type_(type_id);
    let mut rust_type = match *type_ {
        Fundamental(fund) => {
            match fund {
                None => err("()"),
                Boolean => ok("bool"),
                Int8 => ok("i8"),
                UInt8 => ok("u8"),
                Int16 => ok("i16"),
                UInt16 => ok("u16"),
                Int32 => ok("i32"),
                UInt32 => ok("u32"),
                Int64 => ok("i64"),
                UInt64 => ok("u64"),

                Int => ok("i32"),  //maybe dependent on target system
                UInt => ok("u32"), //maybe dependent on target system

                Short => ok("libc::c_short"), //depends of target system
                UShort => ok("libc::c_ushort"), //depends of target system
                Long => ok("libc::c_long"),   //depends of target system
                ULong => ok("libc::c_ulong"), //depends of target system

                Size => ok("usize"),  //depends of target system
                SSize => ok("isize"), //depends of target system

                Float => ok("f32"),
                Double => ok("f64"),

                UniChar => ok("char"),
                Utf8 => if ref_mode.is_ref() {
                    ok("str")
                } else {
                    ok("String")
                },
                Filename => if ref_mode.is_ref() {
                    ok("std::path::Path")
                } else {
                    ok("std::path::PathBuf")
                },
                Type if env.namespaces.glib_ns_id == library::MAIN_NAMESPACE => ok("types::Type"),
                Type => ok("glib::types::Type"),
                Unsupported => err("Unsupported"),
                _ => err(&format!("Fundamental: {:?}", fund)),
            }
        }
        Alias(ref alias) => {
            rust_type_full(env, alias.typ, nullable, ref_mode).map_any(|_| alias.name.clone())
        }
        Record(library::Record { ref c_type, .. }) if c_type == "GVariantType" => {
            if ref_mode.is_ref() {
                ok("VariantTy")
            } else {
                ok("VariantType")
            }
        }
        Enumeration(..) | Bitfield(..) | Record(..) | Union(..) | Class(..) | Interface(..) => {
            let name = type_.get_name().to_owned();
            if env.type_status(&type_id.full_name(&env.library)).ignored() {
                Err(TypeError::Ignored(name))
            } else {
                Ok(name)
            }
        }
        List(inner_tid) | SList(inner_tid) | CArray(inner_tid)
            if ConversionType::of(env, inner_tid) == ConversionType::Pointer =>
        {
            skip_option = true;
            let inner_ref_mode = match *env.library.type_(inner_tid) {
                Class(..) | Interface(..) => RefMode::None,
                _ => ref_mode,
            };
            rust_type_full(env, inner_tid, Nullable(false), inner_ref_mode).map_any(
                |s| if ref_mode.is_ref() {
                    format!("[{}]", s)
                } else {
                    format!("Vec<{}>", s)
                },
            )
        }
        CArray(inner_tid)
            if ConversionType::of(env, inner_tid) == ConversionType::Direct =>
        {
            if let Fundamental(fund) = *env.library.type_(inner_tid) {
                let array_type = match fund {
                    Int8 => Some("i8"),
                    UInt8 => Some("u8"),
                    Int16 => Some("i16"),
                    UInt16 => Some("u16"),
                    Int32 => Some("i32"),
                    UInt32 => Some("u32"),
                    Int64 => Some("i64"),
                    UInt64 => Some("u64"),

                    Int => Some("i32"),  //maybe dependent on target system
                    UInt => Some("u32"), //maybe dependent on target system

                    Float => Some("f32"),
                    Double => Some("f64"),
                    _ => Option::None,
                };

                if let Some(s) = array_type {
                    skip_option = true;
                    if ref_mode.is_ref() {
                        Ok(format!("[{}]", s))
                    } else {
                        Ok(format!("Vec<{}>", s))
                    }
                } else {
                    Err(TypeError::Unimplemented(type_.get_name().to_owned()))
                }
            } else {
                Err(TypeError::Unimplemented(type_.get_name().to_owned()))
            }
        }
        _ => Err(TypeError::Unimplemented(type_.get_name().to_owned())),
    };

    if type_id.ns_id != library::MAIN_NAMESPACE && type_id.ns_id != library::INTERNAL_NAMESPACE
        && !implemented_in_main_namespace(&env.library, type_id)
    {
        if env.type_status(&type_id.full_name(&env.library)).ignored() {
            rust_type = Err(TypeError::Ignored(into_inner(rust_type)));
        }
        rust_type = rust_type.map_any(|s| {
            format!("{}::{}", env.namespaces[type_id.ns_id].higher_crate_name, s)
        });
    }

    match ref_mode {
        RefMode::None | RefMode::ByRefFake => {}
        RefMode::ByRef | RefMode::ByRefImmut => {
            rust_type = rust_type.map_any(|s| format!("&{}", s))
        }
        RefMode::ByRefMut => rust_type = rust_type.map_any(|s| format!("&mut {}", s)),
    }
    if *nullable && !skip_option {
        match ConversionType::of(env, type_id) {
            ConversionType::Pointer | ConversionType::Scalar => {
                rust_type = rust_type.map_any(|s| format!("Option<{}>", s))
            }
            _ => (),
        }
    }

    rust_type
}

pub fn used_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    use library::Type::*;
    match *env.library.type_(type_id) {
        Fundamental(library::Fundamental::Type) |
        Fundamental(library::Fundamental::Short) |
        Fundamental(library::Fundamental::UShort) |
        Fundamental(library::Fundamental::Long) |
        Fundamental(library::Fundamental::ULong) |
        Fundamental(library::Fundamental::Filename) |
        Alias(..) |
        Bitfield(..) |
        Record(..) |
        Union(..) |
        Class(..) |
        Enumeration(..) |
        Interface(..) => rust_type(env, type_id),
        List(inner_tid) | SList(inner_tid) | CArray(inner_tid) => used_rust_type(env, inner_tid),
        _ => Err(TypeError::Ignored("Don't need use".to_owned())),
    }
}

pub fn parameter_rust_type(
    env: &Env,
    type_id: library::TypeId,
    direction: library::ParameterDirection,
    nullable: Nullable,
    ref_mode: RefMode,
) -> Result {
    use library::Type::*;
    let type_ = env.library.type_(type_id);
    let rust_type = rust_type_full(env, type_id, nullable, ref_mode);
    match *type_ {
        Fundamental(fund) => {
            if fund == library::Fundamental::Utf8 || fund == library::Fundamental::Filename {
                if direction == library::ParameterDirection::InOut
                    || (direction == library::ParameterDirection::Out
                        && ref_mode == RefMode::ByRefMut)
                {
                    return Err(TypeError::Unimplemented(into_inner(rust_type)));
                }
            }
            rust_type.map_any(|s| format_parameter(s, direction))
        }

        Alias(ref alias) => rust_type
            .and_then(|s| {
                parameter_rust_type(env, alias.typ, direction, nullable, ref_mode).map_any(|_| s)
            })
            .map_any(|s| format_parameter(s, direction)),

        Enumeration(..) | Union(..) | Bitfield(..) => {
            rust_type.map_any(|s| format_parameter(s, direction))
        }

        Record(..) => if direction == library::ParameterDirection::InOut {
            Err(TypeError::Unimplemented(into_inner(rust_type)))
        } else {
            rust_type
        },

        Class(..) | Interface(..) => match direction {
            library::ParameterDirection::In |
            library::ParameterDirection::Out |
            library::ParameterDirection::Return => rust_type,
            _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
        },

        List(..) | SList(..) => match direction {
            library::ParameterDirection::In | library::ParameterDirection::Return => rust_type,
            _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
        },
        CArray(..) => match direction {
            library::ParameterDirection::In |
            library::ParameterDirection::Out |
            library::ParameterDirection::Return => rust_type,
            _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
        },
        _ => Err(TypeError::Unimplemented(type_.get_name().to_owned())),
    }
}

#[inline]
fn format_parameter(rust_type: String, direction: library::ParameterDirection) -> String {
    if direction.is_out() {
        format!("&mut {}", rust_type)
    } else {
        rust_type
    }
}

//TODO: remove
fn implemented_in_main_namespace(library: &library::Library, type_id: library::TypeId) -> bool {
    type_id.full_name(library) == "GLib.Error"
}
<commit_msg>Add generation `Char` and `UChar` parameters<commit_after>use std::result;

use analysis::ref_mode::RefMode;
use env::Env;
use library::{self, Nullable};
use super::conversion_type::ConversionType;
use traits::*;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TypeError {
    Ignored(String),
    Mismatch(String),
    Unimplemented(String),
}

pub type Result = result::Result<String, TypeError>;

fn into_inner(res: Result) -> String {
    use self::TypeError::*;
    match res {
        Ok(s) | Err(Ignored(s)) | Err(Mismatch(s)) | Err(Unimplemented(s)) => s,
    }
}

impl IntoString for Result {
    fn into_string(self) -> String {
        use self::TypeError::*;
        match self {
            Ok(s) => s,
            Err(Ignored(s)) => format!("/*Ignored*/{}", s),
            Err(Mismatch(s)) => format!("/*Metadata mismatch*/{}", s),
            Err(Unimplemented(s)) => format!("/*Unimplemented*/{}", s),
        }
    }
}

impl MapAny<String> for Result {
    fn map_any<F: FnOnce(String) -> String>(self, op: F) -> Result {
        use self::TypeError::*;
        match self {
            Ok(s) => Ok(op(s)),
            Err(Ignored(s)) => Err(Ignored(op(s))),
            Err(Mismatch(s)) => Err(Mismatch(op(s))),
            Err(Unimplemented(s)) => Err(Unimplemented(op(s))),
        }
    }
}

pub fn rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::None)
}

pub fn bounds_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::ByRefFake)
}

fn rust_type_full(
    env: &Env,
    type_id: library::TypeId,
    nullable: Nullable,
    ref_mode: RefMode,
) -> Result {
    use library::Type::*;
    use library::Fundamental::*;
    let ok = |s: &str| Ok(s.into());
    let err = |s: &str| Err(TypeError::Unimplemented(s.into()));
    let mut skip_option = false;
    let type_ = env.library.type_(type_id);
    let mut rust_type = match *type_ {
        Fundamental(fund) => {
            match fund {
                None => err("()"),
                Boolean => ok("bool"),
                Int8 => ok("i8"),
                UInt8 => ok("u8"),
                Int16 => ok("i16"),
                UInt16 => ok("u16"),
                Int32 => ok("i32"),
                UInt32 => ok("u32"),
                Int64 => ok("i64"),
                UInt64 => ok("u64"),

                Int => ok("i32"),  //maybe dependent on target system
                UInt => ok("u32"), //maybe dependent on target system

                Short => ok("libc::c_short"), //depends of target system
                UShort => ok("libc::c_ushort"), //depends of target system
                Long => ok("libc::c_long"),   //depends of target system
                ULong => ok("libc::c_ulong"), //depends of target system

                Size => ok("usize"),  //depends of target system
                SSize => ok("isize"), //depends of target system

                Float => ok("f32"),
                Double => ok("f64"),

                UniChar => ok("char"),
                Utf8 => if ref_mode.is_ref() {
                    ok("str")
                } else {
                    ok("String")
                },
                Filename => if ref_mode.is_ref() {
                    ok("std::path::Path")
                } else {
                    ok("std::path::PathBuf")
                },
                Type if env.namespaces.glib_ns_id == library::MAIN_NAMESPACE => ok("types::Type"),
                Type => ok("glib::types::Type"),
                Char if env.namespaces.glib_ns_id == library::MAIN_NAMESPACE => ok("Char"),
                Char => ok("glib::Char"),
                UChar if env.namespaces.glib_ns_id == library::MAIN_NAMESPACE => ok("UChar"),
                UChar => ok("glib::UChar"),
                Unsupported => err("Unsupported"),
                _ => err(&format!("Fundamental: {:?}", fund)),
            }
        }
        Alias(ref alias) => {
            rust_type_full(env, alias.typ, nullable, ref_mode).map_any(|_| alias.name.clone())
        }
        Record(library::Record { ref c_type, .. }) if c_type == "GVariantType" => {
            if ref_mode.is_ref() {
                ok("VariantTy")
            } else {
                ok("VariantType")
            }
        }
        Enumeration(..) | Bitfield(..) | Record(..) | Union(..) | Class(..) | Interface(..) => {
            let name = type_.get_name().to_owned();
            if env.type_status(&type_id.full_name(&env.library)).ignored() {
                Err(TypeError::Ignored(name))
            } else {
                Ok(name)
            }
        }
        List(inner_tid) | SList(inner_tid) | CArray(inner_tid)
            if ConversionType::of(env, inner_tid) == ConversionType::Pointer =>
        {
            skip_option = true;
            let inner_ref_mode = match *env.library.type_(inner_tid) {
                Class(..) | Interface(..) => RefMode::None,
                _ => ref_mode,
            };
            rust_type_full(env, inner_tid, Nullable(false), inner_ref_mode).map_any(
                |s| if ref_mode.is_ref() {
                    format!("[{}]", s)
                } else {
                    format!("Vec<{}>", s)
                },
            )
        }
        CArray(inner_tid)
            if ConversionType::of(env, inner_tid) == ConversionType::Direct =>
        {
            if let Fundamental(fund) = *env.library.type_(inner_tid) {
                let array_type = match fund {
                    Int8 => Some("i8"),
                    UInt8 => Some("u8"),
                    Int16 => Some("i16"),
                    UInt16 => Some("u16"),
                    Int32 => Some("i32"),
                    UInt32 => Some("u32"),
                    Int64 => Some("i64"),
                    UInt64 => Some("u64"),

                    Int => Some("i32"),  //maybe dependent on target system
                    UInt => Some("u32"), //maybe dependent on target system

                    Float => Some("f32"),
                    Double => Some("f64"),
                    _ => Option::None,
                };

                if let Some(s) = array_type {
                    skip_option = true;
                    if ref_mode.is_ref() {
                        Ok(format!("[{}]", s))
                    } else {
                        Ok(format!("Vec<{}>", s))
                    }
                } else {
                    Err(TypeError::Unimplemented(type_.get_name().to_owned()))
                }
            } else {
                Err(TypeError::Unimplemented(type_.get_name().to_owned()))
            }
        }
        _ => Err(TypeError::Unimplemented(type_.get_name().to_owned())),
    };

    if type_id.ns_id != library::MAIN_NAMESPACE && type_id.ns_id != library::INTERNAL_NAMESPACE
        && !implemented_in_main_namespace(&env.library, type_id)
    {
        if env.type_status(&type_id.full_name(&env.library)).ignored() {
            rust_type = Err(TypeError::Ignored(into_inner(rust_type)));
        }
        rust_type = rust_type.map_any(|s| {
            format!("{}::{}", env.namespaces[type_id.ns_id].higher_crate_name, s)
        });
    }

    match ref_mode {
        RefMode::None | RefMode::ByRefFake => {}
        RefMode::ByRef | RefMode::ByRefImmut => {
            rust_type = rust_type.map_any(|s| format!("&{}", s))
        }
        RefMode::ByRefMut => rust_type = rust_type.map_any(|s| format!("&mut {}", s)),
    }
    if *nullable && !skip_option {
        match ConversionType::of(env, type_id) {
            ConversionType::Pointer | ConversionType::Scalar => {
                rust_type = rust_type.map_any(|s| format!("Option<{}>", s))
            }
            _ => (),
        }
    }

    rust_type
}

pub fn used_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    use library::Type::*;
    match *env.library.type_(type_id) {
        Fundamental(library::Fundamental::Type) |
        Fundamental(library::Fundamental::Short) |
        Fundamental(library::Fundamental::UShort) |
        Fundamental(library::Fundamental::Long) |
        Fundamental(library::Fundamental::ULong) |
        Fundamental(library::Fundamental::Char) |
        Fundamental(library::Fundamental::UChar) |
        Fundamental(library::Fundamental::Filename) |
        Alias(..) |
        Bitfield(..) |
        Record(..) |
        Union(..) |
        Class(..) |
        Enumeration(..) |
        Interface(..) => rust_type(env, type_id),
        List(inner_tid) | SList(inner_tid) | CArray(inner_tid) => used_rust_type(env, inner_tid),
        _ => Err(TypeError::Ignored("Don't need use".to_owned())),
    }
}

pub fn parameter_rust_type(
    env: &Env,
    type_id: library::TypeId,
    direction: library::ParameterDirection,
    nullable: Nullable,
    ref_mode: RefMode,
) -> Result {
    use library::Type::*;
    let type_ = env.library.type_(type_id);
    let rust_type = rust_type_full(env, type_id, nullable, ref_mode);
    match *type_ {
        Fundamental(fund) => {
            if fund == library::Fundamental::Utf8 || fund == library::Fundamental::Filename {
                if direction == library::ParameterDirection::InOut
                    || (direction == library::ParameterDirection::Out
                        && ref_mode == RefMode::ByRefMut)
                {
                    return Err(TypeError::Unimplemented(into_inner(rust_type)));
                }
            }
            rust_type.map_any(|s| format_parameter(s, direction))
        }

        Alias(ref alias) => rust_type
            .and_then(|s| {
                parameter_rust_type(env, alias.typ, direction, nullable, ref_mode).map_any(|_| s)
            })
            .map_any(|s| format_parameter(s, direction)),

        Enumeration(..) | Union(..) | Bitfield(..) => {
            rust_type.map_any(|s| format_parameter(s, direction))
        }

        Record(..) => if direction == library::ParameterDirection::InOut {
            Err(TypeError::Unimplemented(into_inner(rust_type)))
        } else {
            rust_type
        },

        Class(..) | Interface(..) => match direction {
            library::ParameterDirection::In |
            library::ParameterDirection::Out |
            library::ParameterDirection::Return => rust_type,
            _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
        },

        List(..) | SList(..) => match direction {
            library::ParameterDirection::In | library::ParameterDirection::Return => rust_type,
            _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
        },
        CArray(..) => match direction {
            library::ParameterDirection::In |
            library::ParameterDirection::Out |
            library::ParameterDirection::Return => rust_type,
            _ => Err(TypeError::Unimplemented(into_inner(rust_type))),
        },
        _ => Err(TypeError::Unimplemented(type_.get_name().to_owned())),
    }
}

#[inline]
fn format_parameter(rust_type: String, direction: library::ParameterDirection) -> String {
    if direction.is_out() {
        format!("&mut {}", rust_type)
    } else {
        rust_type
    }
}

//TODO: remove
fn implemented_in_main_namespace(library: &library::Library, type_id: library::TypeId) -> bool {
    type_id.full_name(library) == "GLib.Error"
}
<|endoftext|>


<commit_before>use ContextError;
use CreationError;
use CreationError::OsError;
use GlAttributes;
use GlContext;
use PixelFormatRequirements;

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
use cocoa::base::{id, nil};
use cocoa::appkit::*;
use PixelFormat;
use api::cocoa::helpers;

#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

pub struct HeadlessContext {
    width: u32,
    height: u32,
    context: id,
}

impl HeadlessContext {
    pub fn new((width, height): (u32, u32), pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&HeadlessContext>,
               _: &PlatformSpecificHeadlessBuilderAttributes)
               -> Result<HeadlessContext, CreationError>
    {
        let context = unsafe {

            let attributes = try!(helpers::build_nsattributes(pf_reqs, opengl));

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
            if pixelformat == nil {
                return Err(OsError(format!("Could not create the pixel format")));
            }
            let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            if context == nil {
                return Err(OsError(format!("Could not create the rendering context")));
            }
            context
        };

        let headless = HeadlessContext {
            width: width,
            height: height,
            context: context,
        };

        Ok(headless)
    }
}

impl GlContext for HeadlessContext {
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.context.makeCurrentContext();
        Ok(())
    }

    #[inline]
    fn is_current(&self) -> bool {
        unimplemented!()
    }

    #[inline]
    fn get_proc_address(&self, _addr: &str) -> *const () {
        let symbol_name: CFString = _addr.parse().unwrap();
        let framework_name: CFString = "com.apple.opengl".parse().unwrap();
        let framework = unsafe {
            CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
        };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const ()
    }

    #[inline]
    fn swap_buffers(&self) -> Result<(), ContextError> {
        unsafe { self.context.flushBuffer(); }
        Ok(())
    }

    #[inline]
    fn get_api(&self) -> ::Api {
        ::Api::OpenGl
    }

    #[inline]
    fn get_pixel_format(&self) -> PixelFormat {
        unimplemented!();
    }
}

unsafe impl Send for HeadlessContext {}
unsafe impl Sync for HeadlessContext {}
<commit_msg>Remove unused private fields from cocoa HeadlessContext struct.<commit_after>use ContextError;
use CreationError;
use CreationError::OsError;
use GlAttributes;
use GlContext;
use PixelFormatRequirements;

use core_foundation::base::TCFType;
use core_foundation::string::CFString;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
use cocoa::base::{id, nil};
use cocoa::appkit::*;
use PixelFormat;
use api::cocoa::helpers;

#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

pub struct HeadlessContext {
    context: id,
}

impl HeadlessContext {
    pub fn new((width, height): (u32, u32), pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&HeadlessContext>,
               _: &PlatformSpecificHeadlessBuilderAttributes)
               -> Result<HeadlessContext, CreationError>
    {
        let context = unsafe {

            let attributes = try!(helpers::build_nsattributes(pf_reqs, opengl));

            let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
            if pixelformat == nil {
                return Err(OsError(format!("Could not create the pixel format")));
            }
            let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
            if context == nil {
                return Err(OsError(format!("Could not create the rendering context")));
            }
            context
        };

        let headless = HeadlessContext {
            context: context,
        };

        Ok(headless)
    }
}

impl GlContext for HeadlessContext {
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.context.makeCurrentContext();
        Ok(())
    }

    #[inline]
    fn is_current(&self) -> bool {
        unimplemented!()
    }

    #[inline]
    fn get_proc_address(&self, _addr: &str) -> *const () {
        let symbol_name: CFString = _addr.parse().unwrap();
        let framework_name: CFString = "com.apple.opengl".parse().unwrap();
        let framework = unsafe {
            CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
        };
        let symbol = unsafe {
            CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
        };
        symbol as *const ()
    }

    #[inline]
    fn swap_buffers(&self) -> Result<(), ContextError> {
        unsafe { self.context.flushBuffer(); }
        Ok(())
    }

    #[inline]
    fn get_api(&self) -> ::Api {
        ::Api::OpenGl
    }

    #[inline]
    fn get_pixel_format(&self) -> PixelFormat {
        unimplemented!();
    }
}

unsafe impl Send for HeadlessContext {}
unsafe impl Sync for HeadlessContext {}
<|endoftext|>


<commit_before>#[doc = "Generate markdown from a document tree"];

import std::io;
import std::io::writer_util;

export mk_pass;

fn mk_pass(
    writer: fn~() -> io::writer
) -> pass {
    ret fn~(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        write_markdown(doc, writer());
        doc
    };
}

type ctxt = {
    w: io::writer
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer
    };

    write_crate(ctxt, doc);
}

enum hlvl {
    h1 = 1,
    h2 = 2,
    h3 = 3
}

fn write_header(ctxt: ctxt, lvl: hlvl, title: str) {
    let hashes = str::from_chars(vec::init_elt(lvl as uint, '#'));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
    ctxt.w.write_line("");
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    write_header(ctxt, h1, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    let fullpath = str::connect(moddoc.path + [moddoc.name], "::");
    write_header(ctxt, h2, #fmt("Module `%s`", fullpath));
    write_mod_contents(ctxt, moddoc);
}

#[test]
fn should_write_full_path_to_mod() {
    let markdown = test::render("mod a { mod b { mod c { } } }");
    assert str::contains(markdown, "## Module `a::b::c`");
}

fn write_mod_contents(
    ctxt: ctxt,
    doc: doc::moddoc
) {
    write_brief(ctxt, doc.brief);
    write_desc(ctxt, doc.desc);

    for fndoc in *doc.fns {
        write_fn(ctxt, fndoc);
    }

    for moddoc in *doc.mods {
        write_mod(ctxt, moddoc);
    }
}

#[test]
fn should_write_crate_brief_description() {
    let markdown = test::render("#[doc(brief = \"this is the crate\")];");
    assert str::contains(markdown, "this is the crate");
}

#[test]
fn should_write_crate_description() {
    let markdown = test::render("#[doc = \"this is the crate\"];");
    assert str::contains(markdown, "this is the crate");
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    write_header(ctxt, h3, #fmt("Function `%s`", doc.name));
    write_sig(ctxt, doc.sig);
    write_brief(ctxt, doc.brief);
    write_desc(ctxt, doc.desc);
    write_args(ctxt, doc.args);
    write_return(ctxt, doc.return);
}

fn write_sig(ctxt: ctxt, sig: option<str>) {
    alt sig {
      some(sig) {
        ctxt.w.write_line("```");
        ctxt.w.write_line(#fmt("%s", sig));
        ctxt.w.write_line("```");
        ctxt.w.write_line("");
      }
      none { fail "unimplemented" }
    }
}

#[test]
fn should_write_the_function_signature() {
    let markdown = test::render("#[doc = \"f\"] fn a() { }");
    assert str::contains(markdown, "```\nfn a()\n```");
}

#[test]
fn should_insert_blank_line_after_fn_signature() {
    let markdown = test::render("#[doc = \"f\"] fn a() { }");
    assert str::contains(markdown, "fn a()\n```\n\n");
}

fn write_brief(
    ctxt: ctxt,
    brief: option<str>
) {
    alt brief {
      some(brief) {
        ctxt.w.write_line(brief);
        ctxt.w.write_line("");
      }
      none { }
    }
}

fn write_desc(
    ctxt: ctxt,
    desc: option<str>
) {
    alt desc {
        some(desc) {
            ctxt.w.write_line(desc);
            ctxt.w.write_line("");
        }
        none { }
    }
}

fn write_args(
    ctxt: ctxt,
    args: [doc::argdoc]
) {
    if vec::is_not_empty(args) {
        ctxt.w.write_line("Arguments:");
        ctxt.w.write_line("");
        vec::iter(args) {|arg| write_arg(ctxt, arg) };
        ctxt.w.write_line("");
    }
}

fn write_arg(ctxt: ctxt, arg: doc::argdoc) {
    assert option::is_some(arg.ty);
    ctxt.w.write_str(#fmt(
        "* `%s`: `%s`",
        arg.name,
        option::get(arg.ty)
    ));
    alt arg.desc {
      some(desc) {
        ctxt.w.write_str(#fmt(" - %s", desc));
      }
      none { }
    }
    ctxt.w.write_line("");
}

#[test]
fn should_write_argument_list() {
    let source = "fn a(b: int, c: int) { }";
    let markdown = test::render(source);
    assert str::contains(
        markdown,
        "Arguments:\n\
         \n\
         * `b`: `int`\n\
         * `c`: `int`\n\
         \n"
    );
}

#[test]
fn should_not_write_arguments_if_none() {
    let source = "fn a() { } fn b() { }";
    let markdown = test::render(source);
    assert !str::contains(markdown, "Arguments");
}

#[test]
fn should_write_argument_description() {
    let source = "#[doc(args(a = \"milk\"))] fn f(a: bool) { }";
    let markdown = test::render(source);
    assert str::contains(markdown, "`a`: `bool` - milk");
}

fn write_return(
    ctxt: ctxt,
    doc: doc::retdoc
) {
    alt doc.ty {
      some(ty) {
        ctxt.w.write_str(#fmt("Returns `%s`", ty));
        alt doc.desc {
          some(d) {
            ctxt.w.write_line(#fmt(" - %s", d));
            ctxt.w.write_line("");
          }
          none {
            ctxt.w.write_line("");
            ctxt.w.write_line("");
          }
        }
      }
      none { }
    }
}

#[test]
fn should_write_return_type_on_new_line() {
    let markdown = test::render("fn a() -> int { }");
    assert str::contains(markdown, "\nReturns `int`");
}

#[test]
fn should_write_blank_line_between_return_type_and_next_header() {
    let markdown = test::render(
        "fn a() -> int { } \
         fn b() -> int { }"
    );
    assert str::contains(markdown, "Returns `int`\n\n##");
}

#[test]
fn should_not_write_return_type_when_there_is_none() {
    let markdown = test::render("fn a() { }");
    assert !str::contains(markdown, "Returns");
}

#[test]
fn should_write_blank_line_after_return_description() {
    let markdown = test::render(
        "#[doc(return = \"blorp\")] fn a() -> int { }"
    );
    assert str::contains(markdown, "blorp\n\n");
}

#[test]
fn should_write_return_description_on_same_line_as_type() {
    let markdown = test::render(
        "#[doc(return = \"blorp\")] fn a() -> int { }"
    );
    assert str::contains(markdown, "Returns `int` - blorp");
}

#[cfg(test)]
mod test {
    fn render(source: str) -> str {
        let srv = astsrv::mk_srv_from_str(source);
        let doc = extract::from_srv(srv, "");
        #debug("doc (extract): %?", doc);
        let doc = tystr_pass::mk_pass()(srv, doc);
        #debug("doc (tystr): %?", doc);
        let doc = path_pass::mk_pass()(srv, doc);
        #debug("doc (path): %?", doc);
        let doc = attr_pass::mk_pass()(srv, doc);
        #debug("doc (attr): %?", doc);
        let markdown = write_markdown_str(doc);
        #debug("markdown: %s", markdown);
        markdown
    }

    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let srv = astsrv::mk_srv_from_str("");
        let doc = extract::from_srv(srv, "belch");
        let doc = attr_pass::mk_pass()(srv, doc);
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let markdown = render("fn func() { }");
        assert str::contains(markdown, "## Function `func`");
    }

    #[test]
    fn write_markdown_should_write_mod_headers() {
        let markdown = render("mod moo { }");
        assert str::contains(markdown, "## Module `moo`");
    }

    #[test]
    fn should_leave_blank_line_after_header() {
        let markdown = render("mod morp { }");
        assert str::contains(markdown, "Module `morp`\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_fn_header_and_sig() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "Function `a`\n\n```\nfn a()");
    }

    #[test]
    fn should_leave_blank_line_after_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "brief\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_brief_and_desc() {
        let markdown = render(
            "#[doc(brief = \"brief\", desc = \"desc\")] fn a() { }"
        );
        assert str::contains(markdown, "brief\n\ndesc");
    }

}<commit_msg>rustdoc: Use the standard markdown syntax for code blocks<commit_after>#[doc = "Generate markdown from a document tree"];

import std::io;
import std::io::writer_util;

export mk_pass;

fn mk_pass(
    writer: fn~() -> io::writer
) -> pass {
    ret fn~(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        write_markdown(doc, writer());
        doc
    };
}

type ctxt = {
    w: io::writer
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer
    };

    write_crate(ctxt, doc);
}

enum hlvl {
    h1 = 1,
    h2 = 2,
    h3 = 3
}

fn write_header(ctxt: ctxt, lvl: hlvl, title: str) {
    let hashes = str::from_chars(vec::init_elt(lvl as uint, '#'));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
    ctxt.w.write_line("");
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    write_header(ctxt, h1, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    let fullpath = str::connect(moddoc.path + [moddoc.name], "::");
    write_header(ctxt, h2, #fmt("Module `%s`", fullpath));
    write_mod_contents(ctxt, moddoc);
}

#[test]
fn should_write_full_path_to_mod() {
    let markdown = test::render("mod a { mod b { mod c { } } }");
    assert str::contains(markdown, "## Module `a::b::c`");
}

fn write_mod_contents(
    ctxt: ctxt,
    doc: doc::moddoc
) {
    write_brief(ctxt, doc.brief);
    write_desc(ctxt, doc.desc);

    for fndoc in *doc.fns {
        write_fn(ctxt, fndoc);
    }

    for moddoc in *doc.mods {
        write_mod(ctxt, moddoc);
    }
}

#[test]
fn should_write_crate_brief_description() {
    let markdown = test::render("#[doc(brief = \"this is the crate\")];");
    assert str::contains(markdown, "this is the crate");
}

#[test]
fn should_write_crate_description() {
    let markdown = test::render("#[doc = \"this is the crate\"];");
    assert str::contains(markdown, "this is the crate");
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    write_header(ctxt, h3, #fmt("Function `%s`", doc.name));
    write_sig(ctxt, doc.sig);
    write_brief(ctxt, doc.brief);
    write_desc(ctxt, doc.desc);
    write_args(ctxt, doc.args);
    write_return(ctxt, doc.return);
}

fn write_sig(ctxt: ctxt, sig: option<str>) {
    alt sig {
      some(sig) {
        ctxt.w.write_line(#fmt("    %s", sig));
        ctxt.w.write_line("");
      }
      none { fail "unimplemented" }
    }
}

#[test]
fn should_write_the_function_signature() {
    let markdown = test::render("#[doc = \"f\"] fn a() { }");
    assert str::contains(markdown, "\n    fn a()\n");
}

#[test]
fn should_insert_blank_line_after_fn_signature() {
    let markdown = test::render("#[doc = \"f\"] fn a() { }");
    assert str::contains(markdown, "fn a()\n\n");
}

fn write_brief(
    ctxt: ctxt,
    brief: option<str>
) {
    alt brief {
      some(brief) {
        ctxt.w.write_line(brief);
        ctxt.w.write_line("");
      }
      none { }
    }
}

fn write_desc(
    ctxt: ctxt,
    desc: option<str>
) {
    alt desc {
        some(desc) {
            ctxt.w.write_line(desc);
            ctxt.w.write_line("");
        }
        none { }
    }
}

fn write_args(
    ctxt: ctxt,
    args: [doc::argdoc]
) {
    if vec::is_not_empty(args) {
        ctxt.w.write_line("Arguments:");
        ctxt.w.write_line("");
        vec::iter(args) {|arg| write_arg(ctxt, arg) };
        ctxt.w.write_line("");
    }
}

fn write_arg(ctxt: ctxt, arg: doc::argdoc) {
    assert option::is_some(arg.ty);
    ctxt.w.write_str(#fmt(
        "* `%s`: `%s`",
        arg.name,
        option::get(arg.ty)
    ));
    alt arg.desc {
      some(desc) {
        ctxt.w.write_str(#fmt(" - %s", desc));
      }
      none { }
    }
    ctxt.w.write_line("");
}

#[test]
fn should_write_argument_list() {
    let source = "fn a(b: int, c: int) { }";
    let markdown = test::render(source);
    assert str::contains(
        markdown,
        "Arguments:\n\
         \n\
         * `b`: `int`\n\
         * `c`: `int`\n\
         \n"
    );
}

#[test]
fn should_not_write_arguments_if_none() {
    let source = "fn a() { } fn b() { }";
    let markdown = test::render(source);
    assert !str::contains(markdown, "Arguments");
}

#[test]
fn should_write_argument_description() {
    let source = "#[doc(args(a = \"milk\"))] fn f(a: bool) { }";
    let markdown = test::render(source);
    assert str::contains(markdown, "`a`: `bool` - milk");
}

fn write_return(
    ctxt: ctxt,
    doc: doc::retdoc
) {
    alt doc.ty {
      some(ty) {
        ctxt.w.write_str(#fmt("Returns `%s`", ty));
        alt doc.desc {
          some(d) {
            ctxt.w.write_line(#fmt(" - %s", d));
            ctxt.w.write_line("");
          }
          none {
            ctxt.w.write_line("");
            ctxt.w.write_line("");
          }
        }
      }
      none { }
    }
}

#[test]
fn should_write_return_type_on_new_line() {
    let markdown = test::render("fn a() -> int { }");
    assert str::contains(markdown, "\nReturns `int`");
}

#[test]
fn should_write_blank_line_between_return_type_and_next_header() {
    let markdown = test::render(
        "fn a() -> int { } \
         fn b() -> int { }"
    );
    assert str::contains(markdown, "Returns `int`\n\n##");
}

#[test]
fn should_not_write_return_type_when_there_is_none() {
    let markdown = test::render("fn a() { }");
    assert !str::contains(markdown, "Returns");
}

#[test]
fn should_write_blank_line_after_return_description() {
    let markdown = test::render(
        "#[doc(return = \"blorp\")] fn a() -> int { }"
    );
    assert str::contains(markdown, "blorp\n\n");
}

#[test]
fn should_write_return_description_on_same_line_as_type() {
    let markdown = test::render(
        "#[doc(return = \"blorp\")] fn a() -> int { }"
    );
    assert str::contains(markdown, "Returns `int` - blorp");
}

#[cfg(test)]
mod test {
    fn render(source: str) -> str {
        let srv = astsrv::mk_srv_from_str(source);
        let doc = extract::from_srv(srv, "");
        #debug("doc (extract): %?", doc);
        let doc = tystr_pass::mk_pass()(srv, doc);
        #debug("doc (tystr): %?", doc);
        let doc = path_pass::mk_pass()(srv, doc);
        #debug("doc (path): %?", doc);
        let doc = attr_pass::mk_pass()(srv, doc);
        #debug("doc (attr): %?", doc);
        let markdown = write_markdown_str(doc);
        #debug("markdown: %s", markdown);
        markdown
    }

    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let srv = astsrv::mk_srv_from_str("");
        let doc = extract::from_srv(srv, "belch");
        let doc = attr_pass::mk_pass()(srv, doc);
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let markdown = render("fn func() { }");
        assert str::contains(markdown, "## Function `func`");
    }

    #[test]
    fn write_markdown_should_write_mod_headers() {
        let markdown = render("mod moo { }");
        assert str::contains(markdown, "## Module `moo`");
    }

    #[test]
    fn should_leave_blank_line_after_header() {
        let markdown = render("mod morp { }");
        assert str::contains(markdown, "Module `morp`\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_fn_header_and_sig() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "Function `a`\n\n    fn a()");
    }

    #[test]
    fn should_leave_blank_line_after_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "brief\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_brief_and_desc() {
        let markdown = render(
            "#[doc(brief = \"brief\", desc = \"desc\")] fn a() { }"
        );
        assert str::contains(markdown, "brief\n\ndesc");
    }

}<|endoftext|>


<commit_before>pub fn eq_f64(x: f64, y: f64, error: f64) -> bool {
    (x - y).abs() < error
}
<commit_msg>add tests for eq_f64<commit_after>pub fn eq_f64(x: f64, y: f64, error: f64) -> bool {
    (x - y).abs() < error
}

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

    #[test]
    fn test_eq_f64() {
        // Actual equality (need to supply a >0 error though)
        assert!(eq_f64(1.1, 1.1, 0.000000001));

        // The second is smaller
        assert!(eq_f64(1.1, 1.0, 1.000000001));

        // The second is greater
        assert!(eq_f64(1.1, 1.2, 1.000000001));

    }
}
<|endoftext|>


<commit_before>use std::process;
use std::process::Command;

fn main () {
    #[cfg(target_os = "macos")]
    fn inner() -> &'static str {
        "open"
    }
    #[cfg(target_os = "windows")]
    fn inner() -> &'static str {
        "start"
    }

    let command = inner();
    let arg = "http://groonga.org/docs/";
    let err = match Command::new(command)
        .args(&[arg])
        // .stdout(Stdio::inherit())
        // .stderr(Stdio::inherit())
        .spawn() {
        Ok(_) => return (),
        Err(e) => e,
        };
    println!("Failed to execute docopen subcommand. reason: {:?}", err);
    process::exit(1);

}
<commit_msg>grnenv-docopen: Add settings for unix like environment<commit_after>use std::process;
use std::process::Command;

fn main () {
    #[cfg(target_os = "macos")]
    fn inner() -> &'static str {
        "open"
    }
    #[cfg(target_os = "windows")]
    fn inner() -> &'static str {
        "start"
    }
    #[cfg(target_os = "unix")]
    fn inner() -> &'static str {
        "xdg-open"
    }

    let command = inner();
    let arg = "http://groonga.org/docs/";
    let err = match Command::new(command)
        .args(&[arg])
        // .stdout(Stdio::inherit())
        // .stderr(Stdio::inherit())
        .spawn() {
        Ok(_) => return (),
        Err(e) => e,
        };
    println!("Failed to execute docopen subcommand. reason: {:?}", err);
    process::exit(1);

}
<|endoftext|>


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

//! rustbuild, the Rust build system
//!
//! This is the entry point for the build system used to compile the `rustc`
//! compiler. Lots of documentation can be found in the `README.md` file next to
//! this file, and otherwise documentation can be found throughout the `build`
//! directory in each respective module.

#![deny(warnings)]

extern crate bootstrap;

use std::env;

use bootstrap::{Flags, Config, Build};

fn main() {
    let args = env::args().skip(1).collect::<Vec<_>>();
    let flags = Flags::parse(&args);
    let mut config = Config::parse(&flags.build, flags.config.clone());

    // compat with `./configure` while we're still using that
    if std::fs::metadata("config.mk").is_ok() {
        config.update_with_config_mk();
    }

    Build::new(flags, config).build();
}
<commit_msg>README path correction<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! rustbuild, the Rust build system
//!
//! This is the entry point for the build system used to compile the `rustc`
//! compiler. Lots of documentation can be found in the `README.md` file in the
//! parent directory, and otherwise documentation can be found throughout the `build`
//! directory in each respective module.

#![deny(warnings)]

extern crate bootstrap;

use std::env;

use bootstrap::{Flags, Config, Build};

fn main() {
    let args = env::args().skip(1).collect::<Vec<_>>();
    let flags = Flags::parse(&args);
    let mut config = Config::parse(&flags.build, flags.config.clone());

    // compat with `./configure` while we're still using that
    if std::fs::metadata("config.mk").is_ok() {
        config.update_with_config_mk();
    }

    Build::new(flags, config).build();
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::collections::BTreeSet;
use std::fmt;
use std::hash::Hash;
use std::io;
use std::path::Path;

use error::Error;
use serde::Serialize;

use res;

/// The sets of detected inputs and outputs of a process.
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct Detected {
    inputs: BTreeSet<res::Any>,
    outputs: BTreeSet<res::Any>,
}

impl Detected {
    pub fn new() -> Detected {
        Detected::default()
    }

    pub fn inputs(&self) -> impl Iterator<Item = &res::Any> {
        self.inputs.iter()
    }

    pub fn outputs(&self) -> impl Iterator<Item = &res::Any> {
        self.outputs.iter()
    }

    pub fn add_input(&mut self, r: res::Any) {
        self.inputs.insert(r);
    }

    #[allow(dead_code)]
    pub fn add_output(&mut self, r: res::Any) {
        self.outputs.insert(r);
    }

    pub fn add(&mut self, other: Detected) {
        self.inputs.extend(other.inputs);
        self.outputs.extend(other.outputs);
    }
}

/// A task is a routine to be executed that produces resources as outputs.
///
/// Most tasks will be of the `Command` type. That is, the execution of a
/// process with arguments.
///
/// Since a task is anything that can be executed, we can have other built-in
/// tasks to aid with cross-platform compatibility. For example:
///  * Copying a file or directory.
///  * Downloading a file.
///  * Creating a directory.
pub trait Task:
    Serialize + Ord + PartialOrd + Eq + PartialEq + Hash + fmt::Display
{
    /// Executes the task. The result of a task are the resources it used and
    /// the resources it output. These are its *implicit* inputs and outputs.
    /// Ideally, the *explicit* inputs and outputs are a subset of the
    /// *implicit* inputs and outputs.
    fn execute(
        &self,
        root: &Path,
        log: &mut io::Write,
    ) -> Result<Detected, Error>;

    /// Inputs the task knows about *a priori*. It must calculate these by
    /// *only* looking at the task parameters. It should not do anything fancy
    /// like running an external process to determine these.
    ///
    /// If the task would delete a resource, it should remove it from the set of
    /// inputs. It may be the case that one task adds an input, but a later task
    /// deletes it. In such a case, that file is effectively a temporary file
    /// and can be ignored.
    fn known_inputs(&self, _resources: &mut res::Set) {}

    /// Outputs the task knows about *a priori*. It must calculate these by
    /// *only* looking at the task parameters. It cannot do anything fancy like
    /// running an external process to determine these.
    fn known_outputs(&self, _resources: &mut res::Set) {}
}
<commit_msg>Use HashSet for detected inputs/outputs<commit_after>// Copyright (c) 2017 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::collections::HashSet;
use std::fmt;
use std::hash::Hash;
use std::io;
use std::path::Path;

use error::Error;
use serde::Serialize;

use res;

/// The sets of detected inputs and outputs of a process.
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct Detected {
    inputs: HashSet<res::Any>,
    outputs: HashSet<res::Any>,
}

impl Detected {
    pub fn new() -> Detected {
        Detected::default()
    }

    pub fn inputs(&self) -> impl Iterator<Item = &res::Any> {
        self.inputs.iter()
    }

    pub fn outputs(&self) -> impl Iterator<Item = &res::Any> {
        self.outputs.iter()
    }

    pub fn add_input(&mut self, r: res::Any) {
        self.inputs.insert(r);
    }

    #[allow(dead_code)]
    pub fn add_output(&mut self, r: res::Any) {
        self.outputs.insert(r);
    }

    pub fn add(&mut self, other: Detected) {
        self.inputs.extend(other.inputs);
        self.outputs.extend(other.outputs);
    }
}

/// A task is a routine to be executed that produces resources as outputs.
///
/// Most tasks will be of the `Command` type. That is, the execution of a
/// process with arguments.
///
/// Since a task is anything that can be executed, we can have other built-in
/// tasks to aid with cross-platform compatibility. For example:
///  * Copying a file or directory.
///  * Downloading a file.
///  * Creating a directory.
pub trait Task:
    Serialize + Ord + PartialOrd + Eq + PartialEq + Hash + fmt::Display
{
    /// Executes the task. The result of a task are the resources it used and
    /// the resources it output. These are its *implicit* inputs and outputs.
    /// Ideally, the *explicit* inputs and outputs are a subset of the
    /// *implicit* inputs and outputs.
    fn execute(
        &self,
        root: &Path,
        log: &mut io::Write,
    ) -> Result<Detected, Error>;

    /// Inputs the task knows about *a priori*. It must calculate these by
    /// *only* looking at the task parameters. It should not do anything fancy
    /// like running an external process to determine these.
    ///
    /// If the task would delete a resource, it should remove it from the set of
    /// inputs. It may be the case that one task adds an input, but a later task
    /// deletes it. In such a case, that file is effectively a temporary file
    /// and can be ignored.
    fn known_inputs(&self, _resources: &mut res::Set) {}

    /// Outputs the task knows about *a priori*. It must calculate these by
    /// *only* looking at the task parameters. It cannot do anything fancy like
    /// running an external process to determine these.
    fn known_outputs(&self, _resources: &mut res::Set) {}
}
<|endoftext|>